#!/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)
# <imp@FreeBSD.ORG> 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 <<USAGE;
usage: diskprep [-config fn] disk
USAGE
exit 1;
}
# Parse the command line
sub parse {
local (@argv) = @_;
while ($_ = $argv[0], /^-/) {
shift @argv;
last if /^--$/;
if (/^--?(c|config)$/) { do $argv[0]; shift @argv }
elsif (/^--?(l|label)$/) { $label = $argv[0]; shift @argv }
else { &usage }
}
&usage if $#argv < 0;
$drive = $argv[0];
}
# If specified, apply a label to the disk, otherwise detroy any there.
sub label_disk {
my $dev = "/dev/${drive}";
if ($label ne "") {
system "glabel label $label $dev";
$drive = "label/$label"
} else {
system "glabel clear $dev"
}
}
# Nuke the disk and ask fdisk about the parameters
# we go the extra mile and dd zeros on the the first 64k. When we don't
# do this, we cannot actually boot the disk.
sub get_disk_params {
local($junk);
# Clear the drive so we can figure out how big it is.
$dev = "/dev/${drive}";
system "/bin/dd if=/dev/zero of=$dev count=128 > /dev/null 2>&1";
system "/sbin/fdisk -I $drive > /dev/null 2>&1";
exit ($?) if $?;
open FD, "/sbin/fdisk -s $drive |" || exit(1);
$_ = <FD>;
chop;
($junk, $cyl, $junk, $hd, $junk, $sec, $junk) = split;
$_ = <FD>;
chop;
$_ = <FD>;
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);
$_ = <FD>;
chop;
($junk, $cyl, $junk, $hd, $junk, $sec, $junk) = split;
$_ = <FD>;
chop;
while(<FD>) {
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;
syntax highlighted by Code2HTML, v. 0.9.1