source: trunk/mindi/parted2fdisk.pl @ 89

Last change on this file since 89 was 89, checked in by bcornec, 14 years ago

merge r87:88 of the 2.04_berlios branch
indent some files

  • Property svn:keywords set to Id
File size: 13.0 KB
Line 
1#!/usr/bin/perl -w
2#
3# $Id: parted2fdisk.pl 89 2005-10-27 20:45:34Z bcornec $
4#
5# parted2fdisk: fdisk like interface for parted
6# [developped for mindi/mondo http://mondorescue.berlios.de]
7#
8# Aims to be architecture independant (i386/ia64)
9# Tested on RHAS 2.1 ia64 - Mandrake 9.0 ia64 - RHAS 3.0 ia64
10#
11# (c) Bruno Cornec <Bruno.Cornec@hp.com>
12# Licensed under the GPL
13
14use strict;
15
16$ENV{LANG} = "C";
17$ENV{LANGUAGE} = "C";
18$ENV{LC_ALL} = "C";
19
20# Log
21my $flog = "/tmp/parted2fdisk.log";
22open(FLOG, "> $flog") || die "Unable to open $flog";
23
24my $fdisk = "/sbin/fdisk";
25my $parted = "/sbin/parted";
26
27my $i;
28my $l;
29my $part;
30my $wpart;
31my $start = "";
32my $end = "";
33my %start;
34my %end;
35my %type;
36my %flags;
37my $arch;
38my $fake = 0;
39
40# Determine on which arch we're running
41if (defined ($ENV{ARCH})) {
42    $arch = $ENV{ARCH};
43} else {
44    $arch = `"/bin/arch"`;
45    chomp($arch);
46}
47
48#
49# Looking for fdisk
50#
51$fdisk = is_lsb($fdisk);
52#
53# We always use fdisk except on ia64 with GPT types of
54# partition tables where we need parted
55# All should return fdisk like format so that callers
56# think they have called fdisk directly
57#
58my $un;
59my $type;
60my $args = "";
61my $device = "";
62my $endmax = "";
63
64if ($#ARGV < 0) {
65    printf FLOG "No arguments given exiting ...\n";
66    mysyn();
67}
68
69my %pid = ( "FAT" => "6",
70        "fat32" => "b",
71        "fat16" => "e",
72        "ext2" => "83",
73        "ext3" => "83",
74        "linux-swap" => "82",
75        "LVM" => "8e",
76        "" => "",
77    );
78my %pnum;
79
80# Reverse table of pid
81while (($i,$l) = each %pid) {
82    next if ($i eq "ext2");
83    $pnum{$l} = $i;
84}
85
86foreach $i (@ARGV) {
87    # We support at most one option and one device
88    print FLOG "Parameter found : $i\n";
89    if ($i =~ /^\/dev\//) {
90        $device = $i;
91        next;
92    } elsif ($i =~ /^-/) {
93        $args = $i;
94        next;
95    } else {
96        mysyn();
97    }
98}
99
100if (($args ne "") and ($device eq "")) {
101    mysyn();
102}
103
104# -s takes a partition as arg
105if ($args =~ /-s/) {
106    $wpart = $device;
107    $device =~ s/[0-9]+$//;
108}
109
110if ($args =~ /-n/) {
111    print FLOG "Fake mode. Nothing will be really done\n";
112    $fake = 1;
113}
114
115print FLOG "Called with device $device and arg $args\n";
116
117if ($arch =~ /^ia64/) {
118    # Check partition table type
119    print FLOG "We're on ia64 ...\n";
120    $parted = is_lsb($parted);
121    $type = which_type($device);
122    if ($type ne "msdos") {
123        print FLOG "Not an msdos type of disk label\n";
124        if ($args =~ /-l/) {
125            fdisk_list($device,undef,\%start,\%end);
126        } elsif ($args =~ /-s/) {
127            fdisk_list($device,$wpart,\%start,\%end);
128        } elsif (($args =~ /-/) and ($fake == 0)) {
129            printf FLOG "Option not supported ($args) ...\n";
130            printf FLOG "Please report to the author\n";
131            mysyn();
132        } else {
133            # Read fdisk orders on stdin and pass them to parted
134            # on the command line as parted doesn't read on stdin
135            print FLOG "Translating fdisk command to parted\n";
136            while ($i = <STDIN>) {
137                if ($i =~ /^p$/) {
138                    fdisk_list($device,undef,\%start,\%end);
139                }
140                elsif ($i =~ /^n$/) {
141                    fdisk_list($device,undef,\%start,\%end);
142                    if ($type ne "gpt") {
143                        print FLOG "Forcing GPT type of disk label\n";
144                        print FLOG "mklabel gpt\n";
145                        system "$parted -s $device mklabel gpt\n" if ($fake != 0);
146                        $type = "gpt";
147                    }
148                    $l = <STDIN>;
149                    if (not (defined $l)) {
150                        print FLOG "no primary/extended arg given for creation... assuming primary\n";
151                        $l = "p";
152                    }
153                    chomp($l);
154                    $part = <STDIN>;
155                    if ((not (defined $part)) || ($part eq "")) {
156                        print FLOG "no partition given for creation... skipping\n";
157                        next;
158                    }
159                    chomp($part);
160                    $start = <STDIN>;
161                    chomp($start);
162                    if ((not (defined $start)) || ($start eq "")) {
163                        if (defined $start{$part-1}) {
164                            $start = scalar $end{$part-1} + 0.001;
165                            print FLOG "no start cyl given for creation... assuming the following $start\n";
166                        } else {
167                            print FLOG "no start cyl given for creation... assuming the following 1\n";
168                            $start = 1;
169                        }
170                    }
171                    $start = 1 if ($start < 1);
172                    print FLOG "start cyl : $start\n";
173                    $un = get_un($device);
174                    # parted needs MB
175                    $start = $start * $un / 1048576;
176                    # this is a size in B/KB/MB/GB
177                    $endmax = get_max($device);
178                    $end = <STDIN>;
179                    chomp($end);
180                    if ((not (defined $end)) || ($end eq "")) {
181                        print FLOG "no end cyl given for creation... assuming full disk)\n";
182                        $end = $endmax;
183                    }
184                    # Handles end syntaxes (+, K, M, ...)
185                    # to give cylinders
186                    if ($end =~ /^\+/) {
187                        $end =~ s/^\+//;
188                        if ($end =~ /K$/) {
189                            $end =~ s/K$//;
190                            $end *= 1000;
191                        } elsif ($end =~ /M$/) {
192                            $end =~ s/M$//;
193                            $end *= 1000000;
194                        } elsif ($end =~ /G$/) {
195                            $end =~ s/G$//;
196                            $end *= 1000000000;
197                        }
198                        # This gives the number of cyl
199                        $end /= $un;
200                        $end = sprintf("%d",$end);
201                        $end += $start - 0.001;
202                        # We now have the end cyl
203                    }
204                    print FLOG "end cyl : $end\n";
205                    # parted needs MB
206                    $end = $end * $un / 1048576;
207                    $end = $endmax if ($end > $endmax); 
208                    print FLOG "n $l $part => mkpart primary $start $end\n";
209                    system "$parted -s $device mkpart primary ext2 $start $end\n" if ($fake != 0);
210                }
211                elsif ($i =~ /^d$/) {
212                    $part = <STDIN>;
213                    if (not (defined $part)) {
214                        print FLOG "no partition given for deletion... skipping\n";
215                        next;
216                    }
217                    chomp($part);
218                    print FLOG "d $part => rm $part\n";
219                    system "$parted -s $device rm $part\n" if ($fake != 0);
220                    get_parted($device,undef,\%start,\%end,undef,undef);
221                }
222                elsif ($i =~ /^w$/) {
223                    print FLOG "w => quit\n";
224                }
225                elsif ($i =~ /^t$/) {
226                    $part = <STDIN>;
227                    if (not (defined $part)) {
228                        print FLOG "no partition given for tagging... skipping\n";
229                        next;
230                    }
231                    chomp($part);
232                    $l = <STDIN>;
233                    if (not (defined $l)) {
234                        print FLOG "no type given for tagging partition $part... skipping\n";
235                        next;
236                    }
237                    chomp($l);
238                    if (not (defined $pnum{$l})) {
239                        print FLOG "no partition number given for $l... please report to the author\n";
240                        next;
241                    }
242                    print FLOG "t $part => mkfs $part $pnum{$l}\n";
243                    system "$parted -s $device mkfs $part $pnum{$l}\n" if ($fake != 0);
244                }
245                elsif ($i =~ /^a$/) {
246                    $part = <STDIN>;
247                    if (not (defined $part)) {
248                        print FLOG "no partition given for tagging... skipping\n";
249                        next;
250                    }
251                    chomp($part);
252                    print FLOG "a $part => set $part boot on\n";
253                    system "$parted -s $device set $part boot on\n" if ($fake != 0);
254                }
255                elsif ($i =~ /^q$/) {
256                    print FLOG "q => quit\n";
257                }
258                else {
259                    print FLOG "Unknown command: $i\n";
260                    next;
261                }
262                   
263            }
264        }
265        myexit(0);
266    }
267}
268
269#
270# Else everything is for fdisk
271#
272# Print only mode
273print FLOG "Passing everything to the real fdisk\n";
274my $fargs = join(@ARGV);
275
276if ($args =~ /^-/) {
277    # -l or -s
278    open (FDISK, "$fdisk $fargs |") || die "Unable to read from $fdisk";
279    while (<FDISK>) {
280        print;
281    }
282    close(FDISK);
283} else {
284    # Modification mode
285    open (FDISK, "| $fdisk $fargs") || die "Unable to modify through $fdisk";
286    while (<STDIN>) {
287        print FDISK;
288    }
289    close(FDISK);
290    close(STDIN);
291}
292myexit(0);
293
294
295# Is your system LSB ?
296sub is_lsb {
297
298my $cmd = shift;
299my $basename = basename($cmd);
300my $mindifdisk="/usr/local/bin/fdisk";
301
302if ($cmd =~ /fdisk/) {
303    if ($arch =~ /^ia64/) {
304        if (-l $cmd) {
305            print FLOG "Your system is ready for mondo-archive on ia64\n";
306        } else {
307            print FLOG "Your system is ready for mondo-restore on ia64\n";
308        }
309        if (-x $mindifdisk) {
310            $cmd = $mindifdisk;
311        } else {
312            print FLOG "Your system doesn't provide $mindifdisk\n";
313            print FLOG "Please use mindi-x.yz-ia64.rpm on the system to backup\n";
314            myexit(-1);
315        }
316    }
317}
318if (not (-x $cmd)) {
319    print FLOG "Your system is not LSB/mondo compliant: $basename was not found as $cmd\n";
320    print FLOG "Searching elswhere...";
321    foreach $i (split(':',$ENV{PATH})) {
322        if (-x "$i/$basename") {
323            $cmd = "$i/$basename";
324            print FLOG "Found $cmd, using it !\n";
325            last;
326        }
327    }
328    if (not (-x $cmd)) {
329        print FLOG "Your system doesn't provide $basename in the PATH\n";
330        print FLOG "Please correct it before relaunching\n";
331        myexit(-1);
332    }
333}
334return($cmd);
335}
336
337sub fdisk_list {
338
339my $device = shift;
340my $wpart = shift;
341my $start = shift;
342my $end = shift;
343
344my $un;
345my $endmax;
346my $d;
347my $n;
348
349my %cmt = ( "FAT" => "FAT",
350        "ext2" => "Linux",
351        "ext3" => "Linux",
352        "linux-swap" => "Linux swap",
353        "LVM" => "Linux LVM",
354        "fat16" => "fat16",
355        "fat32" => "fat32",
356        "" => "Linux",
357);
358
359my $part;
360my $mstart;
361my $mend;
362my $length;
363my $pid;
364my $cmt;
365format FLOG1 =
366@<<<<<<<<<<<< @>>>>>>>> @>>>>>>>> @>>>>>>>> @>>>  @<<<<<<<<<<<<<<<<<<<<<<<<<<<<
367$part,        $mstart,   $mend,   $length,  $pid, $cmt
368.
369format FLOG2 =
370@<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
371$part,
372              @>>>>>>>> @>>>>>>>> @>>>>>>>> @>>>  @<<<<<<<<<<<<<<<<<<<<<<<<<<<<
373              $mstart,   $mend,   $length,  $pid, $cmt
374.
375format STDOUT1 =
376@<<<<<<<<<<<< @>>>>>>>> @>>>>>>>> @>>>>>>>> @>>>  @<<<<<<<<<<<<<<<<<<<<<<<<<<<<
377$part,        $mstart,   $mend,   $length,  $pid, $cmt
378.
379format STDOUT2 =
380@<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
381$part,
382              @>>>>>>>> @>>>>>>>> @>>>>>>>> @>>>  @<<<<<<<<<<<<<<<<<<<<<<<<<<<<
383              $mstart,   $mend,   $length,  $pid, $cmt
384.
385#/dev/hda1             1     77579  39099374+  ee  EFI GPT
386
387#
388# Keep Fdisk headers
389#
390# this will return bytes
391$un = get_un ($device,$wpart);
392$endmax = get_max($device);
393# This will return MB
394get_parted ($device,$start,$end,\%type,\%flags);
395
396while (($n,$d) = each %type) {
397    # Print infos fdisk like
398    $part = ${device}.$n;
399    # start and end are in cylinder in fdisk format
400    # so return in MB * 1MB / what represents 1 cyl in B
401    $mstart = sprintf("%d",$$start{$n}*1048576/$un);
402    $mstart = 1 if ($mstart < 1);
403    $mend = sprintf("%d",$$end{$n}*1048576/$un - 1);
404    $mend = $endmax if ($mend > $endmax);
405    # length is in 1K blocks
406    $length = sprintf("%d",($mend-$mstart+1)*$un/1024);
407    $pid = $pid{$type{$n}};
408    $cmt = $cmt{$type{$n}};
409    print FLOG "$part - $mstart - $mend - $length\n";
410
411    if (not (defined $wpart)) {
412        if (length($part) > 13) {
413            open(STDOUT2,">&STDOUT") || die "Unable to open STDOUT2";
414            select(STDOUT2);
415            write;
416            open(FLOG2,">&FLOG") || die "Unable to open FLOG2";
417            select(FLOG2);
418            write;
419            select(STDOUT);
420            close(FLOG2);
421            close(STDOUT2);
422        } else {
423            open(STDOUT1,">&STDOUT") || die "Unable to open STDOUT1";
424            select(STDOUT1);
425            write;
426            open(FLOG1,">&FLOG") || die "Unable to open FLOG1";
427            select(FLOG1);
428            write;
429            select(STDOUT);
430            close(FLOG1);
431            close(STDOUT1);
432        }
433    } else {
434        # manage the -s option of fdisk here
435        print "$length\n" if ($part eq $wpart);
436        print FLOG "$part has $length KBytes\n" if ($part eq $wpart);
437    }
438}
439close(FDISK);
440close(PARTED);
441}
442
443#
444# Get max size from fdisk
445#
446sub get_max {
447
448my $device = shift;
449my $max = 0;
450my $foo;
451
452open (FDISK, "$fdisk -l $device |") || die "Unable to read from $fdisk";
453while (<FDISK>) {
454    if ($_ =~ /heads/) {
455        chomp;
456        $max = $_;
457        $max =~ s/.* ([0-9]+) cylinders/$1/;
458    }
459}
460close(FDISK);
461print FLOG "get_max returns $max\n";
462return($max);
463}
464
465#
466# Get units from fdisk (cylinder size)
467#
468sub get_un {
469
470my $device = shift;
471my $wpart = shift;
472my $un = 0;
473my $foo;
474
475open (FDISK, "$fdisk -l $device |") || die "Unable to read from $fdisk";
476while (<FDISK>) {
477    print if (($_ !~ /^\/dev\//) and (not (defined $wpart)));
478    if ($_ =~ /^Units/) {
479        ($foo, $un , $foo) = split /=/;
480        $un =~ s/[A-z\s=]//g;
481        $un = eval($un);
482    }
483}
484close(FDISK);
485print FLOG "get_un returns $un\n";
486return($un);
487}
488
489#
490# Parted gives info in MB
491#
492sub get_parted {
493
494my $device = shift;
495my $start = shift;
496my $end = shift;
497my $type = shift;
498my $flags = shift;
499my $d;
500my $n;
501
502open (PARTED, "$parted -s $device print |") || die "Unable to read from $parted";
503# Skip 3 first lines
504$d = <PARTED>;
505$d = <PARTED>;
506$d = <PARTED>;
507print FLOG "Got from parted: \n";
508print FLOG "Minor    Start       End     Filesystem                        Flags\n";
509# Get info from each partition line
510while (($n,$d) = split(/\s/, <PARTED>,2)) {
511    chomp($d);
512    next if ($n !~ /^[1-9]/);
513    $d =~ s/^\s*//;
514    $d =~ s/\s+/ /g;
515    ($$start{$n},$$end{$n},$$type{$n},$$flags{$n}) = split(/ /,$d);
516    $$start{$n} = "" if (not defined $$start{$n});
517    $$end{$n} = "" if (not defined $$end{$n});
518    $$type{$n} = "" if (not defined $$type{$n});
519    $$flags{$n} = "" if (not defined $$flags{$n});
520    print FLOG "$n      $$start{$n}      $$end{$n}     $$type{$n}  $$flags{$n}\n";
521}
522close(PARTED);
523}
524
525# Based on Version 2.4  27-Sep-1996  Charles Bailey  bailey@genetics.upenn.edu
526# in Basename.pm
527
528sub basename {
529
530my($fullname) = shift;
531
532my($dirpath,$basename);
533
534($dirpath,$basename) = ($fullname =~ m#^(.*/)?(.*)#s);
535
536return($basename);
537}
538
539sub myexit {
540
541my $val=shift;
542
543close(FLOG);
544exit($val);
545}
546
547sub which_type {
548
549my $device = shift;
550my $type = "";
551
552open (FDISK, "$fdisk -l $device |") || die "Unable to read from $fdisk";
553while (<FDISK>) {
554    if ($_ =~ /EFI GPT/) {
555        $type= "gpt";
556        print FLOG "Found a GPT partition format\n";
557        last;
558    }
559}
560close(FDISK);
561open (PARTED, "$parted -s $device print|") || die "Unable to read from $fdisk";
562while (<PARTED>) {
563    if ($_ =~ /Disk label type: msdos/) {
564        $type= "msdos";
565        print FLOG "Found a msdos partition format\n";
566        last;
567    }
568}
569close(FDISK);
570return ($type);
571}
572
573sub mysyn {
574    print "Syntax: $0 [-l] device | [-s] partition\n";
575    myexit(-1);
576}
Note: See TracBrowser for help on using the repository browser.