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

Last change on this file since 3666 was 3666, checked in by bruno, 16 months ago

Multiple mr-parted2fidsk fixes for parted usage

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