5484l2 Listing 2. make.fdisk #! /usr/bin/perl # A perl script to create a script and input file for fdisk to # re-create the partitions on the hard disk, and format the Linux and # Linux swap partitions. The first parameter is the fully qualified # path of the device of the hard disk, e.g. /dev/hda. The two # resulting files are the script make.dev.x and the data file dev.x # (where x is the hard drive described, e.g. hda, sdc). make.dev.x is # run at restore time to rebuild hard drive x, prior to running # restore.metadata. dev.x is the input file for fdisk. # Time-stamp: <2001-09-18 09:37:46 ccurley make.fdisk> # Copyright 2001 Charles Curley except for the subroutine cut2fmt. # cut2fmt Copyright (c) 1998 Tom Christiansen, Nathan Torkington and # O'Reilly & Associates, Inc. Permission is granted to use this code # freely EXCEPT for book publication. You may use this code for book # publication only with the explicit permission of O'Reilly & # Associates, Inc. # This program is free software; you can redistribute it and/or modify it # under the terms of the GNU General Public License as published by the # Free Software Foundation; either version 2 of the License, or (at your # option) any later version. # This program is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # General Public License for more details. # You should have received a copy of the GNU General Public License along # with this program; if not, write to the Free Software Foundation, Inc., # 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # In addition, as a special exception, Tom Christiansen, Nathan # Torkington and O'Reilly & Associates, Inc. give permission to use # the code of this program with the subroutine cut2fmt (or with # modified versions of the subroutine cut2fmt that use the same # license as the subroutine cut2fmt), and distribute linked # combinations including the two. You must obey the GNU General # Public License in all respects for all of the code used other than # the subroutine cut2fmt. If you modify this file, you may extend # this exception to your version of the file, but you are not # obligated to do so. If you do not wish to do so, delete this # exception statement and the subroutine cut2fmt from your version. # You can also contact the Free Software Foundation at http://www.fsf.org/ # fdisk will spit out a file of the form below if you run it as "fdisk # -l". # root@tester ~/bin $ fdisk -l /dev/hda # Disk /dev/hda: 64 heads, 63 sectors, 1023 cylinders # Units = cylinders of 4032 * 512 bytes # Device Boot Start End Blocks Id System # /dev/hda1 1 9 18112+ 83 Linux # /dev/hda2 10 1023 2044224 5 Extended # /dev/hda5 10 368 723712+ 83 Linux # /dev/hda6 369 727 723712+ 83 Linux # /dev/hda7 728 858 264064+ 83 Linux # /dev/hda8 859 989 264064+ 83 Linux # /dev/hda9 990 1022 66496+ 82 Linux swap # What fdisk does not do is provide output suitable for later # importing into fdisk, a la sfdisk. This script parses the output # from fdisk and creates an input file for fdisk. Use the input file # like so: # fdisk /dev/hdx < dev.hdx # For the bare metal restore package, this script also builds a script # that will execute the above command so you can run it from your zip # disk. Because the bare metal restore scripts all are in /root/bin, # the data file and script created by this script are also placed # there. The same script also creates appropriate Linux file systems, # either ext2fs, or Linux swap. There is limited support for FAT12 and # FAT16. There is no support right now (hint, hint) for FAT32. For # anything else, you're on your own. # Bad block checking right now is a quick read of the partition. A # writing check is also possible; add a -w to each command. You # probably don't need it for a new hard drive, but if you have had a # hard drive crash on you and you are reusing it (while you are # waiting for its replacement to come in, I presume), then I highly # recommend it. # For more information contact the author, Charles Curley, at # http://w3.trib.com/~ccurley/. # cut2fmt figures out the format string for the unpack function we use # to slice and dice the output from fdisk. From Christiansen and # Torkington, Perl Cookbook 5. sub cut2fmt { my (@positions) = @_; my $template = ''; my $lastpos = 1; foreach $place (@positions) { $template .= "A" . ($place - $lastpos) . " "; $lastpos = $place; } $template .= "A*"; return $template; } # prepare format string. $fmt = cut2fmt (11, 19, 24, 34, 45, 49); # print "Format string is $fmt.\n\n"; # define fields in the array @_. $dev = 0; $bootable = 1; $firstcyl = 2; $lastcyl = 3; $parttype = 5; $partstring = 6; $target = "\/target"; $device = $ARGV[0]; $outputfilename = $device; $outputfilename =~ s/\//./g; $outputfilename = substr ($outputfilename, 1, 100); $outputfilepath = "\/root\/bin\/"; # Make a hash of the labels. $mpid = open (MOUNT, "mount -l |") or die "Couldn't fork: $!\n"; while () { if ($_ =~ /^$device/i) { # is this a line with a partition in it? # print $_; # print it just for grins split; if ($_[6] ne "") { # only process if there actually is a label $_[6] =~ s/[[\]]//g; # strike [ and ]. $labels{$_[0]} = $_[6]; # print "The label of file device $_[0] is $labels{$_[0]}.\n"; } # We only mount if it's ext2fs and read and write. if ($_[4] eq "ext2" and $_[5] eq "(rw)" ) { $mountpoints{$_[2]} = $_[0]; # print "$_[2] is the mountpoint for $mountpoints{$_[2]}.\n"; } } } close (MOUNT); $fpid = open (FDISK, "fdisk -l $device |") or die "Couldn't fork: $!\n"; open (OUTPUT, "> $outputfilepath${outputfilename}") or die "Couldn't open output file $outputfilepath${outputfilename}.\n"; while () { if ($_ =~ /^$device/i) { # is this a line with a partition in it? # print $_; # print it just for grins chop; # kill trailing \r @_ = unpack ($fmt, $_); # now strip white spaces from cylinder numbers @_[$firstcyl] =~ s/[ \t]+//; @_[$lastcyl] =~ s/[ \t]+//; @_[$parttype] =~ s/[ \t]+//; $partnumber = substr(@_[$dev], 8, 10); # get partition number for this line # print " $partnumber, @_[$firstcyl], @_[$lastcyl], @_[$partstring]\n"; # just for grins # Here we start creating the input to recreate the partition # this line represents. print OUTPUT "n\n"; if ($partnumber < 5) { # primary Linux partition if (@_[$parttype] == 83) { print OUTPUT "p\n$partnumber\n@_[$firstcyl]\n"; if (@_[$firstcyl] ne @_[$lastcyl]) { # in case it's all on one cylinder print OUTPUT "@_[$lastcyl]\n"; } if ($labels{@_[$dev]}) { # do we have a label? # $format .= "mke2fs @_[$dev] -L $labels{@_[$dev]}\n"; # no bad block check $format .= "echo\necho formatting and checking @_[$dev]\nbadblocks -c 128 -o /tmp/$outputfilename$partnumber @_[$dev]\nmke2fs -L $labels{@_[$dev]} -l /tmp/$outputfilename$partnumber @_[$dev]\n\n"; } else { # $format .= "mke2fs @_[$dev]\n"; # no bad block check $format .= "echo\necho formatting and checking @_[$dev]\nbadblocks -c 128 -o /tmp/$outputfilename$partnumber @_[$dev]\nmke2fs -l /tmp/$outputfilename$partnumber @_[$dev]\n\n"; } # extended partition } elsif (@_[$parttype] == 5) { print OUTPUT "e\n$partnumber\n@_[$firstcyl]\n"; if (@_[$firstcyl] ne @_[$lastcyl]) { print OUTPUT "@_[$lastcyl]\n"; } # primary Linux swap partition } elsif (@_[$parttype] == 82) { print OUTPUT "p\n$partnumber\n@_[$firstcyl]\n"; if (@_[$firstcyl] ne @_[$lastcyl]) { print OUTPUT "@_[$lastcyl]\n"; } print OUTPUT "t\n$partnumber\n82\n"; $format .= "mkswap -c @_[$dev]\n"; # primary mess-dos partition. We don't handle FAT32, # which requires a command line switch for mkdosfs. } elsif ( @_[$parttype] == 1 || @_[$parttype] == 4 || @_[$parttype] == 6 ) { print OUTPUT "p\n$partnumber\n@_[$firstcyl]\n"; if (@_[$firstcyl] ne @_[$lastcyl]) { # in case it's all on one cylinder print OUTPUT "@_[$lastcyl]\n"; } print OUTPUT "t\n$partnumber\n@_[$parttype]\n"; # $format .= "mkdosfs @_[$dev]\n"; # no bad block check $format .= "echo\necho formatting and checking @_[$dev]\nbadblocks -c 128 -o /tmp/$outputfilename$partnumber @_[$dev]\nmkdosfs -l /tmp/$outputfilename$partnumber @_[$dev]\n\n"; } else { # anything else partition print OUTPUT "p\n@_[$firstcyl]\n"; if (@_[$firstcyl] ne @_[$lastcyl]) { print OUTPUT "@_[$lastcyl]\n"; } print OUTPUT "t\n$partnumber\n@_[$parttype]\n"; } } else { # logical Linux partition if (@_[$parttype] == 83) { print OUTPUT "l\n@_[$firstcyl]\n"; if (@_[$firstcyl] ne @_[$lastcyl]) { print OUTPUT "@_[$lastcyl]\n"; } if ($labels{@_[$dev]}) { # do we have a label? # $format .= "mke2fs @_[$dev] -L $labels{@_[$dev]}\n"; # no bad block check $format .= "echo\necho formatting and checking @_[$dev]\nbadblocks -c 128 -o /tmp/$outputfilename$partnumber @_[$dev]\nmke2fs -L $labels{@_[$dev]} -l /tmp/$outputfilename$partnumber @_[$dev]\n\n"; } else { # $format .= "mke2fs @_[$dev]\n"; # no bad block check $format .= "echo\necho formatting and checking @_[$dev]\nbadblocks -c 128 -o /tmp/$outputfilename$partnumber @_[$dev]\nmke2fs -l /tmp/$outputfilename$partnumber @_[$dev]\n\n"; } # logical Linux swap partition } elsif (@_[$parttype] == 82 ) { print OUTPUT "l\n@_[$firstcyl]\n"; if (@_[$firstcyl] ne @_[$lastcyl]) { print OUTPUT "@_[$lastcyl]\n"; } print OUTPUT "t\n$partnumber\n82\n"; $format .= "mkswap -c @_[$dev]\n"; # primary mess-dos partition. We don't handle FAT32, # which requires a command line switch for mkdosfs. } elsif ( @_[$parttype] == 1 || @_[$parttype] == 4 || @_[$parttype] == 6 ) { print OUTPUT "p\n$partnumber\n@_[$firstcyl]\n"; if (@_[$firstcyl] ne @_[$lastcyl]) { # in case it's all on one cylinder print OUTPUT "@_[$lastcyl]\n"; } print OUTPUT "t\n$partnumber\n@_[$parttype]\n"; # $format .= "mkdosfs @_[$dev]\n"; # no bad block check $format .= "echo\necho formatting and checking @_[$dev]\nbadblocks -c 128 -o /tmp/$outputfilename$partnumber @_[$dev]\nmkdosfs -l /tmp/$outputfilename$partnumber @_[$dev]\n\n"; } else { # anything else partition print OUTPUT "l\n@_[$firstcyl]\n"; if (@_[$firstcyl] ne @_[$lastcyl]) { print OUTPUT "@_[$lastcyl]\n"; } print OUTPUT "t\n$partnumber\n@_[$parttype]\n"; } } # handle bootable partitions if (@_[$bootable] =~ /\*/) { print OUTPUT "a\n$partnumber\n"; } } } print OUTPUT "v\nw\n"; close (OUTPUT); close (FDISK); open (OUTPUT, "> ${outputfilepath}make.$outputfilename") or die "Couldn't open output file ${outputfilepath}make.$outputfilename.\n"; print OUTPUT <