package fs::mount; # $Id$ use diagnostics; use strict; use run_program; use common; use fs::type; use log; sub set_loop { my ($part) = @_; $part->{real_device} ||= devices::set_loop(devices::make($part->{device}), $part->{encrypt_key}, $part->{options} =~ /encryption=(\w+)/); } sub swapon { my ($dev) = @_; log::l("swapon called with $dev"); syscall_('swapon', devices::make($dev), 0) or die "swapon($dev) failed: $!"; } sub swapoff { my ($dev) = @_; syscall_('swapoff', devices::make($dev)) or die "swapoff($dev) failed: $!"; } sub mount { my ($dev, $where, $fs, $b_rdonly, $o_options, $o_wait_message) = @_; log::l("mounting $dev on $where as type $fs, options $o_options"); mkdir_p($where); $fs or log::l("not mounting $dev partition"), return; { my @fs_modules = qw(ext3 hfs jfs nfs ntfs romfs reiserfs ufs xfs vfat); my @types = (qw(ext2 proc sysfs usbfs usbdevfs iso9660 devfs devpts), @fs_modules); push @types, 'smb', 'smbfs', 'davfs' if !$::isInstall; if (!member($fs, @types) && !$::move) { log::l("skipping mounting $dev partition ($fs)"); return; } if ($::isInstall) { if (member($fs, @fs_modules)) { eval { modules::load($fs) }; } elsif ($fs eq 'iso9660') { eval { modules::load('isofs') }; } } } $where =~ s|/$||; my @mount_opt = split(',', $o_options || ''); if ($fs eq 'vfat') { @mount_opt = 'check=relaxed'; } elsif ($fs eq 'nfs') { push @mount_opt, 'nolock', 'soft', 'intr' if $::isInstall; } elsif ($fs eq 'jfs' && !$b_rdonly) { fsck_jfs($dev, $o_wait_message); } elsif ($fs eq 'ext2' && !$b_rdonly) { fsck_ext2($dev, $o_wait_message); } push @mount_opt, 'ro' if $b_rdonly; log::l("calling mount -t $fs $dev $where @mount_opt"); $o_wait_message->(N("Mounting partition %s", $dev)) if $o_wait_message; run_program::run('mount', '-t', $fs, $dev, $where, if_(@mount_opt, '-o', join(',', @mount_opt))) or die N("mounting partition %s in directory %s failed", $dev, $where); } sub fsck_ext2 { my ($dev, $o_wait_message) = @_; $o_wait_message->(N("Checking %s", $dev)) if $o_wait_message; foreach ('-a', '-y') { run_program::raw({ timeout => 60 * 60 }, "fsck.ext2", $_, $dev); my $err = $?; if ($err & 0x0100) { log::l("fsck corrected partition $dev"); } if ($err & 0xfeff) { my $txt = sprintf("fsck failed on %s with exit code %d or signal %d", $dev, $err >> 8, $err & 255); $_ eq '-y' ? die($txt) : cdie($txt); } else { last; } } } sub fsck_jfs { my ($dev, $o_wait_message) = @_; $o_wait_message->(N("Checking %s", $dev)) if $o_wait_message; #- needed if the system is dirty otherwise mounting read-write simply fails run_program::raw({ timeout => 60 * 60 }, "fsck.jfs", $dev) or do { my $err = $?; die "fsck.jfs failed" if $err & 0xfc00; }; } #- takes the mount point to umount (can also be the device) sub umount { my ($mntpoint) = @_; $mntpoint =~ s|/$||; log::l("calling umount($mntpoint)"); syscall_('umount2', $mntpoint, 0) or do { kill 15, fuzzy_pidofs('^fam\b'); syscall_('umount2', $mntpoint, 0) or die N("error unmounting %s: %s", $mntpoint, $!); }; substInFile { $_ = '' if /(^|\s)$mntpoint\s/ } '/etc/mtab'; #- do not care about error, if we can not read, we will not manage to write... (and mess mtab) } sub part { my ($part, $b_rdonly, $o_wait_message) = @_; log::l("mount_part: " . join(' ', map { "$_=$part->{$_}" } 'device', 'mntpoint', 'isMounted', 'real_mntpoint')); if ($part->{isMounted} && $part->{real_mntpoint} && $part->{mntpoint}) { log::l("remounting partition on " . fs::get::mntpoint_prefixed($part) . " instead of $part->{real_mntpoint}"); if ($::isInstall) { #- ensure partition will not be busy. require install_any; install_any::getFile('XXX'); } eval { umount($part->{real_mntpoint}); rmdir $part->{real_mntpoint}; symlinkf fs::get::mntpoint_prefixed($part), $part->{real_mntpoint}; delete $part->{real_mntpoint}; $part->{isMounted} = 0; }; } return if $part->{isMounted}; unless ($::testing) { if (isSwap($part)) { $o_wait_message->(N("Enabling swap partition %s", $part->{device})) if $o_wait_message; swapon($part->{device}); } else { $part->{mntpoint} or die "missing mount point for partition $part->{device}"; my $mntpoint = fs::get::mntpoint_prefixed($part); if (isLoopback($part) || $part->{encrypt_key}) { set_loop($part); } elsif ($part->{options} =~ /encrypted/) { log::l("skip mounting $part->{device} since we do not have the encrypt_key"); return; } elsif (fs::type::carry_root_loopback($part)) { $mntpoint = "/initrd/loopfs"; } my $dev = $part->{real_device} || fs::wild_device::from_part('', $part); mount($dev, $mntpoint, $part->{fs_type}, $b_rdonly, $part->{options}, $o_wait_message); } } $part->{isMounted} = 1; set_isFormatted($part, 1); #- assume that if mount works, partition is formatted } sub umount_part { my ($part) = @_; $part->{isMounted} || $part->{real_mntpoint} or return; unless ($::testing) { if (isSwap($part)) { swapoff($part->{device}); } elsif (fs::type::carry_root_loopback($part)) { umount("/initrd/loopfs"); } else { umount(fs::get::mntpoint_prefixed($part) || devices::make($part->{device})); devices::del_loop(delete $part->{real_device}) if $part->{real_device}; } } $part->{isMounted} = 0; } sub umount_all { my ($fstab) = @_; log::l("unmounting all filesystems"); foreach (sort { $b->{mntpoint} cmp $a->{mntpoint} } @$fstab) { $_->{mntpoint} and umount_part($_); } } sub usbfs { my ($prefix) = @_; my $fs = cat_('/proc/filesystems') =~ /usbfs/ ? 'usbfs' : 'usbdevfs'; mount('none', "$prefix/proc/bus/usb", $fs); } 1; 4ac44cb'>perl-install/c/smp-dmi.c