source: branches/2.2.5/mindi/parted2fdisk.pl @ 1857

Last change on this file since 1857 was 1857, checked in by Bruno Cornec, 12 years ago

remove fdisk error messages on ia64 that end up on screen during restore - such as GPT not supported ...

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