source: branches/3.3/mindi/mr-parted2fdisk @ 3664

Last change on this file since 3664 was 3664, checked in by bruno, 2 years ago

Attempts to fix mr-parted2fdisk

  • usage of -m option of parted where possible to ease analysis
  • handle new fdisk formats
  • Property svn:keywords set to Id
File size: 21.0 KB
Line 
1#!/usr/bin/perl -w
2#
3# $Id: mr-parted2fdisk 3664 2017-05-03 09:27:15Z bruno $
4#
5# mr-parted2fdisk: fdisk like interface for parted
6# [developed 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 - RHEL 5 -
10#
11# Copyright B. Cornec 2000-2015
12# Provided under the GPL v2
13
14use strict;
15use File::Basename;
16use Getopt::Long qw(:config auto_abbrev no_ignore_case);
17use Carp qw/confess cluck/;
18use Data::Dumper;
19use English;
20use FileHandle;
21use MondoRescue::Version;
22use MondoRescue::Base;
23use MondoRescue::Disk;
24use ProjectBuilder::Base;
25
26=pod
27
28=head1 NAME
29
30mr-parted2fdisk is a fdisk like command using parted internally for analysing GPT labelled disks
31
32=head1 DESCRIPTION
33
34mr-parted2fdisk behaves like the fdisk command, but dialog internally with parted in order to manipulate partition tables, which allow it to support GPT partition format as well as MBR, contrary to fdisk. It aims at providing compatible external interface with fdisk. Developed initialy for ia64 Linux, it is also useful now on x86 systems using GPT partition format (for large HDDs).
35
36=head1 SYNOPSIS
37
38mr-parted2fdisk -s partition
39
40mr-parted2fdisk -l [device]
41
42mr-parted2fdisk [-n] device
43
44=head1 OPTIONS
45
46=over 4
47
48=item B<-s>
49
50Print the size (in blocks) of the given partition.
51
52=item B<-l>
53
54List the partition tables for the specified device (or all if none specified) and then exit.
55
56=item B<-n>
57
58Fake mode. Doesn't pass the commands just simulate.
59
60=item B<-v>
61
62Verbose mode. Used to help debugging issues.
63
64=item B<no option>
65
66Allow the creation and manipulation of partition tables.
67
68=back
69
70=head1 ARGUMENTS
71
72=over 4
73
74=item B<partition>
75
76partition device file (only used with -s option).
77
78=item B<device>
79
80device file to work on.
81
82=back
83
84=head1 WEB SITES
85
86The 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/>.
87
88=head1 USER MAILING LIST
89
90For community exchanges around MondoRescue please use the list L<http://sourceforge.net/mailarchive/forum.php?forum_name=mondo-devel>
91
92=head1 AUTHORS
93
94The MondoRescue team lead by Bruno Cornec L<mailto:bruno@mondorescue.org>.
95
96=head1 COPYRIGHT
97
98MondoRescue is distributed under the GPL v2.0 license or later,
99described in the file C<COPYING> included with the distribution.
100
101=cut
102
103
104$ENV{LANG} = "C";
105$ENV{LANGUAGE} = "C";
106$ENV{LC_ALL} = "C";
107
108# Log
109my $flog = "/var/log/mr-parted2fdisk.log";
110open(FLOG, "> $flog") || die "Unable to open $flog";
111
112my $i;
113my $l;
114my $part;
115my $wpart;
116my $start = "";
117my $end = "";
118my $cylstart;
119my $cylend;
120my %start;
121my %end;
122my %type;
123my $fake = 0;
124my $mega = 1048576;
125my %opts;
126
127# Immediate flushing to avoids read error from mondorestore in log files
128$| = 1;
129
130#
131# We always use fdisk except 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 $device;
139my $endmax = "";
140my $appname = "mr-parted2fdisk";
141my ($mrver,$mrrev) = mr_version_init();
142
143pb_syntax_init("$appname Version $mrver-$mrrev\n");
144
145if ($#ARGV < 0) {
146    pb_syntax(-1,0);
147}
148
149GetOptions("help|?|h+" => \$opts{'h'}, 
150        "device|d|s=s" => \$opts{'s'},
151        "list|l" => \$opts{'l'},
152        "Log-File|L=s" => \$opts{'L'},
153        "man" => \$opts{'man'},
154        "noop|n" => \$opts{'n'},
155        "quiet|q" => \$opts{'q'},
156        "version|V=s" => \$opts{'V'},
157        "verbose|v+" => \$opts{'v'},
158        "stop-on-error!" => \$Global::pb_stop_on_error,
159) || pb_syntax(-1,0);
160
161if (defined $opts{'L'}) {
162    open(pbLOG,"> $opts{'L'}") || die "Unable to log to $opts{'L'}: $!";
163    $pbLOG = \*pbLOG;
164    }
165pb_log_init($opts{'v'}, $pbLOG);
166
167# We support at most one option and one device
168if ((defined $opts{'l'}) && (defined $opts{'s'})) {
169    pb_syntax(-1,0);
170}
171
172# Create a device var which will be the device or partition on which to work
173# whatever the option used.
174$device = $ARGV[0] if (defined $opts{'l'});
175$device = $ARGV[0] if (defined $ARGV[0]);
176
177# -s takes a partition as arg
178# so create a correct device from that
179if (defined $opts{'s'}) {
180    $device = $opts{'s'};
181    $wpart = $device;
182    # To support dev like cciss/c0d0p1
183    if ($device =~ /([0-9]+)p[0-9]+$/) {
184        $device =~ s/([0-9]+)p[0-9]+$/$1/;
185    } else {
186        $device =~ s/[0-9]+$//;
187    }
188}
189
190if (defined $opts{'n'}) {
191    print FLOG "Fake mode. Nothing will be really done\n";
192    $fake = 1;
193}
194
195# util-linux/fdisk version
196my $fdisk = pb_check_req("fdisk",0);
197open(CMD,"$fdisk -v |") || die "Unable to execute $fdisk";
198my $version = <CMD>;
199close(CMD);
200chomp($version);
201# RHEL 5 has fdisk from util-linux 2.13-pre7
202# Mageia 4 has fdisk from util-linux 2.24.2
203$version =~ s/[^0-9\.]*([0-9a-z\.-]+)[\)]*$/$1/;
204my ($v,$maj,$min) = split(/\./,$version);
205
206# Consider pre version the same as the following for formats
207if ((defined $maj) && ($maj =~ /-pre/)) {
208    $maj =~ s/-pre.*$//;
209    $maj++;
210}
211# Remove potential remaining letters
212$maj =~ s/[a-z]+//;
213
214if ((defined $min) && ($min =~ /-pre/)) {
215    $min =~ s/-pre.*$//;
216    $min++;
217}
218$min =~ s/[a-z]+// if (defined $min);
219
220my %pid = ( "FAT" => "6",
221        "fat32" => "b",
222        "fat16" => "e",
223        "ext2" => "83",
224        "ext3" => "83",
225        "ext4" => "83",
226        "xfs" => "83",
227        "btrfs" => "83",
228        "reiserfs" => "83",
229        "linux-swap" => "82",
230        "lvm" => "8e",
231        "raid" => "fd",
232        "" => "",
233    );
234my %pnum;
235
236# Reverse table of pid
237while (($i,$l) = each %pid) {
238    next if ($i eq "ext2");
239    $pnum{$l} = $i;
240}
241
242# fdisk has a bug when handling more than 1024 disks, seen on RHEL
243# so in that case we want to use parted instead
244# # Cf: http://trac.mondorescue.org/ticket/805
245my $use_parted = 0;
246open(CMD,"LANGUAGE=C $fdisk -l |") || die "Unable to execute $fdisk";
247my $lines = 0;
248while (<CMD>) {
249    $lines++ if ($_ =~ /^Disk \//);
250}
251close(CMD);
252# More than 1000 is a lot of disks so may triggers the issue
253my $maxhdd = 1;
254$use_parted = 1 if ($lines >= $maxhdd);
255
256$device = "" if ((not defined $device) || ($device =~ /^-/));
257pb_log(1,"Called with device: $device\n");
258
259# Check partition table type. Works also if no device
260$type = mr_disk_type($device);
261
262# Replacement code only for GPT disks
263if (((($v == 1) || (($v == 2) && ($maj < 22))) && ($type ne "MBR")) || ($use_parted == 1)) {
264    if ($use_parted == 1) {
265        pb_log(1,"Using parted since we detected more than $maxhdd disks...\n");
266    } else {
267        pb_log(1,"This distribution uses an old fdisk, activating replacement code for GPT disk label...\n");
268    }
269    my $parted = pb_check_req("parted",0);
270    if (defined $opts{'l'}) {
271        fdisk_list_all($device,undef,\%start,\%end, 1);
272    } elsif (defined $opts{'s'}) {
273        fdisk_list($device,$wpart,\%start,\%end, 1);
274    } else {
275        # Read fdisk orders on stdin and pass them to parted
276        # on the command line as parted doesn't read on stdin
277        pb_log(1,"Translating fdisk command to parted\n");
278        while ($i = <STDIN>) {
279            if ($i =~ /^p$/) {
280                fdisk_list($device,undef,\%start,\%end, 1);
281                print "command (m for help) sent back to fake fdisk for mondorestore\n";
282            } elsif ($i =~ /^n$/) {
283                fdisk_list($device,undef,\%start,\%end, 0);
284                if ($type ne "GPT") {
285                    pb_log(1,"Forcing GPT type of disk label\n");
286                    pb_log(1,"mklabel gpt\n");
287                    pb_system("$parted -s $device mklabel gpt\n") if ($fake == 0);
288                    $type = "GPT";
289                }
290                $l = <STDIN>;
291                if (not defined $l) {
292                    pb_log(1,"no primary/extended arg given for creation... assuming primary\n");
293                    $l = "p";
294                }
295                chomp($l);
296                $part = <STDIN>;
297                if ((not defined $part) || ($part eq "")) {
298                    pb_log(1,"no partition given for creation... skipping\n");
299                    next;
300                }
301                chomp($part);
302                $cylstart = <STDIN>;
303                chomp($cylstart);
304                if ((not defined $cylstart) || ($cylstart eq "")) {
305                    if (defined $start{$part-1}) {
306                        # in MB => cyl
307                        $cylstart = sprintf("%d",$end{$part-1}*$mega/$un + 1);
308                    } else {
309                        $cylstart = 1;
310                    }
311                    pb_log(1,"no start cyl given for creation... assuming the following: $cylstart\n");
312                } else {
313                    pb_log(1,"start cyl: $cylstart\n");
314                }
315                $cylstart = 1 if ($cylstart < 1);
316                $un = get_un($device, "", 0);
317                # parted needs MB
318                if ($cylstart == 1) {
319                    $start = 0.01;
320                } else {
321                    $start = $cylstart* $un / $mega + 0.001;
322                }
323                # this is a size in B/KB/MB/GB
324
325                $endmax = get_max($device);
326                $cylend = <STDIN>;
327                chomp($cylend);
328                if ((not defined $cylend) || ($cylend eq "")) {
329                    pb_log(1,"no end cyl given for creation... assuming full disk)\n");
330                    $cylend = $endmax;
331                }
332                # Handles end syntaxes (+, K, M, ...)
333                # to give cylinders
334                if ($cylend =~ /^\+/) {
335                    $cylend =~ s/^\+//;
336                    # Handles suffixes; return bytes
337                    $cylend = decode_Bsuf($cylend,1);
338                    # This gives the number of cyl
339                    $cylend /= $un;
340                    $cylend = sprintf("%d",$cylend);
341                    $cylend += $cylstart - 0.001;
342                    # We now have the end cyl
343                }
344                $cylend = $endmax if ($cylend > $endmax); 
345                pb_log(1,"end cyl: $cylend\n");
346                # parted needs MB
347                $end = $cylend * $un / $mega;
348                pb_log(1,"n $l $part $cylstart $cylend => mkpart primary $start $end\n");
349                pb_system("$parted -s $device mkpart primary ext2 $start $end\n") if ($fake == 0);
350                print "command (m for help) sent back to fake fdisk for mondorestore\n";
351            } elsif ($i =~ /^d$/) {
352                $part = <STDIN>;
353                if (not defined $part) {
354                    pb_log(1,"no partition given for deletion... skipping\n");
355                    next;
356                }
357                chomp($part);
358                pb_log(1,"d $part => rm $part\n");
359                pb_system("$parted -s $device rm $part\n") if ($fake == 0);
360                get_parted($device,undef,\%start,\%end,undef);
361                print "command (m for help) sent back to fake fdisk for mondorestore\n";
362            } elsif ($i =~ /^w$/) {
363                pb_log(1,"w => quit\n");
364            } elsif ($i =~ /^t$/) {
365                $part = <STDIN>;
366                if (not defined $part) {
367                    pb_log(1,"no partition given for tagging... skipping\n");
368                    next;
369                }
370                chomp($part);
371                # If no partition number given it's 1, and we received the type
372                if ($part !~ /\d+/) {
373                    $l = $part;
374                    $part = 1 
375                } else {
376                    $l = <STDIN>;
377                }
378                if (not defined $l) {
379                    pb_log(1,"no type given for tagging partition $part... skipping\n");
380                    next;
381                }
382                chomp($l);
383                if (not defined $pnum{$l}) {
384                    pb_log(1,"no partition number given for $l... please report to the author\n");
385                    next;
386                }
387
388                if ($pnum{$l} eq "lvm") {
389                    # In that case this is a flag set, not a mkfs
390                    pb_log(1,"t $part $l => set $part $pnum{$l} on\n");
391                    pb_system("$parted -s $device set $part $pnum{$l} on\n") if ($fake == 0);
392                } else {
393                    pb_log(1,"t $part $l => mkfs $part $pnum{$l}\n");
394                    pb_system("$parted -s $device mkfs $part $pnum{$l}\n") if ($fake == 0);
395                }
396                print "command (m for help) sent back to fake fdisk for mondorestore\n";
397            } elsif ($i =~ /^a$/) {
398                $part = <STDIN>;
399                if (not defined $part) {
400                    pb_log(1,"no partition given for tagging... skipping\n");
401                    next;
402                }
403                chomp($part);
404
405                # Partition shouldn't be negative or null. Then take the first one.
406                $part = 1 if ($part le 0);
407
408                pb_log(1,"a $part => set $part boot on\n");
409                pb_system("$parted -s $device set $part boot on\n") if ($fake == 0);
410                print "command (m for help) sent back to fake fdisk for mondorestore\n";
411            } elsif ($i =~ /^q$/) {
412                pb_log(1,"q => quit\n");
413            } else {
414                pb_log(1,"Unknown command: $i\n");
415                print "command (m for help) sent back to fake fdisk for mondorestore\n";
416                next;
417            }
418               
419        }
420    }
421    exit(0);
422}
423
424#
425# Else everything is for fdisk
426#
427# Print only mode
428local_fdisk(\%opts,$device);
429exit(0);
430
431# End of main
432
433
434sub local_fdisk {
435
436my $opts=shift;
437my $device=shift;
438
439pb_log(1,"Passing everything to the real fdisk with device: $device\n");
440pb_log(1,"and the -s $wpart option\n") if (defined $opts{'s'});
441
442if ((defined $opts->{'l'}) || (defined $opts->{'s'})) {
443    my $args = "-l $device" if (defined $opts->{'l'});
444    $args = "-s $wpart" if (defined $opts->{'s'});
445    open (FDISK, "$fdisk $args 2>/dev/null |") || die "Unable to read from $fdisk";
446    while (<FDISK>) {
447        print $_;
448    }
449    close(FDISK);
450} else {
451    # Modification mode
452    open (FDISK, "| $fdisk $device 2>/dev/null") || die "Unable to modify through $fdisk";
453    # disable fdisk output buffering
454    autoflush FDISK 1;
455    while (<STDIN>) {
456        print FDISK $_;
457    }
458    close(FDISK);
459    close(STDIN);
460}
461return;
462}
463
464# Unused for now - Kept for reference in case there is a need later on
465sub fdisk_list_all {
466
467my $device = shift;
468my $wpart = shift;
469my $start = shift;
470my $end = shift;
471my $verbose = shift;
472
473return fdisk_list($device,$wpart,$start,$end,$verbose) if ((defined $device) && ($device ne ""));
474
475# If no device given loop on the list of devices found in /proc/partitions
476open(PART,"/proc/partitions") || die "Unable to open /proc/partitions";
477while (<PART>) {
478    # Skip first cmt line if present or empty lines
479    next if (($_ =~ /^maj/) || ($_ =~ /^\s*$/));
480    my ($void,$maj,$min,$blocks,$dev) = split(/\s+/);
481    next if ((not defined $dev) || ($dev =~ /^fd|^sr|^ram/));
482    next if ((not defined $min) || ($min != 0));
483    fdisk_list("/dev/$dev",$wpart,$start,$end,$verbose);
484}
485close(PART);
486}
487
488
489sub fdisk_list {
490
491my $device = shift;
492my $wpart = shift;
493my $start = shift;
494my $end = shift;
495my $verbose = shift;
496
497my $un;
498my $endmax;
499my $d;
500my $n;
501
502my %cmt = ( "FAT" => "FAT",
503        "ext2" => "Linux",
504        "ext3" => "Linux",
505        "ext4" => "Linux",
506        "xfs" => "Linux",
507        "reiserfs" => "Linux",
508        "linux-swap" => "Linux swap",
509        "lvm" => "Linux LVM",
510        "raid" => "RAID Linux auto",
511        "fat16" => "fat16",
512        "fat32" => "fat32",
513        "" => "Linux",
514);
515
516my $part;
517my $mstart;
518my $mend;
519my $length;
520my $pid;
521my $cmt;
522format FLOG1 =
523@<<<<<<<<<<<< @>>>>>>>>>> @>>>>>>>>>> @>>>>>>>>>> @>>>  @<<<<<<<<<<<<<<<<<<<<<<<<<<<<
524$part,        $mstart,   $mend,   $length,  $pid, $cmt
525.
526format FLOG2 =
527@<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
528$part,
529              @>>>>>>>>>> @>>>>>>>>>> @>>>>>>>>>> @>>>  @<<<<<<<<<<<<<<<<<<<<<<<<<<<<
530              $mstart,   $mend,   $length,  $pid, $cmt
531.
532format STDOUT1 =
533@<<<<<<<<<<<< @>>>>>>>>>> @>>>>>>>>>> @>>>>>>>>>> @>>>  @<<<<<<<<<<<<<<<<<<<<<<<<<<<<
534$part,        $mstart,   $mend,   $length,  $pid, $cmt
535.
536format STDOUT2 =
537@<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
538$part,
539              @>>>>>>>>>> @>>>>>>>>>> @>>>>>>>>>> @>>>  @<<<<<<<<<<<<<<<<<<<<<<<<<<<<
540              $mstart,   $mend,   $length,  $pid, $cmt
541.
542#   Device Boot      Start         End      Blocks   Id  System
543#/dev/hda1               1       77579    39099374+  ee  EFI GPT
544
545
546#
547# Keep Fdisk headers
548#
549# this will return bytes
550$un = get_un($device,$wpart,$verbose);
551
552$endmax = get_max($device);
553
554# This will return MB
555get_parted($device,$start,$end,\%type);
556
557while (($n,$d) = each %type) {
558    # Print infos fdisk like
559    $part = ${device}.$n;
560    # start and end are in cylinder in fdisk format
561    # so return in MB * 1MB / what represents 1 cyl in B
562    $mstart = sprintf("%d",$$start{$n}*$mega/$un);
563    pb_log(2,"mstart: $mstart\n");
564    $mstart = 1 if ($mstart < 1);
565    $mstart = $endmax if ($mstart > $endmax);
566    $mend = sprintf("%d",$$end{$n}*$mega/$un - 1);
567    $mend = $endmax if ($mend > $endmax);
568    pb_log(2,"mend $mend\n");
569    $mend = 1 if ($mend < 1);
570    # length is in 1K blocks
571    $length = sprintf("%d",($mend-$mstart+1)*$un/1024);
572    $pid = $pid{$type{$n}};
573    $cmt = $cmt{$type{$n}};
574    pb_log(2,"$part - $mstart - $mend - $length\n");
575
576    if ($verbose == 1) {
577        if (not defined $wpart) {
578            if (length($part) > 13) {
579                open(STDOUT2,">&STDOUT") || die "Unable to open STDOUT2";
580                select(STDOUT2);
581                write;
582                open(FLOG2,">&FLOG") || die "Unable to open FLOG2";
583                select(FLOG2);
584                write;
585                select(STDOUT);
586                close(FLOG2);
587                close(STDOUT2);
588            } else {
589                open(STDOUT1,">&STDOUT") || die "Unable to open STDOUT1";
590                select(STDOUT1);
591                write;
592                open(FLOG1,">&FLOG") || die "Unable to open FLOG1";
593                select(FLOG1);
594                write;
595                select(STDOUT);
596                close(FLOG1);
597                close(STDOUT1);
598            }
599        } else {
600            # manage the -s option of fdisk here
601            print "$length\n" if ($part eq $wpart);
602            pb_log(1,"$part has $length KBytes\n") if ($part eq $wpart);
603        }
604    }
605}
606close(FDISK);
607close(PARTED);
608}
609
610#
611# Get max size from fdisk
612#
613sub get_max {
614
615my $device = shift;
616my $max = 0;
617my $foo;
618
619open (FDISK, "$fdisk -l $device 2>/dev/null |") || die "Unable to read from $fdisk";
620while (<FDISK>) {
621    if ($_ =~ /heads/) {
622        chomp;
623        $max = $_;
624        $max =~ s/.* ([0-9]+) cylinders/$1/;
625    }
626}
627if ($max == 0) {
628    close(FDISK);
629    # Try by forcing the cylinders display, not done by default on more recent fdisk
630    open (FDISK, "$fdisk -u=cylinders -l $device 2>/dev/null |") || die "Unable to read from $fdisk -u=cylinders";
631    while (<FDISK>) {
632        if ($_ =~ /heads/) {
633            chomp;
634            $max = $_;
635            $max =~ s/.* ([0-9]+) cylinders/$1/;
636        }
637    }
638}
639close(FDISK);
640pb_log(2,"get_max returns $max\n");
641return($max);
642}
643
644#
645# Get units from fdisk (cylinder size)
646#
647sub get_un {
648
649my $device = shift;
650my $wpart = shift;
651my $verbose = shift;
652my $un = 0;
653my $foo;
654
655open (FDISK, "$fdisk -l $device 2>/dev/null |") || die "Unable to read from $fdisk";
656while (<FDISK>) {
657    print if (($_ !~ /^\/dev\//) and (not (defined $wpart)) and ($verbose == 1));
658    if ($_ =~ /^Units/) {
659        ($foo, $un , $foo) = split /=/;
660        $un =~ s/[A-z\s=]//g;
661        $un = eval($un);
662    }
663}
664close(FDISK);
665pb_log(2,"get_un returns $un\n");
666return($un);
667}
668
669#
670# Parted gives info in MB
671# (depending on versions - 1.6.25.1 provides suffixes)
672#
673sub get_parted {
674
675my $device = shift;
676my $start = shift;
677my $end = shift;
678my $type = shift;
679my $void;
680my $d;
681my $n;
682my $ret;
683my $mode;
684my $size;
685my $unit;
686my $flag;
687
688my $parted = pb_check_req("parted",0);
689open (PARTED, "$parted -v |") || die "Unable to read from $parted";
690$d = <PARTED>;
691pb_log(2,"$d");
692close(PARTED);
693chomp($d);
694# parted version
695$d =~ s/[^0-9\.]*([0-9\.]+)$/$1/;
696my ($v,$maj,$min) = split(/\./,$d);
697# depending on parted version, information given change:
698# parted >= 1.8.0 has support for -m option
699# Cf: http://git.savannah.gnu.org/cgit/parted.git/commit/?id=30e12276029b0b6c04d2d0edf2b9b00ba797013c
700if ($v >= 2) {
701    # RHEL 5 parted 1.8
702    # RHEL 6 parted 2.1
703    # SLES 11 1.8.8
704    $mode=2;
705} elsif ($v == 1) {
706    if (($maj <= 5) || (($maj == 6) && (defined $min) && ($min < 25))) {
707        # RHEL 3 parted 1.6.3
708        # RHEL 4 parted 1.6.19
709        $mode=0;
710    } elsif ($maj >= 8) {
711        $mode=2;
712    } else {
713        # SLES 10 parted >= 1.6.25
714        $mode=1;
715    }
716} else {
717    $mode=-1;
718}
719pb_log(2,"parted mode: $mode\n");
720
721# Result of parted -m -s /dev/sda print
722#
723# On RHEL7:
724#BYT;
725#/dev/sda:500GB:scsi:512:512:gpt:HP LOGICAL VOLUME:;
726#1:1049kB:211MB:210MB:fat16:EFI System Partition:boot;
727#2:211MB:735MB:524MB:ext4::;
728#3:735MB:500GB:499GB:::lvm;
729#
730# On RHEL6:
731#BYT;
732#/dev/sda:500GB:scsi:512:512:gpt:HP LOGICAL VOLUME;
733#1:1049kB:211MB:210MB:fat16::boot;
734#2:211MB:735MB:524MB:ext4::;
735#3:735MB:500GB:499GB:::lvm;
736#
737# On Debian 8
738#
739#BYT;
740#/dev/sda:500GB:scsi:512:512:gpt:HP LOGICAL VOLUME:;
741#1:1049kB:538MB:537MB:fat32::boot, esp;
742#2:538MB:7538MB:7000MB:ext4::;
743#3:7538MB:10.5GB:3000MB:ext4::;
744#4:10.5GB:44.6GB:34.1GB:linux-swap(v1)::;
745#5:44.6GB:45.0GB:400MB:ext4::;
746#6:45.0GB:500GB:455GB:ext4::;
747
748if ($mode == 2) {
749    # Then use option -m which is available
750    open(PARTED, "$parted -m -s $device print |") || die "Unable to read from $parted";
751    # Skip 2 first lines
752    $d = <PARTED>;
753    if ($d !~ /^BYT/) {
754        die "Your $parted command doesn't behave correctly in machine readable mode";
755    }
756    # Skip device line for now
757    $d = <PARTED>;
758    pb_log(2,"Got from parted: \n");
759    pb_log(2,"Minor    Start       End     Filesystem\n");
760    while (<PARTED>) {
761        ($n,$d) = split(/:/,$_,2);
762        ($$start{$n},$$end{$n},$size,$$type{$n},$void,$flag) = split(/:/,$d);
763        # Handles suffixes. Returns MB
764        $ret = decode_Bsuf($$start{$n},$mega);
765        $$start{$n} = $ret;
766        $ret = decode_Bsuf($$end{$n},$mega);
767        $$end{$n} = $ret;
768        $$type{$n} =~ s/\(..*\)$//;
769        pb_log(2,"$n      $$start{$n}      $$end{$n}     $$type{$n}\n");
770    }
771} else {
772    # Maintaned for compatibility with very old distributions now
773    open(PARTED, "$parted -s $device print |") || die "Unable to read from $parted";
774    # Skip 3 first lines
775    $d = <PARTED>;
776    $d = <PARTED>;
777    $d = <PARTED>;
778
779    pb_log(2,"Got from parted: \n");
780    pb_log(2,"Minor    Start       End     Filesystem\n");
781    # Get info from each partition line
782    while (($n,$d) = split(/\s/, <PARTED>,2)) {
783        chomp($d);
784        next if ($n !~ /^[1-9]/);
785        $d =~ s/^\s*//;
786        $d =~ s/\s+/ /g;
787        if ($mode == 0) {
788            ($$start{$n},$$end{$n},$$type{$n},$void) = split(/ /,$d);
789            $unit = 1;
790        } elsif ($mode == 1) {
791            ($$start{$n},$$end{$n},$size,$$type{$n},$void) = split(/ /,$d);
792            $unit = $mega;
793        } else {
794            die "Undefined mode $mode";
795        }
796        $$start{$n} = "" if (not defined $$start{$n});
797        $$end{$n} = "" if (not defined $$end{$n});
798        $$type{$n} = "" if (not defined $$type{$n});
799        # Handles potential suffixes in latest parted version. Return MB
800        $ret = decode_Bsuf($$start{$n},$unit);
801        $$start{$n} = $ret;
802        $ret = decode_Bsuf($$end{$n},$unit);
803        $$end{$n} = $ret;
804        pb_log(2,"$n      $$start{$n}      $$end{$n}     $$type{$n}\n");
805    }
806}
807close(PARTED);
808}
809
810sub decode_Bsuf {
811
812my $size  = shift;
813my $unit  = shift;
814my $ret = 0;
815my $kilo = 1024;
816
817pb_log(2,"decode_Bsuf input: $size / $unit ");
818if ($size =~ /K[B]*$/i) {
819    $size =~ s/K[B]*$//i;
820    $size *= $kilo;
821} elsif ($size =~ /M[B]*$/i) {
822    $size =~ s/M[B]*$//i;
823    $size *= $kilo*$kilo;
824} elsif ($size =~ /G[B]*$/i) {
825    $size =~ s/G[B]*$//i;
826    $size *= $kilo*$kilo*$kilo;
827} elsif ($size =~ /T[B]*$/i) {
828    $size =~ s/T[B]*$//i;
829    $size *= $kilo*$kilo*$kilo*$kilo;
830} else {
831    # Nothing to do
832}
833$ret = $size / $unit;
834pb_log(2," - output : $size => $ret\n");
835return($ret);
836}
Note: See TracBrowser for help on using the repository browser.