summaryrefslogtreecommitdiffstats
path: root/perl-install/fs.pm
diff options
context:
space:
mode:
Diffstat (limited to 'perl-install/fs.pm')
-rw-r--r--perl-install/fs.pm627
1 files changed, 0 insertions, 627 deletions
diff --git a/perl-install/fs.pm b/perl-install/fs.pm
deleted file mode 100644
index 4771068e1..000000000
--- a/perl-install/fs.pm
+++ /dev/null
@@ -1,627 +0,0 @@
-package fs; # $Id$
-
-use diagnostics;
-use strict;
-
-use MDK::Common::System;
-use MDK::Common::Various;
-use common;
-use log;
-use devices;
-use fs::type;
-use fs::get;
-use fs::format;
-use fs::mount_options;
-use run_program;
-use detect_devices;
-use modules;
-use fsedit;
-use loopback;
-
-
-sub read_fstab {
- my ($prefix, $file, @reading_options) = @_;
-
- if (member('keep_default', @reading_options)) {
- push @reading_options, 'freq_passno', 'keep_devfs_name', 'keep_device_LABEL';
- }
-
- my %comments;
- my $comment;
- my @l = grep {
- if (/^Filename\s*Type\s*Size/) {
- 0; #- when reading /proc/swaps
- } elsif (/^\s*#/) {
- $comment .= chomp_($_) . "\n";
- 0;
- } else {
- $comments{$_} = $comment if $comment;
- $comment = '';
- 1;
- }
- } cat_("$prefix$file");
-
- #- attach comments at the end of fstab to the previous line
- $comments{$l[-1]} = $comment if $comment;
-
- map {
- my ($dev, $mntpoint, $fs_type, $options, $freq, $passno) = split;
- my $comment = $comments{$_};
-
- $options = 'defaults' if $options eq 'rw'; # clean-up for mtab read
-
- if ($fs_type eq 'supermount') {
- # normalize this bloody supermount
- $options = join(",", 'supermount', grep {
- if (/fs=(.*)/) {
- $fs_type = $1;
- 0;
- } elsif (/dev=(.*)/) {
- $dev = $1;
- 0;
- } elsif ($_ eq '--') {
- 0;
- } else {
- 1;
- }
- } split(',', $options));
- } elsif ($fs_type eq 'smb') {
- # prefering type "smbfs" over "smb"
- $fs_type = 'smbfs';
- }
- $mntpoint =~ s/\\040/ /g;
- $dev =~ s/\\040/ /g;
-
- my $h = {
- mntpoint => $mntpoint, fs_type => $fs_type,
- options => $options, comment => $comment,
- if_(member('keep_freq_passno', @reading_options), freq => $freq, passno => $passno),
- };
-
- put_in_hash($h, subpart_from_wild_device_name($dev));
-
- if ($h->{device_LABEL} && member('keep_device_LABEL', @reading_options)) {
- $h->{prefer_device_LABEL} = 1;
- } elsif ($h->{devfs_device} && member('keep_devfs_name', @reading_options)) {
- $h->{prefer_devfs_name} = 1;
- }
-
- if ($h->{options} =~ /credentials=/ && !member('verbatim_credentials', @reading_options)) {
- require network::smb;
- #- remove credentials=file with username=foo,password=bar,domain=zoo
- #- the other way is done in fstab_to_string
- my ($options, $unknown) = fs::mount_options::unpack($h);
- my $file = delete $options->{'credentials='};
- my $credentials = network::smb::read_credentials_raw($file);
- if ($credentials->{username}) {
- $options->{"$_="} = $credentials->{$_} foreach qw(username password domain);
- fs::mount_options::pack($h, $options, $unknown);
- }
- }
-
- $h;
- } @l;
-}
-
-sub merge_fstabs {
- my ($loose, $fstab, @l) = @_;
-
- foreach my $p (@$fstab) {
- my ($l1, $l2) = partition { fsedit::is_same_hd($_, $p) } @l;
- my ($p2) = @$l1 or next;
- @l = @$l2;
-
- $p->{mntpoint} = $p2->{mntpoint} if delete $p->{unsafeMntpoint};
-
- $p->{fs_type} = $p2->{fs_type} if $p2->{fs_type} && !$loose;
- $p->{options} = $p2->{options} if $p2->{options} && !$loose;
- #- important to get isMounted property else DrakX may try to mount already mounted partitions :-(
- add2hash($p, $p2);
- $p->{device_alias} ||= $p2->{device_alias} || $p2->{device} if $p->{device} ne $p2->{device} && $p2->{device} !~ m|/|;
-
- $p->{fs_type} && $p2->{fs_type} && $p->{fs_type} ne $p2->{fs_type}
- && $p->{fs_type} ne 'auto' && $p2->{fs_type} ne 'auto' and
- log::l("err, fstab and partition table do not agree for $p->{device} type: $p->{fs_type} vs $p2->{fs_type}");
- }
- @l;
-}
-
-sub subpart_from_wild_device_name {
- my ($dev) = @_;
-
- if ($dev =~ /^LABEL=(.*)/) {
- return { device_LABEL => $1 };
- } elsif ($dev eq 'none') {
- } elsif ($dev eq 'rootfs') {
- } elsif ($dev =~ m!^(\S+):/\w!) {
- #- nfs
- } elsif ($dev =~ m!^//\w!) {
- #- smb
- } elsif ($dev =~ m!^http://!) {
- #- http
- } else {
- if ($dev !~ m!^/! && -e "$::prefix/dev/$dev") {
- $dev = "/dev/$dev";
- }
- if ($dev =~ m!^/(tmp|u?dev)/(.*)!) {
- my %part;
- if (my $rdev = (stat "$::prefix$dev")[6]) {
- ($part{major}, $part{minor}) = unmakedev($rdev);
- }
-
- if (my $symlink = readlink("$::prefix$dev")) {
- if ($symlink =~ m|^[^/]+$|) {
- $part{device_alias} = $dev;
- $dev = $symlink;
- }
- }
- $dev =~ s!/(tmp|u?dev)/!!;
-
- if (my (undef, $part_number) = $dev =~ m!/(disc|part(\d+))$!) {
- $part{part_number} = $part_number if $part_number;
- $part{devfs_device} = $dev;
- } else {
- $part{device} = $dev;
- my $part_number = devices::part_number(\%part);
- $part{part_number} = $part_number if $part_number;
- }
- return \%part;
- } elsif ($dev =~ m!^/! && -f "$::prefix$dev") {
- #- loopback file
- } else {
- log::l("part_from_wild_device_name: unknown device $dev");
- }
- }
- #- default
- { device => $dev };
-}
-
-sub add2all_hds {
- my ($all_hds, @l) = @_;
-
- @l = merge_fstabs('', [ fs::get::really_all_fstab($all_hds) ], @l);
-
- foreach (@l) {
- my $s =
- $_->{fs_type} eq 'nfs' ? 'nfss' :
- $_->{fs_type} eq 'smbfs' ? 'smbs' :
- $_->{fs_type} eq 'davfs' ? 'davs' :
- isTrueLocalFS($_) || isSwap($_) || isOtherAvailableFS($_) ? '' :
- 'special';
- push @{$all_hds->{$s}}, $_ if $s;
- }
-}
-
-sub get_major_minor {
- eval {
- my (undef, $major, $minor) = devices::entry($_->{device});
- ($_->{major}, $_->{minor}) = ($major, $minor);
- } foreach @_;
-}
-
-sub merge_info_from_mtab {
- my ($fstab) = @_;
-
- my @l1 = map { my $l = $_;
- my $h = fs::type::fs_type2subpart('swap');
- $h->{$_} = $l->{$_} foreach qw(device major minor);
- $h;
- } read_fstab('', '/proc/swaps');
-
- my @l2 = map { read_fstab('', $_) } '/etc/mtab', '/proc/mounts';
-
- foreach (@l1, @l2) {
- log::l("found mounted partition on $_->{device} with $_->{mntpoint}");
- if ($::isInstall && $_->{mntpoint} =~ m!/tmp/(image|hdimage)!) {
- $_->{real_mntpoint} = delete $_->{mntpoint};
- if ($_->{real_mntpoint} eq '/tmp/hdimage') {
- log::l("found hdimage on $_->{device}");
- $_->{mntpoint} = common::usingRamdisk() && "/mnt/hd"; #- remap for hd install.
- }
- }
- $_->{isMounted} = 1;
- set_isFormatted($_, 1);
- delete $_->{options};
- }
- merge_fstabs('loose', $fstab, @l1, @l2);
-}
-
-# - when using "$loose", it does not merge in type&options from the fstab
-sub merge_info_from_fstab {
- my ($fstab, $prefix, $uniq, $loose) = @_;
-
- my @l = grep {
- if ($uniq) {
- my $part = fs::get::mntpoint2part($_->{mntpoint}, $fstab);
- !$part || fsedit::is_same_hd($part, $_); #- keep it only if it is the mountpoint AND the same device
- } else {
- 1;
- }
- } read_fstab($prefix, '/etc/fstab', 'keep_default');
-
- merge_fstabs($loose, $fstab, @l);
-}
-
-sub get_info_from_fstab {
- my ($all_hds) = @_;
- my @l = read_fstab($::prefix, '/etc/fstab', 'keep_default');
- add2all_hds($all_hds, @l)
-}
-
-sub prepare_write_fstab {
- my ($fstab, $o_prefix, $b_keep_smb_credentials) = @_;
- $o_prefix ||= '';
-
- my %new;
- my @smb_credentials;
- my @l = map {
- my $device =
- isLoopback($_) ?
- ($_->{mntpoint} eq '/' ? "/initrd/loopfs" : $_->{loopback_device}{mntpoint}) . $_->{loopback_file} :
- part2device($o_prefix, $_->{prefer_devfs_name} ? $_->{devfs_device} : $_->{device}, $_->{fs_type});
-
- my $real_mntpoint = $_->{mntpoint} || ${{ '/tmp/hdimage' => '/mnt/hd' }}{$_->{real_mntpoint}};
- mkdir_p("$o_prefix$real_mntpoint") if $real_mntpoint =~ m|^/|;
- my $mntpoint = loopback::carryRootLoopback($_) ? '/initrd/loopfs' : $real_mntpoint;
-
- my ($freq, $passno) =
- exists $_->{freq} ?
- ($_->{freq}, $_->{passno}) :
- isTrueLocalFS($_) && $_->{options} !~ /encryption=/ && !$_->{is_removable} ?
- (1, $_->{mntpoint} eq '/' ? 1 : loopback::carryRootLoopback($_) ? 0 : 2) :
- (0, 0);
-
- if (($device eq 'none' || !$new{$device}) && ($mntpoint eq 'swap' || !$new{$mntpoint})) {
- #- keep in mind the new line for fstab.
- $new{$device} = 1;
- $new{$mntpoint} = 1;
-
- my $options = $_->{options};
-
- if ($_->{fs_type} eq 'smbfs' && $options =~ /password=/ && !$b_keep_smb_credentials) {
- require network::smb;
- if (my ($opts, $smb_credentials) = network::smb::fstab_entry_to_credentials($_)) {
- $options = $opts;
- push @smb_credentials, $smb_credentials;
- }
- }
-
- my $fs_type = $_->{fs_type} || 'auto';
-
- my $dev =
- $_->{prefer_device_LABEL} ? 'LABEL=' . $_->{device_LABEL} :
- $_->{device_alias} ? "/dev/$_->{device_alias}" : $device;
-
- $mntpoint =~ s/ /\\040/g;
- $dev =~ s/ /\\040/g;
-
- # handle bloody supermount special case
- if ($options =~ /supermount/) {
- my @l = grep { $_ ne 'supermount' } split(',', $options);
- my ($l1, $l2) = partition { member($_, 'ro', 'exec') } @l;
- $options = join(",", "dev=$dev", "fs=$fs_type", @$l1, if_(@$l2, '--', @$l2));
- ($dev, $fs_type) = ('none', 'supermount');
- } else {
- #- if we were using supermount, the type could be something like ext2:vfat
- #- but this can't be done without supermount, so switching to "auto"
- $fs_type = 'auto' if $fs_type =~ /:/;
- }
-
- [ $mntpoint, $_->{comment} . join(' ', $dev, $mntpoint, $fs_type, $options || 'defaults', $freq, $passno) . "\n" ];
- } else {
- ()
- }
- } grep { $_->{device} && ($_->{mntpoint} || $_->{real_mntpoint}) && $_->{fs_type} && ($_->{isFormatted} || !$_->{notFormatted}) } @$fstab;
-
- join('', map { $_->[1] } sort { $a->[0] cmp $b->[0] } @l), \@smb_credentials;
-}
-
-sub fstab_to_string {
- my ($all_hds, $o_prefix) = @_;
- my $fstab = [ fs::get::really_all_fstab($all_hds), @{$all_hds->{special}} ];
- my ($s, undef) = prepare_write_fstab($fstab, $o_prefix, 'keep_smb_credentials');
- $s;
-}
-
-sub write_fstab {
- my ($all_hds, $o_prefix) = @_;
- log::l("writing $o_prefix/etc/fstab");
- my $fstab = [ fs::get::really_all_fstab($all_hds), @{$all_hds->{special}} ];
- my ($s, $smb_credentials) = prepare_write_fstab($fstab, $o_prefix, '');
- output("$o_prefix/etc/fstab", $s);
- network::smb::save_credentials($_) foreach @$smb_credentials;
-}
-
-sub part2device {
- my ($prefix, $dev, $fs_type) = @_;
- $dev eq 'none' || member($fs_type, qw(nfs smbfs davfs)) ?
- $dev :
- do {
- my $dir = $dev =~ m!^(/|LABEL=)! ? '' : '/dev/';
- eval { devices::make("$prefix$dir$dev") };
- "$dir$dev";
- };
-}
-
-sub auto_fs() {
- grep { chop; $_ && !/nodev/ } cat_("/etc/filesystems");
-}
-
-sub set_removable_mntpoints {
- my ($all_hds) = @_;
-
- my %names;
- foreach (@{$all_hds->{raw_hds}}) {
- my $name = detect_devices::suggest_mount_point($_) or next;
- $name eq 'zip' and next;
-
- my $s = ++$names{$name};
- $_->{mntpoint} ||= "/mnt/$name" . ($s == 1 ? '' : $s);
- }
-}
-
-sub get_raw_hds {
- my ($prefix, $all_hds) = @_;
-
- push @{$all_hds->{raw_hds}}, detect_devices::removables();
- $_->{is_removable} = 1 foreach @{$all_hds->{raw_hds}};
-
- get_major_minor(@{$all_hds->{raw_hds}});
-
- my @fstab = read_fstab($prefix, '/etc/fstab', 'keep_default');
- $all_hds->{nfss} = [ grep { $_->{fs_type} eq 'nfs' } @fstab ];
- $all_hds->{smbs} = [ grep { $_->{fs_type} eq 'smbfs' } @fstab ];
- $all_hds->{davs} = [ grep { $_->{fs_type} eq 'davfs' } @fstab ];
- $all_hds->{special} = [
- (grep { $_->{fs_type} eq 'tmpfs' } @fstab),
- { device => 'none', mntpoint => '/proc', fs_type => 'proc' },
- ];
-}
-
-
-################################################################################
-# mounting functions
-################################################################################
-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 formatMount_part {
- my ($part, $raids, $fstab, $prefix, $wait_message) = @_;
-
- if (isLoopback($part)) {
- formatMount_part($part->{loopback_device}, $raids, $fstab, $prefix, $wait_message);
- }
- if (my $p = fs::get::up_mount_point($part->{mntpoint}, $fstab)) {
- formatMount_part($p, $raids, $fstab, $prefix, $wait_message) unless loopback::carryRootLoopback($part);
- }
- if ($part->{toFormat}) {
- fs::format::part($raids, $part, $prefix, $wait_message);
- }
- mount_part($part, $prefix, 0, $wait_message);
-}
-
-sub formatMount_all {
- my ($raids, $fstab, $prefix, $o_wait_message) = @_;
- formatMount_part($_, $raids, $fstab, $prefix, $o_wait_message)
- foreach sort { isLoopback($a) ? 1 : isSwap($a) ? -1 : 0 } grep { $_->{mntpoint} } @$fstab;
-
- #- ensure the link is there
- loopback::carryRootCreateSymlink($_, $prefix) foreach @$fstab;
-
- #- for fun :)
- #- that way, when install exits via ctrl-c, it gives hand to partition
- eval {
- my ($_type, $major, $minor) = devices::entry(fs::get::root($fstab)->{device});
- output "/proc/sys/kernel/real-root-dev", makedev($major, $minor);
- };
-}
-
-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");
-
- -d $where or mkdir_p($where);
-
- $dev = part2device('', $dev, $fs);
-
- $fs or log::l("not mounting $dev partition"), return;
-
- my @fs_modules = qw(vfat hfs romfs ufs reiserfs xfs jfs ext3);
-
- if (member($fs, 'smb', 'smbfs', 'nfs', 'davfs', 'ntfs') && $::isStandalone || $::move) {
- $o_wait_message->(N("Mounting partition %s", $dev)) if $o_wait_message;
- system('mount', '-t', $fs, $dev, $where, if_($o_options, '-o', $o_options)) == 0 or die N("mounting partition %s in directory %s failed", $dev, $where);
- } else {
- my @types = ('ext2', 'proc', 'sysfs', 'usbdevfs', 'iso9660', 'devfs', 'devpts', @fs_modules);
-
- member($fs, @types) or log::l("skipping mounting $dev partition ($fs)"), return;
-
- $where =~ s|/$||;
-
- my $flag = c::MS_MGC_VAL();
- $flag |= c::MS_RDONLY() if $b_rdonly;
- my $mount_opt = "";
-
- if ($fs eq 'vfat') {
- $mount_opt = 'check=relaxed';
- } elsif ($fs eq 'reiserfs') {
- #- could be better if we knew if there is a /boot or not
- #- without knowing it, / is forced to be mounted with notail
- # if $where =~ m|/(boot)?$|;
- $mount_opt = 'notail'; #- notail in any case
- } elsif ($fs eq 'jfs' && !$b_rdonly) {
- $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;
- };
- } elsif ($fs eq 'ext2' && !$b_rdonly) {
- $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;
- }
- }
- }
- if (member($fs, @fs_modules)) {
- eval { modules::load($fs) };
- } elsif ($fs eq 'iso9660') {
- eval { modules::load('isofs') };
- }
- log::l("calling mount($dev, $where, $fs, $flag, $mount_opt)");
- $o_wait_message->(N("Mounting partition %s", $dev)) if $o_wait_message;
- syscall_('mount', $dev, $where, $fs, $flag, $mount_opt) or die N("mounting partition %s in directory %s failed", $dev, $where) . " ($!)";
-
- eval { #- fail silently, /etc may be read-only
- append_to_file("/etc/mtab", "$dev $where $fs defaults 0 0\n");
- };
- }
-}
-
-#- 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'; #- don't care about error, if we can't read, we won't manage to write... (and mess mtab)
-}
-
-sub mount_part {
- my ($part, $o_prefix, $b_rdonly, $o_wait_message) = @_;
-
- #- root carrier's link can't be mounted
- loopback::carryRootCreateSymlink($part, $o_prefix);
-
- log::l("isMounted=$part->{isMounted}, real_mntpoint=$part->{real_mntpoint}, mntpoint=$part->{mntpoint}");
- if ($part->{isMounted} && $part->{real_mntpoint} && $part->{mntpoint}) {
- log::l("remounting partition on $o_prefix$part->{mntpoint} 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 "$o_prefix$part->{mntpoint}", $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 = ($o_prefix || '') . $part->{mntpoint};
- if (isLoopback($part) || $part->{encrypt_key}) {
- set_loop($part);
- } elsif ($part->{options} =~ /encrypted/) {
- log::l("skip mounting $part->{device} since we don't have the encrypt_key");
- return;
- } elsif (loopback::carryRootLoopback($part)) {
- $mntpoint = "/initrd/loopfs";
- }
- my $dev = $part->{real_device} || $part->{device};
- mount($dev, $mntpoint, $part->{fs_type}, $b_rdonly, $part->{options}, $o_wait_message);
- rmdir "$mntpoint/lost+found";
- }
- }
- $part->{isMounted} = 1;
- set_isFormatted($part, 1); #- assume that if mount works, partition is formatted
-}
-
-sub umount_part {
- my ($part, $o_prefix) = @_;
-
- $part->{isMounted} || $part->{real_mntpoint} or return;
-
- unless ($::testing) {
- if (isSwap($part)) {
- swapoff($part->{device});
- } elsif (loopback::carryRootLoopback($part)) {
- umount("/initrd/loopfs");
- } else {
- umount(($o_prefix || '') . $part->{mntpoint} || devices::make($part->{device}));
- devices::del_loop(delete $part->{real_device}) if $part->{real_device};
- }
- }
- $part->{isMounted} = 0;
-}
-
-sub umount_all($;$) {
- my ($fstab, $prefix) = @_;
-
- log::l("unmounting all filesystems");
-
- foreach (sort { $b->{mntpoint} cmp $a->{mntpoint} } @$fstab) {
- $_->{mntpoint} and umount_part($_, $prefix);
- }
-}
-
-################################################################################
-# various functions
-################################################################################
-sub df {
- my ($part, $o_prefix) = @_;
- my $dir = "/tmp/tmp_fs_df";
-
- return $part->{free} if exists $part->{free};
-
- if ($part->{isMounted}) {
- $dir = ($o_prefix || '') . $part->{mntpoint};
- } elsif ($part->{notFormatted} && !$part->{isFormatted}) {
- return; #- won't even try!
- } else {
- mkdir_p($dir);
- eval { mount($part->{device}, $dir, $part->{fs_type}, 'readonly') };
- if ($@) {
- set_isFormatted($part, 0);
- unlink $dir;
- return;
- }
- }
- my (undef, $free) = MDK::Common::System::df($dir);
-
- if (!$part->{isMounted}) {
- umount($dir);
- unlink($dir)
- }
-
- $part->{free} = 2 * $free if defined $free;
- $part->{free};
-}
-
-1;