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

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

Fix the parted part usage (review creation of partitions with RHEL7)

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