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

Last change on this file was 3886, checked in by Bruno Cornec, 6 weeks ago

Removes support for ia64 depracated in upstream kernel, and elilo

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