source: MondoRescue/branches/3.2/mindi/parted2fdisk.pl@ 3197

Last change on this file since 3197 was 3143, checked in by Bruno Cornec, 11 years ago

r5349@localhost: bruno | 2013-06-14 01:23:53 +0200

  • Adds pod content to the perl scripts used, and generate man pages frmo it as part of the install process. This also fixes rpmlint and deblint issues
  • Property svn:keywords set to Id
File size: 16.8 KB
Line 
1#!/usr/bin/perl -w
2#
3# $Id: parted2fdisk.pl 3143 2013-06-14 04:06:09Z bruno $
4#
5# parted2fdisk: fdisk like interface for parted
6# [developped 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
10#
11# Copyright B. Cornec 2000-2013
12# Provided under the GPL v2
13
14use strict;
15
16
17=pod
18
19=head1 NAME
20
21parted2fdisk is a fdisk lie command using parted internally.
22
23=head1 DESCRIPTION
24
25parted2fdisk behaves like a fdisk command, but dialog internally with parted in order to manipulate partiion tables, which allow it to support GPT partition format as well as MBR, contrary to fdisk. It aimed at providing compatible external interface wti fdisk. Developed initialy for ia64 Linux, but is also useful now on x86 systems using GPT partition format (for large HDDs).
26
27=head1 SYNOPSIS
28
29parted2fdisk -s partition
30parted2fdisk -l device
31parted2fdisk [-n] device
32
33=head1 OPTIONS
34
35=over 4
36
37=item B<-s>
38
39Print the size (in blocks) of the given partition.
40
41=item B<-n>
42
43Fake mode. Doesn't pass the commands just simulate.
44
45=item B<-l>
46
47List the partition tables for the specified device and then exit.
48
49=item B<no option>
50
51Allow the creation and manipulation of partition tables.
52
53=back
54
55=head1 ARGUMENTS
56
57=over 4
58
59=item B<partition>
60
61partition device file (only used with -s option).
62
63=item B<device>
64
65device file to work on.
66
67=back
68
69=head1 WEB SITES
70
71The 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/>.
72
73=head1 USER MAILING LIST
74
75For community exchanges around MondoRescue please use the list L<http://sourceforge.net/mailarchive/forum.php?forum_name=mondo-devel>
76
77=head1 AUTHORS
78
79The MondoRescue team lead by Bruno Cornec L<mailto:bruno@mondorescue.org>.
80
81=head1 COPYRIGHT
82
83MondoRescue is distributed under the GPL v2.0 license or later,
84described in the file C<COPYING> included with the distribution.
85
86=cut
87
88
89$ENV{LANG} = "C";
90$ENV{LANGUAGE} = "C";
91$ENV{LC_ALL} = "C";
92
93# Log
94my $flog = "/var/log/parted2fdisk.log";
95open(FLOG, "> $flog") || die "Unable to open $flog";
96
97my $fdisk = "/sbin/fdisk";
98my $parted = "/sbin/parted";
99
100my $i;
101my $l;
102my $part;
103my $wpart;
104my $start = "";
105my $end = "";
106my $cylstart;
107my $cylend;
108my %start;
109my %end;
110my %type;
111my $arch;
112my $fake = 0;
113my $mega = 1048576;
114
115# Immediate flushing to avoids read error from mondorestore in log files
116$| = 1;
117
118# Determine on which arch we're running
119if (defined ($ENV{ARCH})) {
120 $arch = $ENV{ARCH};
121} else {
122 $arch = `uname -m`;
123 chomp($arch);
124}
125
126#
127# Looking for fdisk
128#
129$fdisk = is_lsb($fdisk);
130#
131# We always use fdisk except on ia64 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 $args = "";
139my $device = "";
140my $endmax = "";
141
142if ($#ARGV < 0) {
143 printf FLOG "No arguments given exiting ...\n";
144 mysyn();
145}
146
147my %pid = ( "FAT" => "6",
148 "fat32" => "b",
149 "fat16" => "e",
150 "ext2" => "83",
151 "ext3" => "83",
152 "ext4" => "83",
153 "xfs" => "83",
154 "reiserfs" => "83",
155 "linux-swap" => "82",
156 "lvm" => "8e",
157 "" => "",
158 );
159my %pnum;
160
161# Reverse table of pid
162while (($i,$l) = each %pid) {
163 next if ($i eq "ext2");
164 $pnum{$l} = $i;
165}
166
167foreach $i (@ARGV) {
168 # We support at most one option and one device
169 print FLOG "Parameter found : $i\n";
170 if ($i =~ /^\/dev\//) {
171 $device = $i;
172 next;
173 } elsif ($i =~ /^-/) {
174 $args = $i;
175 next;
176 } else {
177 mysyn();
178 }
179}
180
181if (($args ne "") and ($device eq "")) {
182 mysyn();
183}
184
185# -s takes a partition as arg
186if ($args =~ /-s/) {
187 $wpart = $device;
188 $device =~ s/[0-9]+$//;
189}
190
191if ($args =~ /-n/) {
192 print FLOG "Fake mode. Nothing will be really done\n";
193 $fake = 1;
194}
195
196print FLOG "Called with device $device and arg $args\n";
197
198if ($arch =~ /^ia64/) {
199 # Check partition table type
200 print FLOG "We're on ia64 ...\n";
201 $parted = is_lsb($parted);
202 $type = which_type($device);
203 if ($type ne "msdos") {
204 print FLOG "Not an msdos type of disk label\n";
205 if ($args =~ /-l/) {
206 fdisk_list($device,undef,\%start,\%end, 1);
207 } elsif ($args =~ /-s/) {
208 fdisk_list($device,$wpart,\%start,\%end, 1);
209 } elsif (($args =~ /-/) and ($fake == 0)) {
210 printf FLOG "Option not supported ($args) ...\n";
211 printf FLOG "Please report to the author\n";
212 mysyn();
213 } else {
214 # Read fdisk orders on stdin and pass them to parted
215 # on the command line as parted doesn't read on stdin
216 print FLOG "Translating fdisk command to parted\n";
217 while ($i = <STDIN>) {
218 if ($i =~ /^p$/) {
219 fdisk_list($device,undef,\%start,\%end, 1);
220 print "command (m for help) send back to fake fdisk for mondorestore\n";
221 } elsif ($i =~ /^n$/) {
222 fdisk_list($device,undef,\%start,\%end, 0);
223 if ($type ne "gpt") {
224 print FLOG "Forcing GPT type of disk label\n";
225 print FLOG "mklabel gpt\n";
226 system "$parted -s $device mklabel gpt\n" if ($fake == 0);
227 $type = "gpt";
228 }
229 $l = <STDIN>;
230 if (not (defined $l)) {
231 print FLOG "no primary/extended arg given for creation... assuming primary\n";
232 $l = "p";
233 }
234 chomp($l);
235 $part = <STDIN>;
236 if ((not (defined $part)) || ($part eq "")) {
237 print FLOG "no partition given for creation... skipping\n";
238 next;
239 }
240 chomp($part);
241 $cylstart = <STDIN>;
242 chomp($cylstart);
243 if ((not (defined $cylstart)) || ($cylstart eq "")) {
244 if (defined $start{$part-1}) {
245 # in MB => cyl
246 $cylstart = sprintf("%d",$end{$part-1}*$mega/$un + 1);
247 print FLOG "no start cyl given for creation... assuming the following $cylstart\n";
248 } else {
249 print FLOG "no start cyl given for creation... assuming the following 1\n";
250 $cylstart = 1;
251 }
252 }
253 $cylstart = 1 if ($cylstart < 1);
254 print FLOG "start cyl : $cylstart\n";
255 $un = get_un($device, "", 0);
256 # parted needs MB
257 if ($cylstart == 1) {
258 $start = 0.01;
259 } else {
260 $start = $cylstart* $un / $mega + 0.001;
261 }
262 # this is a size in B/KB/MB/GB
263
264 $endmax = get_max($device);
265 $cylend = <STDIN>;
266 chomp($cylend);
267 if ((not (defined $cylend)) || ($cylend eq "")) {
268 print FLOG "no end cyl given for creation... assuming full disk)\n";
269 $cylend = $endmax;
270 }
271 # Handles end syntaxes (+, K, M, ...)
272 # to give cylinders
273 if ($cylend =~ /^\+/) {
274 $cylend =~ s/^\+//;
275 # Handles suffixes; return bytes
276 $cylend = decode_Bsuf($cylend,1);
277 # This gives the number of cyl
278 $cylend /= $un;
279 $cylend = sprintf("%d",$cylend);
280 $cylend += $cylstart - 0.001;
281 # We now have the end cyl
282 }
283 $cylend = $endmax if ($cylend > $endmax);
284 print FLOG "end cyl : $cylend\n";
285 # parted needs MB
286 $end = $cylend * $un / $mega;
287 print FLOG "n $l $part $cylstart $cylend => mkpart primary $start $end\n";
288 system "$parted -s $device mkpart primary ext2 $start $end\n" if ($fake == 0);
289 print "command (m for help) send back to fake fdisk for mondorestore\n";
290 } elsif ($i =~ /^d$/) {
291 $part = <STDIN>;
292 if (not (defined $part)) {
293 print FLOG "no partition given for deletion... skipping\n";
294 next;
295 }
296 chomp($part);
297 print FLOG "d $part => rm $part\n";
298 system "$parted -s $device rm $part\n" if ($fake == 0);
299 get_parted($device,undef,\%start,\%end,undef);
300 print "command (m for help) send back to fake fdisk for mondorestore\n";
301 } elsif ($i =~ /^w$/) {
302 print FLOG "w => quit\n";
303 } elsif ($i =~ /^t$/) {
304 $part = <STDIN>;
305 if (not (defined $part)) {
306 print FLOG "no partition given for tagging... skipping\n";
307 next;
308 }
309 chomp($part);
310 # If no partition number given it's 1, and we received the type
311 if ($part !~ /\d+/) {
312 $l = $part;
313 $part = 1
314 } else {
315 $l = <STDIN>;
316 }
317 if (not (defined $l)) {
318 print FLOG "no type given for tagging partition $part... skipping\n";
319 next;
320 }
321 chomp($l);
322 if (not (defined $pnum{$l})) {
323 print FLOG "no partition number given for $l... please report to the author\n";
324 next;
325 }
326
327 if ($pnum{$l} eq "lvm") {
328 # In that case this is a flag set, not a mkfs
329 print FLOG "t $part $l => set $part $pnum{$l} on\n";
330 system "$parted -s $device set $part $pnum{$l} on\n" if ($fake == 0);
331 } else {
332 print FLOG "t $part $l => mkfs $part $pnum{$l}\n";
333 system "$parted -s $device mkfs $part $pnum{$l}\n" if ($fake == 0);
334 }
335 print "command (m for help) send back to fake fdisk for mondorestore\n";
336 } elsif ($i =~ /^a$/) {
337 $part = <STDIN>;
338 if (not (defined $part)) {
339 print FLOG "no partition given for tagging... skipping\n";
340 next;
341 }
342 chomp($part);
343
344 # Partition shouldn't be negative or null. Then take the first one.
345 $part = 1 if ($part le 0);
346
347 print FLOG "a $part => set $part boot on\n";
348 system "$parted -s $device set $part boot on\n" if ($fake == 0);
349 print "command (m for help) send back to fake fdisk for mondorestore\n";
350 } elsif ($i =~ /^q$/) {
351 print FLOG "q => quit\n";
352 } else {
353 print FLOG "Unknown command: $i\n";
354 print "command (m for help) send back to fake fdisk for mondorestore\n";
355 next;
356 }
357
358 }
359 }
360 myexit(0);
361 }
362}
363
364#
365# Else everything is for fdisk
366#
367# Print only mode
368print FLOG "Passing everything to the real fdisk\n";
369my $fargs = join(@ARGV);
370
371if ($args =~ /^-/) {
372 # -l or -s
373 open (FDISK, "$fdisk $fargs 2>/dev/null |") || die "Unable to read from $fdisk";
374 while (<FDISK>) {
375 print;
376 }
377 close(FDISK);
378} else {
379 # Modification mode
380 open (FDISK, "| $fdisk $fargs 2>/dev/null") || die "Unable to modify through $fdisk";
381 while (<STDIN>) {
382 print FDISK;
383 }
384 close(FDISK);
385 close(STDIN);
386}
387myexit(0);
388
389
390# Is your system LSB ?
391sub is_lsb {
392
393my $cmd = shift;
394my $basename = basename($cmd);
395
396if (not (-x $cmd)) {
397 print FLOG "Your system is not LSB/mondo compliant: $basename was not found as $cmd\n";
398 print FLOG "Searching elswhere...";
399 foreach $i (split(':',$ENV{PATH})) {
400 if (-x "$i/$basename") {
401 $cmd = "$i/$basename";
402 print FLOG "Found $cmd, using it !\n";
403 last;
404 }
405 }
406 if (not (-x $cmd)) {
407 print FLOG "Your system doesn't provide $basename in the PATH\n";
408 print FLOG "Please correct it before relaunching\n";
409 myexit(-1);
410 }
411}
412return($cmd);
413}
414
415sub fdisk_list {
416
417my $device = shift;
418my $wpart = shift;
419my $start = shift;
420my $end = shift;
421my $verbose = shift;
422
423my $un;
424my $endmax;
425my $d;
426my $n;
427
428my %cmt = ( "FAT" => "FAT",
429 "ext2" => "Linux",
430 "ext3" => "Linux",
431 "ext4" => "Linux",
432 "xfs" => "Linux",
433 "reiserfs" => "Linux",
434 "linux-swap" => "Linux swap",
435 "lvm" => "Linux LVM",
436 "fat16" => "fat16",
437 "fat32" => "fat32",
438 "" => "Linux",
439);
440
441my $part;
442my $mstart;
443my $mend;
444my $length;
445my $pid;
446my $cmt;
447format FLOG1 =
448@<<<<<<<<<<<< @>>>>>>>>>> @>>>>>>>>>> @>>>>>>>>>> @>>> @<<<<<<<<<<<<<<<<<<<<<<<<<<<<
449$part, $mstart, $mend, $length, $pid, $cmt
450.
451format FLOG2 =
452@<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
453$part,
454 @>>>>>>>>>> @>>>>>>>>>> @>>>>>>>>>> @>>> @<<<<<<<<<<<<<<<<<<<<<<<<<<<<
455 $mstart, $mend, $length, $pid, $cmt
456.
457format STDOUT1 =
458@<<<<<<<<<<<< @>>>>>>>>>> @>>>>>>>>>> @>>>>>>>>>> @>>> @<<<<<<<<<<<<<<<<<<<<<<<<<<<<
459$part, $mstart, $mend, $length, $pid, $cmt
460.
461format STDOUT2 =
462@<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
463$part,
464 @>>>>>>>>>> @>>>>>>>>>> @>>>>>>>>>> @>>> @<<<<<<<<<<<<<<<<<<<<<<<<<<<<
465 $mstart, $mend, $length, $pid, $cmt
466.
467# Device Boot Start End Blocks Id System
468#/dev/hda1 1 77579 39099374+ ee EFI GPT
469
470
471#
472# Keep Fdisk headers
473#
474# this will return bytes
475$un = get_un ($device,$wpart,$verbose);
476
477$endmax = get_max($device);
478
479# This will return MB
480get_parted ($device,$start,$end,\%type);
481
482while (($n,$d) = each %type) {
483 # Print infos fdisk like
484 $part = ${device}.$n;
485 # start and end are in cylinder in fdisk format
486 # so return in MB * 1MB / what represents 1 cyl in B
487 $mstart = sprintf("%d",$$start{$n}*$mega/$un);
488 $mstart = 1 if ($mstart < 1);
489 $mstart = $endmax if ($mstart > $endmax);
490 $mend = sprintf("%d",$$end{$n}*$mega/$un - 1);
491 $mend = $endmax if ($mend > $endmax);
492 $mend = 1 if ($mend < 1);
493 # length is in 1K blocks
494 $length = sprintf("%d",($mend-$mstart+1)*$un/1024);
495 $pid = $pid{$type{$n}};
496 $cmt = $cmt{$type{$n}};
497 #print FLOG "$part - $mstart - $mend - $length\n";
498
499 if ($verbose == 1) {
500 if (not (defined $wpart)) {
501 if (length($part) > 13) {
502 open(STDOUT2,">&STDOUT") || die "Unable to open STDOUT2";
503 select(STDOUT2);
504 write;
505 open(FLOG2,">&FLOG") || die "Unable to open FLOG2";
506 select(FLOG2);
507 write;
508 select(STDOUT);
509 close(FLOG2);
510 close(STDOUT2);
511 } else {
512 open(STDOUT1,">&STDOUT") || die "Unable to open STDOUT1";
513 select(STDOUT1);
514 write;
515 open(FLOG1,">&FLOG") || die "Unable to open FLOG1";
516 select(FLOG1);
517 write;
518 select(STDOUT);
519 close(FLOG1);
520 close(STDOUT1);
521 }
522 } else {
523 # manage the -s option of fdisk here
524 print "$length\n" if ($part eq $wpart);
525 print FLOG "$part has $length KBytes\n" if ($part eq $wpart);
526 }
527 }
528}
529close(FDISK);
530close(PARTED);
531}
532
533#
534# Get max size from fdisk
535#
536sub get_max {
537
538my $device = shift;
539my $max = 0;
540my $foo;
541
542open (FDISK, "$fdisk -l $device 2>/dev/null |") || die "Unable to read from $fdisk";
543while (<FDISK>) {
544 if ($_ =~ /heads/) {
545 chomp;
546 $max = $_;
547 $max =~ s/.* ([0-9]+) cylinders/$1/;
548 }
549}
550close(FDISK);
551print FLOG "get_max returns $max\n";
552return($max);
553}
554
555#
556# Get units from fdisk (cylinder size)
557#
558sub get_un {
559
560my $device = shift;
561my $wpart = shift;
562my $verbose = shift;
563my $un = 0;
564my $foo;
565
566open (FDISK, "$fdisk -l $device 2>/dev/null |") || die "Unable to read from $fdisk";
567while (<FDISK>) {
568 print if (($_ !~ /^\/dev\//) and (not (defined $wpart)) and ($verbose == 1));
569 if ($_ =~ /^Units/) {
570 ($foo, $un , $foo) = split /=/;
571 $un =~ s/[A-z\s=]//g;
572 $un = eval($un);
573 }
574}
575close(FDISK);
576print FLOG "get_un returns $un\n";
577return($un);
578}
579
580#
581# Parted gives info in MB
582# (depending on versions - 1.6.25.1 provides suffixes)
583#
584sub get_parted {
585
586my $device = shift;
587my $start = shift;
588my $end = shift;
589my $type = shift;
590my $void;
591my $d;
592my $n;
593my $ret;
594my $mode;
595my $size;
596my $unit;
597
598open (PARTED, "$parted -v |") || die "Unable to read from $parted";
599$d = <PARTED>;
600print FLOG "$d";
601close(PARTED);
602
603open (PARTED, "$parted -s $device print |") || die "Unable to read from $parted";
604# Skip 3 first lines
605$d = <PARTED>;
606$d = <PARTED>;
607$d = <PARTED>;
608
609# depending on parted version, information given change:
610if ($d =~ /\bSize\b/) {
611 # SLES 10 parted >= 1.6.25
612 $mode=1;
613} else {
614 # RHEL 3 parted 1.6.3
615 # RHEL 4 parted 1.6.19
616 $mode=0;
617}
618print FLOG "mode: $mode\n";
619print FLOG "Got from parted: \n";
620print FLOG "Minor Start End Filesystem\n";
621# Get info from each partition line
622while (($n,$d) = split(/\s/, <PARTED>,2)) {
623 chomp($d);
624 next if ($n !~ /^[1-9]/);
625 $d =~ s/^\s*//;
626 $d =~ s/\s+/ /g;
627 if ($mode == 0) {
628 ($$start{$n},$$end{$n},$$type{$n},$void) = split(/ /,$d);
629 $unit = 1;
630 } elsif ($mode == 1) {
631 ($$start{$n},$$end{$n},$size,$$type{$n},$void) = split(/ /,$d);
632 $unit = $mega;
633 } else {
634 die "Undefined mode $mode";
635 }
636 $$start{$n} = "" if (not defined $$start{$n});
637 $$end{$n} = "" if (not defined $$end{$n});
638 $$type{$n} = "" if (not defined $$type{$n});
639 # Handles potential suffixes in latest parted version. Return MB
640 $ret = decode_Bsuf($$start{$n},$unit);
641 $$start{$n} = $ret;
642 $ret = decode_Bsuf($$end{$n},$unit);
643 $$end{$n} = $ret;
644 print FLOG "$n $$start{$n} $$end{$n} $$type{$n}\n";
645}
646close(PARTED);
647}
648
649sub decode_Bsuf {
650
651my $size = shift;
652my $unit = shift;
653my $ret = 0;
654
655#print FLOG "decode_Bsuf input: $size / $unit ";
656if ($size =~ /K[B]*$/i) {
657 $size =~ s/K[B]*$//i;
658 $size *= 1024;
659} elsif ($size =~ /M[B]*$/i) {
660 $size =~ s/M[B]*$//i;
661 $size *= 1048576;
662} elsif ($size =~ /G[B]*$/i) {
663 $size =~ s/G[B]*$//i;
664 $size *= 1073741824;
665} elsif ($size =~ /T[B]*$/i) {
666 $size =~ s/T[B]*$//i;
667 $size *= 1099511627776;
668} else {
669 # Nothing to do
670}
671$ret = $size / $unit;
672#print FLOG " - output : $size => $ret\n";
673return($ret);
674}
675
676
677# Based on Version 2.4 27-Sep-1996 Charles Bailey bailey@genetics.upenn.edu
678# in Basename.pm
679
680sub basename {
681
682my($fullname) = shift;
683
684my($dirpath,$basename);
685
686($dirpath,$basename) = ($fullname =~ m#^(.*/)?(.*)#s);
687
688return($basename);
689}
690
691sub myexit {
692
693my $val=shift;
694
695close(FLOG);
696exit($val);
697}
698
699sub which_type {
700
701my $device = shift;
702my $type = "";
703
704open (FDISK, "$fdisk -l $device 2>/dev/null |") || die "Unable to read from $fdisk";
705while (<FDISK>) {
706 if ($_ =~ /EFI GPT/) {
707 $type= "gpt";
708 print FLOG "Found a GPT partition format\n";
709 last;
710 }
711}
712close(FDISK);
713open (PARTED, "$parted -s $device print|") || die "Unable to read from $fdisk";
714while (<PARTED>) {
715 if ($_ =~ /Disk label type: msdos/) {
716 $type= "msdos";
717 print FLOG "Found a msdos partition format\n";
718 last;
719 }
720}
721close(FDISK);
722return ($type);
723}
724
725sub mysyn {
726 print "Syntax: $0 [-l] device | [-s] partition\n";
727 myexit(-1);
728}
Note: See TracBrowser for help on using the repository browser.