#!/usr/local/bin/perl -w # $Aero: util/diskprep/diskprep.pl,v 1.8 2006/01/11 22:27:08 brooks Exp $ # # Simple program to prepare an entire disk, safely, to be a FreeBSD volume. # Derived from phk's prep.fla.sh, but converted to perl # # Copyright (c) 2000 M. Warner Losh. All Rights Reserved. # # "THE BEER-WARE LICENSE" (Revision 42): (stolen shamelessly from phk) # wrote this file. As long as you retain this notice you # can do whatever you want with this stuff. If we meet some day, and you think # this stuff is worth it, you can buy me a beer in return. Warner Losh. # use POSIX qw(floor); # make sure that we're root. sub check_root { die "You are not root!\n" if $<; } # set variables that can be overriden. They are overriden in files read # in by -config sub variables { $cyl = -1; $hd = -1; $sec = -1; $start = -1; $size = -1; $fsize = 512; $bsize = 4096; $cpg = 16; $all_part = 'c'; $fbsd_type = 165; $minfree = 8; $opt_perf = "time"; $label = ""; $slices{1}{active} = 1; $slices{1}{size} = "*"; $slices{1}{type} = $fbsd_type; $slices{1}{a}{size} = "*"; $slices{1}{a}{type} = "4.2BSD"; @slice_list = (1, 2, 3, 4); @parts = ("a", "b", "c", "d", "e", "f", "g", "h"); } # And how do I use this again? sub usage { warn < /dev/null 2>&1"; system "/sbin/fdisk -I $drive > /dev/null 2>&1"; exit ($?) if $?; open FD, "/sbin/fdisk -s $drive |" || exit(1); $_ = ; chop; ($junk, $cyl, $junk, $hd, $junk, $sec, $junk) = split; $_ = ; chop; $_ = ; chop; ($junk, $start, $size, $junk, $junk) = split; close FD; } # Inititalize the disk sub init_fdisk { local ($dev); foreach $s (@slice_list) { next unless(defined($slices{$s})); if ($slices{$s}{size} eq "*") { $hog_slice = $s; last; } } print "===> Initalizing slices\n"; if (defined($hog_slice)) { print "------> Hog slice is $hog_slice.\n"; } else { print "------> No hog slice given, hope that's right\n"; } open FD, "| /sbin/fdisk -i -f - $drive" || exit(1); $hog_size = $size; foreach $s (@slice_list) { next if ($s eq $hog_slice); $hog_size -= $slices{$s}{size} if (defined($slices{$s})); } $slices{$hog_slice}{size} = $hog_size; # Calc the slices $off = $start; foreach $s (@slice_list) { if (defined($slices{$s})) { $slices{$s}{offset} = $off; $off += $slices{$s}{size}; } } # dump the slices foreach $s (@slice_list) { if (defined($slices{$s})) { # print "p $s $slices{$s}{type} $slices{$s}{offset} $slices{$s}{size}\n"; print FD "p $s $slices{$s}{type} $slices{$s}{offset} $slices{$s}{size}\n"; # print "a $s\n" if (defined($slices{$s}{active}) && $slices{$s}{active}); print FD "a $s\n" if (defined($slices{$s}{active}) && $slices{$s}{active}); } } close FD; } sub update_sizes { print "===> Getting adjusting sizes\n"; open FD, "/sbin/fdisk -s $drive |" || exit(1); $_ = ; chop; ($junk, $cyl, $junk, $hd, $junk, $sec, $junk) = split; $_ = ; chop; while() { chop; ($slice, $start, $size, $junk, $junk) = split; $slice =~ s/(\d):/$1/; $slices{$slice}{size} = $size; $slices{$slice}{cyl} = floor($size/($hd*$sec)); print "------> slice $slice is $size sectors\n"; } close FD; } sub init_slices { foreach $s (@slice_list) { next unless(defined($slices{$s})); print "===> initializing slice $s\n"; if ($slices{$s}{type} == $fbsd_type and !defined($slices{$s}{action})) { init_disklabel($s); next; } if (defined($slices{$s}{action})) { $slices{$s}{action} =~ s%__DEVICE__%/dev/${drive}s$s%g; system $slices{$s}{action}; } } } # Fake up a disklabel based on what we know about the drive. sub init_disklabel { my $s = shift; local ($off); foreach $p (@parts) { next unless(defined($slices{$s}{$p})); if ($slices{$s}{$p}{size} eq "*") { $hog_part = $p; last; } } if (defined($hog_part)) { print "------> Hog partition is '$hog_part'\n"; } else { print "------> No hog partition given, hope that's right\n"; } open DL, "| /sbin/disklabel -R -r ${drive}s$s /dev/stdin"; print DL "# $drive\n"; $_ = $drive; if (/^fla/) { print DL "type: DOC2K\n"; } elsif (/^(ad|wd)/) { print DL "type: ESDI\n"; } elsif (/^(da)/) { print DL "type: SCSI\n"; } else { print DL "type: unknown\n"; } print DL "disk: $drive$s\n"; print DL "label: diskprep\n"; print DL "flags:\n"; print DL "bytes/sector: 512\n"; print DL "sectors/track: $sec\n"; print DL "tracks/cylinder: $hd\n"; print DL "sectors/cylinder: ", $sec*$hd, "\n"; print DL "cylinders: $slices{$s}{cyl}\n"; print DL "sectors/unit: $slices{$s}{size}\n"; print DL "rpm: 42000\n"; print DL "interleave: 1\n"; print DL "trackskew: 0\n"; print DL "cylinderskew: 0\n"; print DL "headswitch: 0\n"; print DL "track-to-track seek: 0\n"; print DL "drivedata: 0\n"; print DL "\n"; print DL "8 partitions:\n"; # Calc the hog size $hog_size = $slices{$s}{size}; foreach $p (@parts) { next if ($p eq $hog_part); next if ($p eq $all_part); $hog_size -= $slices{$s}{$p}{size} if (defined($slices{$s}{$p})); } $slices{$s}{$hog_part}{size} = $hog_size; # Calc 'c' partition. It is special. It is the whole slice $slices{$s}{c}{size} = $slices{$s}{size}; $slices{$s}{c}{offset} = 0; $slices{$s}{c}{type} = "unused"; # Calc the rest of the partitions $off = 0; foreach $p (@parts) { next if ($p eq $all_part); if (defined($slices{$s}{$p})) { $slices{$s}{$p}{offset} = $off; $off += $slices{$s}{$p}{size}; } } # Dump the partitions foreach $p (@parts) { if (defined($slices{$s}{$p})) { # print "$p: $slices{$s}{$p}{size} $slices{$s}{$p}{offset} $slices{$s}{$p}{type} $fsize $bsize $cpg\n"; print DL "$p: $slices{$s}{$p}{size} $slices{$s}{$p}{offset} $slices{$s}{$p}{type} $fsize $bsize $cpg\n"; } } close DL; # Label the disk! system "/sbin/disklabel -B -r $drive > /dev/null 2>&1"; } # Ah, what the heck, go ahead and newfs the partitions. sub newfs { local($d); my $l; foreach $s (@slice_list) { next unless (defined($slices{$s}) && $slices{$s}{type} == $fbsd_type); foreach $p (@parts) { next if ($p eq $all_part); next unless (defined($slices{$s}{$p})); $d = "/dev/${drive}s$s$p"; if ($slices{$s}{$p}{type} eq "4.2BSD") { system "/sbin/newfs -U $d"; system "/sbin/tunefs -o $opt_perf -m $minfree $d > /dev/null 2>&1"; if (defined($slices{$s}{$p}{label})) { $l = $slices{$s}{$p}{"label"}; system "/sbin/tunefs -L $l $d > /dev/null 2>&1"; } } elsif (defined($slices{$s}{$p}{"label"})) { $l = $slices{$s}{$p}{"label"}; system "glabel label $l $d"; } } } } # Start here &check_root; &variables; &parse(@ARGV); &label_disk; &get_disk_params; &init_fdisk; &update_sizes; &init_slices; &newfs;