summaryrefslogtreecommitdiffstats
path: root/perl-install/fsedit.pm
diff options
context:
space:
mode:
Diffstat (limited to 'perl-install/fsedit.pm')
-rw-r--r--perl-install/fsedit.pm1006
1 files changed, 453 insertions, 553 deletions
diff --git a/perl-install/fsedit.pm b/perl-install/fsedit.pm
index 8dda77319..d209b0196 100644
--- a/perl-install/fsedit.pm
+++ b/perl-install/fsedit.pm
@@ -1,378 +1,383 @@
-package fsedit; # $Id$
+package fsedit;
use diagnostics;
use strict;
use vars qw(%suggestions);
+use feature 'state';
#-######################################################################################
#- misc imports
#-######################################################################################
use common;
-use partition_table qw(:types);
+use partition_table;
use partition_table::raw;
+use fs::get;
+use fs::type;
+use fs::loopback;
+use fs::proc_partitions;
use detect_devices;
-use fsedit;
use devices;
-use loopback;
use log;
use fs;
+# min_hd_size: only suggest this partition if the hd size is bigger than that
%suggestions = (
- __("simple") => [
- { mntpoint => "/", size => 300 << 11, type =>0x483, ratio => 5, maxsize =>3500 << 11 },
- { mntpoint => "swap", size => 64 << 11, type => 0x82, ratio => 1, maxsize => 250 << 11 },
- { mntpoint => "/home", size => 300 << 11, type =>0x483, ratio => 3 },
- ], __("with /usr") => [
- { mntpoint => "/", size => 150 << 11, type =>0x483, ratio => 1, maxsize => 500 << 11 },
- { mntpoint => "swap", size => 64 << 11, type => 0x82, ratio => 1, maxsize => 250 << 11 },
- { mntpoint => "/usr", size => 300 << 11, type =>0x483, ratio => 4, maxsize =>3000 << 11 },
- { mntpoint => "/home", size => 100 << 11, type =>0x483, ratio => 3 },
- ], __("server") => [
- { mntpoint => "/", size => 150 << 11, type =>0x483, ratio => 1, maxsize => 250 << 11 },
- { mntpoint => "swap", size => 64 << 11, type => 0x82, ratio => 2, maxsize => 400 << 11 },
- { mntpoint => "/usr", size => 300 << 11, type =>0x483, ratio => 4, maxsize =>3000 << 11 },
- { mntpoint => "/var", size => 150 << 11, type =>0x483, ratio => 3 },
- { mntpoint => "/home", size => 150 << 11, type =>0x483, ratio => 3 },
- { mntpoint => "/tmp", size => 150 << 11, type =>0x483, ratio => 2, maxsize => 500 << 11 },
+ N_("simple") => [
+ { mntpoint => "/", size => MB(300), fs_type => defaultFS(), ratio => 6, maxsize => MB(51500) },
+ { mntpoint => "swap", size => MB(256), fs_type => 'swap', ratio => 1, maxsize => MB(4096) },
+ { mntpoint => "/home", size => MB(300), fs_type => defaultFS(), ratio => 12, min_hd_size => MB(51200) },
+ ], N_("with /usr") => [
+ { mntpoint => "/", size => MB(250), fs_type => defaultFS(), ratio => 1, maxsize => MB(8000) },
+ { mntpoint => "swap", size => MB(64), fs_type => 'swap', ratio => 1, maxsize => MB(4000) },
+ { mntpoint => "/usr", size => MB(300), fs_type => defaultFS(), ratio => 4, maxsize => MB(8000) },
+ { mntpoint => "/home", size => MB(100), fs_type => defaultFS(), ratio => 3, min_hd_size => MB(10000) },
+ ], N_("server") => [
+ { mntpoint => "/", size => MB(150), fs_type => defaultFS(), ratio => 1, maxsize => MB(8000) },
+ { mntpoint => "swap", size => MB(64), fs_type => 'swap', ratio => 2, maxsize => MB(4000) },
+ { mntpoint => "/usr", size => MB(300), fs_type => defaultFS(), ratio => 4, maxsize => MB(8000) },
+ { mntpoint => "/var", size => MB(200), fs_type => defaultFS(), ratio => 3 },
+ { mntpoint => "/home", size => MB(150), fs_type => defaultFS(), ratio => 3, min_hd_size => MB(10000) },
+ { mntpoint => "/tmp", size => MB(150), fs_type => defaultFS(), ratio => 2, maxsize => MB(4000) },
],
);
-foreach (values %suggestions) {
- if (arch() =~ /ia64/) {
- @$_ = ({ mntpoint => "/boot/efi", size => 50 << 11, type => 0xb, ratio => 1, maxsize => 150 << 11 }, @$_);
+my %bck_suggestions = %suggestions;
+
+sub init_mntpnt_suggestions {
+ my ($all_hds, $o_target, $o_force) = @_;
+
+ my $device = $o_target ? $o_target->{device} : 'all';
+ state $last_device;
+ return if $device eq $last_device && !$o_force;
+ $last_device = $device;
+
+ #- If installing on a removable device, assume that the user wants that device to be self-bootable.
+ my $is_removable = $o_target && $o_target->{is_removable};
+ my @fstab = $is_removable ? partition_table::get_normal_parts($o_target) : fs::get::fstab($all_hds);
+
+ my $mntpoint;
+ # only suggests /boot/EFI if there's not already one:
+ require fs::any;
+ if (is_uefi()) {
+ if (!any { isESP($_) } @fstab) {
+ $mntpoint = { mntpoint => "/boot/EFI", size => MB(100), pt_type => 0xef, ratio => 1, maxsize => MB(300) };
+ }
+ }
+ foreach (keys %suggestions) {
+ $suggestions{$_} = [ if_($mntpoint, $mntpoint), @{$bck_suggestions{$_}} ];
}
}
my @suggestions_mntpoints = (
- "/var/ftp", "/var/www", "/boot",
- arch() =~ /sparc/ ? "/mnt/sunos" : arch() =~ /ppc/ ? "/mnt/macos" : "/mnt/windows",
- #- RedHat also has /usr/local and /opt
-);
-
-my @partitions_signatures = (
- [ 0x8e, 0, "HM\1\0" ],
- [ 0x83, 0x438, "\x53\xEF" ],
- [ 0x183, 0x10034, "ReIsErFs" ],
- [ 0x183, 0x10034, "ReIsEr2Fs" ],
- [ 0x283, 0, 'XFSB', 0x200, 'XAGF', 0x400, 'XAGI' ],
- [ 0x383, 0x8000, 'JFS1' ],
- [ 0x82, 4086, "SWAP-SPACE" ],
- [ 0x82, 4086, "SWAPSPACE2" ],
- [ 0x7, 0x1FE, "\x55\xAA", 0x3, "NTFS" ],
- [ 0xc, 0x1FE, "\x55\xAA", 0x52, "FAT32" ],
-arch() !~ /^sparc/ ? (
- [ 0x6, 0x1FE, "\x55\xAA", 0x36, "FAT" ],
-) : (),
+ "/var/ftp", "/var/www", "/boot", '/usr/local', '/opt',
+ "/mnt/windows",
);
-sub typeOfPart {
- my $dev = devices::make($_[0]);
- my $t = typeFromMagic($dev, @partitions_signatures);
- if ($t == 0x83) {
- #- there is no magic to differentiate ext3 and ext2. Using libext2fs
- #- to check if it has a journal
- $t = 0x483 if c::is_ext3($dev);
- }
- $t;
-}
-
#-######################################################################################
#- Functions
#-######################################################################################
-sub empty_all_hds {
- { hds => [], lvms => [], raids => [], loopbacks => [], raw_hds => [], nfss => [], smbs => [], davs => [], special => [] };
-}
sub recompute_loopbacks {
my ($all_hds) = @_;
- my @fstab = get_all_fstab($all_hds);
+ my @fstab = fs::get::fstab($all_hds);
@{$all_hds->{loopbacks}} = map { isPartOfLoopback($_) ? @{$_->{loopback}} : () } @fstab;
}
sub raids {
- my ($hds) = @_;
+ my ($hds, $raw_hds) = @_;
- my @parts = get_fstab(@$hds);
- {
- my @l = grep { isRawRAID($_) } @parts or return [];
- detect_devices::raidAutoStart(@l);
- }
+ my @parts = fs::get::hds_fstab(@$hds);
- fs::get_major_minor(@parts);
- my %devname2part = map { $_->{dev} => { %$_, device => $_->{dev} } } read_partitions();
-
- my @raids;
- my @mdstat = cat_("/proc/mdstat");
- for (my $i = 0; $i < @mdstat; $i++) {
-
- my ($nb, $level, $mdparts) =
- #- line format is:
- #- md%d : {in}?active{ (read-only)}? {linear|raid1|raid4|raid5}{ DEVNAME[%d]{(F)}?}*
- $mdstat[$i] =~ /^md(.).* ([^ \[\]]+) (\S+\[\d+\].*)/ or next;
-
- $level =~ s/raid//; #- { linear | raid0 | raid1 | raid5 } -> { linear | 0 | 1 | 5 }
-
- my $chunks = $mdstat[$i+1] =~ /(\S+) chunks/ ? $1 : "64k";
-
- my @raw_mdparts = map { /([^\[]+)/ } split ' ', $mdparts;
- my @mdparts =
- map {
- my $mdpart = $devname2part{$_} || { device => $_ };
- if (my ($part) = grep { is_same_hd($mdpart, $_) } @parts) {
- $part->{raid} = $nb;
- delete $part->{mntpoint};
- $part;
- } else {
- #- forget it when not found? that way it won't break much... beurk.
- ();
- }
- } @raw_mdparts;
-
- my $type = typeOfPart("md$nb");
- log::l("RAID: found md$nb (raid $level) chunks $chunks ", if_($type, "type $type "), "with parts ", join(", ", @raw_mdparts));
- $raids[$nb] = { 'chunk-size' => $chunks, type => $type || 0x83, disks => \@mdparts,
- device => "md$nb", notFormatted => !$type, level => $level };
- }
+ my @l = grep { isRawRAID($_) } ( @parts, @$raw_hds ) or return [];
+
+ log::l("looking for raids in " . join(' ', map { $_->{device} } @l));
+
require raid;
- raid::update(@raids);
- \@raids;
+ raid::detect_during_install(@l) if $::isInstall;
+ raid::get_existing(@l);
}
-sub hds {
- my ($drives, $flags) = @_;
- my (@hds);
- my $rc;
-
- foreach (@$drives) {
- my $file = devices::make($_->{device});
-
- my $hd = partition_table::raw::get_geometry($file) or log::l("An error occurred while getting the geometry of block device $file: $!"), next;
- add2hash_($hd, $_);
- $hd->{file} = $file;
- $hd->{prefix} = $hd->{device};
- # for RAID arrays of format c0d0p1
- $hd->{prefix} .= "p" if $hd->{prefix} =~ m,(rd|ida|cciss|ataraid)/,;
-
- eval { partition_table::read($hd, $flags->{clearall} || member($_->{device}, @{$flags->{clear} || []})) };
- if ($@) {
- cdie "ask_before_blanking:$@";
- partition_table::raw::zero_MBR($hd);
- }
- member($_->{device}, @{$flags->{clear} || []}) and partition_table::remove($hd, $_)
- foreach partition_table::get_normal_parts($hd);
+sub dmcrypts {
+ my ($all_hds) = @_;
- # special case for Various type
- $_->{type} = typeOfPart($_->{device}) || 0x100 foreach grep { $_->{type} == 0x100 } partition_table::get_normal_parts($hd);
+ my @parts = fs::get::fstab($all_hds);
- #- special case for type overloading (eg: reiserfs is 0x183)
- foreach (grep { isExt2($_) } partition_table::get_normal_parts($hd)) {
- my $type = typeOfPart($_->{device});
- $_->{type} = $type if $type > 0x100 || $type && $hd->isa('partition_table::gpt');
- }
- push @hds, $hd;
- }
- #- detect raids before LVM allowing LVM on raid
- my $raids = raids(\@hds);
- my $all_hds = { %{ empty_all_hds() }, hds => \@hds, lvms => [], raids => $raids };
+ my @l = grep { fs::type::isRawLUKS($_) } @parts or return;
+
+ log::l("using dm-crypt from " . join(' ', map { $_->{device} } @l));
+
+ require fs::dmcrypt;
+ fs::dmcrypt::read_crypttab($all_hds);
+
+ fs::dmcrypt::get_existing(@l);
+}
+
+sub lvms {
+ my ($all_hds) = @_;
+ my @pvs = grep { isRawLVM($_) } fs::get::fstab($all_hds) or return;
+ scan_pvs(@pvs);
+}
+
+sub scan_pvs {
+ my (@pvs) = @_;
+
+ log::l("looking for vgs in " . join(' ', map { $_->{device} } @pvs));
+
+ #- otherwise vgscan will not find them
+ devices::make($_->{device}) foreach @pvs;
+ require lvm;
my @lvms;
- if (my @pvs = grep { isRawLVM($_) } get_all_fstab($all_hds)) {
- #- otherwise vgscan won't find them
- devices::make($_->{device}) foreach @pvs;
- require lvm;
- foreach (@pvs) {
- my $name = lvm::get_vg($_) or next;
- my ($lvm) = grep { $_->{VG_name} eq $name } @lvms;
- if (!$lvm) {
- $lvm = bless { disks => [], VG_name => $name }, 'lvm';
- lvm::update_size($lvm);
- lvm::get_lvs($lvm);
- push @lvms, $lvm;
- }
- $_->{lvm} = $name;
- push @{$lvm->{disks}}, $_;
+ foreach (@pvs) {
+ my $name = lvm::pv_to_vg($_) or next;
+ my $lvm = find { $_->{VG_name} eq $name } @lvms;
+ if (!$lvm) {
+ $lvm = new lvm($name);
+ lvm::update_size($lvm);
+ lvm::get_lvs($lvm);
+ push @lvms, $lvm;
}
+ $_->{lvm} = $name;
+ push @{$lvm->{disks}}, $_;
}
- $all_hds->{lvms} = \@lvms;
+ @lvms;
+}
- fs::get_major_minor(get_all_fstab($all_hds));
+sub handle_dmraid {
+ my ($drives, $o_in) = @_;
- $all_hds;
-}
+ @$drives > 1 or return;
+
+ devices::make($_->{device}) foreach @$drives;
+
+ require fs::dmraid;
+ eval { fs::dmraid::init() } or log::l("dmraid::init failed"), return;
+
+ my @vgs = fs::dmraid::vgs();
+ log::l(sprintf('dmraid: ' . join(' ', map { "$_->{device} [" . join(' ', @{$_->{disks}}) . "]" } @vgs)));
+
+ if ($o_in && @vgs && $::isInstall) {
+ @vgs = grep {
+ $o_in->ask_yesorno('', N("BIOS software RAID detected on disks %s. Activate it?", join(' ', @{$_->{disks}})), 1);
+ } @vgs or do {
+ fs::dmraid::call_dmraid('-an');
+ return;
+ };
+ }
+ if (!$::isInstall) {
+ fs::dmraid::migrate_device_names($_) foreach @vgs;
+ }
+ log::l("using dmraid on " . join(' ', map { $_->{device} } @vgs));
+
+ my @used_hds = map {
+ my $part = fs::get::device2part($_, $drives) or log::l("handle_dmraid: can't find $_ in known drives");
+ if_($part, $part);
+ } map { @{$_->{disks}} } @vgs;
+ @$drives = difference2($drives, \@used_hds);
-sub read_partitions() {
- my (undef, undef, @all) = cat_("/proc/partitions");
- grep {
- $_->{size} != 1 && # skip main extended partition
- $_->{size} != 0x3fffffff # skip cdroms (otherwise stops cd-audios)
- } map {
- my %l;
- @l{qw(major minor size dev)} = split;
- \%l;
- } @all;
+ push @$drives, @vgs;
}
-sub readProcPartitions {
- my ($hds) = @_;
+sub get_hds {
+ my ($o_flags, $o_in) = @_;
+ my $flags = $o_flags || {};
+ $flags->{readonly} && ($flags->{clearall} || $flags->{clear}) and die "conflicting flags readonly and clear/clearall";
+
+ my @drives = detect_devices::hds();
- my @all = read_partitions();
- my @parts = grep { $_->{dev} =~ /\d$/ } @all;
- my @disks = grep { $_->{dev} !~ /\d$/ } @all;
+ #- replace drives used in dmraid by the merged name
+ handle_dmraid(\@drives, $o_in) if !$flags->{nodmraid};
- my $devfs_like = grep { $_->{dev} =~ m|/disc$| } @disks;
+ foreach my $hd (@drives) {
+ $hd->{file} = devices::make($hd->{device});
+ }
- my %devfs2normal = map {
- my (undef, $major, $minor) = devices::entry($_->{device});
- my ($disk) = grep { $_->{major} == $major && $_->{minor} == $minor } @disks;
- $disk->{dev} => $_->{device};
- } @$hds;
+ @drives = partition_table::raw::get_geometries(@drives);
+
+ my (@hds, @raw_hds);
+ foreach my $hd (@drives) {
+ $hd->{readonly} = $flags->{readonly};
+
+ #- We only create RAID components in disk partitions, but users may have used
+ #- mdadm directly to create them on raw disk devices. Detect that now, before
+ #- looking for a partition table (which is likely to fail badly - mga#26707).
+ if (my $type = fs::type::type_subpart_from_magic($hd)) {
+ if (isRawRAID($type)) {
+ #- Add the necessary information to the raw device to allow the RAID
+ #- array to be properly characterised in diskdrake.
+ put_in_hash($hd, $type);
+ $hd->{size} = $hd->{totalsectors};
+ push @raw_hds, $hd;
+ next;
+ }
+ }
- foreach my $part (@parts) {
- my $dev;
- if ($devfs_like) {
- $dev = -e "/dev/$part->{dev}" ? $part->{dev} : sprintf("0x%x%02x", $part->{major}, $part->{minor});
- $part->{rootDevice} = $devfs2normal{dirname($part->{dev}) . '/disc'};
+ eval { partition_table::raw::test_for_bad_drives($hd) if !$flags->{no_bad_drives} };
+ if (my $err = $@) {
+ log::l("test_for_bad_drives returned $err");
+ if ($err =~ /write error:/) {
+ log::l("setting $hd->{device} readonly");
+ $hd->{readonly} = 1;
+ } elsif ($err =~ /read error:/) {
+ next;
+ } else {
+ $o_in and $o_in->ask_warn('', $err);
+ next;
+ }
+ }
+
+ if ($flags->{clearall} || member($hd->{device}, @{$flags->{clear} || []})) {
+ my $lvms = []; #- temporary one, will be re-created later in get_hds()
+ partition_table_clear_and_initialize($lvms, $hd, $o_in);
} else {
- $dev = $part->{dev};
- foreach my $hd (@$hds) {
- $part->{rootDevice} = $hd->{device} if $part->{dev} =~ /^$hd->{device}./;
+ my $handle_die_and_cdie = sub {
+ if (my $type = fs::type::type_subpart_from_magic($hd)) {
+ #- non partitioned drive?
+ if (exists $hd->{usb_description} && $type->{fs_type}) {
+ #- USB keys
+ put_in_hash($hd, $type);
+ push @raw_hds, $hd;
+ $hd = '';
+ 1;
+ } else {
+ 0;
+ }
+ } elsif ($hd->{readonly}) {
+ log::l("using /proc/partitions since diskdrake failed :(");
+ fs::proc_partitions::use_($hd);
+ 1;
+ } else {
+ 0;
+ }
+ };
+ my $handled;
+ eval {
+ catch_cdie {
+ partition_table::read($hd);
+ if (listlength(partition_table::get_normal_parts($hd)) == 0) {
+ $handled = 1 if $handle_die_and_cdie->();
+ } elsif ($::isInstall) {
+ if (fs::type::is_dmraid($hd)) {
+ if (my $p = find { ! -e "/dev/$_->{device}" } partition_table::get_normal_parts($hd)) {
+ #- dmraid should have created the device, so it means we don't agree
+ die sprintf(q(bad dmraid (missing partition %s), you may try rebooting install with option "nodmraid"), $p->{device});
+ }
+ } else {
+ fs::proc_partitions::compare($hd) if !detect_devices::is_xbox();
+ }
+ }
+ } sub {
+ my $err = $@;
+ if ($handle_die_and_cdie->()) {
+ $handled = 1;
+ 0; #- do not continue, transform cdie into die
+ } else {
+ !$o_in || $o_in->ask_okcancel('', formatError($err));
+ }
+ };
+ };
+ if (my $err = $@) {
+ if ($handled) {
+ #- already handled in cdie handler above
+ } elsif ($handle_die_and_cdie->()) {
+ } elsif ($o_in && $o_in->ask_yesorno(N("Error"),
+N("I cannot read the partition table of device %s, it's too corrupted for me :(
+I can try to go on, erasing over bad partitions (ALL DATA will be lost!).
+The other solution is to not allow DrakX to modify the partition table.
+(the error is %s)
+
+Do you agree to lose all the partitions?
+", $hd->{device}, formatError($err)))) {
+ partition_table::raw::zero_MBR($hd);
+ } else {
+ #- using it readonly
+ log::l("using /proc/partitions since diskdrake failed :(");
+ fs::proc_partitions::use_($hd);
+ }
}
+ $hd or next;
+
+ member($_->{device}, @{$flags->{clear} || []}) and partition_table::remove($hd, $_)
+ foreach partition_table::get_normal_parts($hd);
}
- $part->{device} = $dev;
- $part->{start} = 0; # unknown, but we don't care
- $part->{size} *= 2; # from KB to sectors
- $part->{type} = typeOfPart($dev);
- delete $part->{dev}; # cleanup
- }
- @parts;
-}
+ my @parts = partition_table::get_normal_parts($hd);
-sub all_hds {
- my ($all_hds) = @_;
- (@{$all_hds->{hds}}, @{$all_hds->{lvms}});
-}
-sub part2hd {
- my ($part, $all_hds) = @_;
- my ($hd) = grep { $part->{rootDevice} eq ($_->{device} || $_->{VG_name}) } all_hds($all_hds);
- $hd;
-}
+ # fix installer failures due to udev's race when run too early:
+ run_program::run('udevadm', 'settle');
-sub is_same_hd {
- my ($hd1, $hd2) = @_;
- if ($hd1->{major} && $hd2->{major}) {
- $hd1->{major} == $hd2->{major} && $hd1->{minor} == $hd2->{minor};
- } else {
- $hd1->{device} eq $hd2->{device};
- }
-}
+ # checking the magic of the filesystem, do not rely on pt_type
+ foreach (@parts) {
+ if (my $type = fs::type::type_subpart_from_magic($_)) {
+ $type->{pt_type} = $_->{pt_type}; #- keep {pt_type}
+ put_in_hash($_, $type);
+ } else {
+ $_->{bad_fs_type_magic} = 1;
+ }
+ }
-sub is_same_part {
- my ($part1, $part2) = @_;
- foreach ('start', 'size', 'type', 'rootDevice') {
- $part1->{$_} eq $part2->{$_} or return;
+ if ($hd->{usb_media_type}) {
+ $hd->{is_removable} = 1;
+ $_->{is_removable} = 1 foreach @parts;
+ }
+
+ push @hds, $hd;
}
- 1;
-}
-#- get all normal partition including special ones as found on sparc.
-sub get_fstab {
- map { partition_table::get_normal_parts($_) } @_;
-}
+ #- detect raids before LVM allowing LVM on raid
+ my $raids = raids(\@hds, \@raw_hds);
+ my $all_hds = { %{ fs::get::empty_all_hds() }, hds => \@hds, raw_hds => \@raw_hds, lvms => [], raids => $raids };
-#- get normal partition that should be visible for working on.
-sub get_visible_fstab {
- grep { $_ && !partition_table::isWholedisk($_) && !partition_table::isHiddenMacPart($_) }
- map { partition_table::get_normal_parts($_) } @_;
-}
+ $all_hds->{lvms} = [ lvms($all_hds) ];
-sub get_fstab_and_holes {
- map {
- if (isLVM($_)) {
- my @parts = partition_table::get_normal_parts($_);
- my $free = $_->{totalsectors} - sum map { $_->{size} } @parts;
- my $free_part = { start => 0, size => $free, type => 0, rootDevice => $_->{VG_name} };
- @parts, if_($free >= $_->cylinder_size, $free_part);
- } else {
- partition_table::get_normal_parts_and_holes($_);
- }
- } @_;
-}
-sub get_holes {
- grep { $_->{type} == 0 } get_fstab_and_holes(@_);
-}
+ fs::get_major_minor([ fs::get::fstab($all_hds) ]);
-sub get_all_fstab {
- my ($all_hds) = @_;
- my @parts = map { partition_table::get_normal_parts($_) } all_hds($all_hds);
- my @raids = grep { $_ } @{$all_hds->{raids}};
- @parts, @raids, @{$all_hds->{loopbacks}};
-}
-sub get_really_all_fstab {
- my ($all_hds) = @_;
- my @parts = map { partition_table::get_normal_parts($_) } all_hds($all_hds);
- my @raids = grep { $_ } @{$all_hds->{raids}};
- @parts, @raids, @{$all_hds->{loopbacks}}, @{$all_hds->{raw_hds}}, @{$all_hds->{nfss}}, @{$all_hds->{smbs}}, @{$all_hds->{davs}};
-}
-sub get_all_fstab_and_holes {
- my ($all_hds) = @_;
- my @raids = grep { $_ } @{$all_hds->{raids}};
- get_fstab_and_holes(all_hds($all_hds)), @raids, @{$all_hds->{loopbacks}};
-}
-sub get_all_holes {
- my ($all_hds) = @_;
- grep { $_->{type} == 0 } get_all_fstab_and_holes($all_hds);
-}
+ # must be done after getting major/minor
+ $all_hds->{dmcrypts} = [ dmcrypts($all_hds) ];
+ # allow lvm on dmcrypt
+ $all_hds->{lvms} = [ lvms($all_hds) ];
-sub all_free_space {
- my ($all_hds) = @_;
- sum map { $_->{size} } get_all_holes($all_hds);
+ $_->{faked_device} = 0 foreach fs::get::fstab($all_hds);
+
+ $all_hds;
}
-sub free_space {
- sum map { $_->{size} } get_holes(@_);
+
+#- are_same_partitions() do not look at the device name since things may have changed
+sub are_same_partitions {
+ my ($part1, $part2) = @_;
+ foreach ('start', 'size', 'pt_type', 'fs_type', 'rootDevice') {
+ $part1->{$_} eq $part2->{$_} or return 0;
+ }
+ 1;
}
-sub is_one_big_fat {
+sub is_one_big_fat_or_NT {
my ($hds) = @_;
- @$hds == 1 or return;
+ @$hds == 1 or return 0;
- my @l = get_fstab(@$hds);
- @l == 1 && isFat($l[0]) && free_space(@$hds) < 10 << 11;
-}
-
-sub file2part {
- my ($fstab, $file, $keep_simple_symlinks) = @_;
- my $part;
-
- $file = $keep_simple_symlinks ? common::expand_symlinks_but_simple("$::prefix$file") : expand_symlinks("$::prefix$file");
- unless ($file =~ s/^$::prefix//) {
- my ($part) = grep { loopback::carryRootLoopback($_) } @$fstab or die;
- log::l("found $part->{mntpoint}");
- $file =~ s|/initrd/loopfs|$part->{mntpoint}|;
- }
- foreach (@$fstab) {
- my $m = $_->{mntpoint};
- $part = $_ if
- $file =~ /^\Q$m/ &&
- (!$part || length $part->{mntpoint} < length $m);
- }
- $part or die "file2part: not found $file";
- $file =~ s|$part->{mntpoint}/?|/|;
- ($part, $file);
+ my @l = fs::get::hds_fstab(@$hds);
+ @l == 1 && isFat_or_NTFS($l[0]) && fs::get::hds_free_space(@$hds) < MB(10);
}
sub computeSize {
- my ($part, $best, $all_hds, $suggestions) = @_;
+ my ($part, $best, $all_hds, $suggestions, $o_target) = @_;
my $max = $part->{maxsize} || $part->{size};
return min($max, $best->{size}) unless $best->{ratio};
- my $free_space = all_free_space($all_hds);
- my @l = my @L = grep {
- if (!has_mntpoint($_->{mntpoint}, $all_hds) && $free_space >= $_->{size}) {
- $free_space -= $_->{size};
+ my %free_space;
+ $free_space{$_->{rootDevice}} += $_->{size} foreach fs::get::holes($all_hds);
+
+ my @l = my @L = grep {
+ my @possible = $_->{hd} ? $_->{hd} : keys %free_space;
+ my $size = $_->{size};
+ if (my $dev = find { $free_space{$_} >= $size } @possible) {
+ $free_space{$dev} -= $size;
1;
} else { 0 } } @$suggestions;
+ my $free_space = $o_target && $free_space{$o_target->{device}} || $best->{hd} && $free_space{$best->{hd}} || sum(values %free_space);
+
+ my $cylinder_size_maxsize_adjusted;
my $tot_ratios = 0;
while (1) {
my $old_free_space = $free_space;
@@ -386,6 +391,9 @@ sub computeSize {
$_->{size} + $_->{ratio} / $tot_ratios * $old_free_space >= $_->{maxsize}) {
return min($max, $best->{maxsize}) if $best->{mntpoint} eq $_->{mntpoint};
$free_space -= $_->{maxsize} - $_->{size};
+ if (!$cylinder_size_maxsize_adjusted++) {
+ eval { $free_space += fs::get::part2hd($part, $all_hds)->cylinder_size - 1 };
+ }
0;
} else {
$_->{ratio};
@@ -394,123 +402,95 @@ sub computeSize {
}
my $size = int min($max, $best->{size} + $free_space * ($tot_ratios && $best->{ratio} / $tot_ratios));
#- verify other entry can fill the hole
- if (grep { $_->{size} < $max - $size } @L) { $size } else { $max }
+ (any { $_->{size} <= $max - $size } @L) ? $size : $max;
}
sub suggest_part {
- my ($part, $all_hds, $suggestions) = @_;
- $suggestions ||= $suggestions{server} || $suggestions{simple};
+ my ($part, $all_hds, $o_suggestions, $o_target) = @_;
+ my $suggestions = $o_suggestions || $suggestions{server} || $suggestions{simple};
+
+ #- suggestions now use {fs_type}, but still keep compatibility
+ foreach (@$suggestions) {
+ fs::type::set_pt_type($_, $_->{pt_type}) if !exists $_->{fs_type};
+ }
- my $has_swap = grep { isSwap($_) } get_all_fstab($all_hds);
+ my $hd = fs::get::part2hd($part, $all_hds);
+ my $hd_size = $hd && $hd->{totalsectors}; # nb: no $hd if $part is /dev/mdX
+ my @fstab = $hd->{is_removable} ? partition_table::get_normal_parts($hd) : fs::get::fstab($all_hds);
+ my $has_swap = any { isSwap($_) } @fstab;
- my ($best, $second) =
- grep { !$_->{maxsize} || $part->{size} <= $_->{maxsize} }
- grep { $_->{size} <= ($part->{maxsize} || $part->{size}) }
- grep { !has_mntpoint($_->{mntpoint}, $all_hds) || isSwap($_) && !$has_swap }
+ my @local_suggestions =
+ grep { $::auto_install || !$_->{mntpoint} && !$_->{VG_name} || !fs::get::has_mntpoint($_->{mntpoint}, $all_hds) || isSwap($_) && !$has_swap }
+ grep { !$_->{min_hd_size} || !$hd_size || $_->{min_hd_size} <= $hd_size }
grep { !$_->{hd} || $_->{hd} eq $part->{rootDevice} }
- grep { !$part->{type} || $part->{type} == $_->{type} || isTrueFS($part) && isTrueFS($_) }
- @$suggestions or return;
+ @$suggestions;
+
+ #- this allows specifying the size using a relative size.
+ #- one should rather use {ratio} instead
+ foreach (@local_suggestions) {
+ if ($_->{percent_size} && $_->{percent_size} =~ /(.+?)%?$/) {
+ $_->{size} = $1 / 100 * $hd_size;
+ log::l("in suggestion, setting size=$_->{size} for percent_size=$_->{percent_size}");
+ }
+ }
-#- if (arch() =~ /i.86/) {
-#- $best = $second if
-#- $best->{mntpoint} eq '/boot' &&
-#- $part->{start} + $best->{size} > 1024 * $hd->cylinder_size(); #- if the empty slot is beyond the 1024th cylinder, no use having /boot
-#- }
+ my ($best) =
+ grep { !$_->{maxsize} || $part->{size} <= $_->{maxsize} }
+ grep { $_->{size} <= ($part->{maxsize} || $part->{size}) }
+ grep { !$part->{fs_type} || $part->{fs_type} eq $_->{fs_type} || isTrueFS($part) && isTrueFS($_) }
+ @local_suggestions;
- defined $best or return; #- sorry no suggestion :(
+ defined $best or return 0; #- sorry no suggestion :(
$part->{mntpoint} = $best->{mntpoint};
- $part->{type} = $best->{type} if !(isTrueFS($best) && isTrueFS($part));
- $part->{size} = computeSize($part, $best, $all_hds, $suggestions);
- $part->{options} = $best->{options} if $best->{options};
- 1;
+ fs::type::set_type_subpart($part, $best) if !isTrueFS($best) || !isTrueFS($part);
+ $part->{size} = computeSize($part, $best, $all_hds, \@local_suggestions, $o_target);
+ foreach ('options', 'lv_name', 'encrypt_key', 'primaryOrExtended',
+ 'device_LABEL', 'prefer_device_LABEL', 'device_UUID', 'prefer_device_UUID', 'prefer_device') {
+ $part->{$_} = $best->{$_} if $best->{$_};
+ }
+ $best;
}
sub suggestions_mntpoint {
my ($all_hds) = @_;
- sort grep { !/swap/ && !has_mntpoint($_, $all_hds) }
+ sort grep { !/swap/ && !fs::get::has_mntpoint($_, $all_hds) }
(@suggestions_mntpoints, map { $_->{mntpoint} } @{$suggestions{server} || $suggestions{simple}});
}
-#-sub partitionDrives {
-#-
-#- my $cmd = "/sbin/fdisk";
-#- -x $cmd or $cmd = "/usr/bin/fdisk";
-#-
-#- my $drives = findDrivesPresent() or die "You don't have any hard drives available! You probably forgot to configure a SCSI controller.";
-#-
-#- foreach (@$drives) {
-#- my $text = "/dev/" . $_->{device};
-#- $text .= " - SCSI ID " . $_->{id} if $_->{device} =~ /^sd/;
-#- $text .= " - Model " . $_->{info};
-#- $text .= " array" if $_->{device} =~ /^c.d/;
-#-
-#- #- truncate at 50 columns for now
-#- $text = substr $text, 0, 50;
-#- }
-#- #-TODO TODO
-#-}
-
-
-sub mntpoint2part {
- my ($mntpoint, $fstab) = @_;
- first(grep { $mntpoint eq $_->{mntpoint} } @$fstab);
-}
-sub has_mntpoint {
- my ($mntpoint, $all_hds) = @_;
- mntpoint2part($mntpoint, [ get_really_all_fstab($all_hds) ]);
-}
-sub get_root_ {
- my ($fstab, $boot) = @_;
- $boot && mntpoint2part("/boot", $fstab) || mntpoint2part("/", $fstab);
-}
-sub get_root { &get_root_ || {} }
+#- you can do this before modifying $part->{mntpoint}
+#- so $part->{mntpoint} should not be used here, use $mntpoint instead
+sub check_mntpoint {
+ my ($mntpoint, $part, $all_hds) = @_;
-#- do this before modifying $part->{type}
-sub check_type {
- my ($type, $hd, $part) = @_;
- isThisFs("jfs", { type => $type }) && $part->{size} < 16 << 11 and die _("You can't use JFS for partitions smaller than 16MB");
- isThisFs("reiserfs", { type => $type }) && $part->{size} < 32 << 11 and die _("You can't use ReiserFS for partitions smaller than 32MB");
-}
+ $mntpoint eq '' || isSwap($part) || isNonMountable($part) and return 0;
+ $mntpoint =~ m|^/| or die N("Mount points must begin with a leading /");
+ $mntpoint =~ m|[\x7f-\xff]| and cdie N("Mount points should contain only alphanumerical characters");
+ fs::get::mntpoint2part($mntpoint, [ grep { $_ ne $part } fs::get::really_all_fstab($all_hds) ]) and die N("There is already a partition with mount point %s\n", $mntpoint);
-sub package_needed_for_partition_type {
- my ($part) = @_;
- my %l = (
- reiserfs => 'reiserfsprogs',
- xfs => 'xfsprogs',
- jfs => 'jfsprogs',
- );
- $l{type2fs($part)};
-}
+ if ($mntpoint eq "/" && (isLUKS($part) || isRawLUKS($part)) && !fs::get::has_mntpoint("/boot", $all_hds)) {
+ cdie N("You've selected an encrypted partition as root (/).
+No bootloader is able to handle this without a /boot partition.
+Please be sure to add a separate /boot partition");
+ }
-#- do this before modifying $part->{mntpoint}
-#- $part->{mntpoint} should not be used here, use $mntpoint instead
-sub check_mntpoint {
- my ($mntpoint, $hd, $part, $all_hds) = @_;
-
- $mntpoint eq '' || isSwap($part) || isNonMountable($part) and return;
- $mntpoint =~ m|^/| or die _("Mount points must begin with a leading /");
- $mntpoint ne $part->{mntpoint} && has_mntpoint($mntpoint, $all_hds) and die _("There is already a partition with mount point %s\n", $mntpoint);
-
- die "raid / with no /boot"
- if $mntpoint eq "/" && isRAID($part) && !has_mntpoint("/boot", $all_hds);
- die _("You can't use a LVM Logical Volume for mount point %s", $mntpoint)
- if ($mntpoint eq '/' || $mntpoint eq '/boot') && isLVM($hd);
- die _("This directory should remain within the root filesystem")
- if member($mntpoint, qw(/bin /dev /etc /lib /sbin /root /mnt));
- die _("You need a true filesystem (ext2/ext3, reiserfs, xfs, or jfs) for this mount point\n")
- if !isTrueFS($part) && member($mntpoint, qw(/ /home /tmp /usr /var));
- die _("You can't use an encrypted file system for mount point %s", $mntpoint)
- if $part->{options} =~ /encrypted/ && member($mntpoint, qw(/ /usr /var));
+ if ($mntpoint eq "/boot" && (isLUKS($part) || isRawLUKS($part))) {
+ die N("You cannot use an encrypted filesystem for mount point %s", "/boot");
+ }
- local $part->{mntpoint} = $mntpoint;
- loopback::check_circular_mounts($hd, $part, $all_hds);
-}
+ cdie N("This directory should remain within the root filesystem")
+ if member($mntpoint, qw(/root));
+ die N("This directory should remain within the root filesystem")
+ if member($mntpoint, qw(/bin /dev /etc /lib /sbin /mnt /media));
+ die N("You need a true filesystem (ext2/3/4, reiserfs, xfs, or jfs) for this mount point\n")
+ if !isTrueLocalFS($part) && $mntpoint eq '/';
+ die N("You need a true filesystem (ext2/3/4, reiserfs, xfs, or jfs) for this mount point\n") . $mntpoint
+ if !isTrueFS($part) && member($mntpoint, '/home', fs::type::directories_needed_to_boot_not_ESP());
+ die N("You cannot use an encrypted filesystem for mount point %s", $mntpoint)
+ if $part->{options} =~ /encrypted/ && member($mntpoint, qw(/ /usr /var /boot));
-sub check {
- my ($hd, $part, $all_hds) = @_;
- check_mntpoint($part->{mntpoint}, $hd, $part, $all_hds);
- check_type($part->{type}, $hd, $part);
+ local $part->{mntpoint} = $mntpoint;
+ fs::loopback::check_circular_mounts($part, $all_hds);
}
sub add {
@@ -518,7 +498,7 @@ sub add {
isSwap($part) ?
($part->{mntpoint} = 'swap') :
- $options->{force} || check_mntpoint($part->{mntpoint}, $hd, $part, $all_hds);
+ $options->{force} || check_mntpoint($part->{mntpoint}, $part, $all_hds);
delete $part->{maxsize};
@@ -527,32 +507,44 @@ sub add {
} else {
partition_table::add($hd, $part, $options->{primaryOrExtended});
}
+ fs::get_major_minor([ $part ]);
}
sub allocatePartitions {
- my ($all_hds, $to_add) = @_;
-
- foreach my $part (get_all_holes($all_hds)) {
- my ($start, $size, $dev) = @$part{"start", "size", "rootDevice"};
- my $part;
- while (suggest_part($part = { start => $start, size => 0, maxsize => $size, rootDevice => $dev },
- $all_hds, $to_add)) {
- my ($hd) = fsedit::part2hd($part, $all_hds);
- add($hd, $part, $all_hds);
+ my ($all_hds, $to_add, $o_hd) = @_;
+
+ my @to_add = @$to_add;
+
+ foreach my $part_ (fs::get::holes($all_hds, 'non_readonly')) {
+ my ($start, $size, $dev) = @$part_{"start", "size", "rootDevice"};
+ next if $o_hd && (($o_hd->{device} || $o_hd->{VG_name}) ne $dev);
+ my ($part, $suggested);
+ while ($suggested = suggest_part($part = { start => $start, size => 0, maxsize => $size, rootDevice => $dev },
+ $all_hds, \@to_add, $o_hd)) {
+ my $hd = fs::get::part2hd($part, $all_hds);
+ add($hd, $part, $all_hds, { primaryOrExtended => $part->{primaryOrExtended} });
$size -= $part->{size} + $part->{start} - $start;
$start = $part->{start} + $part->{size};
+ @to_add = grep { $_ != $suggested } @to_add;
}
}
}
sub auto_allocate {
- my ($all_hds, $suggestions) = @_;
- my $before = listlength(fsedit::get_all_fstab($all_hds));
+ my ($all_hds, $o_suggestions, $o_target) = @_;
+ my $before = listlength(fs::get::fstab($all_hds));
+
+ #- Make sure we don't finish with more than one /boot/EFI mount point
+ if (is_uefi()) {
+ delete $_->{mntpoint} foreach grep { $_->{mntpoint} eq '/boot/EFI' } fs::get::fstab($all_hds);
+ }
- my $suggestions_ = $suggestions || $suggestions{simple};
- allocatePartitions($all_hds, $suggestions_);
+ auto_allocate_bios_boot_parts($all_hds, $o_target) if !is_uefi();
- if ($suggestions) {
+ my $suggestions = $o_suggestions || $suggestions{simple};
+ allocatePartitions($all_hds, $suggestions, $o_target);
+
+ if ($o_suggestions) {
auto_allocate_raids($all_hds, $suggestions);
if (auto_allocate_vgs($all_hds, $suggestions)) {
#- allocatePartitions needs to be called twice, once for allocating PVs, once for allocating LVs
@@ -564,49 +556,73 @@ sub auto_allocate {
partition_table::assign_device_numbers($_) foreach @{$all_hds->{hds}};
- if ($before == listlength(fsedit::get_all_fstab($all_hds))) {
+ if ($before == listlength(fs::get::fstab($all_hds))) {
# find out why auto_allocate failed
- if (my @l = grep { !has_mntpoint($_->{mntpoint}, $all_hds) } @$suggestions_) {
- die _("Not enough free space for auto-allocating");
+ if (any { !fs::get::has_mntpoint($_->{mntpoint}, $all_hds) } @$suggestions) {
+ die N("Not enough free space for auto-allocating");
} else {
- die _("Nothing to do");
+ die N("Nothing to do");
}
}
+
+ #- Don't suggest mount points on other drives when installing on a removable disk
+ return if $o_target && $o_target->{is_removable};
+
+ my @fstab = fs::get::fstab($all_hds);
+ fs::mount_point::suggest_mount_points_always(\@fstab);
+}
+
+sub auto_allocate_bios_boot_parts {
+ my ($all_hds, $o_hd) = @_;
+ foreach my $hd (@{$all_hds->{hds}}) {
+ # skip if not the selected device
+ next if $o_hd && ($o_hd->{device} ne $hd->{device});
+ # skip non-GPT disks
+ next if ($hd->{pt_table_type} || partition_table::default_type($hd)) ne 'gpt';
+ # check if a BIOS boot partition already exists
+ my @parts = map { partition_table::get_normal_parts($_) } $hd;
+ next if any { isBIOS_GRUB($_) } @parts;
+ # try to allocate a BIOS boot partition
+ my $suggest = { mntpoint => "", size => MB(1), pt_type => 'BIOS_GRUB', ratio => 1, maxsize => MB(2) };
+ allocatePartitions($all_hds, [ $suggest ], $hd);
+ }
}
sub auto_allocate_raids {
my ($all_hds, $suggestions) = @_;
- my @raids = grep { isRawRAID($_) } get_all_fstab($all_hds) or return;
+ my @raids = grep { isRawRAID($_) } fs::get::fstab($all_hds) or return;
require raid;
my @mds = grep { $_->{hd} =~ /md/ } @$suggestions;
foreach my $md (@mds) {
my @raids_ = grep { !$md->{parts} || $md->{parts} =~ /\Q$_->{mntpoint}/ } @raids;
@raids = difference2(\@raids, \@raids_);
- my $nb = raid::new($all_hds->{raids}, @raids_);
- my $part = $all_hds->{raids}[$nb];
my %h = %$md;
- delete @h{'hd', 'parts'};
- put_in_hash($part, \%h); # mntpoint, level, chunk-size, type
+ delete @h{'hd', 'parts'}; # keeping mntpoint, level, chunk-size, fs_type/pt_type
+ $h{disks} = \@raids_;
+
+ my $part = raid::new($all_hds->{raids}, %h);
+
raid::updateSize($part);
+ push @raids, $part; #- we can build raid over raid
}
}
sub auto_allocate_vgs {
my ($all_hds, $suggestions) = @_;
- my @pvs = grep { isRawLVM($_) } get_all_fstab($all_hds) or return;
+ my @pvs = grep { isRawLVM($_) } fs::get::fstab($all_hds) or return 0;
- my @vgs = grep { $_->{VG_name} } @$suggestions or return;
+ my @vgs = grep { $_->{VG_name} } @$suggestions or return 0;
- partition_table::write(@{$all_hds->{hds}});
+ partition_table::write($_) foreach @{$all_hds->{hds}};
require lvm;
foreach my $vg (@vgs) {
- my $lvm = bless { disks => [], VG_name => $vg->{VG_name} }, 'lvm';
+ my $lvm = new lvm($vg->{VG_name});
push @{$all_hds->{lvms}}, $lvm;
my @pvs_ = grep { !$vg->{parts} || $vg->{parts} =~ /\Q$_->{mntpoint}/ } @pvs;
@@ -624,154 +640,38 @@ sub auto_allocate_vgs {
1;
}
-sub undo_prepare {
- my ($all_hds) = @_;
- require Data::Dumper;
- $Data::Dumper::Purity = 1;
- foreach (@{$all_hds->{hds}}) {
- my @h = @{$_}{@partition_table::fields2save};
- push @{$_->{undo}}, Data::Dumper->Dump([\@h], ['$h']);
- }
-}
-sub undo {
- my ($all_hds) = @_;
- foreach (@{$all_hds->{hds}}) {
- my $h; eval pop @{$_->{undo}} || next;
- @{$_}{@partition_table::fields2save} = @$h;
-
- $_->{isDirty} = $_->{needKernelReread} = 1 if $_->{hasBeenDirty};
- }
-
-}
-
-sub move {
- my ($hd, $part, $hd2, $sector2) = @_;
-
- die 'TODO'; # doesn't work for the moment
- my $part1 = { %$part };
- my $part2 = { %$part };
- $part2->{start} = $sector2;
- $part2->{size} += $hd2->cylinder_size() - 1;
- partition_table::remove($hd, $part);
- {
- local ($part2->{notFormatted}, $part2->{isFormatted}); #- do not allow partition::add to change this
- partition_table::add($hd2, $part2);
- }
-
- return if $part2->{notFormatted} && !$part2->{isFormatted} || $::testing;
-
- local (*F, *G);
- sysopen F, $hd->{file}, 0 or die '';
- sysopen G, $hd2->{file}, 2 or die _("Error opening %s for writing: %s", $hd2->{file}, "$!");
-
- my $base = $part1->{start};
- my $base2 = $part2->{start};
- my $step = 10;
- if ($hd eq $hd2) {
- $base == $base2 and return;
- $step = min($step, abs($base2 - $base));
-
- if ($base < $base2) {
- $base += $part1->{size} - $step;
- $base2 += $part1->{size} - $step;
- $step = -$step;
- }
- }
-
- my $f = sub {
- $base < 0 and $base2 += -$base, $base = 0;
- $base2 < 0 and $base += -$base2, $base2 = 0;
- c::lseek_sector(fileno(F), $base, 0) or die "seeking to sector $base failed on drive $hd->{device}";
- c::lseek_sector(fileno(G), $base2, 0) or die "seeking to sector $base2 failed on drive $hd2->{device}";
-
- my $buf;
- sysread F, $buf, $SECTORSIZE * abs($_[0]) or die '';
- syswrite G, $buf;
- };
-
- for (my $i = 0; $i < $part1->{size} / abs($step); $i++, $base += $step, $base2 += $step) {
- print "$base $base2\n";
- &$f($step);
- }
- if (my $v = ($part1->{size} % abs($step)) * sign($step)) {
- $base += $v;
- $base2 += $v;
- &$f($v);
- }
-}
-
sub change_type {
my ($type, $hd, $part) = @_;
- $type != $part->{type} or return;
- check_type($type, $hd, $part);
+ $type->{pt_type} != $part->{pt_type} || $type->{fs_type} ne $part->{fs_type} or return;
+ fs::type::check($type->{fs_type}, $hd, $part);
+ delete $part->{device_UUID};
$hd->{isDirty} = 1;
$part->{mntpoint} = '' if isSwap($part) && $part->{mntpoint} eq "swap";
- $part->{mntpoint} = '' if isRawLVM({ type => $type }) || isRawRAID({ type => $type });
- $part->{type} = $type;
- $part->{notFormatted} = 1;
- $part->{isFormatted} = 0;
-}
-
-sub rescuept($) {
- my ($hd) = @_;
- my ($ext, @hd);
-
- my $dev = devices::make($hd->{device});
- local *F; open F, "rescuept $dev|";
- local $_;
- while (<F>) {
- my ($st, $si, $id) = /start=\s*(\d+),\s*size=\s*(\d+),\s*Id=\s*(\d+)/ or next;
- my $part = { start => $st, size => $si, type => hex($id) };
- if (isExtended($part)) {
- $ext = $part;
- } else {
- push @hd, $part;
- }
- }
- close F or die "rescuept failed";
-
- partition_table::raw::zero_MBR($hd);
- foreach (@hd) {
- my $b = partition_table::verifyInside($_, $ext);
- if ($b) {
- $_->{start}--;
- $_->{size}++;
- }
- local $_->{notFormatted};
-
- partition_table::add($hd, $_, ($b ? 'Extended' : 'Primary'), 1);
- }
+ $part->{mntpoint} = '' if fs::type::cannotBeMountable($part);
+ set_isFormatted($part, 0);
+ fs::type::set_type_subpart($part, $type);
+ fs::mount_options::rationalize($part);
+ 1;
}
-sub verifyHds {
- my ($hds, $readonly, $ok) = @_;
+=item partition_table_clear_and_initialize($lvms, $hd, $o_in, $o_type, $b_warn) = @_;
- if (is_empty_array_ref($hds)) { #- no way
- die _("An error occurred - no valid devices were found on which to create new filesystems. Please check your hardware for the cause of this problem");
- }
+wrapper around partition_table::initialize() but which also create a singleton VG
+automatically (so that it's easier for the user)
- my @parts = readProcPartitions($hds);
- foreach my $hd (@$hds) {
- my @l1 = partition_table::get_normal_parts($hd);
- my @l2 = grep { $_->{rootDevice} eq $hd->{device} } @parts;
- if (int(@l1) != int(@l2) && arch() ne 'ppc') {
- log::l(sprintf
- "/proc/partitions doesn't agree with drakx %d != %d:\n%s\n", int(@l1), int(@l2),
- "/proc/partitions: " . join(", ", map { "$_->{device} ($_->{rootDevice})" } @parts));
- $ok = 0;
- }
- }
+=cut
- if ($readonly && !$ok) {
- log::l("using /proc/partitions as diskdrake failed :(");
- foreach my $hd (@$hds) {
- partition_table::raw::zero_MBR($hd);
- $hd->{primary} = { normal => [ grep { $hd->{device} eq $_->{rootDevice} } @parts ] };
+sub partition_table_clear_and_initialize {
+ my ($lvms, $hd, $o_in, $o_type, $b_warn) = @_;
+ partition_table::initialize($hd, $o_type);
+ if ($hd->isa('partition_table::lvm')) {
+ if ($b_warn && $o_in) {
+ $o_in->ask_okcancel_('', N("ALL existing partitions and their data will be lost on drive %s", partition_table::description($hd))) or return;
}
- $ok = 1;
+ require lvm;
+ lvm::check($o_in ? $o_in->do_pkgs : do_pkgs_standalone->new) if $::isStandalone;
+ lvm::create_singleton_vg($lvms, fs::get::hds_fstab($hd));
}
- $readonly && get_fstab(@$hds) == 0 and die _("You don't have any partitions!");
- $ok;
}
1;