source: branches/2.05/mindi/parted2fdisk.pl @ 196

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

Usage of parted2fdisk instead of fdisk everywhere.
on ia64 this is mandatory, and simplifies the infrastructure
on other archs, it doesn't change anything as parted2fdisk here is a link to fdisk

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