#!/usr/bin/perl # (c) 1999/2000/2001,2002,2003 Mandriva, # Chmouel Boudjnah , Denis HAVLIK # And others Coooker contributor. # See http://www.gnu.org for license. ## Enable or disable supermount. # $Id$ my $file = $ENV{FSTAB} || '/etc/fstab'; my ($ofile, $mpoint); #"bad" or "nessesary" options for "normal" and "supermount" entry # "bad" options can be regexp. my @normal_bad = qw ( fs=\S+ dev=\S+ --); my @super_bad = qw (sync user noauto); my @normal_must = qw (user noauto nodev nosuid); my @super_must = qw (nodev nosuid); my $fs_ok = '(auto|vfat|iso9660)'; my $dev_ok = '(fd|floppy|zip|cdrom)\d*'; my $mnt_ok = '(floppy|zip|cdrom)\d*'; my ($enable, $disable, $infile); while ($ARGV[0] =~ /^--/ || $ARGV[0] =~ /^-/) { $_ = shift; if (/^--file=([^ \t]+)/ || /^-f=([^ \t]+)/) { $file = $1; } elsif (/^--mountpoint=([^ \t]+)/ || /^-m=([^ \t]+)/) { $mpoint = $1; } elsif (/^--infile/ || /^-i/) { $infile++; } elsif (/^--help/ || /^-h/ || /^-\?/) { usage(0); } else { print STDERR "Unrecognized switch: $_\n"; usage(1); } } if ($ARGV[0] =~ /enable/) { $enable++; } elsif ( $ARGV[0] =~ /disable/ ) { $disable++; } else { usage(1); } open FH, $file or die "Can't open $file\n"; if ($infile) { $ofile = `mktemp /tmp/fstab.XXXXXX` || die "Can't create temporary file\n"; chomp $ofile; open OU, ">$ofile" or die "Can't write to $ofile\n"; select OU; } while () { my ($dev, $point, $fs, $opt, $d1, $d2) = split; my @opt = split (',', $opt); if ( $disable && ($fs eq "supermount") && (!defined($mpoint) || $point eq $mpoint) && $_ !~ /^#/ ) { my @must; map { m/^fs=(\S+)/ && ($fs = $1); m/dev=(\S+)/ && ($dev= $1); } @opt; $fs = 'auto' if $fs =~ /:/; &clean_options(\@opt,\@normal_must,\@normal_bad); if ($dev =~ /^\/dev\/(fd[0-1]|floppy$)/ ) { @must = qw (sync); &clean_options(\@opt,\@must, []); } elsif (($dev =~ /^\/dev\/cdrom\d*$/) || ($fs eq "iso9660" )) { @must = qw (ro exec); &clean_options(\@opt,\@must, []); } $opt = join (',' , @opt); print "$dev\t$point\t$fs $opt\t$d1 $d2\n"; next; } elsif ( $enable && (!defined($mpoint) || $point eq $mpoint) && ( $fs eq "iso9660" || ( $_ !~ /^#/ && $fs =~ m/$fs_ok/ && ( $dev =~ /^\/dev\/($dev_ok)$/ || $point =~ m|^/mnt/($mnt_ok)$| ) ) ) && ($opt =~ m/(^|.*,)user.*/) ) { if ($fs eq "auto") { if ($point =~ m,.*/cdrom\d*$, or $dev =~ m,.*/cdrom\d*$,) { $fs = "udf:iso9660"; } else { $fs = "ext2:vfat"; } } &clean_options(\@opt,\@super_must, \@super_bad); $opt = join (',' , @opt); print "none\t$point\tsupermount\tfs=$fs,dev=$dev,--,$opt 0 0\n"; next; } print; } close FH; if ($infile) { close OU; system("cp -f", $file, "$file.old"); system("mv", $ofile, $file);chmod 0644, $file; } sub clean_options { my ($ap_opt, $ap_must, $ap_bad) = @_; my $o; my %union; my @opt = @$ap_bad; foreach $o (@$ap_bad) {@$ap_opt = grep ( !/^$o$/ ,@$ap_opt);} foreach my $o (@$ap_opt, @$ap_must) { $union{$o}++;} @$ap_opt=keys %union; } sub usage { my $e = shift @_; $0 =~ s|.*/||; print { $e ? STDERR : STDOUT } << "EOF"; Usage: $0 [OPTION]... Enable or disable supermount in fstab. -m=DIR, --mountpoint=DIR: Specifiy single mount point to enable/disable. (default: all) -f=FILE, --file=FILE: Specify an alternarte fstab file . (default: /etc/fstab). -i, --infile: Make modification directly in the file. EOF exit($e); } __END__ CHANGELOG: Thu Feb 25 2001 Andrej Borsenkow - added ``--'' as delimiter for supermount fs options to avoid mount errors on fs-specific options - added --mountpoint option to operate on single mount point - changed condition to enable supermount to (($fs eq iso9660) || (($fs =~ m/$fs_ok) && ($dev =~ /^\/dev\/($dev_ok)$/))) && ($opt =~ m/(^|.*,)user.*/ ) Before it tried to supermount Windows vfat partitions that were defined with user option. Thu Apr 13 2000 Denis Havlik - moved definitions of "good" and "bad" fs-options, "allowed fs-s" and "good devices" to top of the script for easier maintainance. - added &clean_options(\@opt,\@must, \@bad) function, which parses the @opt array, adds the "must" options and removes the "bad" ones, and re-wrote the while () {} loop to take advantage of this functions. - simplified the fstab parsing (split instead of regexp-s) - changed the rules used to decide which mount points are going to be supermounted to: ($fs eq "iso9660") || (( $fs =~ m/$fs_ok/ ) && (($dev =~ /^\/dev\/($dev_ok)$/) || ($opt =~ m/(^|.*,)user.*/ )) )