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.pm187
1 files changed, 187 insertions, 0 deletions
diff --git a/perl-install/fsedit.pm b/perl-install/fsedit.pm
new file mode 100644
index 000000000..fb2703e8f
--- /dev/null
+++ b/perl-install/fsedit.pm
@@ -0,0 +1,187 @@
+package fsedit;
+
+use diagnostics;
+use strict;
+
+use common qw(:common);
+use partition_table qw(:types);
+use partition_table_raw;
+use devices;
+use log;
+
+1;
+
+my @suggestions = (
+ { mntpoint => "/boot", minsize => 10 << 11, size => 16 << 11, type => 0x83 },
+ { mntpoint => "/", minsize => 50 << 11, size => 100 << 11, type => 0x83 },
+ { mntpoint => "swap", minsize => 30 << 11, size => 60 << 11, type => 0x82 },
+ { mntpoint => "/usr", minsize => 200 << 11, size => 500 << 11, type => 0x83 },
+ { mntpoint => "/home", minsize => 50 << 11, size => 200 << 11, type => 0x83 },
+ { mntpoint => "/var", minsize => 200 << 11, size => 250 << 11, type => 0x83 },
+ { mntpoint => "/tmp", minsize => 50 << 11, size => 100 << 11, type => 0x83 },
+ { mntpoint => "/mnt/iso", minsize => 700 << 11, size => 800 << 11, type => 0x83 },
+);
+
+
+1;
+
+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 die "An error occurred while getting the geometry of block device $file: $!";
+ $hd->{file} = $file;
+ $hd->{prefix} = $hd->{device} = $_->{device};
+ # for RAID arrays of format c0d0p1
+ $hd->{prefix} .= "p" if $hd->{prefix} =~ m,(rd|ida)/,;
+
+ eval { $rc = partition_table::read($hd, $flags->{clearall}) };
+ if ($@) {
+ $@ =~ /bad magic number/ or die;
+ $flags->{forcezero} && !$::testing ? partition_table_raw::zero_MBR($hd) : die;
+ }
+ $rc ? push @hds, $hd : log::l("An error occurred reading the partition table for the block device $_->{device}");
+ }
+ [ @hds ];
+}
+
+sub get_fstab(@) {
+ map { partition_table::get_normal_parts($_) } @_;
+}
+
+sub suggest_part($$$;$) {
+ my ($hd, $part, $hds, $suggestions) = @_;
+ $suggestions ||= \@suggestions;
+ foreach (@$suggestions) { $_->{minsize} ||= $_->{size} }
+
+ my $has_swap;
+ my @mntpoints = map { $has_swap ||= isSwap($_); $_->{mntpoint} } get_fstab(@$hds);
+ my %mntpoints; @mntpoints{@mntpoints} = undef;
+
+ my ($best, $second) =
+ grep { $part->{size} >= $_->{minsize} }
+ grep { !exists $mntpoints{$_->{mntpoint}} || isSwap($_) && !$has_swap }
+ @$suggestions or return;
+
+ $best = $second if
+ $best->{mntpoint} eq '/boot' &&
+ $part->{start} + $best->{minsize} > 1024 * partition_table::cylinder_size($hd); # if the empty slot is beyond the 1024th cylinder, no use having /boot
+
+ defined $best or return; # sorry no suggestion :(
+
+ $part->{mntpoint} = $best->{mntpoint};
+ $part->{type} = $best->{type};
+ $part->{size} = min($part->{size}, $best->{size});
+ 1;
+}
+
+
+#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 checkMountPoint($$) {
+# my $type = shift;
+# local $_ = shift;
+#
+# m|^/| or die "The mount point $_ is illegal.\nMount points must begin with a leading /";
+# m|(.)/$| and die "The mount point $_ is illegal.\nMount points may not end with a /";
+# c::isprint($_) or die "The mount point $_ is illegal.\nMount points must be made of printable characters (no accents...)";
+#
+# foreach my $dev (qw(/dev /bin /sbin /etc /lib)) {
+# /^$dev/ and die "The $_ directory must be on the root filesystem.",
+# }
+#
+# if ($type eq 'linux_native') {
+# $_ eq '/'; and return 1;
+# foreach my $r (qw(/var /tmp /boot /root)) {
+# /^$r/ and return 1;
+# }
+# die "The mount point $_ is illegal.\nSystem partitions must be on Linux Native partitions";
+# }
+# 1;
+}
+
+sub removeFromList($$$) {
+ my ($start, $end, $list) = @_;
+ my $err = "error in removeFromList: removing an non-free block";
+
+ for (my $i = 0; $i < @$list; $i += 2) {
+ $start < $list->[$i] and die $err;
+ $start > $list->[$i + 1] and next;
+
+ if ($start == $list->[$i]) {
+ $end > $list->[$i + 1] and die $err;
+ if ($end == $list->[$i + 1]) {
+ # the free block is just the same size, removing it
+ splice(@$list, 0, 2);
+ } else {
+ # the free block now start just after this block
+ $list->[$i] = $end;
+ }
+ } else {
+ $end <= $list->[$i + 1] or die $err;
+ if ($end < $list->[$i + 1]) {
+ splice(@$list, $i + 2, 0, $end, $list->[$i + 1]);
+ }
+ $list->[$i + 1] = $start; # shorten the free block
+ }
+ return;
+ }
+}
+
+
+sub allocatePartitions($$) {
+ my ($hds, $to_add) = @_;
+ my %free_sectors = map { $_->{device} => [1, $_->{totalsectors} ] } @$hds; # first sector is always occupied by the MBR
+ my $remove = sub { removeFromList($_->{start}, $_->{start} + $_->{size}, $free_sectors{$_->{rootDevice}}) };
+ my $success = 0;
+
+ foreach (get_fstab(@$hds)) { &$remove(); }
+
+ FSTAB: foreach (@$to_add) {
+ foreach my $hd (@$hds) {
+ my $v = $free_sectors{$hd->{device}};
+ for (my $i = 0; $i < @$v; $i += 2) {
+ my $size = $v->[$i + 1] - $v->[$i];
+ $_->{size} > $size and next;
+ $_->{start} = $v->[$i];
+ $_->{rootDevice} = $hd->{device};
+ partition_table::adjustStartAndEnd($hd, $_);
+ &$remove();
+ partition_table::add($hd, $_);
+ $success++;
+ next FSTAB;
+ }
+ }
+ log::ld("can't allocate partition $_->{mntpoint} of size $_->{size}, not enough room");
+ }
+ $success;
+}
+
+sub auto_allocate($;$) {
+ my ($hds, $suggestions) = @_;
+ allocatePartitions($hds, $suggestions || \@suggestions);
+ map { partition_table::assign_device_numbers($_) } @$hds;
+}