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

Last change on this file since 3661 was 3647, checked in by Bruno Cornec, 7 years ago
  • Fix #805 by forcing the usage of parted when more than 1000 disks are reported by fdisk
  • Property svn:keywords set to Id
File size: 18.9 KB
RevLine 
[1]1#!/usr/bin/perl -w
2#
[88]3# $Id: mr-parted2fdisk 3647 2017-01-13 16:35:12Z bruno $
4#
[3377]5# mr-parted2fdisk: fdisk like interface for parted
[3343]6# [developed for mindi/mondo http://www.mondorescue.org]
[1]7#
8# Aims to be architecture independant (i386/ia64)
[3355]9# Tested on ia64 with RHAS 2.1 - Mandrake 9.0 - RHEL 3.0 - SLES 10 - RHEL 5 -
[1]10#
[3343]11# Copyright B. Cornec 2000-2015
[3143]12# Provided under the GPL v2
[1]13
14use strict;
[3343]15use File::Basename;
[3370]16use Getopt::Long qw(:config auto_abbrev no_ignore_case);
17use Carp qw/confess cluck/;
18use Data::Dumper;
19use English;
[3631]20use FileHandle;
[3370]21use MondoRescue::Version;
22use MondoRescue::Base;
23use MondoRescue::Disk;
24use ProjectBuilder::Base;
[1]25
[3143]26=pod
27
28=head1 NAME
29
[3377]30mr-parted2fdisk is a fdisk like command using parted internally for analysing GPT labelled disks
[3143]31
32=head1 DESCRIPTION
33
[3377]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).
[3143]35
36=head1 SYNOPSIS
37
[3377]38mr-parted2fdisk -s partition
[3370]39
[3377]40mr-parted2fdisk -l [device]
[3370]41
[3377]42mr-parted2fdisk [-n] device
[3143]43
44=head1 OPTIONS
45
46=over 4
47
48=item B<-s>
49
50Print the size (in blocks) of the given partition.
51
[3370]52=item B<-l>
53
54List the partition tables for the specified device (or all if none specified) and then exit.
55
[3143]56=item B<-n>
57
58Fake mode. Doesn't pass the commands just simulate.
59
[3377]60=item B<-v>
61
62Verbose mode. Used to help debugging issues.
63
[3143]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
[1]104$ENV{LANG} = "C";
105$ENV{LANGUAGE} = "C";
106$ENV{LC_ALL} = "C";
107
108# Log
[3377]109my $flog = "/var/log/mr-parted2fdisk.log";
[1]110open(FLOG, "> $flog") || die "Unable to open $flog";
111
112my $i;
113my $l;
114my $part;
115my $wpart;
116my $start = "";
117my $end = "";
[90]118my $cylstart;
119my $cylend;
[1]120my %start;
121my %end;
122my %type;
[88]123my $fake = 0;
[1801]124my $mega = 1048576;
[3370]125my %opts;
[1]126
[2163]127# Immediate flushing to avoids read error from mondorestore in log files
128$| = 1;
129
[1]130#
[3343]131# We always use fdisk except with GPT types of
[1]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;
[3370]138my $device;
[88]139my $endmax = "";
[3377]140my $appname = "mr-parted2fdisk";
[3370]141my ($mrver,$mrrev) = mr_version_init();
[1]142
[3370]143pb_syntax_init("$appname Version $mrver-$mrrev\n");
144
[1]145if ($#ARGV < 0) {
[3370]146 pb_syntax(-1,0);
[1]147}
148
[3370]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
[3647]172# Create a device var which will be the device or partition on which to work
[3370]173# whatever the option used.
174$device = $ARGV[0] if (defined $opts{'l'});
175$device = $opts{'s'} if (defined $opts{'s'});
176$device = $ARGV[0] if (defined $ARGV[0]);
177$device = "" if ((not defined $device) || ($device =~ /^-/));
178
179# -s takes a partition as arg
180# so create a correct device from that
181if (defined $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
196pb_log(1,"Called with device: $device\n");
197
[1]198my %pid = ( "FAT" => "6",
199 "fat32" => "b",
200 "fat16" => "e",
201 "ext2" => "83",
202 "ext3" => "83",
[2087]203 "ext4" => "83",
204 "xfs" => "83",
[3330]205 "btrfs" => "83",
[1565]206 "reiserfs" => "83",
[1]207 "linux-swap" => "82",
[2158]208 "lvm" => "8e",
[3343]209 "raid" => "fd",
[1]210 "" => "",
211 );
212my %pnum;
213
214# Reverse table of pid
215while (($i,$l) = each %pid) {
216 next if ($i eq "ext2");
217 $pnum{$l} = $i;
218}
219
[3343]220# util-linux/fdisk version
[3370]221my $fdisk = pb_check_req("fdisk",0);
[3343]222open(CMD,"$fdisk -v |") || die "Unable to execute $fdisk";
223my $version = <CMD>;
224close(CMD);
225chomp($version);
[3383]226# RHEL 5 has fdisk from util-linux 2.13-pre7
[3355]227# Mageia 4 has fdisk from util-linux 2.24.2
228$version =~ s/[^0-9\.]*([0-9a-z\.-]+)[\)]*$/$1/;
[3343]229my ($v,$maj,$min) = split(/\./,$version);
230
[3355]231# Consider pre version the same as the following for formats
232if ((defined $maj) && ($maj =~ /-pre/)) {
233 $maj =~ s/-pre.*$//;
234 $maj++;
235}
[3576]236# Remove potential remaining letters
237$maj =~ s/[a-z]+//;
238
[3355]239if ((defined $min) && ($min =~ /-pre/)) {
240 $min =~ s/-pre.*$//;
241 $min++;
242}
[3582]243$min =~ s/[a-z]+// if (defined $min);
[3355]244
[3647]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
256$use_parted = 1 if ($lines >= 1000);
257
[3370]258# Check partition table type
259$type = mr_disk_type($device);
260# Replacement code only for GPT disks
[3647]261if (((($v == 1) || (($v == 2) && ($maj < 22))) && ($type ne "MBR")) || ($use_parted == 1)) {
[3370]262 pb_log(1,"This distribution uses an old fdisk, activating replacement code for GPT disk label...\n");
263 my $parted = pb_check_req("parted",0);
264 if (defined $opts{'l'}) {
265 fdisk_list($device,undef,\%start,\%end, 1);
266 } elsif (defined $opts{'s'}) {
267 fdisk_list($device,$wpart,\%start,\%end, 1);
268 } else {
269 # Read fdisk orders on stdin and pass them to parted
270 # on the command line as parted doesn't read on stdin
271 pb_log(1,"Translating fdisk command to parted\n");
272 while ($i = <STDIN>) {
273 if ($i =~ /^p$/) {
274 fdisk_list($device,undef,\%start,\%end, 1);
275 print "command (m for help) sent back to fake fdisk for mondorestore\n";
276 } elsif ($i =~ /^n$/) {
277 fdisk_list($device,undef,\%start,\%end, 0);
[3553]278 if ($type ne "GPT") {
[3370]279 pb_log(1,"Forcing GPT type of disk label\n");
280 pb_log(1,"mklabel gpt\n");
281 pb_system("$parted -s $device mklabel gpt\n") if ($fake == 0);
[3553]282 $type = "GPT";
[3370]283 }
284 $l = <STDIN>;
285 if (not defined $l) {
286 pb_log(1,"no primary/extended arg given for creation... assuming primary\n");
287 $l = "p";
288 }
289 chomp($l);
290 $part = <STDIN>;
291 if ((not defined $part) || ($part eq "")) {
292 pb_log(1,"no partition given for creation... skipping\n");
293 next;
294 }
295 chomp($part);
296 $cylstart = <STDIN>;
297 chomp($cylstart);
298 if ((not defined $cylstart) || ($cylstart eq "")) {
299 if (defined $start{$part-1}) {
300 # in MB => cyl
301 $cylstart = sprintf("%d",$end{$part-1}*$mega/$un + 1);
[90]302 } else {
[3370]303 $cylstart = 1;
[90]304 }
[3370]305 pb_log(1,"no start cyl given for creation... assuming the following: $cylstart\n");
306 } else {
307 pb_log(1,"start cyl: $cylstart\n");
308 }
309 $cylstart = 1 if ($cylstart < 1);
310 $un = get_un($device, "", 0);
311 # parted needs MB
312 if ($cylstart == 1) {
313 $start = 0.01;
314 } else {
315 $start = $cylstart* $un / $mega + 0.001;
316 }
317 # this is a size in B/KB/MB/GB
[90]318
[3370]319 $endmax = get_max($device);
320 $cylend = <STDIN>;
321 chomp($cylend);
322 if ((not defined $cylend) || ($cylend eq "")) {
323 pb_log(1,"no end cyl given for creation... assuming full disk)\n");
324 $cylend = $endmax;
325 }
326 # Handles end syntaxes (+, K, M, ...)
327 # to give cylinders
328 if ($cylend =~ /^\+/) {
329 $cylend =~ s/^\+//;
330 # Handles suffixes; return bytes
331 $cylend = decode_Bsuf($cylend,1);
332 # This gives the number of cyl
333 $cylend /= $un;
334 $cylend = sprintf("%d",$cylend);
335 $cylend += $cylstart - 0.001;
336 # We now have the end cyl
337 }
338 $cylend = $endmax if ($cylend > $endmax);
339 pb_log(1,"end cyl: $cylend\n");
340 # parted needs MB
341 $end = $cylend * $un / $mega;
342 pb_log(1,"n $l $part $cylstart $cylend => mkpart primary $start $end\n");
343 pb_system("$parted -s $device mkpart primary ext2 $start $end\n") if ($fake == 0);
344 print "command (m for help) sent back to fake fdisk for mondorestore\n";
345 } elsif ($i =~ /^d$/) {
346 $part = <STDIN>;
347 if (not defined $part) {
348 pb_log(1,"no partition given for deletion... skipping\n");
349 next;
350 }
351 chomp($part);
352 pb_log(1,"d $part => rm $part\n");
353 pb_system("$parted -s $device rm $part\n") if ($fake == 0);
354 get_parted($device,undef,\%start,\%end,undef);
355 print "command (m for help) sent back to fake fdisk for mondorestore\n";
356 } elsif ($i =~ /^w$/) {
357 pb_log(1,"w => quit\n");
358 } elsif ($i =~ /^t$/) {
359 $part = <STDIN>;
360 if (not defined $part) {
361 pb_log(1,"no partition given for tagging... skipping\n");
362 next;
363 }
364 chomp($part);
365 # If no partition number given it's 1, and we received the type
366 if ($part !~ /\d+/) {
367 $l = $part;
368 $part = 1
369 } else {
370 $l = <STDIN>;
371 }
372 if (not defined $l) {
373 pb_log(1,"no type given for tagging partition $part... skipping\n");
374 next;
375 }
376 chomp($l);
377 if (not defined $pnum{$l}) {
378 pb_log(1,"no partition number given for $l... please report to the author\n");
379 next;
380 }
[2158]381
[3370]382 if ($pnum{$l} eq "lvm") {
383 # In that case this is a flag set, not a mkfs
384 pb_log(1,"t $part $l => set $part $pnum{$l} on\n");
385 pb_system("$parted -s $device set $part $pnum{$l} on\n") if ($fake == 0);
[2154]386 } else {
[3370]387 pb_log(1,"t $part $l => mkfs $part $pnum{$l}\n");
388 pb_system("$parted -s $device mkfs $part $pnum{$l}\n") if ($fake == 0);
389 }
390 print "command (m for help) sent back to fake fdisk for mondorestore\n";
391 } elsif ($i =~ /^a$/) {
392 $part = <STDIN>;
393 if (not defined $part) {
394 pb_log(1,"no partition given for tagging... skipping\n");
[1]395 next;
396 }
[3370]397 chomp($part);
398
399 # Partition shouldn't be negative or null. Then take the first one.
400 $part = 1 if ($part le 0);
401
402 pb_log(1,"a $part => set $part boot on\n");
403 pb_system("$parted -s $device set $part boot on\n") if ($fake == 0);
404 print "command (m for help) sent back to fake fdisk for mondorestore\n";
405 } elsif ($i =~ /^q$/) {
406 pb_log(1,"q => quit\n");
407 } else {
408 pb_log(1,"Unknown command: $i\n");
409 print "command (m for help) sent back to fake fdisk for mondorestore\n";
410 next;
[1]411 }
[3370]412
[1]413 }
414 }
[3370]415 exit(0);
[1]416}
417
418#
419# Else everything is for fdisk
420#
421# Print only mode
[3370]422local_fdisk(\%opts,$device);
423exit(0);
[3355]424
[3370]425# End of main
426
427
[3355]428sub local_fdisk {
429
[3370]430my $opts=shift;
[3355]431my $device=shift;
432
[3370]433pb_log(1,"Passing everything to the real fdisk with device: $device\n");
434pb_log(1,"and the -s $wpart option\n") if (defined $opts{'s'});
[1]435
[3370]436if ((defined $opts->{'l'}) || (defined $opts->{'s'})) {
437 my $args = "-l $device" if (defined $opts->{'l'});
438 $args = "-s $wpart" if (defined $opts->{'s'});
439 open (FDISK, "$fdisk $args 2>/dev/null |") || die "Unable to read from $fdisk";
[1]440 while (<FDISK>) {
[3344]441 print $_;
[1]442 }
443 close(FDISK);
444} else {
445 # Modification mode
[3370]446 open (FDISK, "| $fdisk $device 2>/dev/null") || die "Unable to modify through $fdisk";
[3591]447 # disable fdisk output buffering
448 autoflush FDISK 1;
[1]449 while (<STDIN>) {
[3344]450 print FDISK $_;
[1]451 }
452 close(FDISK);
453 close(STDIN);
454}
[3355]455return;
456}
[1]457
[3355]458# Unused for now - Kept for reference in case there is a need later on
459sub fdisk_list_all {
[3370]460
[3355]461my $device = shift;
462my $wpart = shift;
463my $start = shift;
464my $end = shift;
465my $verbose = shift;
466
467return fdisk_list($device,$wpart,$start,$end,$verbose) if ((defined $device) && ($device ne ""));
468
469# If no device given loop on the list of devices found in /proc/partitions
470open(PART,"/proc/partitions") || die "Unable to open /proc/partitions";
471while (<PART>) {
472 my ($maj,$min,$blocks,$dev) = split(/\s+/);
473 next if ($dev =~ /^fd|^sr/);
474 next if ($min != 0);
475 fdisk_list("/dev/$dev",$wpart,$start,$end,$verbose);
476}
477close(PART);
478}
479
480
[1]481sub fdisk_list {
482
483my $device = shift;
484my $wpart = shift;
485my $start = shift;
486my $end = shift;
[90]487my $verbose = shift;
[1]488
489my $un;
[88]490my $endmax;
[1]491my $d;
492my $n;
493
494my %cmt = ( "FAT" => "FAT",
495 "ext2" => "Linux",
496 "ext3" => "Linux",
[2087]497 "ext4" => "Linux",
498 "xfs" => "Linux",
[1565]499 "reiserfs" => "Linux",
[1]500 "linux-swap" => "Linux swap",
[2158]501 "lvm" => "Linux LVM",
[3343]502 "raid" => "RAID Linux auto",
[1]503 "fat16" => "fat16",
504 "fat32" => "fat32",
505 "" => "Linux",
506);
507
508my $part;
509my $mstart;
510my $mend;
511my $length;
512my $pid;
513my $cmt;
514format FLOG1 =
[1565]515@<<<<<<<<<<<< @>>>>>>>>>> @>>>>>>>>>> @>>>>>>>>>> @>>> @<<<<<<<<<<<<<<<<<<<<<<<<<<<<
[1]516$part, $mstart, $mend, $length, $pid, $cmt
517.
518format FLOG2 =
519@<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
520$part,
[1565]521 @>>>>>>>>>> @>>>>>>>>>> @>>>>>>>>>> @>>> @<<<<<<<<<<<<<<<<<<<<<<<<<<<<
[1]522 $mstart, $mend, $length, $pid, $cmt
523.
524format STDOUT1 =
[1565]525@<<<<<<<<<<<< @>>>>>>>>>> @>>>>>>>>>> @>>>>>>>>>> @>>> @<<<<<<<<<<<<<<<<<<<<<<<<<<<<
[1]526$part, $mstart, $mend, $length, $pid, $cmt
527.
528format STDOUT2 =
529@<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
530$part,
[1565]531 @>>>>>>>>>> @>>>>>>>>>> @>>>>>>>>>> @>>> @<<<<<<<<<<<<<<<<<<<<<<<<<<<<
[1]532 $mstart, $mend, $length, $pid, $cmt
533.
[1565]534# Device Boot Start End Blocks Id System
535#/dev/hda1 1 77579 39099374+ ee EFI GPT
[1]536
[1565]537
[1]538#
539# Keep Fdisk headers
540#
[88]541# this will return bytes
[3364]542$un = get_un($device,$wpart,$verbose);
[90]543
[88]544$endmax = get_max($device);
[90]545
[88]546# This will return MB
[3355]547get_parted($device,$start,$end,\%type);
[1]548
549while (($n,$d) = each %type) {
550 # Print infos fdisk like
551 $part = ${device}.$n;
[88]552 # start and end are in cylinder in fdisk format
553 # so return in MB * 1MB / what represents 1 cyl in B
[1801]554 $mstart = sprintf("%d",$$start{$n}*$mega/$un);
[88]555 $mstart = 1 if ($mstart < 1);
[1565]556 $mstart = $endmax if ($mstart > $endmax);
[1801]557 $mend = sprintf("%d",$$end{$n}*$mega/$un - 1);
[88]558 $mend = $endmax if ($mend > $endmax);
[1565]559 $mend = 1 if ($mend < 1);
[88]560 # length is in 1K blocks
561 $length = sprintf("%d",($mend-$mstart+1)*$un/1024);
[1]562 $pid = $pid{$type{$n}};
563 $cmt = $cmt{$type{$n}};
[90]564 #print FLOG "$part - $mstart - $mend - $length\n";
[1]565
[90]566 if ($verbose == 1) {
[3370]567 if (not defined $wpart) {
[90]568 if (length($part) > 13) {
569 open(STDOUT2,">&STDOUT") || die "Unable to open STDOUT2";
570 select(STDOUT2);
571 write;
572 open(FLOG2,">&FLOG") || die "Unable to open FLOG2";
573 select(FLOG2);
574 write;
575 select(STDOUT);
576 close(FLOG2);
577 close(STDOUT2);
578 } else {
579 open(STDOUT1,">&STDOUT") || die "Unable to open STDOUT1";
580 select(STDOUT1);
581 write;
582 open(FLOG1,">&FLOG") || die "Unable to open FLOG1";
583 select(FLOG1);
584 write;
585 select(STDOUT);
586 close(FLOG1);
587 close(STDOUT1);
588 }
[1]589 } else {
[90]590 # manage the -s option of fdisk here
591 print "$length\n" if ($part eq $wpart);
[3370]592 pb_log(1,"$part has $length KBytes\n") if ($part eq $wpart);
[1]593 }
594 }
595}
596close(FDISK);
597close(PARTED);
598}
599
600#
601# Get max size from fdisk
602#
603sub get_max {
604
605my $device = shift;
606my $max = 0;
607my $foo;
608
[1857]609open (FDISK, "$fdisk -l $device 2>/dev/null |") || die "Unable to read from $fdisk";
[1]610while (<FDISK>) {
[88]611 if ($_ =~ /heads/) {
612 chomp;
613 $max = $_;
614 $max =~ s/.* ([0-9]+) cylinders/$1/;
[1]615 }
616}
617close(FDISK);
[3370]618pb_log(2,"get_max returns $max\n");
[1]619return($max);
620}
621
622#
[88]623# Get units from fdisk (cylinder size)
[1]624#
625sub get_un {
626
627my $device = shift;
628my $wpart = shift;
[90]629my $verbose = shift;
[1]630my $un = 0;
631my $foo;
632
[1857]633open (FDISK, "$fdisk -l $device 2>/dev/null |") || die "Unable to read from $fdisk";
[1]634while (<FDISK>) {
[90]635 print if (($_ !~ /^\/dev\//) and (not (defined $wpart)) and ($verbose == 1));
[1]636 if ($_ =~ /^Units/) {
637 ($foo, $un , $foo) = split /=/;
638 $un =~ s/[A-z\s=]//g;
639 $un = eval($un);
640 }
641}
642close(FDISK);
[3370]643pb_log(2,"get_un returns $un\n");
[1]644return($un);
645}
646
[88]647#
648# Parted gives info in MB
[1565]649# (depending on versions - 1.6.25.1 provides suffixes)
[88]650#
[1]651sub get_parted {
652
653my $device = shift;
654my $start = shift;
655my $end = shift;
656my $type = shift;
[1565]657my $void;
[1]658my $d;
659my $n;
[1565]660my $ret;
661my $mode;
662my $size;
[1801]663my $unit;
[1]664
[3370]665my $parted = pb_check_req("parted",0);
[1565]666open (PARTED, "$parted -v |") || die "Unable to read from $parted";
667$d = <PARTED>;
[3370]668pb_log(2,"$d");
[1565]669close(PARTED);
[3343]670chomp($d);
671# parted version
672$d =~ s/[^0-9\.]*([0-9\.]+)$/$1/;
673my ($v,$maj,$min) = split(/\./,$d);
674# depending on parted version, information given change:
675if ($v == 2) {
676 # RHEL 6 parted 2.1
677 $mode=2;
678} elsif ($v == 1) {
679 if (($maj <= 5) || (($maj == 6) && (defined $min) && ($min < 25))) {
680 # RHEL 3 parted 1.6.3
681 # RHEL 4 parted 1.6.19
682 $mode=0;
683 } else {
684 # SLES 10 parted >= 1.6.25
685 $mode=1;
686 }
687} else {
688 $mode=-1;
689}
[3370]690pb_log(2,"parted mode: $mode\n");
[1565]691
[3370]692open(PARTED, "$parted -s $device print |") || die "Unable to read from $parted";
[1]693# Skip 3 first lines
694$d = <PARTED>;
695$d = <PARTED>;
696$d = <PARTED>;
[1565]697
[3343]698if ($mode == 2) {
699 $d = <PARTED>;
700 $d = <PARTED>;
701 $d = <PARTED>;
[1565]702}
[3370]703pb_log(2,"Got from parted: \n");
704pb_log(2,"Minor Start End Filesystem\n");
[1]705# Get info from each partition line
706while (($n,$d) = split(/\s/, <PARTED>,2)) {
707 chomp($d);
[3343]708 # v2 of parted ends with empty line
709 next if (($mode == 2) && ($n eq "") && ($d eq ""));
710 # v2 of parted starts with space potentially
711 ($n,$d) = split(/\s/, $d,2) if (($mode == 2) && ($n eq ""));
[1]712 next if ($n !~ /^[1-9]/);
713 $d =~ s/^\s*//;
714 $d =~ s/\s+/ /g;
[1565]715 if ($mode == 0) {
716 ($$start{$n},$$end{$n},$$type{$n},$void) = split(/ /,$d);
[1801]717 $unit = 1;
[1565]718 } elsif ($mode == 1) {
719 ($$start{$n},$$end{$n},$size,$$type{$n},$void) = split(/ /,$d);
[1801]720 $unit = $mega;
[3343]721 } elsif ($mode == 2) {
722 ($$start{$n},$$end{$n},$size,$$type{$n},$void) = split(/ /,$d);
723 $unit = $mega;
[1565]724 } else {
725 die "Undefined mode $mode";
726 }
[1]727 $$start{$n} = "" if (not defined $$start{$n});
728 $$end{$n} = "" if (not defined $$end{$n});
729 $$type{$n} = "" if (not defined $$type{$n});
[1565]730 # Handles potential suffixes in latest parted version. Return MB
[1801]731 $ret = decode_Bsuf($$start{$n},$unit);
[1565]732 $$start{$n} = $ret;
[1801]733 $ret = decode_Bsuf($$end{$n},$unit);
[1565]734 $$end{$n} = $ret;
[3370]735 pb_log(2,"$n $$start{$n} $$end{$n} $$type{$n}\n");
[1]736}
737close(PARTED);
738}
739
[1565]740sub decode_Bsuf {
741
742my $size = shift;
743my $unit = shift;
744my $ret = 0;
745
[3370]746pb_log(2,"decode_Bsuf input: $size / $unit ");
[1837]747if ($size =~ /K[B]*$/i) {
748 $size =~ s/K[B]*$//i;
[1565]749 $size *= 1024;
[1837]750} elsif ($size =~ /M[B]*$/i) {
751 $size =~ s/M[B]*$//i;
[1565]752 $size *= 1048576;
[1837]753} elsif ($size =~ /G[B]*$/i) {
754 $size =~ s/G[B]*$//i;
[1565]755 $size *= 1073741824;
[1837]756} elsif ($size =~ /T[B]*$/i) {
757 $size =~ s/T[B]*$//i;
[1565]758 $size *= 1099511627776;
759} else {
760 # Nothing to do
761}
762$ret = $size / $unit;
[3370]763pb_log(2," - output : $size => $ret\n");
[1565]764return($ret);
765}
Note: See TracBrowser for help on using the repository browser.