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

Last change on this file since 3664 was 3664, checked in by Bruno Cornec, 7 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.