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

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