# linux-lib.pl # Mount table functions for linux if (!$no_check_support) { if (&has_command("amd")) { local $amd = &read_amd_conf(); $amd_support = $amd =~ /\[\s*global\s*\]/i ? 2 : 1; } $autofs_support = &has_command("automount"); if (&has_command("mount.cifs")) { $cifs_support = 4; } if (&has_command("mount.smbfs")) { $smbfs_support = &backquote_command("mount.smbfs -v", 1) =~ /username=/i ? 4 : 3; $smbfs_fs = "smbfs"; } elsif (&has_command("mount.smb")) { $smbfs_support = &backquote_command("mount.smb -v", 1) =~ /username=/i ? 4 : 3; $smbfs_fs = "smb"; } elsif (&has_command("smbmount")) { $smbfs_support = &backquote_command("smbmount -v", 1) =~ /Version\s+2/i ? 2 : 1; $smbfs_fs = "smbfs"; } $swaps_support = -r "/proc/swaps"; if (`uname -r` =~ /^(\d+\.\d+)/ && $1 >= 2.4) { $tmpfs_support = 1; $ext3_support = 1; $no_mount_check = 1; $bind_support = 1; # XXX which version? if ($1 >= 2.6) { $ext4_support = 1; } } if (&has_command("mkfs.xfs")) { $xfs_support = 1; } if (&has_command("mkfs.jfs")) { $jfs_support = 1; } } # We always need to check this, to fix up LABEL= mounts if (&has_command("e2label")) { $has_e2label = 1; } if (&has_command("xfs_db")) { $has_xfs_db = 1; } if (&has_command("vol_id")) { $has_volid = 1; } if (&has_command("reiserfstune")) { $has_reiserfstune = 1; } $uuid_directory = "/dev/disk/by-uuid"; # Return information about a filesystem, in the form: # directory, device, type, options, fsck_order, mount_at_boot # If a field is unused or ignored, a - appears instead of the value. # Swap-filesystems (devices or files mounted for VM) have a type of 'swap', # and 'swap' in the directory field sub list_mounts { return @list_mounts_cache if (@list_mounts_cache); local(@rv, @p, @o, $_, $i, $j); $i = 0; # Get /etc/fstab mounts open(FSTAB, $config{fstab_file}); while() { local(@o, $at_boot); chop; s/#.*$//g; if (!/\S/ || /\signore\s/) { next; } @p = split(/\s+/, $_); if ($p[2] eq "proc") { $p[0] = "proc"; } elsif ($p[2] eq "auto") { $p[2] = "*"; } elsif ($p[2] eq "swap") { $p[1] = "swap"; } elsif ($p[2] eq $smbfs_fs || $p[2] eq "cifs") { $p[0] =~ s/\\040/ /g; $p[0] =~ s/\//\\/g; } $rv[$i] = [ $p[1], $p[0], $p[2] ]; $rv[$i]->[5] = "yes"; @o = split(/,/ , $p[3] eq "defaults" ? "" : $p[3]); if (($j = &indexof("noauto", @o)) >= 0) { # filesytem is not mounted at boot splice(@o, $j, 1); $rv[$i]->[5] = "no"; } if (($j = &indexof("bind", @o)) >= 0) { # Special bind option, which indicates a loopback filesystem splice(@o, $j, 1); $p[0] = "bind"; } $rv[$i]->[3] = (@o ? join(',' , @o) : "-"); $rv[$i]->[4] = (@p >= 5 ? $p[5] : 0); $i++; } close(FSTAB); if ($amd_support == 1) { # Get old automounter configuration, as used by redhat local $amd = &read_amd_conf(); if ($amd =~ /MOUNTPTS='(.*)'/) { @p = split(/\s+/, $1); for($j=0; $j<@p; $j+=2) { $rv[$i++] = [ $p[$j], $p[$j+1], "auto", "-", 0, "yes" ]; } } } elsif ($amd_support == 2) { # Guess what? There's now a *new* amd config file format, introduced # in redhat 6.1 and caldera 2.3 local @amd = &parse_amd_conf(); local @sp = split(/:/, $amd[0]->{'opts'}->{'search_path'}); local ($am, $sp); foreach $am (@amd) { local $mn = $am->{'opts'}->{'map_name'}; if ($mn !~ /^\//) { foreach $sp (@sp) { if (-r "$sp/$mn") { $mn = "$sp/$mn"; last; } } } $rv[$i++] = [ $am->{'dir'}, $mn, "auto", $am->{'opts'}, 0, "yes" ] if ($am->{'dir'} ne 'global'); } } # Get kernel automounter configuration if ($autofs_support) { open(AUTO, $config{'autofs_file'}); while() { chop; s/#.*$//g; if (/^\s*(\S+)\s+(\S+)\s*(.*)$/) { $rv[$i++] = [ $1, $2, "autofs", ($3 ? &autofs_options($3) : "-"), 0, "yes" ]; } } close(AUTO); } @list_mounts_cache = @rv; return @rv; } # create_mount(directory, device, type, options, fsck_order, mount_at_boot) # Add a new entry to the fstab file, old or new automounter file sub create_mount { local(@mlist, @amd, $_); local($opts); if ($_[2] eq "auto") { if ($amd_support == 1) { # Adding an old automounter mount local $amd = &read_amd_conf(); local $m = "$_[0] $_[1]"; if ($amd =~ /MOUNTPTS=''/) { $amd =~ s/MOUNTPTS=''/MOUNTPTS='$m'/; } else { $amd =~ s/MOUNTPTS='(.*)'/MOUNTPTS='$1 $m'/; } &write_amd_conf($amd); } elsif ($amd_support == 2) { # Adding a new automounter mount local @amfs = split(/\s+/, $config{'auto_file'}); &open_tempfile(AMD, ">>$amfs[0]"); &print_tempfile(AMD, "\n"); &print_tempfile(AMD, "[ $_[0] ]\n"); &print_tempfile(AMD, "map_name = $_[1]\n"); &close_tempfile(AMD); } } elsif ($_[2] eq "autofs") { # Adding a new automounter mount &open_tempfile(AUTO, ">> $config{'autofs_file'}"); &print_tempfile(AUTO, "$_[0] $_[1]"); if ($_[3]) { &print_tempfile(AUTO, " ",&autofs_args($_[3])); } &print_tempfile(AUTO, "\n"); &close_tempfile(AUTO); } else { # Adding a normal mount to the fstab file local $dev = $_[1]; if ($_[2] eq $smbfs_fs || $_[2] eq "cifs") { $dev =~ s/\\/\//g; $dev =~ s/ /\\040/g; } &open_tempfile(FSTAB, ">> $config{fstab_file}"); &print_tempfile(FSTAB, "$dev $_[0] $_[2]"); local @opts = $_[3] eq "-" ? ( ) : split(/,/, $_[3]); if ($_[5] eq "no") { push(@opts, "noauto"); } else { @opts = grep { $_ !~ /^(auto|noauto)$/ } @opts; } if ($_[2] eq "bind") { push(@opts, "bind"); } if (!@opts) { &print_tempfile(FSTAB, " defaults"); } else { &print_tempfile(FSTAB, " ".join(",", @opts)); } &print_tempfile(FSTAB, " 0 "); &print_tempfile(FSTAB, $_[4] eq "-" ? "0\n" : "$_[4]\n"); &close_tempfile(FSTAB); } undef(@list_mounts_cache); } # change_mount(num, directory, device, type, options, fsck_order, mount_at_boot) # Change an existing permanent mount sub change_mount { local($i, @fstab, $line, $opts, $j, @amd); $i = 0; # Update fstab file open(FSTAB, $config{fstab_file}); @fstab = ; close(FSTAB); &open_tempfile(FSTAB, "> $config{fstab_file}"); foreach (@fstab) { chop; ($line = $_) =~ s/#.*$//g; if ($line =~ /\S/ && $line !~ /\signore\s/ && $i++ == $_[0]) { # Found the line to replace local $dev = $_[2]; $dev =~ s/ /\\040/g; &print_tempfile(FSTAB, "$dev $_[1] $_[3]"); local @opts = $_[4] eq "-" ? ( ) : split(/,/, $_[4]); if ($_[6] eq "no") { push(@opts, "noauto"); } else { @opts = grep { $_ !~ /^(auto|noauto)$/ } @opts; } if ($_[3] eq "bind") { push(@opts, "bind"); } if (!@opts) { &print_tempfile(FSTAB, " defaults"); } else { &print_tempfile(FSTAB, " ".join(",", @opts)); } &print_tempfile(FSTAB, " 0 "); &print_tempfile(FSTAB, $_[5] eq "-" ? "0\n" : "$_[5]\n"); } else { &print_tempfile(FSTAB, $_,"\n"); } } &close_tempfile(FSTAB); if ($amd_support == 1) { # Update older amd configuration local $amd = &read_amd_conf(); if ($amd =~ /MOUNTPTS='(.*)'/) { # found mount points line.. local @mpts = split(/\s+/, $1); for($j=0; $j<@mpts; $j+=2) { if ($i++ == $_[0]) { $mpts[$j] = $_[1]; $mpts[$j+1] = $_[2]; } } local $mpts = join(" ", @mpts); $amd =~ s/MOUNTPTS='(.*)'/MOUNTPTS='$mpts'/; } &write_amd_conf($amd); } elsif ($amd_support == 2) { # Update new amd configuration local @amd = &parse_amd_conf(); foreach $am (@amd) { next if ($am->{'dir'} eq 'global'); if ($i++ == $_[0]) { local $lref = &read_file_lines($am->{'file'}); local @nl = ( "[ $_[1] ]" ); local %opts = %{$am->{'opts'}}; $opts{'map_name'} = $_[2]; foreach $o (keys %opts) { push(@nl, "$o = $opts{$o}"); } splice(@$lref, $am->{'line'}, $am->{'eline'} - $am->{'line'} + 1, @nl); &flush_file_lines(); } } } # Update autofs configuration if ($autofs_support) { open(AUTO, $config{'autofs_file'}); @auto = ; close(AUTO); &open_tempfile(AUTO, "> $config{'autofs_file'}"); foreach (@auto) { chop; ($line = $_) =~ s/#.*$//g; if ($line =~ /\S/ && $i++ == $_[0]) { &print_tempfile(AUTO, "$_[1] $_[2]"); if ($_[4]) { &print_tempfile(AUTO, " ",&autofs_args($_[4])); } &print_tempfile(AUTO, "\n"); } else { &print_tempfile(AUTO, $_,"\n"); } } &close_tempfile(AUTO); } undef(@list_mounts_cache); } # delete_mount(index) # Delete an existing permanent mount sub delete_mount { local($i, @fstab, $line, $opts, $j, @amd); $i = 0; # Update fstab file open(FSTAB, $config{fstab_file}); @fstab = ; close(FSTAB); &open_tempfile(FSTAB, ">$config{fstab_file}"); foreach (@fstab) { chop; ($line = $_) =~ s/#.*$//g; if ($line !~ /\S/ || $line =~ /\signore\s/ || $i++ != $_[0]) { # Don't delete this line &print_tempfile(FSTAB, $_,"\n"); } } &close_tempfile(FSTAB); if ($amd_support == 1) { # Update older amd configuration local $foundamd = 0; local $amd = &read_amd_conf(); if ($amd =~ /MOUNTPTS='(.*)'/) { # found mount points line.. local @mpts = split(/\s+/, $1); for($j=0; $j<@mpts; $j+=2) { if ($i++ == $_[0]) { splice(@mpts, $j, 2); $foundamd = 1; } } local $mpts = join(" ", @mpts); $amd =~ s/MOUNTPTS='(.*)'/MOUNTPTS='$mpts'/; } &write_amd_conf($amd) if ($foundamd); } elsif ($amd_support == 2) { # Update new amd configuration local @amd = &parse_amd_conf(); foreach $am (@amd) { next if ($am->{'dir'} eq 'global'); if ($i++ == $_[0]) { local $lref = &read_file_lines($am->{'file'}); splice(@$lref, $am->{'line'}, $am->{'eline'} - $am->{'line'} + 1); &flush_file_lines(); } } } # Update AMD file if ($amd_support) { open(AMD, $config{auto_file}); @amd = ; close(AMD); &open_tempfile(AMD, ">$config{auto_file}"); foreach (@amd) { if (/MOUNTPTS='(.*)'/) { # found mount points line.. @mpts = split(/\s+/, $1); for($j=0; $j<@mpts; $j+=2) { if ($i++ != $_[0]) { push(@nmpts, $mpts[$j]); push(@nmpts, $mpts[$j+1]); } } &print_tempfile(AMD, "MOUNTPTS='".join(' ', @nmpts)."'\n"); } else { &print_tempfile(AMD, $_); } } &close_tempfile(AMD); } # Update autofs file if ($autofs_support) { open(AUTO, $config{'autofs_file'}); @auto = ; close(AUTO); &open_tempfile(AUTO, ">$config{'autofs_file'}"); foreach (@auto) { chop; ($line = $_) =~ s/#.*$//g; if ($line !~ /\S/ || $i++ != $_[0]) { # keep this line &print_tempfile(AUTO, $_,"\n"); } } &close_tempfile(AUTO); } undef(@list_mounts_cache); } # list_mounted([no-label]) # Return a list of all the currently mounted filesystems and swap files. # The list is in the form: # directory device type options sub list_mounted { return @list_mounted_cache if (@list_mounted_cache && $list_mounted_cache_mode == $_[0]); local(@rv, @p, @o, $mo, $_, %smbopts); local @mounts = &list_mounts(); &read_smbopts(); open(MTAB, "/etc/mtab"); while() { chop; s/#.*$//g; if (!/\S/) { next; } @p = split(/\s+/, $_); if ($p[2] eq "auto" || $p[0] =~ /^\S+:\(pid\d+\)$/) { # Automounter map.. turn the map= option into the device @o = split(/,/ , $p[3]); ($mo) = grep {/^map=/} (@o); $mo =~ /^map=(.*)$/; $p[0] = $1; $p[3] = join(',' , grep {!/^map=/} (@o)); $p[2] = "auto"; } elsif ($p[2] eq "autofs") { # Kernel automounter map.. use the pid to find the map $p[0] =~ /automount\(pid(\d+)\)/ || next; $out = &backquote_command("ps hwwww $1", 1); $out =~ /automount\s+(.*)\s*(\S+)\s+(file|program|yp)(,\S+)?\s+(\S+)/ || next; $p[0] = $5; $p[3] = $1 ? &autofs_options($1) : "-"; } elsif ($p[2] eq $smbfs_fs || $p[2] eq "cifs") { # Change from //FOO/BAR to \\foo\bar $p[0] =~ s/\//\\/g; $p[0] = lc($p[0]); $p[3] = $smbopts{$p[1]}; } elsif ($p[2] eq "proc") { # The source for proc mounts is always proc $p[0] = "proc"; } if (!$_[0] && ($p[2] =~ /^ext[23]$/ && $has_e2label || $p[2] eq "xfs" && $has_xfs_db || $p[2] eq "reiserfs" && $has_reiserfstune)) { # Check for a label on this partition, and there is one # and this filesystem is in fstab with the label, change # the device. local $label; if ($p[2] eq "xfs") { local $out = &backquote_command("xfs_db -x -p xfs_admin -c label -r $p[0] 2>&1", 1); $label = $1 if ($out =~ /label\s*=\s*"(.*)"/ && $1 ne '(null)'); } elsif ($p[2] eq "reiserfs") { local $out = &backquote_command("reiserfstune $p[0] 2>&1"); if ($out =~ /LABEL:\s*(\S+)/) { $label = $1; } } else { $label = &backquote_command("e2label $p[0] 2>&1", 1); chop($label); } if (!$?) { foreach $m (@mounts) { if ($m->[0] eq $p[1] && $m->[1] eq "LABEL=$label") { $p[0] = "LABEL=$label"; last; } } } } # Check for a UUID on this partition, and if there is one # and the filesystem is in fstab with the label, change # the device. if (!$_[0]) { local $uuid = &device_to_uuid($p[0], \@mounts); if ($uuid) { $p[0] = "UUID=$uuid"; } } # check fstab for a mount on the same dir which is a symlink # to the device local @st = stat($p[0]); foreach $m (@mounts) { if ($m->[0] eq $p[1]) { local @fst = stat($m->[1]); if ($fst[0] == $st[0] && $fst[1] == $st[1]) { # symlink to the same place! $p[0] = $m->[1]; last; } } } push(@rv, [ $p[1], $p[0], $p[2], $p[3] ]); } close(MTAB); open(SWAPS, "/proc/swaps"); while() { chop; if (/^(\/\S+)\s+/) { local $sf = $1; if ($sf =~ /^\/dev\/ide\// || $sf =~ /^\/dev\/mapper\//) { # check fstab for a mount on a device which is a symlink local @st = stat($sf); foreach $m (@mounts) { local @fst = stat($m->[1]); if ($m->[2] eq 'swap' && $fst[0] == $st[0] && $fst[1] == $st[1]) { $sf = $m->[1]; last; } } } # Convert to UUID format if used in fstab if (!$_[0]) { local $uuid = &device_to_uuid($sf, \@mounts); if ($uuid) { $sf = "UUID=$uuid"; } } push(@rv, [ "swap", $sf, "swap", "-" ]); } } close(SWAPS); @list_mounted_cache = @rv; $list_mounted_cache_mode = $_[0]; return @rv; } # device_to_uuid(device, [&mounts]) # Given a device name like /dev/sda1, return the UUID for it. # If a list of mounts are given, only match if found in mount list. sub device_to_uuid { local ($device, $mounts) = @_; local $uuid; if ($device =~ /^\/dev\// && ($has_volid || -d $uuid_directory)) { if (-d $uuid_directory) { # Use UUID mapping directory opendir(DIR, $uuid_directory); foreach my $f (readdir(DIR)) { local $linkdest = &simplify_path( &resolve_links("$uuid_directory/$f")); if ($linkdest eq $device) { $uuid = $f; last; } } closedir(DIR); } else { # Use vol_id command local $out = &backquote_command( "vol_id ".quotemeta($device)." 2>&1", 1); if ($out =~ /ID_FS_UUID=(\S+)/) { $uuid = $1; } } } if ($uuid && @$mounts) { my $found; foreach my $m (@$mounts) { if ($m->[1] eq "UUID=$uuid") { $found++; last; } } $uuid = undef if (!$found); } return $uuid; } # mount_dir(directory, device, type, options) # Mount a new directory from some device, with some options. Returns 0 if ok, # or an error string if failed sub mount_dir { local($out, $opts, $shar, %options, %smbopts); local @opts = $_[3] eq "-" || $_[3] eq "" ? ( ) : grep { $_ ne "noauto" } split(/,/, $_[3]); if ($_[2] eq "bind") { push(@opts, "bind"); } $opts = @opts ? "-o ".quotemeta(join(",", @opts)) : ""; &parse_options($_[2], $_[3]); # Work out args for label or UUID local $devargs; if ($_[1] =~ /LABEL=(.*)/) { $devargs = "-L ".quotemeta($1); } elsif ($_[1] =~ /UUID=(\S+)/) { $devargs = "-U ".quotemeta($1); } else { $devargs = quotemeta($_[1]); } if ($_[2] eq "swap") { # Use swapon to add the swap space.. local $priarg = $options{'pri'} ne "" ? "-p $options{'pri'}" : ""; $out = &backquote_logged("swapon $priarg $devargs 2>&1"); if ($out =~ /Invalid argument/) { # looks like this swap partition isn't ready yet.. set it up $out = &backquote_logged("mkswap $devargs 2>&1"); if ($?) { return "mkswap failed :
$out
"; } $out = &backquote_logged("swapon $devargs 2>&1"); } if ($?) { return "
$out
"; } } elsif ($_[2] eq "auto") { # Old automounter filesystem $out = &backquote_logged("amd $_[0] $_[1] >/dev/null 2>/dev/null"); if ($?) { return $text{'linux_eamd'}; } } elsif ($_[2] eq "autofs") { # New automounter filesystem $opts = &autofs_args($_[3]); $type = $_[1] !~ /^\// ? "yp" : (-x $_[1]) ? "program" : "file"; $out = &backquote_logged("automount $opts $_[0] $type $_[1] 2>&1"); if ($?) { return &text('linux_eauto', "
$out
"); } } elsif ($_[2] eq $smbfs_fs || $_[2] eq "cifs") { local $shar = $_[1]; $shar =~ s/\\/\//g if ($shar =~ /^\\/); local $support = $_[2] eq $smbfs_fs ? $smbfs_support : $cifs_support; return uc($_[2])." not supported" if (!$support); local $qshar = quotemeta($shar); if ($support >= 3) { # SMB filesystem mounted with mount command local $temp = &transname(); local $ex = &system_logged("mount -t $_[2] $opts $qshar $_[0] >$temp 2>&1 /dev/null 2>&1"); return "
$out
"; } } elsif ($support == 2) { # SMB filesystem mounted with version 2.x smbmount $opts = ($options{'user'} ? "-U $options{'user'} " : ""). ($options{'passwd'} ? "" : "-N "). ($options{'workgroup'} ? "-W $options{'workgroup'} " : ""). ($options{'clientname'} ? "-n $options{'clientname'} " : ""). ($options{'machinename'} ? "-I $options{'machinename'} " : ""); &foreign_require("proc"); local ($fh, $fpid) = &proc::pty_process_exec_logged( "sh -c 'smbmount $shar $_[0] -d 0 $opts'"); if ($options{'passwd'}) { local $w = &wait_for($fh, "word:"); if ($w < 0) { &system_logged("umount $_[0] >/dev/null 2>&1"); return $text{'linux_esmbconn'}; } local $p = "$options{'passwd'}\n"; syswrite($fh, $p, length($p)); } local $got; while(<$fh>) { $got .= $_; } if ($got =~ /failed/) { &system_logged("umount $_[0] >/dev/null 2>&1"); return "
$got
\n"; } close($fh); } elsif ($support == 1) { # SMB filesystem mounted with older smbmount $shortname = &get_system_hostname(); if ($shortname =~ /^([^\.]+)\.(.+)$/) { $shortname = $1; } $opts = ($options{servername} ? "-s $options{servername} " : ""). ($options{clientname} ? "-c $options{clientname} " : "-c $shortname "). ($options{machinename} ? "-I $options{machinename} " : ""). ($options{user} ? "-U $options{user} " : ""). ($options{passwd} ? "-P $options{passwd} " : "-n "). ($options{uid} ? "-u $options{uid} " : ""). ($options{gid} ? "-g $options{gid} " : ""). ($options{fmode} ? "-f $options{fmode} " : ""). ($options{dmode} ? "-d $options{dmode} " : ""); $out = &backquote_logged("smbmount $shar $_[0] $opts 2>&1 /dev/null 2>&1"); return "
$out
"; } } &read_smbopts(); $smbopts{$_[0]} = $_[3] eq "-" ? "dummy=1" : $_[3]; &write_smbopts(); } else { # some filesystem supported by mount local $fs = $_[2] eq "*" ? "auto" : $_[2]; $cmd = "mount -t $fs $opts $devargs ".quotemeta($_[0]); $out = &backquote_logged("$cmd 2>&1 $out"; } } undef(@list_mounted_cache); return 0; } # os_remount_dir(directory, device, type, options) # Adjusts the options for some mounted filesystem, by re-mounting sub os_remount_dir { if ($_[2] eq "swap" || $_[2] eq "auto" || $_[2] eq "autofs" || $_[2] eq $smbfs_fs || $_[2] eq "cifs") { # Cannot use remount local $err = &unmount_dir(@_); return $err if ($err); return &mount_dir(@_); } else { # Attempt to use remount local @opts = $_[3] eq "-" || $_[3] eq "" ? ( ) : grep { $_ ne "noauto" } split(/,/, $_[3]); push(@opts, "remount"); local $opts = @opts ? "-o ".quotemeta(join(",", @opts)) : ""; local $fs = $_[2] eq "*" ? "auto" : $_[2]; if ($_[1] =~ /LABEL=(.*)/) { $cmd = "mount -t $fs -L $1 $opts $_[0]"; } elsif ($_[1] =~ /UUID=(\S+)/) { $cmd = "mount -t $fs -U $1 $opts $_[0]"; } else { $cmd = "mount -t $fs $opts $_[1] $_[0]"; } $out = &backquote_logged("$cmd 2>&1 $out"; } undef(@list_mounted_cache); return undef; } } # unmount_dir(directory, device, type, options, [force]) # Unmount a directory that is currently mounted. Returns 0 if ok, # or an error string if failed sub unmount_dir { local($out, %smbopts, $dir); if ($_[2] eq "swap") { # Use swapoff to remove the swap space.. $out = &backquote_logged("swapoff $_[1]"); if ($?) { return "
$out
"; } } elsif ($_[2] eq "auto") { # Kill the amd process $dir = $_[0]; if (&backquote_command("cat /etc/mtab") =~ /:\(pid([0-9]+)\)\s+$dir\s+(auto|nfs)\s+/) { &kill_logged('TERM', $1) || return $text{'linux_ekillamd'}; } sleep(2); } elsif ($_[2] eq "autofs") { # Kill the automount process $dir = $_[0]; &backquote_command("cat /etc/mtab") =~ /automount\(pid([0-9]+)\)\s+$dir\s+autofs\s+/; &kill_logged('TERM', $1) || return $text{'linux_ekillauto'}; sleep(2); } else { local $fflag = $_[4] ? "-l" : ""; $out = &backquote_logged("umount $fflag $_[0] 2>&1"); if ($?) { return "
$out
"; } if ($_[2] eq $smbfs_fs || $_[2] eq "cifs") { # remove options from list &read_smbopts(); delete($smbopts{$_[0]}); &write_smbopts(); &execute_command("rmmod smbfs"); &execute_command("rmmod cifs"); } } undef(@list_mounted_cache); return 0; } # can_force_unmount_dir(directory, device, type) # Returns 1 if some directory can be forcibly un-mounted sub can_force_unmount_dir { if ($_[2] ne "swap" && $_[2] ne "auto" && $_[2] ne "autofs") { # All filesystems using the normal 'mount' command can be return 1; } else { return 0; } } # mount_modes(type) # Given a filesystem type, returns 4 numbers that determine how the file # system can be mounted, and whether it can be fsck'd # 0 - cannot be permanently recorded # (smbfs under linux before 2.2) # 1 - can be permanently recorded, and is always mounted at boot # (swap under linux) # 2 - can be permanently recorded, and may or may not be mounted at boot # (most normal filesystems) # The second is: # 0 - mount is always permanent => mounted when saved # (swap under linux before 2.2, or any filesystem that is always # mounted at boot by some script) # 1 - doesn't have to be permanent # (normal fs types) # The third is: # 0 - cannot be fsck'd at boot time # 1 - can be be fsck'd at boot # The fourth is: # 0 - can be unmounted # 1 - cannot be unmounted # The (optional) fourth is: # 0 - can be edited # 1 - cannot be edited (because is always mounted at boot by some script) sub mount_modes { if ($_[0] eq "swap") { return (1, $swaps_support ? 1 : 0, 0, 0); } elsif ($_[0] eq "auto" || $_[0] eq "autofs") { return (1, 1, 0, 0); } elsif ($_[0] eq $smbfs_fs) { return ($smbfs_support >= 3 ? 2 : 0, 1, 0, 0); } elsif ($_[0] eq "cifs") { return (2, 1, 0, 0); } elsif ($_[0] =~ /^ext\d+$/ || $_[0] eq "minix" || $_[0] eq "xiafs" || $_[0] eq "xfs" || $_[0] eq "jfs") { return (2, 1, 1, 0); } else { return (2, 1, 0, 0); } } # disk_space(type, directory) # Returns the amount of total and free space for some filesystem, or an # empty array if not appropriate. sub disk_space { if (&get_mounted($_[1], "*") < 0) { return (); } if ($_[0] eq "proc" || $_[0] eq "swap" || $_[0] eq "auto" || $_[0] eq "autofs") { return (); } local $out = &backquote_command("LC_ALL='' LANG='' df -k ".quotemeta($_[1]), 1); if ($out =~ /Mounted on\n\S+\s+(\S+)\s+\S+\s+(\S+)/) { return ($1, $2); } return ( ); } # inode_space(type, directory) # Returns the total and free number of inodes for some filesystem. sub inode_space { if (&get_mounted($_[1], "*") < 0) { return (); } if (&backquote_command("LC_ALL='' LANG='' df -i $_[1]", 1) =~ /Mounted on\n\S+\s+(\S+)\s+\S+\s+(\S+)/) { return ($1, $2); } return ( ); } # list_fstypes() # Returns an array of all the supported filesystem types. If a filesystem is # found that is not one of the supported types, generate_location() and # generate_options() will not be called for it. sub list_fstypes { local @sup = ("ext2", "minix", "msdos", "nfs", "nfs4", "iso9660", "ext", "xiafs", "hpfs", "fat", "vfat", "umsdos", "sysv", "reiserfs", "ntfs", "hfs", "fatx"); push(@sup, $smbfs_fs) if ($smbfs_support); push(@sup, "cifs") if ($cifs_support); push(@sup, "auto") if ($amd_support); push(@sup, "autofs") if ($autofs_support); push(@sup, "tmpfs") if ($tmpfs_support); push(@sup, "ext3") if ($ext3_support); push(@sup, "ext4") if ($ext4_support); push(@sup, "xfs") if ($xfs_support); push(@sup, "jfs") if ($jfs_support); push(@sup, "bind") if ($bind_support); push(@sup, "swap"); return @sup; } # fstype_name(type) # Given a short filesystem type, return a human-readable name for it sub fstype_name { local(%fsmap); %fsmap = ("ext2","Old Linux Native Filesystem", "ext3","Linux Native Filesystem", "ext4","New Linux Native Filesystem", "minix","Minix Filesystem", "msdos","MS-DOS Filesystem", "nfs","Network Filesystem", "nfs4","Network Filesystem v4", $smbfs_fs,"Windows Networking Filesystem", "cifs","Common Internet Filesystem", "iso9660","ISO9660 CD-ROM", "ext","Old EXT Linux Filesystem", "xiafs","Old XIAFS Linux Filesystem", "hpfs","OS/2 Filesystem", "fat","MS-DOS Filesystem", "vfat","Windows Filesystem", "umsdos","Linux on top of MS-DOS Filesystem", "sysv","System V Filesystem", "swap","Virtual Memory", "proc","Kernel Filesystem", "devpts","PTS Filesystem", "auto",($autofs_support ? "Old " : "")."Automounter Filesystem", "reiserfs","Reiser Filesystem", "autofs","New Automounter Filesystem", "usbdevfs","USB Devices", "shm","SysV Shared Memory", "tmpfs","RAM Disk", "xfs","SGI Filesystem", "jfs","IBM Journalling Filesystem", "ntfs","Windows NT Filesystem", "bind","Loopback Filesystem", "hfs","Apple Filesystem", "fatx","XBOX Filesystem", ); return $config{long_fstypes} && $fsmap{$_[0]} ? $fsmap{$_[0]} : uc($_[0]); } # multiple_mount(type) # Returns 1 if filesystems of this type can be mounted multiple times, 0 if not sub multiple_mount { return ($_[0] eq "nfs" || $_[0] eq "nfs4" || $_[0] eq "auto" || $_[0] eq "autofs" || $_[0] eq "bind" || $_[0] eq "tmpfs"); } # generate_location(type, location) # Output HTML for editing the mount location of some filesystem. sub generate_location { if (($_[0] eq "nfs") || ($_[0] eq "nfs4")) { # NFS mount from some host and directory $_[1] =~ /^([^:]+):(.*)$/; print " ", &hlink("$text{'linux_nfshost'}", "nfshost"), "\n"; print "\n"; &nfs_server_chooser_button("nfs_host"); print " ", &hlink("$text{'linux_nfsdir'}", "nfsdir"), "\n"; printf "\n", ($_[0] eq "nfs4") && ($2 eq "") ? "/" : $2; &nfs_export_chooser_button("nfs_host", "nfs_dir"); print " \n"; } elsif ($_[0] eq "auto") { # Using some automounter map print " $text{'linux_map'}\n"; print "\n"; print &file_chooser_button("auto_map", 0); print " \n"; } elsif ($_[0] eq "autofs") { # Using some kernel automounter map print " $text{'linux_map'}\n"; print "\n"; print &file_chooser_button("autofs_map", 0); print " \n"; } elsif ($_[0] eq "swap") { # Swap file or device &foreign_require("fdisk"); printf " $text{'linux_swapfile'}\n"; print "\n"; local ($found, $ufound); # Show partitions input local $sel = &fdisk::partition_select("lnx_disk", $_[1], 3, \$found); printf " %s %s
\n", $found ? "checked" : "", $text{'linux_disk'}, $sel; # Show UUID input if ($has_volid || -d $uuid_directory) { local $u = $_[1] =~ /UUID=(\S+)/ ? $1 : undef; local $usel = &fdisk::volid_select("lnx_uuid", $u, \$ufound); if ($usel) { printf " %s %s
\n", $ufound ? "checked" : "", $text{'linux_usel'}, $usel; } } # Show other file input printf " %s\n", $found || $ufound ? "" : "checked", $text{'linux_swapfile'}; printf " %s
\n", $found || $ufound ? "" : $_[1], &file_chooser_button("lnx_other"); print " \n"; } elsif ($_[0] eq $smbfs_fs || $_[0] eq "cifs") { # Windows filesystem $_[1] =~ /^\\\\(.*)\\(.*)$/; local ($server, $share) = ($1, $2); print " $text{'linux_smbserver'}\n"; print "\n"; &smb_server_chooser_button("smbfs_server"); print "\n"; print "$text{'linux_smbshare'}\n"; print "\n"; &smb_share_chooser_button("smbfs_server", "smbfs_share"); print " \n"; } elsif ($_[0] eq "tmpfs") { # RAM disk (no location needed) } elsif ($_[0] eq "bind") { # Loopback filesystem, mounted from some other directory print " $text{'linux_bind'} \n"; printf " %s \n", $_[1], &file_chooser_button("bind_dir", 1); } else { # This is some linux disk-based filesystem &foreign_require("fdisk"); printf " %s\n", &fstype_name($_[0]); print "\n"; local ($found, $rfound, $lfound, $vfound, $ufound, $rsel, $c); # Show regular partition input local $sel = &fdisk::partition_select("lnx_disk", $_[1], 0, \$found); printf " %s %s
\n", $found ? "checked" : "", $text{'linux_disk'}, $sel; # Show RAID input if (&foreign_check("raid")) { &foreign_require("raid"); local $conf = &raid::get_raidtab(); foreach $c (@$conf) { if ($c->{'active'}) { $rsel .= sprintf "