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.pm208
1 files changed, 113 insertions, 95 deletions
diff --git a/perl-install/fsedit.pm b/perl-install/fsedit.pm
index a46049d8a..9765da02e 100644
--- a/perl-install/fsedit.pm
+++ b/perl-install/fsedit.pm
@@ -97,7 +97,7 @@ sub raids {
}
fs::get_major_minor(@parts);
- my %devname2part = map { $_->{dev} => { %$_, device => $_->{dev} } } read_partitions();
+ my %devname2part = map { $_->{dev} => { %$_, device => $_->{dev} } } read_proc_partitions_raw();
my @raids;
my @mdstat = cat_("/proc/mdstat");
@@ -136,28 +136,76 @@ sub raids {
\@raids;
}
+sub lvms {
+ my ($all_hds) = @_;
+ my @pvs = grep { isRawLVM($_) } get_all_fstab($all_hds) or return;
+
+ #- otherwise vgscan won't find them
+ devices::make($_->{device}) foreach @pvs;
+ require lvm;
+
+ my @lvms;
+ 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}}, $_;
+ }
+ @lvms;
+}
+
sub hds {
- my ($drives, $flags) = @_;
+ my ($flags, $ask_before_blanking) = @_;
+ $flags ||= {};
+ $flags->{readonly} && ($flags->{clearall} || $flags->{clear}) and die "conflicting flags readonly and clear/clearall";
+
+ my @drives = detect_devices::hds();
+
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);
+ foreach my $hd (@drives) {
+ $hd->{file} = devices::make($hd->{device});
+ $hd->{prefix} ||= $hd->{device};
+ $hd->{readonly} = $flags->{readonly};
+
+ my $h = partition_table::raw::get_geometry($hd->{file}) or log::l("An error occurred while getting the geometry of block device $hd->{file}: $!"), next;
+ add2hash_($hd, $h);
+
+ eval { partition_table::raw::test_for_bad_drives($hd) if $::isInstall };
+ if (my $err = $@) {
+ if ($err =~ /write error:/) {
+ $hd->{readonly} = 1;
+ } else {
+ cdie $err if $err !~ /read error:/;
+ next;
+ }
+ }
+
+ if ($flags->{clearall} || member($hd->{device}, @{$flags->{clear} || []})) {
+ partition_table::raw::zero_MBR_and_dirty($hd);
+ } else {
+ eval {
+ partition_table::read($hd);
+ compare_with_proc_partitions($hd) if $::isInstall;
+ };
+ if (my $err = $@) {
+ if ($hd->{readonly}) {
+ use_proc_partitions($hd);
+ } elsif ($ask_before_blanking && $ask_before_blanking->($hd->{device}, $err)) {
+ partition_table::raw::zero_MBR($hd);
+ } else {
+ #- using it readonly
+ use_proc_partitions($hd);
+ }
+ }
+ member($_->{device}, @{$flags->{clear} || []}) and partition_table::remove($hd, $_)
+ foreach partition_table::get_normal_parts($hd);
}
- member($_->{device}, @{$flags->{clear} || []}) and partition_table::remove($hd, $_)
- foreach partition_table::get_normal_parts($hd);
# special case for Various type
$_->{type} = typeOfPart($_->{device}) || 0x100 foreach grep { $_->{type} == 0x100 } partition_table::get_normal_parts($hd);
@@ -169,37 +217,40 @@ sub hds {
}
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 @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}}, $_;
- }
- }
- $all_hds->{lvms} = \@lvms;
+ $all_hds->{lvms} = [ lvms($all_hds) ];
fs::get_major_minor(get_all_fstab($all_hds));
$all_hds;
}
+sub get_hds {
+ #- $in is optional
+ my ($flags, $in) = @_;
+
+ if ($in) {
+ catch_cdie { hds($flags, sub {
+ my ($dev, $err) = @_;
+ $in->ask_yesorno(_("Error"),
+_("I can't 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 loose all the partitions?
+", $dev, formatError($err)));
+ }) } sub { $in->ask_okcancel('', formatError($@)) };
+ } else {
+ catch_cdie { hds($flags) } sub { 1 }
+ }
+}
-sub read_partitions() {
+sub read_proc_partitions_raw() {
my (undef, undef, @all) = cat_("/proc/partitions");
grep {
$_->{size} != 1 && # skip main extended partition
@@ -211,10 +262,10 @@ sub read_partitions() {
} @all;
}
-sub readProcPartitions {
+sub read_proc_partitions {
my ($hds) = @_;
- my @all = read_partitions();
+ my @all = read_proc_partitions_raw();
my @parts = grep { $_->{dev} =~ /\d$/ } @all;
my @disks = grep { $_->{dev} !~ /\d$/ } @all;
@@ -226,6 +277,7 @@ sub readProcPartitions {
$disk->{dev} => $_->{device};
} @$hds;
+ my $prev_part;
foreach my $part (@parts) {
my $dev;
if ($devfs_like) {
@@ -238,10 +290,10 @@ sub readProcPartitions {
}
}
$part->{device} = $dev;
- $part->{start} = 0; # unknown, but we don't care
$part->{size} *= 2; # from KB to sectors
$part->{type} = typeOfPart($dev);
-
+ $part->{start} = $prev_part ? $prev_part->{start} + $prev_part->{size} : 0;
+ $prev_part = $part;
delete $part->{dev}; # cleanup
}
@parts;
@@ -411,12 +463,6 @@ sub suggest_part {
grep { !$part->{type} || $part->{type} == $_->{type} || isTrueFS($part) && isTrueFS($_) }
@$suggestions or return;
-#- 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
-#- }
-
defined $best or return; #- sorry no suggestion :(
$part->{mntpoint} = $best->{mntpoint};
@@ -432,26 +478,6 @@ sub suggestions_mntpoint {
(@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);
@@ -743,35 +769,27 @@ sub rescuept($) {
}
}
-sub verifyHds {
- my ($hds, $readonly, $ok) = @_;
+sub compare_with_proc_partitions {
+ my ($hd) = @_;
- 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");
+ my @l1 = partition_table::get_normal_parts($hd);
+ my @l2 = grep { $_->{rootDevice} eq $hd->{device} } read_proc_partitions([$hd]);
+
+ if (int(@l1) != int(@l2) && arch() ne 'ppc') {
+ die sprintf(
+ "/proc/partitions doesn't agree with drakx %d != %d:\n%s\n", int(@l1), int(@l2),
+ "/proc/partitions: " . join(", ", map { "$_->{device} ($_->{rootDevice})" } @l2));
}
+ int @l2;
+}
- 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;
- }
- }
+sub use_proc_partitions {
+ my ($hd) = @_;
- 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 ] };
- }
- $ok = 1;
- }
- $readonly && get_fstab(@$hds) == 0 and die _("You don't have any partitions!");
- $ok;
+ log::l("using /proc/partitions since diskdrake failed :(");
+ partition_table::raw::zero_MBR($hd);
+ $hd->{readonly} = 1;
+ $hd->{primary} = { normal => [ grep { $_->{rootDevice} eq $hd->{device} } read_proc_partitions([$hd]) ] };
}
1;