diff options
Diffstat (limited to 'perl-install/fs')
-rw-r--r-- | perl-install/fs/any.pm | 85 | ||||
-rw-r--r-- | perl-install/fs/dmcrypt.pm | 83 | ||||
-rw-r--r-- | perl-install/fs/dmraid.pm | 91 | ||||
-rw-r--r-- | perl-install/fs/format.pm | 197 | ||||
-rw-r--r-- | perl-install/fs/get.pm | 35 | ||||
-rw-r--r-- | perl-install/fs/loopback.pm | 2 | ||||
-rw-r--r-- | perl-install/fs/mount.pm | 14 | ||||
-rw-r--r-- | perl-install/fs/mount_options.pm | 12 | ||||
-rw-r--r-- | perl-install/fs/mount_point.pm | 29 | ||||
-rw-r--r-- | perl-install/fs/partitioning.pm | 8 | ||||
-rw-r--r-- | perl-install/fs/partitioning_wizard.pm | 258 | ||||
-rw-r--r-- | perl-install/fs/proc_partitions.pm | 18 | ||||
-rw-r--r-- | perl-install/fs/remote.pm | 2 | ||||
-rw-r--r-- | perl-install/fs/remote/davfs.pm | 16 | ||||
-rw-r--r-- | perl-install/fs/remote/nfs.pm | 45 | ||||
-rw-r--r-- | perl-install/fs/remote/smb.pm | 2 | ||||
-rw-r--r-- | perl-install/fs/type.pm | 161 | ||||
-rw-r--r-- | perl-install/fs/wild_device.pm | 14 |
18 files changed, 749 insertions, 323 deletions
diff --git a/perl-install/fs/any.pm b/perl-install/fs/any.pm index 65ca02403..ce4de2ca3 100644 --- a/perl-install/fs/any.pm +++ b/perl-install/fs/any.pm @@ -1,11 +1,15 @@ -package fs::any; # $Id: any.pm 269745 2010-06-02 11:21:42Z pterjan $ +package fs::any; use diagnostics; use strict; +use c; use common; use fsedit; +use fs::get; use fs::mount_point; +use fs::type; +use run_program; sub get_hds { my ($all_hds, $fstab, $manual_fstab, $partitioning_flags, $skip_mtab, $o_in) = @_; @@ -58,21 +62,26 @@ sub set_cdrom_symlink { my $alias = basename($_->{mntpoint}) or next; log::l("using alias $alias for $_->{device}"); $_->{device_alias} = $alias; - symlink($_->{device}, "/dev/$alias") if $::prefix; # do create the symlink to have it during install (otherwise fs::wild_device::from_part will give a non accessible device) - symlink($_->{device}, "$::prefix/dev/$alias"); + symlink($_->{device}, "/dev/$alias"); } } sub check_hds_boot_and_root { - my ($all_hds, $fstab) = @_; + my ($all_hds, $fstab, $isUpgrade, $o_match_all_hardware) = @_; fs::get::root_($fstab) or die "Oops, no root partition"; - if (arch() =~ /ppc/ && detect_devices::get_mac_generation() =~ /NewWorld/) { - die "Need bootstrap partition to boot system!" if !(defined $partition_table::mac::bootstrap_part); - } - - if (arch() =~ /ia64/ && !fs::get::has_mntpoint("/boot/efi", $all_hds)) { - die N("You must have a FAT partition mounted in /boot/efi"); + return if $o_match_all_hardware || $::local_install; + + if (is_uefi()) { + if (!fs::get::has_mntpoint("/boot/EFI", $all_hds)) { + die N("You must have a ESP FAT32 partition mounted in /boot/EFI"); + } + } else { + # if we are doing an upgrade, the user may still be using a legacy bootloader + return if $isUpgrade; + if (is_boot_bios_part_needed($all_hds)) { + die N("You must have a BIOS boot partition for non-UEFI GPT-partitioned disks. Please create one before continuing."); + } } } @@ -81,28 +90,24 @@ sub create_minimal_files() { qw(dev etc etc/profile.d etc/rpm etc/sysconfig etc/sysconfig/console etc/sysconfig/network-scripts etc/sysconfig/console/consolefonts etc/sysconfig/console/consoletrans - home mnt tmp var var/tmp var/lib var/lib/rpm var/lib/urpmi); + home mnt run tmp var var/tmp var/lib var/lib/rpm var/lib/urpmi); mkdir "$::prefix/$_", 0700 foreach qw(root root/tmp root/drakx); - - devices::make("$::prefix/dev/null"); - chmod 0666, "$::prefix/dev/null"; } -sub prepare_minimal_root { - my ($all_hds) = @_; +sub prepare_minimal_root() { - fs::any::create_minimal_files(); + create_minimal_files(); + # ensure we've all needed devices, for bootloader install and mkinitrd: + run_program::run('mount', '--bind', '/dev', "$::prefix/dev"); + run_program::run('mount', '--bind', '/run', "$::prefix/run"); eval { fs::mount::mount('none', "$::prefix/proc", 'proc') }; eval { fs::mount::mount('none', "$::prefix/sys", 'sysfs') }; - eval { fs::mount::usbfs($::prefix) }; - - # copy all needed devices, for bootloader install and mkinitrd - cp_af("/dev", "$::prefix"); + eval { fs::mount::sys_kernel_debug($::prefix) }; } -sub getAvailableSpace { - my ($fstab, $o_skip_mounted) = @_; +sub getNeededMinSpace { + my ($n) = @_; #- make sure of this place to be available for installation, this could help a lot. #- currently doing a very small install use 36Mb of postinstall-rpm, but installing @@ -110,9 +115,15 @@ sub getAvailableSpace { #- 65mb may be a good choice to avoid almost all problem of insuficient space left... my $minAvailableSize = 65 * sqr(1024); + max(0.1 * $n, $minAvailableSize); +} + +sub getAvailableSpace { + my ($fstab, $o_skip_mounted, $o_skip_min_space) = @_; + my $n = !$::testing && !$o_skip_mounted && getAvailableSpace_mounted($::prefix) || getAvailableSpace_raw($fstab) * 512 / 1.07; - $n - max(0.1 * $n, $minAvailableSize); + $o_skip_min_space ? $n : $n - getNeededMinSpace($n); } sub getAvailableSpace_mounted { @@ -136,4 +147,30 @@ sub getAvailableSpace_raw { die "missing root partition"; } +=head3 is_boot_bios_part_needed($all_hds) + +Returns whether a Boot BIOS Partition is needed + +Returns true if all of the following are true: + - legacy boot (not UEFI) + - all disks are (or will be) GPT + - no disks have a BIOS boot partition + +=cut + +sub is_boot_bios_part_needed { + my ($all_hds) = @_; + # never needed for UEFI boot + return if is_uefi(); + # do we already have one? + my @parts = map { partition_table::get_normal_parts($_) } fs::get::hds($all_hds); + return if any { isBIOS_GRUB($_) } @parts; + # do we have any non-GPT disks? + foreach my $hd (@{$all_hds->{hds}}) { + my $type = $hd->{pt_table_type} || partition_table::default_type($hd); + return if $type ne 'gpt'; + } + 1; +} + 1; diff --git a/perl-install/fs/dmcrypt.pm b/perl-install/fs/dmcrypt.pm index a226bcbc7..a78a495d1 100644 --- a/perl-install/fs/dmcrypt.pm +++ b/perl-install/fs/dmcrypt.pm @@ -1,4 +1,4 @@ -package fs::dmcrypt; # $Id: $ +package fs::dmcrypt; use diagnostics; use strict; @@ -11,12 +11,28 @@ use fs::type; use fs::get; use run_program; +=head1 SYNOPSYS + +Manage encrypted file systems using cryptsetup + +=head1 Functions + +=over + +=cut + sub _crypttab() { "$::prefix/etc/crypttab" } +=item init() + +Load kernel modules and init device mapper. + +=cut + sub init() { whereis_binary('cryptsetup') or die "cryptsetup not installed"; - eval { modules::load('dm-crypt', 'xts', 'cbc', 'sha256_generic', if_(arch() =~ /i.86/, 'aes-i586'), if_( arch() =~ /x86_64/, 'aes-x86_64'), 'aes_generic') }; + eval { modules::load('dm-crypt', list_modules::category2modules('various/crypto')) }; devices::init_device_mapper(); 1; } @@ -25,25 +41,38 @@ sub _ensure_initialized() { $initialized++ or init(); } -sub read_crypttab { - my ($all_hds) = @_; +sub read_crypttab_ { + my ($all_hds, $crypttab) = @_; - -e _crypttab() or return; + -e $crypttab or return; my @raw_parts = grep { fs::type::isRawLUKS($_) } fs::get::really_all_fstab($all_hds); - foreach (cat_(_crypttab())) { + foreach (cat_($crypttab)) { + next if /^#/; my ($dm_name, $dev) = split; my $raw_part = fs::get::device2part($dev, \@raw_parts) or log::l("crypttab: unknown device $dev for $dm_name"), next; $raw_part->{dm_name} = $dm_name; + _get_existing_one_with_state($raw_part); } } -sub save_crypttab { +=item read_crypttab($all_hds) + +Read /etc/crypttab + +=cut + +sub read_crypttab { my ($all_hds) = @_; + read_crypttab_($all_hds, _crypttab()); +} + +sub save_crypttab_ { + my ($all_hds, $crypttab) = @_; my @raw_parts = grep { $_->{dm_name} } fs::get::really_all_fstab($all_hds) or return; @@ -57,7 +86,18 @@ sub save_crypttab { if (eof) { $_ .= join('', map { "$_ $names{$_}\n" } sort keys %names); } - } _crypttab(); + } $crypttab; +} + +=item save_crypttab($all_hds) + +Save /etc/crypttab + +=cut + +sub save_crypttab { + my ($all_hds) = @_; + save_crypttab_($all_hds, _crypttab()); } sub format_part { @@ -67,7 +107,7 @@ sub format_part { common::with_private_tmp_file($tmp_key_file, $part->{dmcrypt_key}, sub { _run_or_die('--cipher=aes-xts-benbi', '--key-size=512', 'luksFormat', '--batch-mode', devices::make($part->{device}), $_[0]); }); - fs::format::after_formatting($part, 1); + fs::format::after_formatting($part); } sub open_part { @@ -80,9 +120,15 @@ sub open_part { }); run_program::run('udevadm', 'settle'); + push @$dmcrypts, _get_existing_one_with_state($part); +} + + +sub _get_existing_one_with_state { + my ($part) = @_; my $active_dmcrypt = _parse_dmsetup_table($part->{dm_name}, run_program::get_stdout('dmsetup', 'table', $part->{dm_name})); - push @$dmcrypts, _get_existing_one([$part], $active_dmcrypt); + _get_existing_one([$part], $active_dmcrypt); } sub close_part { @@ -90,7 +136,12 @@ sub close_part { my $dm_part = fs::get::device2part("mapper/$part->{dm_name}", $dmcrypts); _run_or_die('luksClose', devices::make($dm_part->{device})); $part->{dm_active} = 0; - @$dmcrypts = grep { $_ != $dm_part } @$dmcrypts; + @$dmcrypts = grep { $_ != $dm_part } @$dmcrypts; + # remove partition from /etc/crypttab when deleted (mga#25891) + substInFile { + my ($name, $_dev) = split; + undef $_ if $name eq $part->{dm_name}; + } _crypttab(); } sub _run_or_die { @@ -127,8 +178,10 @@ sub _get_existing_one { put_in_hash($part, $type); } fs::type::set_isFormatted($part, to_bool($part->{fs_type})); - - $part->{fs_type} or fs::type::set_fs_type($part, defaultFS()); + + unless (fs::type::cannotBeMountable($part)) { + $part->{fs_type} or fs::type::set_fs_type($part, defaultFS()); + } log::l("dmcrypt: found $part->{device} type $part->{fs_type} with rootDevice $part->{rootDevice}"); @@ -156,4 +209,8 @@ sub active_dm() { } run_program::get_stdout('dmsetup', 'table'); } +=back + +=cut + 1; diff --git a/perl-install/fs/dmraid.pm b/perl-install/fs/dmraid.pm index a744f01af..7a279abc7 100644 --- a/perl-install/fs/dmraid.pm +++ b/perl-install/fs/dmraid.pm @@ -1,4 +1,4 @@ -package fs::dmraid; # $Id: dmraid.pm 265309 2010-01-27 00:28:23Z pterjan $ +package fs::dmraid; use diagnostics; use strict; @@ -14,23 +14,54 @@ use fs::wild_device; use run_program; +=head1 SYNOPSYS + +Manage fake RAIDs using dmraid + +=head1 Functions + +=over + +=item init() + +Load kernel modules, init device mapper then scan for fake RAIDs. + +=cut + sub init() { whereis_binary('dmraid') or die "dmraid not installed"; eval { modules::load('dm-mirror', 'dm-zero') }; devices::init_device_mapper(); if ($::isInstall) { - call_dmraid('-ay'); + foreach my $name (call_dmraid('-s', '-c', '-i')) { + chomp($name); + log::l("got: $name"); + call_dmraid('-ay', '-i', '--rm_partitions', '-p', $name); + run_program::run('/sbin/kpartx', '-u', '-a', '/dev/mapper/' . $name); + } } 1; } -#- call_dmraid is overloaded when debugging, see the end of this file +=item call_dmraid($option, @args) + +Runs dmraid with $option & @args. +It is overloaded when debugging, see the end of this file. + +=cut + sub call_dmraid { my ($option, @args) = @_; run_program::get_stdout('dmraid', $option, @args); } +=item check($in) + +Ensures dmraid is installed. If yes, calls init(). + +=cut + sub check { my ($in) = @_; @@ -39,29 +70,36 @@ sub check { 1; } +=item _raid_devices_raw() + +Get the real VG names, needed for ddf1, and safer than begins_with for raid10 + +=cut + sub _raid_devices_raw() { - # get the real vg names, needed for ddf1, and safer than begins_with for raid10 log::l("_raid_devices_raw"); my %vgs; my %pv2vg = map { + chomp(); log::l("got: $_"); my %l; @l{qw(name size stride level status subsets devs spares)} = split(':'); $vgs{$l{name}} = 1 if defined $l{spares}; - if(/freeing device "(.*)", path "(.*)"/ && defined $vgs{$1}) { + if (/freeing device "(.*)", path "(.*)"/ && defined $vgs{$1}) { log::l("$2 => $1"); - { $2 => $1 }; + $2 => $1; } - } call_dmraid('-d', '-s', '-c', '-c'); + } call_dmraid(qw(-d -s -c -c)); + map { chomp; log::l("got: $_"); my %l; @l{qw(pv format vg level status size)} = split(':'); - if(defined $l{size} && defined $l{vg} && defined $pv2vg{$l{pv}} && !defined $vgs{$l{vg}}) { + if (defined $l{size} && defined $l{vg} && defined $pv2vg{$l{pv}} && !defined $vgs{$l{vg}}) { log::l("using $pv2vg{$l{pv}} instead of $l{vg}"); $l{vg} = $pv2vg{$l{pv}}; } if_(defined $l{size}, \%l); - } call_dmraid('-r', '-c', '-c'); + } call_dmraid(qw(-r -c -c)); } sub _raid_devices() { @@ -108,6 +146,12 @@ sub _sets() { @sets; } +=item vgs() + +Returns the list of VGs corresponding to dmraid + +=cut + sub vgs() { map { my $dev = "mapper/$_->{name}"; @@ -116,7 +160,12 @@ sub vgs() { #- device should exist, created by dmraid(8) using libdevmapper #- if it doesn't, we suppose it's not in use - if_(-e "/dev/$dev", $vg); + if (-e "/dev/$dev") { + $vg; + } else { + log::l("ignoring $dev as /dev/$dev doesn't exist"); + (); + } } grep { if ($_->{status} eq 'ok') { @@ -128,11 +177,15 @@ sub vgs() { } _sets(); } -# the goal is to handle migration from /dev/mapper/xxx1 to /dev/mapper/xxxp1, -# as used by initrd/nash. -# dmraid has been patched to follow xxxp1 device names. -# so until the box has rebooted on new initrd/dmraid, we must cope with /dev/mapper/xxx1 device names -# (cf #44182) +=item migrate_device_names ($vg) + +Handles migration from /dev/mapper/xxx1 to /dev/mapper/xxxp1, as used by initrd/nash. +dmraid has been patched to follow xxxp1 device names. +So until the box has rebooted on new initrd/dmraid, we must cope with /dev/mapper/xxx1 device names +(cf mdk#44182) + +=cut + sub migrate_device_names { my ($vg) = @_; @@ -148,6 +201,14 @@ sub migrate_device_names { } } +=back + +=head1 Debugging + +If $ENV{DRAKX_DEBUG_DMRAID} is set, debugging dmraid is done. +The C<call_dmraid()> function is overloaded and will spit out warnings. +=cut + if ($ENV{DRAKX_DEBUG_DMRAID}) { eval(<<'EOF'); my %debug_data = ( diff --git a/perl-install/fs/format.pm b/perl-install/fs/format.pm index de444c694..1fa90c29e 100644 --- a/perl-install/fs/format.pm +++ b/perl-install/fs/format.pm @@ -1,4 +1,4 @@ -package fs::format; # $Id: format.pm 268842 2010-05-17 06:54:44Z pterjan $ +package fs::format; use diagnostics; use strict; @@ -10,30 +10,57 @@ use fs::type; use fs::loopback; use log; +=head1 SYNOPSYS + +B<fs::format> enables to format filesystems. + +=head1 Variables + +=over + +=item %cmds + +Commands to format filesystem: + +For each filesystem, list: [ package_name, command_to_use, options_to_use ] + +=cut + my %cmds = ( ext2 => [ 'e2fsprogs', 'mkfs.ext2', '-F' ], ext3 => [ 'e2fsprogs', 'mkfs.ext3', '-F' ], ext4 => [ 'e2fsprogs', 'mkfs.ext4', '-F' ], + f2fs => [ 'f2fs-tools', 'mkfs.f2fs', '-f' ], reiserfs => [ 'reiserfsprogs', 'mkfs.reiserfs', '-ff' ], - reiser4 => [ 'reiser4progs', 'mkfs.reiser4', '-f', '-y' ], xfs => [ 'xfsprogs', 'mkfs.xfs', '-f', '-q' ], jfs => [ 'jfsutils', 'mkfs.jfs', '-f' ], hfs => [ 'hfsutils', 'hformat' ], - dos => [ 'dosfstools', 'mkdosfs' ], - vfat => [ 'dosfstools', 'mkdosfs', '-F', '32' ], + dos => [ 'dosfstools', 'mkfs.fat' ], + vfat => [ 'dosfstools', 'mkfs.fat', '-F', '32' ], + exfat => [ 'exfatprogs', 'mkfs.exfat' ], swap => [ 'util-linux', 'mkswap' ], - ntfs => [ 'ntfsprogs', 'mkntfs', '--fast' ], - 'ntfs-3g' => [ 'ntfsprogs', 'mkntfs', '--fast' ], - btrfs => [ 'btrfs-progs', 'mkfs.btrfs' ], - nilfs2 => [ 'nilfs-utils', 'mkfs.nilfs2' ], + ntfs => [ 'ntfs-3g', 'mkfs.ntfs', '--fast' ], + 'ntfs-3g' => [ 'ntfs-3g', 'mkfs.ntfs', '--fast' ], + btrfs => [ 'btrfs-progs', 'mkfs.btrfs', '-f' ], + nilfs2 => [ 'nilfs-utils', 'mkfs.nilfs2', '-f' ], ); -my %LABELs = ( #- option, length, handled_by_mount + +=item %LABELs + +mkfs option to use in order to set the label + label specs. + +For each filesystem, list: [ option, max_length, handled_by_mount ] + +=cut + +my %LABELs = ( ext2 => [ '-L', 16, 1 ], ext3 => [ '-L', 16, 1 ], ext4 => [ '-L', 16, 1 ], + exfat => [ '-L', 16, 1 ], + f2fs => [ '-l', 16, 1 ], reiserfs => [ '-l', 16, 1 ], - reiser4 => [ '-L', 16, 1 ], xfs => [ '-L', 12, 1 ], jfs => [ '-L', 16, 1 ], hfs => [ '-l', 27, 0 ], @@ -46,34 +73,63 @@ my %LABELs = ( #- option, length, handled_by_mount nilfs2 => [ '-L', 16, 1 ], ); -my %edit_LABEL = ( # package, command, option -# If option is defined, run <command> <option> <label> <device> -# If no option, run <command> <device> <label> +=item %edit_LABEL + +Commands to set the file system label. + +For each filesystem, list: [ package, command, option ] + +If option is defined, run <command> <option> <label> <device> + +If no option, run <command> <device> <label> + +=cut + +my %edit_LABEL = ( # ext2 => [ 'e2fsprogs', 'tune2fs', '-L' ], ext3 => [ 'e2fsprogs', 'tune2fs', '-L' ], ext4 => [ 'e2fsprogs', 'tune2fs', '-L' ], reiserfs => [ 'reiserfsprogs', 'reiserfstune', '-l' ], -# reiser4 xfs => [ 'xfsprogs', 'xfs_admin', '-L' ], jfs => [ 'jfsutils', 'jfs_tune', '-L' ], # hfs dos => [ 'mtools', 'mlabel', '-i' ], + exfat => [ 'exfatprogs', 'tune.exfat', '-L' ], vfat => [ 'mtools', 'mlabel', '-i' ], swap => [ 'util-linux', 'swaplabel', '-L' ], - ntfs => [ 'ntfsprogs', 'ntfslabel' ], - 'ntfs-3g' => [ 'ntfsprogs', 'ntfslabel' ], - btrfs => [ 'btrfs-progs', 'btrfs', 'filesystem', 'label' ], - nilfs2 => [ 'nilfs-utils', 'nilfs-tune', '-L' ], + ntfs => [ 'ntfs-3g', 'ntfslabel' ], + 'ntfs-3g' => [ 'ntfs-3g', 'ntfslabel' ], + btrfs => [ 'btrfs-progs', 'btrfs', 'filesystem', 'label' ], + nilfs2 => [ 'nilfs-utils', 'nilfs-tune', '-L' ], ); -# Preserve UUID on fs where we couldn't enforce it while formatting -my %preserve_UUID = ( # package, commande - #btrfs => [ 'btrfs-progs', 'FIXME' ], +=item %preserve_UUID + +For each filesystem, list: [ option, max_length, handled_by_mount ] + +Those are used in order to preserve UUID on fs where we couldn't enforce it while formatting. + +=cut + +my %preserve_UUID = ( # package, command jfs => [ 'jfsutils', 'jfs_tune', ], xfs => [ 'xfsprogs', 'xfs_admin' ], nilfs2 => [ 'nilfs-utils', 'nilfs-tune' ], ); - + + +=back + +=head1 Functions + +=over + +=item package_needed_for_partition_type($part) + +Return the package needed for that partition's type. + +=cut + sub package_needed_for_partition_type { my ($part) = @_; my $l = $cmds{$part->{fs_type}} or return; @@ -104,6 +160,12 @@ sub canEditLabel { to_bool($edit_LABEL{$part->{fs_type}}); } +=item part($all_hds, $part, $wait_message) + +Frontend to part_raw() + +=cut + sub part { my ($all_hds, $part, $wait_message) = @_; if (isRAID($part)) { @@ -117,8 +179,15 @@ sub part { $wait_message->(N("Formatting partition %s", $part->{device})) if $wait_message; part_raw($part, $wait_message); } + undef $part->{toFormat}; } +=item write_label($part) + +Set the label on the filesystem hold in $part. + +=cut + sub write_label { my ($part) = @_; @@ -146,6 +215,36 @@ sub write_label { delete $part->{device_LABEL_changed}; } +sub write_btrfs_uuid { + my ($UUID, $dev) = @_; + $dev = devices::make($dev); + my $status = system("echo y|btrfstune -U $UUID $dev") == 0; + die "failed to set UUID to '$UUID' on $dev (status=$status)" if !$status; +} + +=item sub option_to_preserve_UUID_while_formating($part, $fs_type) + +Return the options needed to preserve UUID while formating + +=cut + +sub option_to_preserve_UUID_while_formating { + my ($part, $fs_type) = @_; + if (member($fs_type, qw(swap ext2 ext3 ext4))) { + return '-U', $part->{device_UUID} if $part->{device_UUID}; + } elsif ($fs_type eq 'reiserfs') { + return '-u', $part->{device_UUID} if $part->{device_UUID}; + } + return (); +} + +=item part_raw($part, $wait_message) + +Actually format the $part partition disk. $wait_message is only used when formating ext3/4. +If not set, ext[3-4] will be formated without any progression bar, like other fses... + +=cut + sub part_raw { my ($part, $wait_message) = @_; @@ -172,13 +271,8 @@ sub part_raw { push @options, '-l', 'bootstrap'; } - # Preserve UUID - if (member($fs_type, 'swap', 'ext2', 'ext3', 'ext4')) { - push @options, '-U', $part->{device_UUID} if $part->{device_UUID}; - } elsif ($fs_type eq 'reiserfs') { - push @options, '-u', $part->{device_UUID} if $part->{device_UUID}; - } - + push @options, option_to_preserve_UUID_while_formating($part, $fs_type); + if ($part->{device_LABEL}) { push @options, @{$LABELs{$fs_type}}[0], $part->{device_LABEL}; } @@ -195,10 +289,8 @@ sub part_raw { delete $part->{device_LABEL_changed}; - # Preserve UUID on fs where we couldn't enforce it while formatting - my ($_pkg, $cmd) = @{$preserve_UUID{$fs_type}}; - run_program::raw($cmd, '-U', devices::make($dev)) if $cmd; - + preserve_UUID_after_format($dev, $part, $fs_type); + if (member($fs_type, qw(ext3 ext4))) { disable_forced_fsck($dev); } @@ -206,6 +298,28 @@ sub part_raw { after_formatting($part); } +=item preserve_UUID_after_format($dev, $part, $fs_type) + +Preserve UUID on fs where we couldn't enforce it while formatting + +=cut + +sub preserve_UUID_after_format { + my ($dev, $part, $fs_type) = @_; + if (my $uuid_cmd = $preserve_UUID{$fs_type}) { + my (undef, $cmd) = @$uuid_cmd; + run_program::raw({}, $cmd, '-U', $part->{device_UUID}, devices::make($dev)) if $cmd; + } elsif ($fs_type eq 'btrfs' && $part->{device_UUID}) { + write_btrfs_uuid($part->{device_UUID}, $dev); + } +} + +=item after_formatting($part) + +Misc post formating tags (rereading UUID & setting state) + +=cut + sub after_formatting { my ($part) = @_; @@ -215,6 +329,12 @@ sub after_formatting { set_isFormatted($part, 1); } +=item mkfs_ext3($wait_message, @args) + +Display a progression bar whike formating ext3/4 + +=cut + sub mkfs_ext3 { my ($wait_message, @args) = @_; @@ -231,6 +351,12 @@ sub mkfs_ext3 { return close($F); } +=item disable_forced_fsck($dev) + +Disable automatic fsck on extX (infinite number of mounts & duration between 2 fsck runs) + +=cut + sub disable_forced_fsck { my ($dev) = @_; run_program::run("tune2fs", "-c0", "-i0", devices::make($dev)); @@ -241,7 +367,7 @@ sub clean_label { if ($part->{device_LABEL}) { my $fs_type = $part->{fs_type}; if ($LABELs{$fs_type}) { - my ($option, $length, $handled_by_mount) = @{$LABELs{$fs_type}}; + my ($_option, $length, $handled_by_mount) = @{$LABELs{$fs_type}}; if (length $part->{device_LABEL} > $length) { my $short = substr($part->{device_LABEL}, 0, $length); log::l("shortening LABEL $part->{device_LABEL} to $short"); @@ -302,5 +428,8 @@ sub formatMount_all { }; } +=back + +=cut 1; diff --git a/perl-install/fs/get.pm b/perl-install/fs/get.pm index 461984431..00c807738 100644 --- a/perl-install/fs/get.pm +++ b/perl-install/fs/get.pm @@ -1,4 +1,4 @@ -package fs::get; # $Id: get.pm 245972 2008-09-18 17:00:11Z pixel $ +package fs::get; use diagnostics; use strict; @@ -11,6 +11,17 @@ use fs; use common; use log; + +=head1 SYNOPSYS + +B<fs::get> + +=head1 Functions + +=over + +=cut + sub empty_all_hds() { { hds => [], lvms => [], raids => [], dmcrypts => [], loopbacks => [], raw_hds => [], nfss => [], smbs => [], davs => [], special => [] }; } @@ -22,7 +33,7 @@ sub fstab { sub really_all_fstab { my ($all_hds) = @_; my @l = fstab($all_hds); - @l, @{$all_hds->{raw_hds}}, @{$all_hds->{nfss}}, @{$all_hds->{smbs}}, @{$all_hds->{davs}}; + @l, (grep { !$_->{is_removable} } @{$all_hds->{raw_hds}}), @{$all_hds->{nfss}}, @{$all_hds->{smbs}}, @{$all_hds->{davs}}; } sub fstab_and_holes { @@ -51,7 +62,12 @@ sub hds { (@{$all_hds->{hds}}, @{$all_hds->{lvms}}); } -#- get all normal partition including special ones as found on sparc. +=item hds_fstab(@hds) + +Get all normal partition. + +=cut + sub hds_fstab { map { partition_table::get_normal_parts($_) } @_; } @@ -119,6 +135,15 @@ sub has_mntpoint { my ($mntpoint, $all_hds) = @_; mntpoint2part($mntpoint, [ really_all_fstab($all_hds) ]); } + +sub root_from_mounted() { + foreach (`df -P`) { + next if m!^[^/]!; # ignore tootfs + my ($fs, undef, undef, undef, undef, $mntpnt) = split(/\s+/); + return $fs if $mntpnt eq '/'; + } +} + sub root_ { my ($fstab, $o_boot) = @_; $o_boot && mntpoint2part("/boot", $fstab) || mntpoint2part("/", $fstab); @@ -156,4 +181,8 @@ sub mntpoint_prefixed { $::prefix . $part->{mntpoint}; } +=back + +=cut + 1; diff --git a/perl-install/fs/loopback.pm b/perl-install/fs/loopback.pm index 8620e6068..8d0c729ec 100644 --- a/perl-install/fs/loopback.pm +++ b/perl-install/fs/loopback.pm @@ -1,4 +1,4 @@ -package fs::loopback; # $Id: loopback.pm 212860 2005-06-28 09:12:16Z prigaux $ +package fs::loopback; use diagnostics; use strict; diff --git a/perl-install/fs/mount.pm b/perl-install/fs/mount.pm index 4365c0caa..6afaa9260 100644 --- a/perl-install/fs/mount.pm +++ b/perl-install/fs/mount.pm @@ -1,4 +1,4 @@ -package fs::mount; # $Id: mount.pm 267516 2010-04-12 16:40:47Z pterjan $ +package fs::mount; use diagnostics; use strict; @@ -35,8 +35,8 @@ sub mount { $fs or log::l("not mounting $dev partition"), return; { - my @fs_modules = qw(btrfs ext3 ext4 hfs jfs nilfs2 nfs ntfs romfs reiserfs ufs xfs vfat); - my @types = (qw(ext2 proc sysfs usbfs usbdevfs iso9660 devpts auto ntfs-3g), @fs_modules); + my @fs_modules = qw(btrfs ext3 ext4 f2fs hfs jfs nilfs2 nfs ntfs romfs reiserfs ufs xfs vfat); + my @types = (qw(ext2 proc sysfs iso9660 devpts auto ntfs-3g), @fs_modules); push @types, 'smb', 'cifs', 'davfs2' if !$::isInstall; @@ -83,6 +83,7 @@ sub mount { push @mount_opt, 'ro' if $b_rdonly; $o_wait_message->(N("Mounting partition %s", $dev)) if $o_wait_message; + modules::load("fuse") if $::isInstall && $fs eq 'ntfs-3g' && ! -e '/dev/fuse'; 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); } @@ -160,8 +161,6 @@ sub part { set_loop($part); $options = join(',', grep { !/^(encryption=|encrypted$|loop$)/ } split(',', $options)); #- we take care of this, don't let it mount see it } elsif (isLoopback($part)) { - #- mount will take care, but we must help it - devices::make("loop$_") foreach 0 .. 7; $options = join(',', uniq('loop', split(',', $options))); #- ensure the loop options is used } elsif ($part->{options} =~ /encrypted/) { log::l("skip mounting $part->{device} since we do not have the encrypt_key"); @@ -227,11 +226,10 @@ sub umount_all { } } -sub usbfs { +sub sys_kernel_debug { my ($prefix) = @_; - my $fs = cat_('/proc/filesystems') =~ /usbfs/ ? 'usbfs' : 'usbdevfs'; - mount('none', "$prefix/proc/bus/usb", $fs); + mount('none', "$prefix/sys/kernel/debug/usb", 'debugfs'); } 1; diff --git a/perl-install/fs/mount_options.pm b/perl-install/fs/mount_options.pm index bae101679..0b63f7260 100644 --- a/perl-install/fs/mount_options.pm +++ b/perl-install/fs/mount_options.pm @@ -1,4 +1,4 @@ -package fs::mount_options; # $Id: mount_options.pm 268841 2010-05-17 06:52:12Z pterjan $ +package fs::mount_options; use diagnostics; use strict; @@ -12,7 +12,7 @@ sub list() { my %non_defaults = ( sync => 'async', noatime => 'atime', noauto => 'auto', ro => 'rw', user => 'nouser', nodev => 'dev', noexec => 'exec', nosuid => 'suid', - user_xattr => 'nouser_xattr', acl => 'noacl', + user_xattr => 'nouser_xattr', ); my @user_implies = qw(noexec nodev nosuid); \%non_defaults, \@user_implies; @@ -35,9 +35,10 @@ sub unpack { reiserfs => [ 'notail' ], ); push @{$per_fs{$_}}, 'usrquota', 'grpquota' foreach 'ext2', 'ext3', 'ext4', 'xfs'; + push @{$per_fs{$_}}, 'acl' foreach 'ext2', 'ext3', 'ext4', 'reiserfs'; while (my ($fs, $l) = each %per_fs) { - $part->{fs_type} eq $fs || $part->{fs_type} eq 'auto' && member($fs, @auto_fs) or next; + member($part->{fs_type}, $fs, 'auto') && member($fs, @auto_fs) or next; $non_defaults->{$_} = 1 foreach @$l; } @@ -186,7 +187,6 @@ sub set_default { if (!$opts{ignore_is_removable} && $part->{is_removable} && !member($part->{mntpoint}, fs::type::directories_needed_to_boot()) && (!$part->{fs_type} || $part->{fs_type} eq 'auto' || $part->{fs_type} =~ /:/)) { - $options->{supermount} = 0; #- always disable supermount $part->{fs_type} = 'auto'; $options->{flush} = 1 if $part->{media_type} ne 'cdrom'; } @@ -207,7 +207,7 @@ sub set_default { #- filesystem (e.g, for faster access on the #- news spool to speed up news servers). $options->{relatime} = $options->{noatime} = 0; - $options->{detect_devices::isLaptop() ? 'noatime': 'relatime'} = 1 if !$opts{force_atime}; + $options->{ detect_devices::isLaptop() ? 'noatime' : 'relatime' } = 1 if !$opts{force_atime}; } if ($part->{fs_type} eq 'nfs') { put_in_hash($options, { @@ -224,7 +224,7 @@ sub set_default { }) if $part->{is_removable}; put_in_hash($options, { - 'umask=0' => $opts{security} <= 1, + 'umask=0' => $opts{security} <= 1 && !isESP($part), 'iocharset=' => $opts{iocharset}, 'codepage=' => $opts{codepage}, }); } diff --git a/perl-install/fs/mount_point.pm b/perl-install/fs/mount_point.pm index 8dc4521ae..56f2405e9 100644 --- a/perl-install/fs/mount_point.pm +++ b/perl-install/fs/mount_point.pm @@ -1,4 +1,4 @@ -package fs::mount_point; # $Id: mount_point.pm 269270 2010-05-24 09:55:20Z pterjan $ +package fs::mount_point; use diagnostics; use strict; @@ -24,7 +24,10 @@ sub guess_mount_point { my $d = $handle->{dir}; my $mnt = find { -e "$d/$l{$_}" } keys %l; $mnt ||= (stat("$d/.bashrc"))[4] ? '/root' : '/home/user' . ++$$user if -e "$d/.bashrc"; - $mnt ||= (any { -d $_ && (stat($_))[4] >= 500 && -e "$_/.bashrc" } glob_($d)) ? '/home' : ''; + $mnt ||= (any { -d $_ && (stat($_))[4] >= 1000 && -e "$_/.bashrc" } glob_($d)) ? '/home' : ''; + # Keep uid 500 here for guesswork, but base it on .bash_history to increase + # changes it's a real user. + $mnt ||= (any { -d $_ && (stat($_))[4] >= 500 && -e "$_/.bash_history" } glob_($d)) ? '/home' : ''; ($mnt, $handle); } @@ -43,30 +46,32 @@ sub suggest_mount_points { #- try to find other mount points via fstab fs::merge_info_from_fstab($fstab, $handle->{dir}, $uniq, 'loose') if $mnt eq '/'; } + # reuse existing ESP under UEFI: + my @ESP = if_(is_uefi(), grep { isESP($_) } @$fstab); + if (@ESP) { + $ESP[0]{mntpoint} = '/boot/EFI'; + delete $ESP[0]{unsafeMntpoint}; + } $_->{mntpoint} and log::l("suggest_mount_points: $_->{device} -> $_->{mntpoint}") foreach @$fstab; } sub suggest_mount_points_always { my ($fstab) = @_; - my @win = grep { isFat_or_NTFS($_) && !$_->{isMounted} && maybeFormatted($_) && !$_->{is_removable} && $_->{pt_type} != 0x12 && !isRecovery($_)} @$fstab; + my @ESP = if_(is_uefi(), grep { isESP($_) && maybeFormatted($_) && !$_->{is_removable} } @$fstab); + if (@ESP) { + $ESP[0]{mntpoint} = "/boot/EFI"; + } + my @win = grep { isnormal_Fat_or_NTFS($_) && !$_->{isMounted} && maybeFormatted($_) && !$_->{is_removable} } @$fstab; log::l("win parts: ", join ",", map { $_->{device} } @win) if @win; if (@win == 1) { - #- Suggest /boot/efi on ia64. - $win[0]{mntpoint} = arch() =~ /ia64/ ? "/boot/efi" : "/media/windows"; + $win[0]{mntpoint} = "/media/windows"; } else { my %w; foreach (@win) { my $v = $w{$_->{device_windobe}}++; $_->{mntpoint} = $_->{unsafeMntpoint} = "/media/win_" . lc($_->{device_windobe}) . ($v ? $v+1 : ''); #- lc cuz of StartOffice(!) cf dadou } } - - my @sunos = grep { $_->{pt_type} == 2 } @$fstab; #- take only into account root partitions. - if (@sunos) { - my $v = ''; - map { $_->{mntpoint} = $_->{unsafeMntpoint} = "/mnt/sunos" . ($v && ++$v) } @sunos; - } - #- a good job is to mount SunOS root partition, and to use mount point described here in /etc/vfstab. } sub validate_mount_points { diff --git a/perl-install/fs/partitioning.pm b/perl-install/fs/partitioning.pm index 015a7e4e8..18fa7e114 100644 --- a/perl-install/fs/partitioning.pm +++ b/perl-install/fs/partitioning.pm @@ -1,16 +1,18 @@ -package fs::partitioning; # $Id: partitioning.pm 243679 2008-07-29 11:55:58Z tv $ +package fs::partitioning; use diagnostics; use strict; use common; use fs::format; +use fs::get; use fs::type; sub guess_partitions_to_format { my ($fstab) = @_; + my $root_part = fs::get::root($fstab); foreach (@$fstab) { - $_->{mntpoint} = "swap" if isSwap($_); + $_->{mntpoint} = "swap" if isSwap($_) && ($_->{rootDevice} eq $root_part->{rootDevice} || !$_->{is_removable} && !$root_part->{is_removable}); $_->{mntpoint} or next; add2hash_($_, { toFormat => $_->{notFormatted} }) if $_->{fs_type}; #- eg: do not set toFormat for isRawRAID (0xfd) @@ -52,7 +54,7 @@ sub choose_partitions_to_format { ({ text => partition_table::description($e), type => 'bool', val => \$e->{toFormatTmp} - }, if_(!isLoopback($_) && !member($_->{fs_type}, 'reiserfs', 'xfs', 'jfs'), { + }, if_(!isLoopback($_) && isBlockCheckable($_), { text => partition_table::description($e), type => 'bool', advanced => 1, disabled => sub { !$e->{toFormatTmp} }, val => \$e->{toFormatCheck} diff --git a/perl-install/fs/partitioning_wizard.pm b/perl-install/fs/partitioning_wizard.pm index 97e7472f5..6e77f3eff 100644 --- a/perl-install/fs/partitioning_wizard.pm +++ b/perl-install/fs/partitioning_wizard.pm @@ -1,4 +1,4 @@ -package fs::partitioning_wizard; # $Id: partitioning_wizard.pm 269969 2010-06-09 13:01:09Z pterjan $ +package fs::partitioning_wizard; use diagnostics; use strict; @@ -14,12 +14,26 @@ use partition_table::raw; use partition_table::dos; use POSIX qw(ceil); -#- unit of $mb is mega bytes, min and max are in sectors, this -#- function is used to convert back to sectors count the size of -#- a partition ($mb) given from the interface (on Resize or Create). -#- modified to take into account a true bounding with min and max. + +=head1 SYNOPSYS + +B<fs::partitioning_wizard> implements the partitioning wizard. + +=head1 Functions + +=over + +=item from_Mb($mb, $min, $max) + +This function is used to convert back to sectors count the size of +a partition ($mb) given from the interface (on Resize or Create). +modified to take into account a true bounding with min and max. +Unit of $mb is mega bytes, min and max are in sectors. + +=cut + sub from_Mb { - my ($mb, $min, $max) = @_; + emy ($mb, $min, $max) = @_; $mb <= to_Mb($min) and return $min; $mb >= to_Mb($max) and return $max; MB($mb); @@ -30,15 +44,28 @@ sub to_Mb { } sub partition_with_diskdrake { - my ($in, $all_hds, $fstab, $manual_fstab, $partitions, $partitioning_flags, $skip_mtab) = @_; + my ($in, $all_hds, $fstab, $manual_fstab, $_partitions, $partitioning_flags, $skip_mtab) = @_; my $ok; + # The classic installer sets $skip_mtab to either undef or 1. The live + # installer sets it to 'skip_mtab'. If $skip_mtab is not set, this has + # already been done by fs::any::get_hds. + if ($skip_mtab eq 'skip_mtab') { + fs::mount_point::suggest_mount_points_always($fstab); + } + do { $ok = 1; my $do_force_reload = sub { + require File::Temp; + require fs::dmcrypt; + my (undef, $tmp_file) = File::Temp::mkstemp('/tmp/crypttab.XXXXXXX'); + fs::dmcrypt::save_crypttab_($all_hds, $tmp_file); my $new_hds = fs::get::empty_all_hds(); fs::any::get_hds($new_hds, $fstab, $manual_fstab, $partitioning_flags, $skip_mtab, $in); %$all_hds = %$new_hds; + fs::dmcrypt::read_crypttab_($all_hds, $tmp_file); + rm_rf($tmp_file); $all_hds; }; require diskdrake::interactive; @@ -48,7 +75,7 @@ sub partition_with_diskdrake { } my @fstab = fs::get::fstab($all_hds); - unless ($root = fs::get::root_(\@fstab)) { + unless (fs::get::root_(\@fstab)) { $ok = 0; $in->ask_okcancel(N("Partitioning"), N("You must have a root partition. To accomplish this, create a partition (or click on an existing one). @@ -58,22 +85,30 @@ Then choose action ``Mount point'' and set it to `/'"), 1) or return; if (!any { isSwap($_) } @fstab) { $ok &&= $in->ask_okcancel('', N("You do not have a swap partition.\n\nContinue anyway?")); } - if (arch() =~ /ia64/ && !fs::get::has_mntpoint("/boot/efi", $all_hds)) { - $in->ask_warn('', N("You must have a FAT partition mounted in /boot/efi")); + if (is_uefi()) { + my $part = fs::get::has_mntpoint("/boot/EFI", $all_hds); + if (!$part || !isESP($part)) { + $in->ask_warn('', N("You must have a ESP FAT32 partition mounted in /boot/EFI")); $ok = ''; + } + } else { + if (fs::any::is_boot_bios_part_needed($all_hds)) { + $in->ask_warn('', N("You must have a BIOS boot partition for non-UEFI GPT-partitioned disks. Please create one before continuing.")); + $ok = ''; + } } } until $ok; 1; } sub partitionWizardSolutions { - my ($in, $all_hds, $all_fstab, $manual_fstab, $partitions, $partitioning_flags, $skip_mtab, $target) = @_; + my ($in, $all_hds, $all_fstab, $manual_fstab, $partitions, $partitioning_flags, $skip_mtab, $o_target) = @_; my $hds = $all_hds->{hds}; my $fstab; my $full_fstab = [ fs::get::fstab($all_hds) ]; - if ($target) { - $hds = [ $target ]; - $fstab = [ grep { $_->{rootDevice} eq $target->{device} } fs::get::fstab($all_hds) ]; + if ($o_target) { + $hds = [ $o_target ]; + $fstab = [ grep { $_->{rootDevice} eq $o_target->{device} } fs::get::fstab($all_hds) ]; } else { $fstab = $full_fstab; } @@ -84,13 +119,14 @@ sub partitionWizardSolutions { my $min_linux = MB(600); my $min_swap = MB(50); my $min_freewin = MB(100); + fsedit::init_mntpnt_suggestions($all_hds, $o_target); # each solution is a [ score, text, function ], where the function retunrs true if succeeded my @hds_rw = grep { !$_->{readonly} } @$hds; my @hds_can_add = grep { $_->{type} ne 'hd' || $_->can_add } @hds_rw; if (fs::get::hds_free_space(@hds_can_add) > $min_linux) { - $solutions{free_space} = [ 30, N("Use free space"), sub { fsedit::auto_allocate($all_hds, $partitions); 1 } ]; + $solutions{free_space} = [ 30, N("Use free space"), sub { fsedit::auto_allocate($all_hds, $partitions, $o_target); 1 } ]; } else { push @wizlog, N("Not enough free space to allocate new partitions") . ": " . (@hds_can_add ? @@ -105,8 +141,8 @@ sub partitionWizardSolutions { push @wizlog, N("There is no existing partition to use"); } - if (my @ok_for_resize_fat = grep { isFat_or_NTFS($_) && !fs::get::part2hd($_, $all_hds)->{readonly} - && !isRecovery($_) && $_->{size} > $min_linux + $min_swap + $min_freewin } @$fstab) { + if (my @ok_for_resize_fat = grep { isnormal_Fat_or_NTFS($_) && !fs::get::part2hd($_, $all_hds)->{readonly} + && $_->{size} > $min_linux + $min_swap + $min_freewin } @$fstab) { @ok_for_resize_fat = map { my $part = $_; my $hd = fs::get::part2hd($part, $all_hds); @@ -146,12 +182,12 @@ sub partitionWizardSolutions { $part->{min_win} = $min_win; $part->{min_linux} = $min_linux_all; #- try to keep at least 1GB free for Windows - #- try to use from 6GB to 10% free space for Linux + #- try to use from 20GB to 20% free space for Linux my $suggested_size = max( $part->{min_win} + 1 * MB(1024), min( - $part->{size} - int(0.1 * ($part->{size} - $part->{min_win})), - $part->{size} - 6 * MB(1024), + $part->{size} - int(0.2 * ($part->{size} - $part->{min_win})), + $part->{size} - 20 * MB(1024), ), ); $part->{req_size} = max(min($suggested_size, $part->{size} - $part->{min_linux}), $part->{min_win}); @@ -171,7 +207,13 @@ sub partitionWizardSolutions { }, \&partition_table::description, \@ok_for_resize_fat) or return; $part->{size} > $part->{min_linux} + $part->{min_win} or die N("Your Microsoft Windows® partition is too fragmented. Please reboot your computer under Microsoft Windows®, run the ``defrag'' utility, then restart the %s installation.", N("Mageia")); } else { - $part = top(grep { $_->{req_size} } @ok_for_resize_fat); + my @selected = grep { + $_->{selected_for_resize} && + $o_target->{device} eq $_->{rootDevice}; # Not needed but let's be safe + } @ok_for_resize_fat; + my $nb_parts = @selected; + die N("Failed to find the partition to resize (%d choices)", $nb_parts) unless $nb_parts == 1; + $part = $selected[0]; } my $resize_fat = $part->{resize_fat}; my $hd = fs::get::part2hd($part, $all_hds); @@ -218,7 +260,7 @@ filesystem checks will be run on your next boot into Microsoft Windows®")) if $ partition_table::adjust_local_extended($hd, $part); partition_table::adjust_main_extended($hd); - fsedit::auto_allocate($all_hds, $partitions); + fsedit::auto_allocate($all_hds, $partitions, $hd); 1; }, \@ok_for_resize_fat ]; } @@ -238,13 +280,16 @@ filesystem checks will be run on your next boot into Microsoft Windows®")) if $ }, \&partition_table::description, \@hds_rw) or return; } else { - $hd = $target; + $hd = $o_target; } $in->ask_okcancel_({ messages => N("ALL existing partitions and their data will be lost on drive %s", partition_table::description($hd)), title => N("Partitioning"), interactive_help_id => 'takeOverHdConfirm' }) or return; fsedit::partition_table_clear_and_initialize($all_hds->{lvms}, $hd, $in); - fsedit::auto_allocate($all_hds, $partitions); + # FIXME: reread all_hds: + # re add suggestions if needed (as we might just have erased eg Boot BIOS partition): + fsedit::init_mntpnt_suggestions($all_hds, $hd, 1); + fsedit::auto_allocate($all_hds, $partitions, $hd); 1; } ]; } @@ -263,11 +308,7 @@ filesystem checks will be run on your next boot into Microsoft Windows®")) if $ When you are done, do not forget to save using `w'", partition_table::description($_)); print "\n\n"; my $pid = 0; - if (arch() =~ /ppc/) { - $pid = fork() or exec "pdisk", devices::make($_->{device}); - } else { - $pid = fork() or exec "fdisk", devices::make($_->{device}); - } + $pid = fork() or exec "fdisk", devices::make($_->{device}); waitpid($pid, 0); } $in->leave_console; @@ -285,35 +326,48 @@ sub warn_reboot_needed { sub create_display_box { my ($kind, $resize, $fill_empty, $button) = @_; - my @parts = fs::get::hds_fstab_and_holes($kind->{val}); - my $totalsectors = $kind->{val}{totalsectors}; + # Hide empty space < 2MB, wehave such holes due to alignment + my @parts = grep { $_->{size} > MB(2) || !isEmpty($_) } diskdrake::hd_gtk::kind2parts($kind); + + my $totalsectors = diskdrake::hd_gtk::kind2sectors($kind, @parts); - my $width = 540; + my $width = 520; my $minwidth = 40; - my $display_box = ugtk2::gtkset_size_request(Gtk2::HBox->new(0,0), -1, 26); + my $display_box = ugtk3::gtkset_size_request(Gtk3::HBox->new(0,0), -1, 26); + $display_box->set_spacing(1); my $sep_count = @parts - 1; #- ratio used to compute initial partition pixel width (each partition should be > min_width) #- though, the pixel/sectors ratio cannot be the same for all the partitions my $initial_ratio = $totalsectors ? ($width - @parts * $minwidth - $sep_count) / $totalsectors : 1; - my $vbox = Gtk2::VBox->new; + my $vbox = Gtk3::VBox->new; - my $part_sep; my $desc; - my $last = $resize && $resize->[-1]; + if ($resize) { + my %resizable_parts; + foreach my $entry (@$resize) { + # selected_for_resize may have been set on another disk, clear it + $entry->{selected_for_resize} = 0; + $resizable_parts{$entry->{device}} = $entry; + } + # find resizable parts on this disk + my @choices = grep { $resizable_parts{$_->{device}} } @parts; + my @sorted_resize = sort { + $a->{size} - $a->{req_size} <=> $b->{size} - $b->{req_size}; + } @choices; + $sorted_resize[-1]{selected_for_resize} = 1; + } foreach my $entry (@parts) { - my $part_info = Gtk2::Label->new($entry->{device_LABEL}); + my $part_info = Gtk3::Label->new($entry->{device_LABEL}); my @colorized_fs_types = qw(ext2 ext3 ext4 xfs swap vfat ntfs ntfs-3g); - my $part_widget = Gtk2::EventBox->new; + my $part_widget = Gtk3::EventBox->new; $entry->{width} = int($entry->{size} * $initial_ratio) + $minwidth; - if ($last && $last->{device} eq $entry->{device}) { - #- entry is the last resizable partition - + if ($resize && $entry->{selected_for_resize}) { my $ratio; my $update_ratio = sub { $ratio = $entry->{width} / $entry->{size} }; $update_ratio->(); @@ -321,33 +375,31 @@ sub create_display_box { $part_widget->set_name("PART_vfat"); $part_info->set_size_request(ceil($ratio * $entry->{min_win}), 0); - my $mdv_widget = gtkadd(gtkset_name(Gtk2::EventBox->new, "PART_new"), + my $mdv_widget = gtkadd(gtkset_name(Gtk3::EventBox->new, "PART_new"), gtkset_size_request(gtknew("Image", file => "small-logo"), $ratio * MB(600), 0)); - my $hpane = Gtk2::HPaned->new; - $hpane->add1($part_widget); - $hpane->child1_shrink(0); - $hpane->add2($mdv_widget); - $hpane->child2_shrink(0); + my $hpane = Gtk3::HPaned->new; + $hpane->pack1($part_widget, 1, 0); + $hpane->pack2($mdv_widget, 1, 0); $hpane->set_position(ceil($ratio * $entry->{req_size})); - ugtk2::gtkset_size_request($hpane, $entry->{width}, 0); - ugtk2::gtkpack__($display_box, $hpane); + ugtk3::gtkset_size_request($hpane, $entry->{width}, 0); + ugtk3::gtkpack__($display_box, $hpane); my $add_part_size_info = sub { my ($name, $label) = @_; - ugtk2::gtkpack__($desc, - gtkadd(gtkset_name(Gtk2::EventBox->new, $name), - Gtk2::Label->new(" " x 4)), + ugtk3::gtkpack__($desc, + gtkadd(gtkset_name(Gtk3::EventBox->new, $name), + Gtk3::Label->new(" " x 4)), gtkset_size_request(gtkset_alignment($label, 0, 0.5), 150, 20)); }; - $desc = Gtk2::HBox->new(0,0); + $desc = Gtk3::HBox->new(0,0); - my $win_size_label = Gtk2::Label->new; + my $win_size_label = Gtk3::Label->new; $add_part_size_info->("PART_vfat", $win_size_label); - my $mdv_size_label = Gtk2::Label->new; + my $mdv_size_label = Gtk3::Label->new; $add_part_size_info->("PART_new", $mdv_size_label); my $update_size_labels = sub { @@ -365,7 +417,7 @@ sub create_display_box { }; $hpane->signal_connect('size-allocate' => sub { my (undef, $alloc) = @_; - $entry->{width} = $alloc->width; + $entry->{width} = $alloc->{width}; $update_ratio->(); 0; }); @@ -388,24 +440,19 @@ sub create_display_box { 'other')); } $part_widget->set_size_request($entry->{width}, 0); - ugtk2::gtkpack($display_box, $part_widget); + ugtk3::gtkpack($display_box, $part_widget); } $part_widget->add($part_info); - - $part_sep = gtkadd(Gtk2::EventBox->new, - gtkset_size_request(Gtk2::Label->new("."), 1, 0)); - gtkpack__($display_box, $part_sep); } - $display_box->remove($part_sep) if $part_sep; unless ($resize || $fill_empty) { - my @types = (N_("Ext2/3/4"), N_("XFS"), N_("Swap"), arch() =~ /sparc/ ? N_("SunOS") : arch() eq "ppc" ? N_("HFS") : N_("Windows"), + my @types = (N_("Ext2/3/4"), N_("XFS"), N_("Swap"), N_("Windows"), N_("Other"), N_("Empty")); my %name2fs_type = ('Ext2/3/4' => 'ext3', 'XFS' => 'xfs', Swap => 'swap', Other => 'other', "Windows" => 'vfat', HFS => 'hfs'); - $desc = ugtk2::gtkpack(Gtk2::HBox->new, + $desc = ugtk3::gtkpack(Gtk3::HBox->new, map { my $t = $name2fs_type{$_}; - my $ev = Gtk2::EventBox->new; - my $w = Gtk2::Label->new(translate($_)); + my $ev = Gtk3::EventBox->new; + my $w = Gtk3::Label->new(translate($_)); $ev->add($w); $ev->set_name('PART_' . ($t || 'empty')); $ev; @@ -423,8 +470,8 @@ sub display_choices { my @solutions = sort { $solutions{$b}[0] <=> $solutions{$a}[0] } keys %solutions; my @sol = grep { $solutions{$_}[0] >= 0 } @solutions; - log::l('' . "solutions found: " . join('', map { $solutions{$_}[1] } @sol) . - " (all solutions found: " . join('', map { $solutions{$_}[1] } @solutions) . ")"); + log::l('' . "solutions found: " . join(', ', map { $solutions{$_}[1] } @sol) . + " (all solutions found: " . join(', ', map { $solutions{$_}[1] } @solutions) . ")"); @solutions = @sol if @sol > 1; log::l("solutions: ", int @solutions); @@ -435,8 +482,8 @@ sub display_choices { $contentbox->foreach(sub { $contentbox->remove($_[0]) }); $mainw->{kind}{display_box} ||= create_display_box($mainw->{kind}); - ugtk2::gtkpack2__($contentbox, $mainw->{kind}{display_box}); - ugtk2::gtkpack__($contentbox, gtknew('Label', + ugtk3::gtkpack2__($contentbox, $mainw->{kind}{display_box}); + ugtk3::gtkpack__($contentbox, gtknew('Label', text => N("The DrakX Partitioning wizard found the following solutions:"), alignment => [0, 0])); @@ -453,30 +500,30 @@ sub display_choices { $item = create_display_box($mainw->{kind}, $solutions{$s}[3], undef, $button); } elsif ($s eq 'existing_part') { } elsif ($s eq 'wipe_drive') { - $item = Gtk2::EventBox->new; + $item = Gtk3::EventBox->new; my $b2 = gtknew("Image", file => "small-logo"); $item->add($b2); - $item->set_size_request(540,26); + $item->set_size_request(520,26); $item->set_name("PART_new"); } elsif ($s eq 'diskdrake') { } else { log::l($s); next; } - ugtk2::gtkpack($vbox, + ugtk3::gtkpack($vbox, gtknew('Label', text => $solutions{$s}[1], alignment => [0, 0])); - ugtk2::gtkpack($vbox, $item) if defined($item); - $button->set_group($oldbutton->get_group) if $oldbutton; + ugtk3::gtkpack($vbox, $item) if defined($item); + $button->join_group($oldbutton) if $oldbutton; $oldbutton = $button; $button->signal_connect('toggled', sub { $mainw->{sol} = $solutions{$s} if $_[0]->get_active }); - ugtk2::gtkpack2__($choicesbox, $button); + ugtk3::gtkpack2__($choicesbox, $button); $sep = gtknew('HSeparator'); - ugtk2::gtkpack2__($choicesbox, $sep); + ugtk3::gtkpack2__($choicesbox, $sep); } $choicesbox->remove($sep); - ugtk2::gtkadd($contentbox, $choicesbox); + ugtk3::gtkadd($contentbox, $choicesbox); $mainw->{sol} = $solutions{@solutions[0]}; } @@ -486,30 +533,30 @@ sub main { my $sol; if ($o->isa('interactive::gtk')) { - require mygtk2; - mygtk2->import(qw(gtknew)); - require ugtk2; - ugtk2->import(qw(:wrappers)); + require mygtk3; + mygtk3->import(qw(gtknew)); + require ugtk3; + ugtk3->import(qw(:wrappers)); - my $mainw = ugtk2->new(N("Partitioning"), %$o, if__($::main_window, transient => $::main_window)); + my $mainw = ugtk3->new(N("Partitioning"), %$o, if__($::main_window, transient => $::main_window)); $mainw->{box_allow_grow} = 1; - mygtk2::set_main_window_size($mainw->{rwindow}); + mygtk3::set_main_window_size($mainw->{rwindow}); require diskdrake::hd_gtk; diskdrake::hd_gtk::load_theme(); - my $mainbox = Gtk2::VBox->new; + my $mainbox = Gtk3::VBox->new; - my @kinds = map { diskdrake::hd_gtk::hd2kind($_) } sort { $a->{is_removable} <=> $b->{is_removable} } @{$all_hds->{hds} }; - push @kinds, map { diskdrake::hd_gtk::raid2kind($_) } @{$all_hds->{raids}}; + my @kinds = map { diskdrake::hd_gtk::hd2kind($_) } sort { $a->{is_removable} <=> $b->{is_removable} } @{ $all_hds->{hds} }; + #push @kinds, diskdrake::hd_gtk::raid2real_kind($_) foreach @{$all_hds->{raids}}; push @kinds, map { diskdrake::hd_gtk::lvm2kind($_) } @{$all_hds->{lvms}}; - my $hdchoice = Gtk2::HBox->new; + my $hdchoice = Gtk3::HBox->new; - my $hdchoicelabel = Gtk2::Label->new(N("Here is the content of your disk drive ")); + my $hdchoicelabel = Gtk3::Label->new(N("Here is the content of your disk drive ")); - my $combobox = Gtk2::ComboBox->new_text; + my $combobox = Gtk3::ComboBoxText->new; foreach (@kinds) { my $info = $_->{val}{info} || $_->{val}{device}; $info =~ s|^(?:.*/)?(.{24}).*|$1|; @@ -518,29 +565,31 @@ sub main { } $combobox->set_active(0); - ugtk2::gtkpack2__($hdchoice, $hdchoicelabel); + ugtk3::gtkpack2__($hdchoice, $hdchoicelabel); $hdchoice->add($combobox); - ugtk2::gtkpack2__($mainbox, $hdchoice); + ugtk3::gtkpack2__($mainbox, $hdchoice); - my $contentbox = Gtk2::VBox->new(0, 12); + my $contentbox = Gtk3::VBox->new(0, 12); - my $scroll = Gtk2::ScrolledWindow->new; - $scroll->set_policy('never', 'automatic'), - my $vp = Gtk2::Viewport->new; + my $scroll = Gtk3::ScrolledWindow->new; + $scroll->set_policy('automatic', 'automatic'), + my $vp = Gtk3::Viewport->new; $vp->set_shadow_type('none'); $vp->add($contentbox); $scroll->add($vp); $mainbox->add($scroll); - my $kind = @kinds[$combobox->get_active]; + my $kind = $kinds[$combobox->get_active]; my %solutions = partitionWizardSolutions($o, $all_hds, $fstab, $manual_fstab, $partitions, $partitioning_flags, $skip_mtab, diskdrake::hd_gtk::kind2hd($kind)); delete $solutions{diskdrake} if $b_nodiskdrake; $mainw->{kind} = $kind; display_choices($o, $contentbox, $mainw, %solutions); $combobox->signal_connect("changed", sub { - $mainw->{kind} = @kinds[$combobox->get_active]; + my $curr = $kinds[$combobox->get_active]; + return if !$curr; + $mainw->{kind} = $curr; my %solutions = partitionWizardSolutions($o, $all_hds, $fstab, $manual_fstab, $partitions, $partitioning_flags, $skip_mtab, diskdrake::hd_gtk::kind2hd($mainw->{kind})); delete $solutions{diskdrake} if $b_nodiskdrake; display_choices($o, $contentbox, $mainw, %solutions); @@ -551,12 +600,12 @@ sub main { if_($::isInstall, [ gtknew('Install_Button', text => N("Help"), - clicked => sub { interactive::gtk::display_help($o, {interactive_help_id => 'doPartitionDisks' }, $mainw) }), + clicked => sub { interactive::gtk::display_help($o, {interactive_help_id => 'doPartitionDisks' }) }), undef, 1 ]), ); my $buttons_pack = $mainw->create_okcancel(N("Next"), undef, '', @more_buttons); $mainbox->pack_end($buttons_pack, 0, 0, 0); - ugtk2::gtkadd($mainw->{window}, $mainbox); + ugtk3::gtkadd($mainw->{window}, $mainbox); $mainw->{window}->show_all; $mainw->main; @@ -570,8 +619,8 @@ sub main { my @solutions = sort { $b->[0] <=> $a->[0] } values %solutions; my @sol = grep { $_->[0] >= 0 } @solutions; - log::l('' . "solutions found: " . join('', map { $_->[1] } @sol) . - " (all solutions found: " . join('', map { $_->[1] } @solutions) . ")"); + log::l('' . "solutions found: " . join(', ', map { $_->[1] } @sol) . + " (all solutions found: " . join(', ', map { $_->[1] } @solutions) . ")"); @solutions = @sol if @sol > 1; log::l("solutions: ", int @solutions); @solutions or $o->ask_warn(N("Partitioning"), N("I cannot find any room for installing")), die 'already displayed'; @@ -591,6 +640,7 @@ sub main { if ($err =~ /wizcancel/) { $_->destroy foreach $::WizardTable->get_children; } else { + log::l("Partitioning failed: $err"); $o->ask_warn('', N("Partitioning failed: %s", formatError($err))); } } @@ -598,4 +648,8 @@ sub main { 1; } +=back + +=cut + 1; diff --git a/perl-install/fs/proc_partitions.pm b/perl-install/fs/proc_partitions.pm index 8a1bc8ab0..ea714ca5b 100644 --- a/perl-install/fs/proc_partitions.pm +++ b/perl-install/fs/proc_partitions.pm @@ -1,4 +1,4 @@ -package fs::proc_partitions; # $Id: proc_partitions.pm 232285 2007-12-03 16:41:16Z pixel $ +package fs::proc_partitions; use common; @@ -6,8 +6,12 @@ use common; sub read_raw() { my (undef, undef, @all) = cat_("/proc/partitions"); grep { - $_->{size} != 1 && # skip main extended partition - $_->{size} != 0x3fffffff; # skip cdroms (otherwise stops cd-audios) + $_->{size} != 1 && # skip main extended partition + $_->{size} != 0x3fffffff && # skip cdroms (otherwise stops cd-audios) + $_->{dev} !~ /mmcblk\d+[^p]/; # only keep partitions like mmcblk0p0 + # not mmcblk0rpmb or mmcblk0boot0 as they + # are not in the partition table and + # things will break (mga#15759) } map { my %l; @l{qw(major minor size dev)} = split; @@ -16,7 +20,7 @@ sub read_raw() { } sub read { - my ($hds) = @_; + my ($hds, $o_ignore_fstype) = @_; my @all = read_raw(); my ($parts, $_disks) = partition { $_->{dev} =~ /\d$/ && $_->{dev} !~ /^(sr|scd)/ } @all; @@ -36,7 +40,7 @@ sub read { $part->{size} *= 2; # from KB to sectors $part->{start} = $prev_part ? $prev_part->{start} + $prev_part->{size} : 0; require fs::type; - put_in_hash($part, fs::type::type_subpart_from_magic($part)); + put_in_hash($part, fs::type::type_subpart_from_magic($part)) if !$o_ignore_fstype; $prev_part = $part; delete $part->{dev}; # cleanup } @@ -50,7 +54,7 @@ sub compare { my @l1 = partition_table::get_normal_parts($hd); - my @l2 = grep { $_->{rootDevice} eq $hd->{device} } &read([$hd]); + my @l2 = grep { $_->{rootDevice} eq $hd->{device} } &read([$hd], 1); #- /proc/partitions includes partition with type "empty" and a non-null size #- so add them for comparison @@ -61,7 +65,7 @@ sub compare { log::l("not using /proc/partitions because of the presence of solaris extended partition"); #- cf #33866 } else { die sprintf( - "/proc/partitions does not agree with drakx %d != %d:\n%s\n", $len1, $len2, + "/proc/partitions does not agree with drakx %d != %d for %s:\n%s\n", $len1, $len2, $hd->{device}, "/proc/partitions: " . join(", ", map { "$_->{device} ($_->{rootDevice})" } @l2)); } } diff --git a/perl-install/fs/remote.pm b/perl-install/fs/remote.pm index efc630d4c..ea5944a25 100644 --- a/perl-install/fs/remote.pm +++ b/perl-install/fs/remote.pm @@ -1,4 +1,4 @@ -package fs::remote; # $Id: remote.pm 215411 2007-04-25 12:26:16Z pixel $ +package fs::remote; use strict; use diagnostics; diff --git a/perl-install/fs/remote/davfs.pm b/perl-install/fs/remote/davfs.pm index 5df0fe771..890530cb9 100644 --- a/perl-install/fs/remote/davfs.pm +++ b/perl-install/fs/remote/davfs.pm @@ -1,4 +1,4 @@ -package fs::remote::davfs; # $Id: smb.pm 231184 2007-10-24 14:36:29Z pixel $ +package fs::remote::davfs; use strict; use diagnostics; @@ -6,7 +6,7 @@ use diagnostics; use common; use fs::mount_options; -sub secrets_file { "$::prefix/etc/davfs2/secrets" } +sub secrets_file() { "$::prefix/etc/davfs2/secrets" } sub fstab_entry_to_credentials { my ($part) = @_; @@ -14,7 +14,7 @@ sub fstab_entry_to_credentials { my ($options, $unknown) = fs::mount_options::unpack($part); my %h = map { $_ => delete $options->{"$_="} } qw(username password); foreach (qw(username password)) { - $h{$_} = 'nobody' if !$h{$_}; + $h{$_} ||= 'nobody'; } $h{mntpoint} = $part->{mntpoint} or return; fs::mount_options::pack_($part, $options, $unknown), \%h; @@ -25,7 +25,7 @@ sub save_credentials { @$credentials or return; output_with_perm(secrets_file(), 0600, - map { to_double_quoted($_->{mntpoint}, $_->{username}, $_->{password}, $_->{comment}) . "\n" } @$credentials); + map { to_double_quoted($_->{mntpoint}, $_->{username}, $_->{password}) . "\n" } @$credentials); } sub mountpoint_credentials_save { @@ -45,7 +45,7 @@ sub mountpoint_credentials_save { } -sub read_credentials_raw { +sub read_credentials_raw() { from_double_quoted(cat_(secrets_file())); } @@ -66,12 +66,12 @@ sub from_double_quoted { my ($file) = @_; my @l; my @lines = split("\n",$file); - foreach (@lines){ + foreach (@lines) { my ($mnt, $user, $pass, $comment); if (/^\s*(#.*)?$/) { $comment = $1; } else { - if(/^(?:"((?:\\.|[^"])*)"|((?:\\.|[^"\s#])+))\s+(?:"((?:\\.|[^"])*)"|((?:\\.|[^"\s#])+))(?:\s+(?:"((?:\\.|[^"])*)"|((?:\\.|[^"\s#])+)))?(?:\s*|\s*(#.*))?$/) { + if (/^(?:"((?:\\.|[^"])*)"|((?:\\.|[^"\s#])+))\s+(?:"((?:\\.|[^"])*)"|((?:\\.|[^"\s#])+))(?:\s+(?:"((?:\\.|[^"])*)"|((?:\\.|[^"\s#])+)))?(?:\s*|\s*(#.*))?$/) { $mnt = "$1$2"; $mnt =~ s/\\(.)/$1/g; $user = "$3$4"; @@ -83,7 +83,7 @@ sub from_double_quoted { die "bad entry $_"; } } - push @l, {'mntpoint'=>$mnt, 'username'=>$user, 'password'=>$pass, 'comment'=>$comment}; + push @l, { 'mntpoint' => $mnt, 'username' => $user, 'password' => $pass, 'comment' => $comment }; } @l; } diff --git a/perl-install/fs/remote/nfs.pm b/perl-install/fs/remote/nfs.pm index 7ebda3b11..f7a98cb69 100644 --- a/perl-install/fs/remote/nfs.pm +++ b/perl-install/fs/remote/nfs.pm @@ -1,10 +1,11 @@ -package fs::remote::nfs; # $Id: nfs.pm 254157 2009-03-17 16:13:42Z eugeni $ +package fs::remote::nfs; use strict; use diagnostics; use common; use fs::remote; +use network::tools; use log; our @ISA = 'fs::remote'; @@ -28,34 +29,36 @@ sub to_dev_raw { sub check { my ($_class, $in) = @_; - $in->do_pkgs->ensure_binary_is_installed('nfs-utils-clients', 'showmount') or return; + $in->do_pkgs->ensure_files_are_installed([ [ qw(nfs-utils showmount) ] , [ qw(nmap nmap) ] ]); require services; - services::start_not_running_service('portmap'); + services::start_not_running_service('rpcbind'); services::start('nfs-common'); #- TODO: once nfs-common is fixed, it could use start_not_running_service() 1; } sub find_servers { - open(my $F2, "rpcinfo-flushed -b mountd 2 |"); - open(my $F3, "rpcinfo-flushed -b mountd 3 |"); - - common::nonblock($F2); - common::nonblock($F3); - my $domain = chomp_(`domainname`); - my ($s, %servers); - my $quit; - while (!$quit) { - $quit = 1; - sleep 1; - while ($s = <$F2> || <$F3>) { - $quit = 0; - my ($ip, $name) = $s =~ /(\S+)\s+(\S+)/ or log::explanations("bad line in rpcinfo output"), next; - $name =~ s/\.$//; - $domain && $name =~ s/\Q.$domain\E$// - || $name =~ s/^([^.]*)\.local$/$1/; - $servers{$ip} ||= { ip => $ip, if_($name ne '(unknown)', name => $name) }; + my @hosts; + my %servers; + my @routes = cat_("/proc/net/route"); + @routes = reverse(@routes) if common::cmp_kernel_versions(c::kernel_version(), "2.6.39") >= 0; + foreach (@routes) { + if (/^(\S+)\s+([0-9A-F]+)\s+([0-9A-F]+)\s+[0-9A-F]+\s+\d+\s+\d+\s+(\d+)\s+([0-9A-F]+)/) { + my $net = network::tools::host_hex_to_dotted($2); + my $gateway = $3; + # get the netmask in binary and remove leading zeros + my $mask = unpack('B*', pack('h*', $5)); + $mask =~ s/^0*//; + push @hosts, $net . "/" . length($mask) if $gateway eq '00000000' && $net ne '169.254.0.0'; } + } + # runs the nmap command on the local subnet + my $cmd = "/usr/bin/nmap -p 111 --open --system-dns -oG - " . (join ' ',@hosts); + open my $FH, "$cmd |" or die "Could not perform nmap scan - $!"; + foreach (<$FH>) { + my ($ip, $name) = /^H\S+\s(\S+)\s+\((\S*)\).+Port/ or next; + $servers{$ip} ||= { ip => $ip, name => $name || $ip }; } + close $FH; values %servers; } diff --git a/perl-install/fs/remote/smb.pm b/perl-install/fs/remote/smb.pm index 616636807..d440fc174 100644 --- a/perl-install/fs/remote/smb.pm +++ b/perl-install/fs/remote/smb.pm @@ -1,4 +1,4 @@ -package fs::remote::smb; # $Id: smb.pm 258615 2009-07-27 06:26:03Z pterjan $ +package fs::remote::smb; use strict; use diagnostics; diff --git a/perl-install/fs/type.pm b/perl-install/fs/type.pm index 12db643bc..141d5b5e2 100644 --- a/perl-install/fs/type.pm +++ b/perl-install/fs/type.pm @@ -1,4 +1,4 @@ -package fs::type; # $Id: type.pm 269283 2010-05-24 15:31:58Z pterjan $ +package fs::type; use diagnostics; use strict; @@ -6,10 +6,19 @@ use strict; use common; use devices; +=head1 SYNOPSYS + +B<fs::type> enables to perform various tests on filesystem types. + +=head1 Functions + +=over + +=cut our @ISA = qw(Exporter); our @EXPORT = qw( - isEmpty isExtended isTrueLocalFS isTrueFS isDos isSwap isOtherAvailableFS isRawLVM isRawRAID isRawLUKS isRAID isLVM isLUKS isMountableRW isNonMountable isPartOfLVM isPartOfRAID isPartOfLoopback isLoopback isMounted isBusy isSpecial isApple isAppleBootstrap isWholedisk isFat_or_NTFS isRecovery + isBlockCheckable isEmpty isExtended isFormatable isTrueLocalFS isTrueFS isDos isSwap isOtherAvailableFS isRawLVM isRawRAID isRawLUKS isRAID isLVM isLUKS isMountableRW isNonMountable isPartOfLVM isPartOfRAID isPartOfLoopback isLoopback isMounted isBusy isSpecial isApple isAppleBootstrap isBIOS_GRUB isESP isFat_or_NTFS isnormal_Fat_or_NTFS isRecovery maybeFormatted set_isFormatted defaultFS ); @@ -23,22 +32,19 @@ my (%type_name2pt_type, %type_name2fs_type, %fs_type2pt_type, %pt_type2fs_type, 0x83 => 'ext2', 'Linux native', 0x83 => 'ext3', 'Journalised FS: ext3', 0x83 => 'ext4', 'Journalised FS: ext4', - 0x83 => 'reiserfs', 'Journalised FS: ReiserFS', -if_(arch() =~ /ppc|i.86|ia64|x86_64/, - 0x83 => 'xfs', 'Journalised FS: XFS', + 0x83 => 'btrfs', 'Journalised FS: Btrfs', +(is_uefi() ? + (0xef => 'vfat', 'EFI System Partition') : + ('BIOS_GRUB' => 'BIOS_GRUB', 'BIOS boot or Empty partition') ), -if_(arch() =~ /ppc|i.86|x86_64/, +if_(arch() =~ /i.86|x86_64/, + 0x83 => 'xfs', 'Journalised FS: XFS', 0x83 => 'jfs', 'Journalised FS: JFS', -), -if_(arch() =~ /i.86|ia64|x86_64/, 0x0b => 'vfat', 'FAT32', 0x07 => 'ntfs-3g', 'NTFS-3G', 0x07 => 'ntfs', 'NTFS', -), -if_(arch() =~ /ppc/, - 0x401 => '', 'Apple Bootstrap', - 0x402 => 'hfs', 'Apple HFS Partition', - 0x41 => '', 'PPC PReP Boot', + 0x07 => 'ntfs3', 'NTFS3', + 0x07 => 'exfat', 'exFAT', ), ], @@ -56,20 +62,7 @@ if_(arch() =~ /ppc/, ], other => [ - if_(arch() =~ /^ia64/, - 0x100 => '', 'Various', -), if_(arch() =~ /^ppc/, - 0x401 => 'apple', 'Apple Partition', -), if_(arch() =~ /^sparc/, - 0x01 => 'ufs', 'SunOS boot', - 0x02 => 'ufs', 'SunOS root', - 0x03 => '', 'SunOS swap', - 0x04 => 'ufs', 'SunOS usr', - 0x05 => '', 'Whole disk', - 0x06 => 'ufs', 'SunOS stand', - 0x07 => 'ufs', 'SunOS var', - 0x08 => 'ufs', 'SunOS home', -), if_(arch() =~ /^i.86|x86_64/, + if_(arch() =~ /^i.86|x86_64/, 0x01 => 'vfat', 'FAT12', 0x02 => '', 'XENIX root', 0x03 => '', 'XENIX usr', @@ -96,9 +89,7 @@ if_(arch() =~ /ppc/, 0x39 => '', 'Plan 9', 0x3c => '', 'PartitionMagic recovery', 0x40 => '', 'Venix 80286', -if_(arch() !~ /ppc/, 0x41 => '', 'PPC PReP Boot', -), 0x42 => '', 'SFS', 0x4d => '', 'QNX4.x', 0x4e => '', 'QNX4.x 2nd part', @@ -119,11 +110,9 @@ if_(arch() !~ /ppc/, 0x75 => '', 'PC/IX', 0x80 => '', 'Old Minix', 0x81 => '', 'Minix / old Linux', - if_(!$::isInstall, - 0x83 => 'reiser4', 'Journalised FS: Reiser4', - ), - 0x83 => 'nilfs2', 'NILFS2', - 0x83 => 'btrfs', 'Btrfs', + 0x83 => 'f2fs', 'Journalised FS: F2FS', + 0x83 => 'reiserfs', 'Journalised FS: ReiserFS', + 0x83 => 'nilfs2', 'Journalised FS: NILFS2', 0x84 => '', 'OS/2 hidden C: drive', 0x86 => '', 'NTFS volume set (0x86)', 0x87 => '', 'NTFS volume set (0x87)', @@ -155,7 +144,6 @@ if_(arch() !~ /ppc/, 0xe4 => '', 'SpeedStor (FAT-16)', 0xeb => 'befs', 'BeOS fs', 0xee => '', 'EFI GPT', - 0xef => 'vfat', 'EFI (FAT-12/16/32)', 0xf0 => '', 'Linux/PA-RISC boot', 0xf4 => '', 'SpeedStor (large part.)', 0xf2 => '', 'DOS secondary', @@ -187,9 +175,10 @@ sub type_names { my @l = @{$type_names{important}}; push @l, grep { $_ ne 'Encrypted' } @{$type_names{non_fs_type}}; push @l, sort @{$type_names{other}} if $expert; - if ($o_hd && !$o_hd->use_pt_type) { + # not show partition types which have no associated filesystem for LVM LV: + if ($o_hd && isLVM($o_hd)) { @l = grep { $type_name2fs_type{$_} } @l; - @l = uniq_ { $type_name2fs_type{$_[0]} } @l; + @l = uniq_ { $type_name2fs_type{$_} } @l; (@l, @{$type_names{non_fs_type}}); } else { @l; @@ -274,9 +263,10 @@ sub fs_type_from_magic { sub call_blkid { my ($part) = @_; + # IMPORTANT: Always use the -p argument with blkid. See r7324 commit msg my %h = map { if_(/(.*?)=(.*)/, $1 => $2); - } run_program::get_stdout('blkid', '2>', '/dev/null', '-o', 'udev', '-p', devices::make($part->{device})); + } run_program::get_stdout_raw({ timeout => 30 }, 'blkid', '2>', '/dev/null', '-o', 'udev', '-p', devices::make($part->{device})); \%h; } @@ -302,6 +292,7 @@ sub type_subpart_from_magic { } if ($p) { + $p->{fs_type} = '' if $part->{pt_type} eq 'BIOS_GRUB' && $p->{fs_type} ne 'iso9660'; $part->{fs_type_from_magic} = $p->{fs_type}; $p->{device_LABEL} = $ids->{ID_FS_LABEL} if $ids->{ID_FS_LABEL}; $p->{device_UUID} = $ids->{ID_FS_UUID} if $ids->{ID_FS_UUID}; @@ -310,40 +301,78 @@ sub type_subpart_from_magic { $p; } -sub defaultFS { 'ext4' } +# helpers +sub defaultFS() { 'ext4' } +sub true_local_fs_types() { qw(btrfs ext3 ext2 ext4 f2fs reiserfs xfs jfs) } -sub true_local_fs_types() { qw(btrfs ext3 ext2 ext4 reiserfs reiser4 xfs jfs) } - -sub isEmpty { !$_[0]{fs_type} && $_[0]{pt_type} == 0 } -sub isEfi { arch() =~ /ia64/ && $_[0]{pt_type} == 0xef } -sub isWholedisk { arch() =~ /^sparc/ && $_[0]{pt_type} == 5 } -sub isExtended { arch() !~ /^sparc/ && ($_[0]{pt_type} == 5 || $_[0]{pt_type} == 0xf || $_[0]{pt_type} == 0x85) } +sub isEmpty { !$_[0]{fs_type} && !$_[0]{pt_type} } +sub isBIOS_GRUB { $_[0]{pt_type} eq 'BIOS_GRUB' } +sub isESP { $_[0]{pt_type} == 0xef && member($_[0]{fs_type}, qw(fat32 vfat)) } +sub isExtended { $_[0]{pt_type} == 5 || $_[0]{pt_type} == 0xf || $_[0]{pt_type} == 0x85 } +sub isBlockCheckable { !member($_[0]{fs_type}, qw(btrfs hfs ntfs ntfs-3g reiserfs xfs)) } sub isRawLVM { $_[0]{pt_type} == 0x8e || $_[0]{type_name} eq 'Linux Logical Volume Manager' } sub isRawRAID { $_[0]{pt_type} == 0xfd || $_[0]{type_name} eq 'Linux RAID' } sub isRawLUKS { $_[0]{type_name} eq 'Encrypted' } sub isSwap { $_[0]{fs_type} eq 'swap' } -sub isDos { arch() !~ /^sparc/ && ${{ 1 => 1, 4 => 1, 6 => 1 }}{$_[0]{pt_type}} } -sub isFat_or_NTFS { member($_[0]{fs_type}, 'vfat', 'ntfs', 'ntfs-3g') } +sub isDos { ${{ 1 => 1, 4 => 1, 6 => 1 }}{$_[0]{pt_type}} } +sub isFat_or_NTFS { member($_[0]{fs_type}, qw(vfat ntfs ntfs3 ntfs-3g)) } +sub isnormal_Fat_or_NTFS { grep { isFat_or_NTFS($_) && !isESP($_) && !isRecovery($_) } @_ } sub isApple { $_[0]{pt_type} == 0x401 && defined $_[0]{isDriver} } sub isAppleBootstrap { $_[0]{pt_type} == 0x401 && defined $_[0]{isBoot} } sub isRecovery { isFat_or_NTFS($_[0]) && ($_[0]{type_name} =~ /^Hidden/ || + $_[0]{pt_type} == 0x12 || # "Compaq diagnostics" member($_[0]{device_LABEL} , - # Extracted from /usr/share/hal/fdi/policy/10osvendor/20-storage-methods.fdi - # Hopefuly we'll ask to hal/udev someday - 'RECOVERY', 'PQSERVICE', 'HP_RECOVERY', 'Recovery Partition', 'DellUtility', 'DellRestore', 'IBM_SERVICE', 'SERVICEV001', 'SERVICEV002') - ) + # Extracted from /usr/lib/udev/rules.d/80-udisks2.rules + # Hopefuly we'll ask to udev/udisk2 someday + # generated by grep Recovery /usr/lib/udev/rules.d/80-udisks2.rules : + qw(Recovery RECOVERY Lenovo_Recovery HP_RECOVERY Recovery_Partition DellUtility DellRestore IBM_SERVICE SERVICEV001 SERVICEV002 SYSTEM_RESERVED System_Reserved WINRE_DRV DIAGS IntelRST), + # gathered over the years (Hald, mga#1371, mga#15999): + qw(PQSERVICE Packard_Bell Push_Button_Reset SYSTEM_DRV)) + ); } -sub isTrueFS { isTrueLocalFS($_[0]) || member($_[0]{fs_type}, qw(nfs)) } +=item isTrueLocalFS($part) + +Like isTrueFS(), to make a distinction between ext3/reiserfs/... and NFS + => allow /home on NFS + +=cut + +sub isTrueFS { isTrueLocalFS($_[0]) || $_[0]{fs_type} eq 'nfs' } + +=item isTrueFS($part) + +Is is a general purpose file system with the right Unix properties + +=cut + sub isTrueLocalFS { member($_[0]{fs_type}, true_local_fs_types()) } -sub isOtherAvailableFS { isEfi($_[0]) || isFat_or_NTFS($_[0]) || member($_[0]{fs_type}, 'ufs', 'hfs', 'iso9660') } #- other OS that linux can access its filesystem +=item isOtherAvailableFS($part) + +Is it another OS that linux can access its filesystem + +=cut + +sub isOtherAvailableFS { isESP($_[0]) || isFat_or_NTFS($_[0]) || member($_[0]{fs_type}, 'ufs', 'hfs', 'iso9660', 'nilfs2', 'exfat') } sub isMountableRW { (isTrueFS($_[0]) || isOtherAvailableFS($_[0])) && $_[0]{fs_type} ne 'ntfs' } sub cannotBeMountable { my ($part) = @_; - isRawRAID($part) || isRawLUKS($part) || isRawLVM($part); + isRawRAID($part) || isRawLUKS($part) || isRawLVM($part) || isBIOS_GRUB($part); +} + +=item isFormatable($part) + +Is not a special sg that cannot be mounted/formatted (parts of RAID/LVM, BIOS_GRUB). Basically the reverse of cannotBeMountable(). + +=cut + +sub isFormatable { + my ($part) = @_; + !cannotBeMountable($part); } + sub isNonMountable { my ($part) = @_; cannotBeMountable($part) || $part->{fs_type} eq 'ntfs' && !$part->{isFormatted} && $part->{notFormatted}; @@ -361,7 +390,12 @@ sub isMounted { $_[0]{isMounted} } sub isBusy { isMounted($_[0]) || isPartOfRAID($_[0]) || isPartOfLVM($_[0]) || $_[0]{dm_active} || isPartOfLoopback($_[0]) } sub isSpecial { isRAID($_[0]) || isLVM($_[0]) || isLoopback($_[0]) || isUBD($_[0]) } -#- not for partitions, but for hds: +=item is_dmraid($hd) + +Check that a disk (not a partition) is in a fake/soft RAID + +=cut + sub is_dmraid { $_[0]{bus} =~ /^dmraid_/ } sub can_be_this_fs_type { @@ -386,24 +420,37 @@ sub set_isFormatted { delete $part->{fs_type_from_magic}; } -#- do this before modifying $part->{fs_type} +=item check($fs_type, $_hd, $part) + +Called before before modifying $part->{fs_type} + +=cut + sub check { my ($fs_type, $_hd, $part) = @_; $fs_type eq "jfs" && $part->{size} < MB(16) and die N("You cannot use JFS for partitions smaller than 16MB"); $fs_type eq "reiserfs" && $part->{size} < MB(32) and die N("You cannot use ReiserFS for partitions smaller than 32MB"); + $fs_type eq "btrfs" && $part->{size} < MB(256) and die N("You cannot use btrfs for partitions smaller than 256MB"); } sub guessed_by_mount() { grep { $_ && !/nodev/ } chomp_(cat_('/etc/filesystems')); } -sub directories_needed_to_boot() { +sub directories_needed_to_boot_not_ESP() { qw(/ /usr /var /boot /tmp); } +sub directories_needed_to_boot() { + directories_needed_to_boot_not_ESP(), '/boot/EFI'; +} sub carry_root_loopback { my ($part) = @_; any { $_->{mntpoint} eq '/' } @{$part->{loopback} || []}; } +=back + +=cut + 1; diff --git a/perl-install/fs/wild_device.pm b/perl-install/fs/wild_device.pm index efb48d9d7..ff5a32253 100644 --- a/perl-install/fs/wild_device.pm +++ b/perl-install/fs/wild_device.pm @@ -1,8 +1,8 @@ -package fs::wild_device; # $Id: wild_device.pm 268572 2010-05-11 16:42:46Z pterjan $ +package fs::wild_device; use diagnostics; use strict; - +use devices; use common; @@ -11,13 +11,13 @@ sub analyze { if ($dev =~ m!^/u?dev/(.*)!) { 'dev', $dev; - } elsif ($dev !~ m!^/! && (-e "/dev/$dev" || -e "$::prefix/dev/$dev")) { + } elsif ($dev !~ m!^/! && (-e "/dev/$dev" || -e "/dev/$dev")) { 'dev', "/dev/$dev"; } elsif ($dev =~ /^LABEL=(.*)/) { 'label', $1; } elsif ($dev =~ /^UUID=(.*)/) { 'uuid', $1; - } elsif ($dev eq 'none' || $dev eq 'rootfs') { + } elsif (member($dev, qw(none rootfs))) { 'virtual'; } elsif ($dev =~ m!^(\S+):/(\w|$)!) { 'nfs'; @@ -40,11 +40,11 @@ sub to_subpart { $part->{device_UUID} = $val; } elsif ($kind eq 'dev') { my %part = (faked_device => 0); - if (my $rdev = (stat "$::prefix$dev")[6]) { + if (my $rdev = (stat "$dev")[6]) { ($part{major}, $part{minor}) = unmakedev($rdev); } - my $symlink = readlink("$::prefix$dev") unless $dev =~ m!mapper/!; + my $symlink = $dev !~ m!mapper/! ? readlink("$dev") : undef; $dev =~ s!/u?dev/!!; if ($symlink && $symlink !~ m!^/!) { @@ -67,7 +67,7 @@ sub to_subpart { return \%part; } } else { - if ($dev =~ m!^/! && -f "$::prefix$dev") { + if ($dev =~ m!^/! && -f "$dev") { #- it must be a loopback file or directory to bind } else { log::l("part_from_wild_device_name: unknown device $dev"); |