source: branches/3.0/mindi/parted2fdisk.pl @ 3143

Last change on this file since 3143 was 3143, checked in by Bruno Cornec, 7 years ago

r5349@localhost: bruno | 2013-06-14 01:23:53 +0200

  • Adds pod content to the perl scripts used, and generate man pages frmo it as part of the install process. This also fixes rpmlint and deblint issues
  • Property svn:keywords set to Id
File size: 16.8 KB
Line 
1#!/usr/bin/perl -w
2#
3# $Id: parted2fdisk.pl 3143 2013-06-14 04:06:09Z 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 ia64 with RHAS 2.1 - Mandrake 9.0 - RHEL 3.0 - SLES 10
10#
11# Copyright B. Cornec 2000-2013
12# Provided under the GPL v2
13
14use strict;
15
16
17=pod
18
19=head1 NAME
20
21parted2fdisk is a fdisk lie command using parted internally.
22
23=head1 DESCRIPTION
24
25parted2fdisk behaves like a fdisk command, but dialog internally with parted in order to manipulate partiion tables, which allow it to support GPT partition format as well as MBR, contrary to fdisk. It aimed at providing compatible external interface wti fdisk. Developed initialy for ia64 Linux, but is also useful now on x86 systems using GPT partition format (for large HDDs).
26
27=head1 SYNOPSIS
28
29parted2fdisk -s partition
30parted2fdisk -l device
31parted2fdisk [-n] device
32
33=head1 OPTIONS
34
35=over 4
36
37=item B<-s>
38
39Print the size (in blocks) of the given partition.
40
41=item B<-n>
42
43Fake mode. Doesn't pass the commands just simulate.
44
45=item B<-l>
46
47List the partition tables for the specified device and then exit.
48
49=item B<no option>
50
51Allow the creation and manipulation of partition tables.
52
53=back
54
55=head1 ARGUMENTS
56
57=over 4
58
59=item B<partition>
60
61partition device file (only used with -s option).
62
63=item B<device>
64
65device file to work on.
66
67=back
68
69=head1 WEB SITES
70
71The main Web site of the project is available at L<http://www.mondorescue.org>. Bug reports should be filled using the trac instance of the project at L<http://trac.mondorescue.org/>.
72
73=head1 USER MAILING LIST
74
75For community exchanges around MondoRescue please use the list L<http://sourceforge.net/mailarchive/forum.php?forum_name=mondo-devel>
76
77=head1 AUTHORS
78
79The MondoRescue team lead by Bruno Cornec L<mailto:bruno@mondorescue.org>.
80
81=head1 COPYRIGHT
82
83MondoRescue is distributed under the GPL v2.0 license or later,
84described in the file C<COPYING> included with the distribution.
85
86=cut
87
88
89$ENV{LANG} = "C";
90$ENV{LANGUAGE} = "C";
91$ENV{LC_ALL} = "C";
92
93# Log
94my $flog = "/var/log/parted2fdisk.log";
95open(FLOG, "> $flog") || die "Unable to open $flog";
96
97my $fdisk = "/sbin/fdisk";
98my $parted = "/sbin/parted";
99
100my $i;
101my $l;
102my $part;
103my $wpart;
104my $start = "";
105my $end = "";
106my $cylstart;
107my $cylend;
108my %start;
109my %end;
110my %type;
111my $arch;
112my $fake = 0;
113my $mega = 1048576;
114
115# Immediate flushing to avoids read error from mondorestore in log files
116$| = 1;
117
118# Determine on which arch we're running
119if (defined ($ENV{ARCH})) {
120    $arch = $ENV{ARCH};
121} else {
122    $arch = `uname -m`;
123    chomp($arch);
124}
125
126#
127# Looking for fdisk
128#
129$fdisk = is_lsb($fdisk);
130#
131# We always use fdisk except on ia64 with GPT types of
132# partition tables where we need parted
133# All should return fdisk like format so that callers
134# think they have called fdisk directly
135#
136my $un;
137my $type;
138my $args = "";
139my $device = "";
140my $endmax = "";
141
142if ($#ARGV < 0) {
143    printf FLOG "No arguments given exiting ...\n";
144    mysyn();
145}
146
147my %pid = ( "FAT" => "6",
148        "fat32" => "b",
149        "fat16" => "e",
150        "ext2" => "83",
151        "ext3" => "83",
152        "ext4" => "83",
153        "xfs" => "83",
154        "reiserfs" => "83",
155        "linux-swap" => "82",
156        "lvm" => "8e",
157        "" => "",
158    );
159my %pnum;
160
161# Reverse table of pid
162while (($i,$l) = each %pid) {
163    next if ($i eq "ext2");
164    $pnum{$l} = $i;
165}
166
167foreach $i (@ARGV) {
168    # We support at most one option and one device
169    print FLOG "Parameter found : $i\n";
170    if ($i =~ /^\/dev\//) {
171        $device = $i;
172        next;
173    } elsif ($i =~ /^-/) {
174        $args = $i;
175        next;
176    } else {
177        mysyn();
178    }
179}
180
181if (($args ne "") and ($device eq "")) {
182    mysyn();
183}
184
185# -s takes a partition as arg
186if ($args =~ /-s/) {
187    $wpart = $device;
188    $device =~ s/[0-9]+$//;
189}
190
191if ($args =~ /-n/) {
192    print FLOG "Fake mode. Nothing will be really done\n";
193    $fake = 1;
194}
195
196print FLOG "Called with device $device and arg $args\n";
197
198if ($arch =~ /^ia64/) {
199    # Check partition table type
200    print FLOG "We're on ia64 ...\n";
201    $parted = is_lsb($parted);
202    $type = which_type($device);
203    if ($type ne "msdos") {
204        print FLOG "Not an msdos type of disk label\n";
205        if ($args =~ /-l/) {
206            fdisk_list($device,undef,\%start,\%end, 1);
207        } elsif ($args =~ /-s/) {
208            fdisk_list($device,$wpart,\%start,\%end, 1);
209        } elsif (($args =~ /-/) and ($fake == 0)) {
210            printf FLOG "Option not supported ($args) ...\n";
211            printf FLOG "Please report to the author\n";
212            mysyn();
213        } else {
214            # Read fdisk orders on stdin and pass them to parted
215            # on the command line as parted doesn't read on stdin
216            print FLOG "Translating fdisk command to parted\n";
217            while ($i = <STDIN>) {
218                if ($i =~ /^p$/) {
219                    fdisk_list($device,undef,\%start,\%end, 1);
220                    print "command (m for help) send back to fake fdisk for mondorestore\n";
221                } elsif ($i =~ /^n$/) {
222                    fdisk_list($device,undef,\%start,\%end, 0);
223                    if ($type ne "gpt") {
224                        print FLOG "Forcing GPT type of disk label\n";
225                        print FLOG "mklabel gpt\n";
226                        system "$parted -s $device mklabel gpt\n" if ($fake == 0);
227                        $type = "gpt";
228                    }
229                    $l = <STDIN>;
230                    if (not (defined $l)) {
231                        print FLOG "no primary/extended arg given for creation... assuming primary\n";
232                        $l = "p";
233                    }
234                    chomp($l);
235                    $part = <STDIN>;
236                    if ((not (defined $part)) || ($part eq "")) {
237                        print FLOG "no partition given for creation... skipping\n";
238                        next;
239                    }
240                    chomp($part);
241                    $cylstart = <STDIN>;
242                    chomp($cylstart);
243                    if ((not (defined $cylstart)) || ($cylstart eq "")) {
244                        if (defined $start{$part-1}) {
245                            # in MB => cyl
246                            $cylstart = sprintf("%d",$end{$part-1}*$mega/$un + 1);
247                            print FLOG "no start cyl given for creation... assuming the following $cylstart\n";
248                        } else {
249                            print FLOG "no start cyl given for creation... assuming the following 1\n";
250                            $cylstart = 1;
251                        }
252                    }
253                    $cylstart = 1 if ($cylstart < 1);
254                    print FLOG "start cyl : $cylstart\n";
255                    $un = get_un($device, "", 0);
256                    # parted needs MB
257                    if ($cylstart == 1) {
258                        $start = 0.01;
259                    } else {
260                        $start = $cylstart* $un / $mega + 0.001;
261                    }
262                    # this is a size in B/KB/MB/GB
263
264                    $endmax = get_max($device);
265                    $cylend = <STDIN>;
266                    chomp($cylend);
267                    if ((not (defined $cylend)) || ($cylend eq "")) {
268                        print FLOG "no end cyl given for creation... assuming full disk)\n";
269                        $cylend = $endmax;
270                    }
271                    # Handles end syntaxes (+, K, M, ...)
272                    # to give cylinders
273                    if ($cylend =~ /^\+/) {
274                        $cylend =~ s/^\+//;
275                        # Handles suffixes; return bytes
276                        $cylend = decode_Bsuf($cylend,1);
277                        # This gives the number of cyl
278                        $cylend /= $un;
279                        $cylend = sprintf("%d",$cylend);
280                        $cylend += $cylstart - 0.001;
281                        # We now have the end cyl
282                    }
283                    $cylend = $endmax if ($cylend > $endmax); 
284                    print FLOG "end cyl : $cylend\n";
285                    # parted needs MB
286                    $end = $cylend * $un / $mega;
287                    print FLOG "n $l $part $cylstart $cylend => mkpart primary $start $end\n";
288                    system "$parted -s $device mkpart primary ext2 $start $end\n" if ($fake == 0);
289                    print "command (m for help) send back to fake fdisk for mondorestore\n";
290                } elsif ($i =~ /^d$/) {
291                    $part = <STDIN>;
292                    if (not (defined $part)) {
293                        print FLOG "no partition given for deletion... skipping\n";
294                        next;
295                    }
296                    chomp($part);
297                    print FLOG "d $part => rm $part\n";
298                    system "$parted -s $device rm $part\n" if ($fake == 0);
299                    get_parted($device,undef,\%start,\%end,undef);
300                    print "command (m for help) send back to fake fdisk for mondorestore\n";
301                } elsif ($i =~ /^w$/) {
302                    print FLOG "w => quit\n";
303                } elsif ($i =~ /^t$/) {
304                    $part = <STDIN>;
305                    if (not (defined $part)) {
306                        print FLOG "no partition given for tagging... skipping\n";
307                        next;
308                    }
309                    chomp($part);
310                    # If no partition number given it's 1, and we received the type
311                    if ($part !~ /\d+/) {
312                        $l = $part;
313                        $part = 1 
314                    } else {
315                        $l = <STDIN>;
316                    }
317                    if (not (defined $l)) {
318                        print FLOG "no type given for tagging partition $part... skipping\n";
319                        next;
320                    }
321                    chomp($l);
322                    if (not (defined $pnum{$l})) {
323                        print FLOG "no partition number given for $l... please report to the author\n";
324                        next;
325                    }
326
327                    if ($pnum{$l} eq "lvm") {
328                        # In that case this is a flag set, not a mkfs
329                        print FLOG "t $part $l => set $part $pnum{$l} on\n";
330                        system "$parted -s $device set $part $pnum{$l} on\n" if ($fake == 0);
331                    } else {
332                        print FLOG "t $part $l => mkfs $part $pnum{$l}\n";
333                        system "$parted -s $device mkfs $part $pnum{$l}\n" if ($fake == 0);
334                    }
335                    print "command (m for help) send back to fake fdisk for mondorestore\n";
336                } elsif ($i =~ /^a$/) {
337                    $part = <STDIN>;
338                    if (not (defined $part)) {
339                        print FLOG "no partition given for tagging... skipping\n";
340                        next;
341                    }
342                    chomp($part);
343
344                    # Partition shouldn't be negative or null. Then take the first one.
345                    $part = 1 if ($part le 0);
346
347                    print FLOG "a $part => set $part boot on\n";
348                    system "$parted -s $device set $part boot on\n" if ($fake == 0);
349                    print "command (m for help) send back to fake fdisk for mondorestore\n";
350                } elsif ($i =~ /^q$/) {
351                    print FLOG "q => quit\n";
352                } else {
353                    print FLOG "Unknown command: $i\n";
354                    print "command (m for help) send back to fake fdisk for mondorestore\n";
355                    next;
356                }
357                   
358            }
359        }
360        myexit(0);
361    }
362}
363
364#
365# Else everything is for fdisk
366#
367# Print only mode
368print FLOG "Passing everything to the real fdisk\n";
369my $fargs = join(@ARGV);
370
371if ($args =~ /^-/) {
372    # -l or -s
373    open (FDISK, "$fdisk $fargs 2>/dev/null |") || die "Unable to read from $fdisk";
374    while (<FDISK>) {
375        print;
376    }
377    close(FDISK);
378} else {
379    # Modification mode
380    open (FDISK, "| $fdisk $fargs 2>/dev/null") || die "Unable to modify through $fdisk";
381    while (<STDIN>) {
382        print FDISK;
383    }
384    close(FDISK);
385    close(STDIN);
386}
387myexit(0);
388
389
390# Is your system LSB ?
391sub is_lsb {
392
393my $cmd = shift;
394my $basename = basename($cmd);
395
396if (not (-x $cmd)) {
397    print FLOG "Your system is not LSB/mondo compliant: $basename was not found as $cmd\n";
398    print FLOG "Searching elswhere...";
399    foreach $i (split(':',$ENV{PATH})) {
400        if (-x "$i/$basename") {
401            $cmd = "$i/$basename";
402            print FLOG "Found $cmd, using it !\n";
403            last;
404        }
405    }
406    if (not (-x $cmd)) {
407        print FLOG "Your system doesn't provide $basename in the PATH\n";
408        print FLOG "Please correct it before relaunching\n";
409        myexit(-1);
410    }
411}
412return($cmd);
413}
414
415sub fdisk_list {
416
417my $device = shift;
418my $wpart = shift;
419my $start = shift;
420my $end = shift;
421my $verbose = shift;
422
423my $un;
424my $endmax;
425my $d;
426my $n;
427
428my %cmt = ( "FAT" => "FAT",
429        "ext2" => "Linux",
430        "ext3" => "Linux",
431        "ext4" => "Linux",
432        "xfs" => "Linux",
433        "reiserfs" => "Linux",
434        "linux-swap" => "Linux swap",
435        "lvm" => "Linux LVM",
436        "fat16" => "fat16",
437        "fat32" => "fat32",
438        "" => "Linux",
439);
440
441my $part;
442my $mstart;
443my $mend;
444my $length;
445my $pid;
446my $cmt;
447format FLOG1 =
448@<<<<<<<<<<<< @>>>>>>>>>> @>>>>>>>>>> @>>>>>>>>>> @>>>  @<<<<<<<<<<<<<<<<<<<<<<<<<<<<
449$part,        $mstart,   $mend,   $length,  $pid, $cmt
450.
451format FLOG2 =
452@<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
453$part,
454              @>>>>>>>>>> @>>>>>>>>>> @>>>>>>>>>> @>>>  @<<<<<<<<<<<<<<<<<<<<<<<<<<<<
455              $mstart,   $mend,   $length,  $pid, $cmt
456.
457format STDOUT1 =
458@<<<<<<<<<<<< @>>>>>>>>>> @>>>>>>>>>> @>>>>>>>>>> @>>>  @<<<<<<<<<<<<<<<<<<<<<<<<<<<<
459$part,        $mstart,   $mend,   $length,  $pid, $cmt
460.
461format STDOUT2 =
462@<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
463$part,
464              @>>>>>>>>>> @>>>>>>>>>> @>>>>>>>>>> @>>>  @<<<<<<<<<<<<<<<<<<<<<<<<<<<<
465              $mstart,   $mend,   $length,  $pid, $cmt
466.
467#   Device Boot      Start         End      Blocks   Id  System
468#/dev/hda1               1       77579    39099374+  ee  EFI GPT
469
470
471#
472# Keep Fdisk headers
473#
474# this will return bytes
475$un = get_un ($device,$wpart,$verbose);
476
477$endmax = get_max($device);
478
479# This will return MB
480get_parted ($device,$start,$end,\%type);
481
482while (($n,$d) = each %type) {
483    # Print infos fdisk like
484    $part = ${device}.$n;
485    # start and end are in cylinder in fdisk format
486    # so return in MB * 1MB / what represents 1 cyl in B
487    $mstart = sprintf("%d",$$start{$n}*$mega/$un);
488    $mstart = 1 if ($mstart < 1);
489    $mstart = $endmax if ($mstart > $endmax);
490    $mend = sprintf("%d",$$end{$n}*$mega/$un - 1);
491    $mend = $endmax if ($mend > $endmax);
492    $mend = 1 if ($mend < 1);
493    # length is in 1K blocks
494    $length = sprintf("%d",($mend-$mstart+1)*$un/1024);
495    $pid = $pid{$type{$n}};
496    $cmt = $cmt{$type{$n}};
497    #print FLOG "$part - $mstart - $mend - $length\n";
498
499    if ($verbose == 1) {
500        if (not (defined $wpart)) {
501            if (length($part) > 13) {
502                open(STDOUT2,">&STDOUT") || die "Unable to open STDOUT2";
503                select(STDOUT2);
504                write;
505                open(FLOG2,">&FLOG") || die "Unable to open FLOG2";
506                select(FLOG2);
507                write;
508                select(STDOUT);
509                close(FLOG2);
510                close(STDOUT2);
511            } else {
512                open(STDOUT1,">&STDOUT") || die "Unable to open STDOUT1";
513                select(STDOUT1);
514                write;
515                open(FLOG1,">&FLOG") || die "Unable to open FLOG1";
516                select(FLOG1);
517                write;
518                select(STDOUT);
519                close(FLOG1);
520                close(STDOUT1);
521            }
522        } else {
523            # manage the -s option of fdisk here
524            print "$length\n" if ($part eq $wpart);
525            print FLOG "$part has $length KBytes\n" if ($part eq $wpart);
526        }
527    }
528}
529close(FDISK);
530close(PARTED);
531}
532
533#
534# Get max size from fdisk
535#
536sub get_max {
537
538my $device = shift;
539my $max = 0;
540my $foo;
541
542open (FDISK, "$fdisk -l $device 2>/dev/null |") || die "Unable to read from $fdisk";
543while (<FDISK>) {
544    if ($_ =~ /heads/) {
545        chomp;
546        $max = $_;
547        $max =~ s/.* ([0-9]+) cylinders/$1/;
548    }
549}
550close(FDISK);
551print FLOG "get_max returns $max\n";
552return($max);
553}
554
555#
556# Get units from fdisk (cylinder size)
557#
558sub get_un {
559
560my $device = shift;
561my $wpart = shift;
562my $verbose = shift;
563my $un = 0;
564my $foo;
565
566open (FDISK, "$fdisk -l $device 2>/dev/null |") || die "Unable to read from $fdisk";
567while (<FDISK>) {
568    print if (($_ !~ /^\/dev\//) and (not (defined $wpart)) and ($verbose == 1));
569    if ($_ =~ /^Units/) {
570        ($foo, $un , $foo) = split /=/;
571        $un =~ s/[A-z\s=]//g;
572        $un = eval($un);
573    }
574}
575close(FDISK);
576print FLOG "get_un returns $un\n";
577return($un);
578}
579
580#
581# Parted gives info in MB
582# (depending on versions - 1.6.25.1 provides suffixes)
583#
584sub get_parted {
585
586my $device = shift;
587my $start = shift;
588my $end = shift;
589my $type = shift;
590my $void;
591my $d;
592my $n;
593my $ret;
594my $mode;
595my $size;
596my $unit;
597
598open (PARTED, "$parted -v |") || die "Unable to read from $parted";
599$d = <PARTED>;
600print FLOG "$d";
601close(PARTED);
602
603open (PARTED, "$parted -s $device print |") || die "Unable to read from $parted";
604# Skip 3 first lines
605$d = <PARTED>;
606$d = <PARTED>;
607$d = <PARTED>;
608
609# depending on parted version, information given change:
610if ($d =~ /\bSize\b/) {
611    # SLES 10 parted >= 1.6.25
612    $mode=1;
613} else {
614    # RHEL 3 parted 1.6.3
615    # RHEL 4 parted 1.6.19
616    $mode=0;
617}
618print FLOG "mode: $mode\n";
619print FLOG "Got from parted: \n";
620print FLOG "Minor    Start       End     Filesystem\n";
621# Get info from each partition line
622while (($n,$d) = split(/\s/, <PARTED>,2)) {
623    chomp($d);
624    next if ($n !~ /^[1-9]/);
625    $d =~ s/^\s*//;
626    $d =~ s/\s+/ /g;
627    if ($mode == 0) {
628        ($$start{$n},$$end{$n},$$type{$n},$void) = split(/ /,$d);
629        $unit = 1;
630    } elsif ($mode == 1) {
631        ($$start{$n},$$end{$n},$size,$$type{$n},$void) = split(/ /,$d);
632        $unit = $mega;
633    } else {
634        die "Undefined mode $mode";
635    }
636    $$start{$n} = "" if (not defined $$start{$n});
637    $$end{$n} = "" if (not defined $$end{$n});
638    $$type{$n} = "" if (not defined $$type{$n});
639    # Handles potential suffixes in latest parted version. Return MB
640    $ret = decode_Bsuf($$start{$n},$unit);
641    $$start{$n} = $ret;
642    $ret = decode_Bsuf($$end{$n},$unit);
643    $$end{$n} = $ret;
644    print FLOG "$n      $$start{$n}      $$end{$n}     $$type{$n}\n";
645}
646close(PARTED);
647}
648
649sub decode_Bsuf {
650
651my $size  = shift;
652my $unit  = shift;
653my $ret = 0;
654
655#print FLOG "decode_Bsuf input: $size / $unit ";
656if ($size =~ /K[B]*$/i) {
657    $size =~ s/K[B]*$//i;
658    $size *= 1024;
659} elsif ($size =~ /M[B]*$/i) {
660    $size =~ s/M[B]*$//i;
661    $size *= 1048576;
662} elsif ($size =~ /G[B]*$/i) {
663    $size =~ s/G[B]*$//i;
664    $size *= 1073741824;
665} elsif ($size =~ /T[B]*$/i) {
666    $size =~ s/T[B]*$//i;
667    $size *= 1099511627776;
668} else {
669    # Nothing to do
670}
671$ret = $size / $unit;
672#print FLOG " - output : $size => $ret\n";
673return($ret);
674}
675
676
677# Based on Version 2.4  27-Sep-1996  Charles Bailey  bailey@genetics.upenn.edu
678# in Basename.pm
679
680sub basename {
681
682my($fullname) = shift;
683
684my($dirpath,$basename);
685
686($dirpath,$basename) = ($fullname =~ m#^(.*/)?(.*)#s);
687
688return($basename);
689}
690
691sub myexit {
692
693my $val=shift;
694
695close(FLOG);
696exit($val);
697}
698
699sub which_type {
700
701my $device = shift;
702my $type = "";
703
704open (FDISK, "$fdisk -l $device 2>/dev/null |") || die "Unable to read from $fdisk";
705while (<FDISK>) {
706    if ($_ =~ /EFI GPT/) {
707        $type= "gpt";
708        print FLOG "Found a GPT partition format\n";
709        last;
710    }
711}
712close(FDISK);
713open (PARTED, "$parted -s $device print|") || die "Unable to read from $fdisk";
714while (<PARTED>) {
715    if ($_ =~ /Disk label type: msdos/) {
716        $type= "msdos";
717        print FLOG "Found a msdos partition format\n";
718        last;
719    }
720}
721close(FDISK);
722return ($type);
723}
724
725sub mysyn {
726    print "Syntax: $0 [-l] device | [-s] partition\n";
727    myexit(-1);
728}
Note: See TracBrowser for help on using the repository browser.