diff options
Diffstat (limited to 'perl-install/fs/format.pm')
| -rw-r--r-- | perl-install/fs/format.pm | 191 |
1 files changed, 161 insertions, 30 deletions
diff --git a/perl-install/fs/format.pm b/perl-install/fs/format.pm index a92db89f7..0be25e3d7 100644 --- a/perl-install/fs/format.pm +++ b/perl-install/fs/format.pm @@ -1,7 +1,8 @@ -package fs::format; # $Id$ +package fs::format; use diagnostics; use strict; +use String::ShellQuote; use run_program; use common; @@ -11,20 +12,25 @@ use log; my %cmds = ( ext2 => [ 'e2fsprogs', 'mkfs.ext2', '-F' ], - ext3 => [ 'e2fsprogs', 'mkfs.ext2', '-F', '-j' ], + ext3 => [ 'e2fsprogs', 'mkfs.ext3', '-F' ], + ext4 => [ 'e2fsprogs', 'mkfs.ext4', '-F' ], reiserfs => [ 'reiserfsprogs', 'mkfs.reiserfs', '-ff' ], - reiser4 => [ 'reiser4progs', 'mkfs.reiser4', '-f' ], xfs => [ 'xfsprogs', 'mkfs.xfs', '-f', '-q' ], - jfs => [ 'jfsprogs', 'mkfs.jfs', '-f' ], + jfs => [ 'jfsutils', 'mkfs.jfs', '-f' ], hfs => [ 'hfsutils', 'hformat' ], dos => [ 'dosfstools', 'mkdosfs' ], vfat => [ 'dosfstools', 'mkdosfs', '-F', '32' ], swap => [ 'util-linux', 'mkswap' ], + ntfs => [ 'ntfsprogs', 'mkntfs', '--fast' ], + 'ntfs-3g' => [ 'ntfsprogs', 'mkntfs', '--fast' ], + btrfs => [ 'btrfs-progs', 'mkfs.btrfs', '-f' ], + nilfs2 => [ 'nilfs-utils', 'mkfs.nilfs2' ], ); my %LABELs = ( #- option, length, handled_by_mount ext2 => [ '-L', 16, 1 ], ext3 => [ '-L', 16, 1 ], + ext4 => [ '-L', 16, 1 ], reiserfs => [ '-l', 16, 1 ], xfs => [ '-L', 12, 1 ], jfs => [ '-L', 16, 1 ], @@ -32,8 +38,38 @@ my %LABELs = ( #- option, length, handled_by_mount dos => [ '-n', 11, 0 ], vfat => [ '-n', 11, 0 ], swap => [ '-L', 15, 1 ], + ntfs => [ '-L', 128, 0 ], + 'ntfs-3g' => [ '-L', 128, 0 ], + btrfs => [ '-L', 256, 1 ], + 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> + ext2 => [ 'e2fsprogs', 'tune2fs', '-L' ], + ext3 => [ 'e2fsprogs', 'tune2fs', '-L' ], + ext4 => [ 'e2fsprogs', 'tune2fs', '-L' ], + reiserfs => [ 'reiserfsprogs', 'reiserfstune', '-l' ], + xfs => [ 'xfsprogs', 'xfs_admin', '-L' ], + jfs => [ 'jfsutils', 'jfs_tune', '-L' ], +# hfs + dos => [ 'mtools', 'mlabel', '-i' ], + 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' ], +); + +# Preserve UUID on fs where we couldn't enforce it while formatting +my %preserve_UUID = ( # package, command + jfs => [ 'jfsutils', 'jfs_tune', ], + xfs => [ 'xfsprogs', 'xfs_admin' ], + nilfs2 => [ 'nilfs-utils', 'nilfs-tune' ], +); + sub package_needed_for_partition_type { my ($part) = @_; my $l = $cmds{$part->{fs_type}} or return; @@ -45,11 +81,23 @@ sub known_type { to_bool($cmds{$part->{fs_type}}); } -sub check_package_is_installed { +sub check_package_is_installed_format { my ($do_pkgs, $fs_type) = @_; my ($pkg, $binary) = @{$cmds{$fs_type} || return}; - $do_pkgs->ensure_binary_is_installed($pkg, $binary); + whereis_binary($binary) || $do_pkgs->ensure_binary_is_installed($pkg, $binary); #- ensure_binary_is_installed checks binary chrooted, whereas we run the binary non-chrooted (pb for Mageia One) +} + +sub check_package_is_installed_label { + my ($do_pkgs, $fs_type) = @_; + + my ($pkg, $binary) = @{$edit_LABEL{$fs_type} || return}; + whereis_binary($binary) || $do_pkgs->ensure_binary_is_installed($pkg, $binary); #- ensure_binary_is_installed checks binary chrooted, whereas we run the binary non-chrooted (pb for Mageia One) +} + +sub canEditLabel { + my ($part) = @_; + to_bool($edit_LABEL{$part->{fs_type}}); } sub part { @@ -65,6 +113,41 @@ sub part { $wait_message->(N("Formatting partition %s", $part->{device})) if $wait_message; part_raw($part, $wait_message); } + undef $part->{toFormat}; +} + +sub write_label { + my ($part) = @_; + + $part->{device_LABEL_changed} or return; + maybeFormatted($part) or return; + + if ($part->{encrypt_key}) { + fs::mount::set_loop($part); + } + + my $dev = $part->{real_device} || $part->{device}; + my ($_pkg, $cmd, @first_options) = @{$edit_LABEL{$part->{fs_type}} || die N("I do not know how to set label on %s with type %s", $part->{device}, $part->{fs_type})}; + my @args; + if ($cmd eq 'mlabel') { + @args = ($cmd, @first_options, devices::make($dev), '::' . $part->{device_LABEL}); + } elsif ($cmd eq 'btrfs') { + # btrfs needs reverse ordering + @args = ($cmd, @first_options, devices::make($dev), $part->{device_LABEL}); + } elsif (defined $first_options[0]) { + @args = ($cmd, @first_options, $part->{device_LABEL}, devices::make($dev)); + } else { + @args = ($cmd, devices::make($dev), $part->{device_LABEL}); + } + run_program::raw({ timeout => 'never' }, @args) or die N("setting label on %s failed, is it formatted?", $dev); + 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; } sub part_raw { @@ -83,7 +166,7 @@ sub part_raw { my $fs_type = $part->{fs_type}; - if ($fs_type eq 'ext2' || $fs_type eq 'ext3') { + if (member($fs_type, qw(ext2 ext3 ext4))) { push @options, "-m", "0" if $part->{mntpoint} =~ m|^/home|; } elsif (isDos($part)) { $fs_type = 'dos'; @@ -93,46 +176,59 @@ sub part_raw { push @options, '-l', 'bootstrap'; } - if ($part->{device_LABEL}) { - if ($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"); - $part->{device_LABEL} = $short; - } - delete $part->{prefer_device_LABEL} - if !$handled_by_mount || $part->{mntpoint} eq '/' && !member($fs_type, 'ext2', 'ext3'); + # Preserve UUID + if (member($fs_type, qw(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, $part->{device_LABEL}; - } else { - log::l("dropping LABEL=$part->{device_LABEL} since we don't know how to set labels for fs_type $part->{fs_type}"); - delete $part->{device_LABEL}; - delete $part->{prefer_device_LABEL}; - } + if ($part->{device_LABEL}) { + push @options, @{$LABELs{$fs_type}}[0], $part->{device_LABEL}; } my ($_pkg, $cmd, @first_options) = @{$cmds{$fs_type} || die N("I do not know how to format %s in type %s", $part->{device}, $part->{fs_type})}; my @args = ($cmd, @first_options, @options, devices::make($dev)); - if ($cmd eq 'mkfs.ext2' && $wait_message) { - mkfs_ext2($wait_message, @args) or die N("%s formatting of %s failed", $fs_type, $dev); + if ($cmd =~ /^mkfs.ext[34]$/ && $wait_message) { + mkfs_ext3($wait_message, @args) or die N("%s formatting of %s failed", $fs_type, $dev); } else { - run_program::raw({ timeout => 60 * 60 }, @args) or die N("%s formatting of %s failed", $fs_type, $dev); + run_program::raw({ timeout => 'never' }, @args) or die N("%s formatting of %s failed", $fs_type, $dev); } - if ($fs_type eq 'ext3') { + delete $part->{device_LABEL_changed}; + + # Preserve UUID on fs where we couldn't enforce it while formatting + if (my $uuid_cmd = $preserve_UUID{$fs_type}) { + (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); + } + + if (member($fs_type, qw(ext3 ext4))) { disable_forced_fsck($dev); } + after_formatting($part); +} + +sub after_formatting { + my ($part) = @_; + + my $p = fs::type::type_subpart_from_magic($part); + $part->{device_UUID} = $p && $p->{device_UUID}; + set_isFormatted($part, 1); } -sub mkfs_ext2 { +sub mkfs_ext3 { my ($wait_message, @args) = @_; - open(my $F, "@args |"); + my $cmd = shell_quote_best_effort(@args); + log::l("running: $cmd"); + open(my $F, "$cmd |"); local $/ = "\b"; local $_; @@ -148,6 +244,28 @@ sub disable_forced_fsck { run_program::run("tune2fs", "-c0", "-i0", devices::make($dev)); } +sub clean_label { + my ($part) = @_; + if ($part->{device_LABEL}) { + my $fs_type = $part->{fs_type}; + if ($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"); + $part->{device_LABEL} = $short; + } + delete $part->{prefer_device_LABEL} + if !$handled_by_mount || $part->{mntpoint} eq '/' && !member($fs_type, qw(ext2 ext3 ext4)); + } else { + log::l("dropping LABEL=$part->{device_LABEL} since we don't know how to set labels for fs_type $fs_type"); + delete $part->{device_LABEL}; + delete $part->{prefer_device_LABEL}; + delete $part->{device_LABEL_changed}; + } + } +} + sub formatMount_part { my ($part, $all_hds, $fstab, $wait_message) = @_; @@ -157,15 +275,28 @@ sub formatMount_part { if (my $p = fs::get::up_mount_point($part->{mntpoint}, $fstab)) { formatMount_part($p, $all_hds, $fstab, $wait_message) if !fs::type::carry_root_loopback($part); } + + clean_label($part); + if ($part->{toFormat}) { fs::format::part($all_hds, $part, $wait_message); + } else { + fs::format::write_label($part); + } + + #- setting user_xattr on /home (or "/" if no /home) + if (!$part->{isMounted} && member($part->{fs_type}, qw(ext2 ext3 ext4)) + && ($part->{mntpoint} eq '/home' || + !fs::get::has_mntpoint('/home', $all_hds) && $part->{mntpoint} eq '/')) { + run_program::run('tune2fs', '-o', 'user_xattr', devices::make($part->{real_device} || $part->{device})); } + fs::mount::part($part, 0, $wait_message); } sub formatMount_all { my ($all_hds, $fstab, $wait_message) = @_; - formatMount_part($_, $all_hds, $fstab, $wait_message) + formatMount_part($_, $all_hds, $fstab, $wait_message) foreach sort { isLoopback($a) ? 1 : isSwap($a) ? -1 : 0 } grep { $_->{mntpoint} } @$fstab; #- ensure the link is there |
