source: MondoRescue/branches/2.2.5/mindi/parted2fdisk.pl@ 1815

Last change on this file since 1815 was 1801, checked in by Bruno Cornec, 16 years ago

on ia64 now use the perl script parted2fdisk at retore time also

  • Property svn:keywords set to Id
File size: 14.1 KB
Line 
1#!/usr/bin/perl -w
2#
3# $Id: parted2fdisk.pl 1801 2007-11-15 14:32:23Z 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 RHAS 2.1 ia64 - Mandrake 9.0 ia64 - RHAS 3.0 ia64 - SLES 10
10#
11# (c) Bruno Cornec <Bruno.Cornec@hp.com>
12# Licensed under the GPL
13
14use strict;
15
16$ENV{LANG} = "C";
17$ENV{LANGUAGE} = "C";
18$ENV{LC_ALL} = "C";
19
20# Log
21my $flog = "/tmp/parted2fdisk.log";
22open(FLOG, "> $flog") || die "Unable to open $flog";
23
24my $fdisk = "/sbin/fdisk";
25my $parted = "/sbin/parted";
26
27my $i;
28my $l;
29my $part;
30my $wpart;
31my $start = "";
32my $end = "";
33my $cylstart;
34my $cylend;
35my %start;
36my %end;
37my %type;
38my $arch;
39my $fake = 0;
40my $mega = 1048576;
41
42# Determine on which arch we're running
43if (defined ($ENV{ARCH})) {
44 $arch = $ENV{ARCH};
45} else {
46 $arch = `uname -m`;
47 chomp($arch);
48}
49
50#
51# Looking for fdisk
52#
53$fdisk = is_lsb($fdisk);
54#
55# We always use fdisk except on ia64 with GPT types of
56# partition tables where we need parted
57# All should return fdisk like format so that callers
58# think they have called fdisk directly
59#
60my $un;
61my $type;
62my $args = "";
63my $device = "";
64my $endmax = "";
65
66if ($#ARGV < 0) {
67 printf FLOG "No arguments given exiting ...\n";
68 mysyn();
69}
70
71my %pid = ( "FAT" => "6",
72 "fat32" => "b",
73 "fat16" => "e",
74 "ext2" => "83",
75 "ext3" => "83",
76 "reiserfs" => "83",
77 "linux-swap" => "82",
78 "LVM" => "8e",
79 "" => "",
80 );
81my %pnum;
82
83# Reverse table of pid
84while (($i,$l) = each %pid) {
85 next if ($i eq "ext2");
86 $pnum{$l} = $i;
87}
88
89foreach $i (@ARGV) {
90 # We support at most one option and one device
91 print FLOG "Parameter found : $i\n";
92 if ($i =~ /^\/dev\//) {
93 $device = $i;
94 next;
95 } elsif ($i =~ /^-/) {
96 $args = $i;
97 next;
98 } else {
99 mysyn();
100 }
101}
102
103if (($args ne "") and ($device eq "")) {
104 mysyn();
105}
106
107# -s takes a partition as arg
108if ($args =~ /-s/) {
109 $wpart = $device;
110 $device =~ s/[0-9]+$//;
111}
112
113if ($args =~ /-n/) {
114 print FLOG "Fake mode. Nothing will be really done\n";
115 $fake = 1;
116}
117
118print FLOG "Called with device $device and arg $args\n";
119
120if ($arch =~ /^ia64/) {
121 # Check partition table type
122 print FLOG "We're on ia64 ...\n";
123 $parted = is_lsb($parted);
124 $type = which_type($device);
125 if ($type ne "msdos") {
126 print FLOG "Not an msdos type of disk label\n";
127 if ($args =~ /-l/) {
128 fdisk_list($device,undef,\%start,\%end, 1);
129 } elsif ($args =~ /-s/) {
130 fdisk_list($device,$wpart,\%start,\%end, 1);
131 } elsif (($args =~ /-/) and ($fake == 0)) {
132 printf FLOG "Option not supported ($args) ...\n";
133 printf FLOG "Please report to the author\n";
134 mysyn();
135 } else {
136 # Read fdisk orders on stdin and pass them to parted
137 # on the command line as parted doesn't read on stdin
138 print FLOG "Translating fdisk command to parted\n";
139 while ($i = <STDIN>) {
140 if ($i =~ /^p$/) {
141 fdisk_list($device,undef,\%start,\%end, 1);
142 }
143 elsif ($i =~ /^n$/) {
144 fdisk_list($device,undef,\%start,\%end, 0);
145 if ($type ne "gpt") {
146 print FLOG "Forcing GPT type of disk label\n";
147 print FLOG "mklabel gpt\n";
148 system "$parted -s $device mklabel gpt\n" if ($fake == 0);
149 $type = "gpt";
150 }
151 $l = <STDIN>;
152 if (not (defined $l)) {
153 print FLOG "no primary/extended arg given for creation... assuming primary\n";
154 $l = "p";
155 }
156 chomp($l);
157 $part = <STDIN>;
158 if ((not (defined $part)) || ($part eq "")) {
159 print FLOG "no partition given for creation... skipping\n";
160 next;
161 }
162 chomp($part);
163 $cylstart = <STDIN>;
164 chomp($cylstart);
165 if ((not (defined $cylstart)) || ($cylstart eq "")) {
166 if (defined $start{$part-1}) {
167 # in MB => cyl
168 $cylstart = sprintf("%d",$end{$part-1}*$mega/$un + 1);
169 print FLOG "no start cyl given for creation... assuming the following $cylstart\n";
170 } else {
171 print FLOG "no start cyl given for creation... assuming the following 1\n";
172 $cylstart = 1;
173 }
174 }
175 $cylstart = 1 if ($cylstart < 1);
176 print FLOG "start cyl : $cylstart\n";
177 $un = get_un($device, "", 0);
178 # parted needs MB
179 if ($cylstart == 1) {
180 $start = 0.01;
181 } else {
182 $start = $cylstart* $un / $mega + 0.001;
183 }
184 # this is a size in B/KB/MB/GB
185
186 $endmax = get_max($device);
187 $cylend = <STDIN>;
188 chomp($cylend);
189 if ((not (defined $cylend)) || ($cylend eq "")) {
190 print FLOG "no end cyl given for creation... assuming full disk)\n";
191 $cylend = $endmax;
192 }
193 # Handles end syntaxes (+, K, M, ...)
194 # to give cylinders
195 if ($cylend =~ /^\+/) {
196 $cylend =~ s/^\+//;
197 # Handles suffixes; return bytes
198 $cylend = decode_Bsuf($cylend,1);
199 # This gives the number of cyl
200 $cylend /= $un;
201 $cylend = sprintf("%d",$cylend);
202 $cylend += $cylstart - 0.001;
203 # We now have the end cyl
204 }
205 $cylend = $endmax if ($cylend > $endmax);
206 print FLOG "end cyl : $cylend\n";
207 # parted needs MB
208 $end = $cylend * $un / $mega;
209 print FLOG "n $l $part $cylstart $cylend => mkpart primary $start $end\n";
210 system "$parted -s $device mkpart primary ext2 $start $end\n" if ($fake == 0);
211 }
212 elsif ($i =~ /^d$/) {
213 $part = <STDIN>;
214 if (not (defined $part)) {
215 print FLOG "no partition given for deletion... skipping\n";
216 next;
217 }
218 chomp($part);
219 print FLOG "d $part => rm $part\n";
220 system "$parted -s $device rm $part\n" if ($fake == 0);
221 get_parted($device,undef,\%start,\%end,undef);
222 }
223 elsif ($i =~ /^w$/) {
224 print FLOG "w => quit\n";
225 }
226 elsif ($i =~ /^t$/) {
227 $part = <STDIN>;
228 if (not (defined $part)) {
229 print FLOG "no partition given for tagging... skipping\n";
230 next;
231 }
232 chomp($part);
233 $l = <STDIN>;
234 if (not (defined $l)) {
235 print FLOG "no type given for tagging partition $part... skipping\n";
236 next;
237 }
238 chomp($l);
239 if (not (defined $pnum{$l})) {
240 print FLOG "no partition number given for $l... please report to the author\n";
241 next;
242 }
243 print FLOG "t $part $l => mkfs $part $pnum{$l}\n";
244 system "$parted -s $device mkfs $part $pnum{$l}\n" if ($fake == 0);
245 }
246 elsif ($i =~ /^a$/) {
247 $part = <STDIN>;
248 if (not (defined $part)) {
249 print FLOG "no partition given for tagging... skipping\n";
250 next;
251 }
252 chomp($part);
253 print FLOG "a $part => set $part boot on\n";
254 system "$parted -s $device set $part boot on\n" if ($fake == 0);
255 }
256 elsif ($i =~ /^q$/) {
257 print FLOG "q => quit\n";
258 }
259 else {
260 print FLOG "Unknown command: $i\n";
261 next;
262 }
263
264 }
265 }
266 myexit(0);
267 }
268}
269
270#
271# Else everything is for fdisk
272#
273# Print only mode
274print FLOG "Passing everything to the real fdisk\n";
275my $fargs = join(@ARGV);
276
277if ($args =~ /^-/) {
278 # -l or -s
279 open (FDISK, "$fdisk $fargs |") || die "Unable to read from $fdisk";
280 while (<FDISK>) {
281 print;
282 }
283 close(FDISK);
284} else {
285 # Modification mode
286 open (FDISK, "| $fdisk $fargs") || die "Unable to modify through $fdisk";
287 while (<STDIN>) {
288 print FDISK;
289 }
290 close(FDISK);
291 close(STDIN);
292}
293myexit(0);
294
295
296# Is your system LSB ?
297sub is_lsb {
298
299my $cmd = shift;
300my $basename = basename($cmd);
301
302if (not (-x $cmd)) {
303 print FLOG "Your system is not LSB/mondo compliant: $basename was not found as $cmd\n";
304 print FLOG "Searching elswhere...";
305 foreach $i (split(':',$ENV{PATH})) {
306 if (-x "$i/$basename") {
307 $cmd = "$i/$basename";
308 print FLOG "Found $cmd, using it !\n";
309 last;
310 }
311 }
312 if (not (-x $cmd)) {
313 print FLOG "Your system doesn't provide $basename in the PATH\n";
314 print FLOG "Please correct it before relaunching\n";
315 myexit(-1);
316 }
317}
318return($cmd);
319}
320
321sub fdisk_list {
322
323my $device = shift;
324my $wpart = shift;
325my $start = shift;
326my $end = shift;
327my $verbose = shift;
328
329my $un;
330my $endmax;
331my $d;
332my $n;
333
334my %cmt = ( "FAT" => "FAT",
335 "ext2" => "Linux",
336 "ext3" => "Linux",
337 "reiserfs" => "Linux",
338 "linux-swap" => "Linux swap",
339 "LVM" => "Linux LVM",
340 "fat16" => "fat16",
341 "fat32" => "fat32",
342 "" => "Linux",
343);
344
345my $part;
346my $mstart;
347my $mend;
348my $length;
349my $pid;
350my $cmt;
351format FLOG1 =
352@<<<<<<<<<<<< @>>>>>>>>>> @>>>>>>>>>> @>>>>>>>>>> @>>> @<<<<<<<<<<<<<<<<<<<<<<<<<<<<
353$part, $mstart, $mend, $length, $pid, $cmt
354.
355format FLOG2 =
356@<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
357$part,
358 @>>>>>>>>>> @>>>>>>>>>> @>>>>>>>>>> @>>> @<<<<<<<<<<<<<<<<<<<<<<<<<<<<
359 $mstart, $mend, $length, $pid, $cmt
360.
361format STDOUT1 =
362@<<<<<<<<<<<< @>>>>>>>>>> @>>>>>>>>>> @>>>>>>>>>> @>>> @<<<<<<<<<<<<<<<<<<<<<<<<<<<<
363$part, $mstart, $mend, $length, $pid, $cmt
364.
365format STDOUT2 =
366@<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
367$part,
368 @>>>>>>>>>> @>>>>>>>>>> @>>>>>>>>>> @>>> @<<<<<<<<<<<<<<<<<<<<<<<<<<<<
369 $mstart, $mend, $length, $pid, $cmt
370.
371# Device Boot Start End Blocks Id System
372#/dev/hda1 1 77579 39099374+ ee EFI GPT
373
374
375#
376# Keep Fdisk headers
377#
378# this will return bytes
379$un = get_un ($device,$wpart,$verbose);
380
381$endmax = get_max($device);
382
383# This will return MB
384get_parted ($device,$start,$end,\%type);
385
386while (($n,$d) = each %type) {
387 # Print infos fdisk like
388 $part = ${device}.$n;
389 # start and end are in cylinder in fdisk format
390 # so return in MB * 1MB / what represents 1 cyl in B
391 $mstart = sprintf("%d",$$start{$n}*$mega/$un);
392 $mstart = 1 if ($mstart < 1);
393 $mstart = $endmax if ($mstart > $endmax);
394 $mend = sprintf("%d",$$end{$n}*$mega/$un - 1);
395 $mend = $endmax if ($mend > $endmax);
396 $mend = 1 if ($mend < 1);
397 # length is in 1K blocks
398 $length = sprintf("%d",($mend-$mstart+1)*$un/1024);
399 $pid = $pid{$type{$n}};
400 $cmt = $cmt{$type{$n}};
401 #print FLOG "$part - $mstart - $mend - $length\n";
402
403 if ($verbose == 1) {
404 if (not (defined $wpart)) {
405 if (length($part) > 13) {
406 open(STDOUT2,">&STDOUT") || die "Unable to open STDOUT2";
407 select(STDOUT2);
408 write;
409 open(FLOG2,">&FLOG") || die "Unable to open FLOG2";
410 select(FLOG2);
411 write;
412 select(STDOUT);
413 close(FLOG2);
414 close(STDOUT2);
415 } else {
416 open(STDOUT1,">&STDOUT") || die "Unable to open STDOUT1";
417 select(STDOUT1);
418 write;
419 open(FLOG1,">&FLOG") || die "Unable to open FLOG1";
420 select(FLOG1);
421 write;
422 select(STDOUT);
423 close(FLOG1);
424 close(STDOUT1);
425 }
426 } else {
427 # manage the -s option of fdisk here
428 print "$length\n" if ($part eq $wpart);
429 print FLOG "$part has $length KBytes\n" if ($part eq $wpart);
430 }
431 }
432}
433close(FDISK);
434close(PARTED);
435}
436
437#
438# Get max size from fdisk
439#
440sub get_max {
441
442my $device = shift;
443my $max = 0;
444my $foo;
445
446open (FDISK, "$fdisk -l $device |") || die "Unable to read from $fdisk";
447while (<FDISK>) {
448 if ($_ =~ /heads/) {
449 chomp;
450 $max = $_;
451 $max =~ s/.* ([0-9]+) cylinders/$1/;
452 }
453}
454close(FDISK);
455print FLOG "get_max returns $max\n";
456return($max);
457}
458
459#
460# Get units from fdisk (cylinder size)
461#
462sub get_un {
463
464my $device = shift;
465my $wpart = shift;
466my $verbose = shift;
467my $un = 0;
468my $foo;
469
470open (FDISK, "$fdisk -l $device |") || die "Unable to read from $fdisk";
471while (<FDISK>) {
472 print if (($_ !~ /^\/dev\//) and (not (defined $wpart)) and ($verbose == 1));
473 if ($_ =~ /^Units/) {
474 ($foo, $un , $foo) = split /=/;
475 $un =~ s/[A-z\s=]//g;
476 $un = eval($un);
477 }
478}
479close(FDISK);
480print FLOG "get_un returns $un\n";
481return($un);
482}
483
484#
485# Parted gives info in MB
486# (depending on versions - 1.6.25.1 provides suffixes)
487#
488sub get_parted {
489
490my $device = shift;
491my $start = shift;
492my $end = shift;
493my $type = shift;
494my $void;
495my $d;
496my $n;
497my $ret;
498my $mode;
499my $size;
500my $unit;
501
502open (PARTED, "$parted -v |") || die "Unable to read from $parted";
503$d = <PARTED>;
504print FLOG "$d";
505close(PARTED);
506
507open (PARTED, "$parted -s $device print |") || die "Unable to read from $parted";
508# Skip 3 first lines
509$d = <PARTED>;
510$d = <PARTED>;
511$d = <PARTED>;
512
513# depending on parted version, information given change:
514if ($d =~ /\bSize\b/) {
515 # SLES 10 parted >= 1.6.25
516 $mode=1;
517} else {
518 # RHEL 3 parted 1.6.3
519 # RHEL 4 parted 1.6.19
520 $mode=0;
521}
522print FLOG "mode: $mode\n";
523print FLOG "Got from parted: \n";
524print FLOG "Minor Start End Filesystem\n";
525# Get info from each partition line
526while (($n,$d) = split(/\s/, <PARTED>,2)) {
527 chomp($d);
528 next if ($n !~ /^[1-9]/);
529 $d =~ s/^\s*//;
530 $d =~ s/\s+/ /g;
531 if ($mode == 0) {
532 ($$start{$n},$$end{$n},$$type{$n},$void) = split(/ /,$d);
533 $unit = 1;
534 } elsif ($mode == 1) {
535 ($$start{$n},$$end{$n},$size,$$type{$n},$void) = split(/ /,$d);
536 $unit = $mega;
537 } else {
538 die "Undefined mode $mode";
539 }
540 $$start{$n} = "" if (not defined $$start{$n});
541 $$end{$n} = "" if (not defined $$end{$n});
542 $$type{$n} = "" if (not defined $$type{$n});
543 # Handles potential suffixes in latest parted version. Return MB
544 $ret = decode_Bsuf($$start{$n},$unit);
545 $$start{$n} = $ret;
546 $ret = decode_Bsuf($$end{$n},$unit);
547 $$end{$n} = $ret;
548 print FLOG "$n $$start{$n} $$end{$n} $$type{$n}\n";
549}
550close(PARTED);
551}
552
553sub decode_Bsuf {
554
555my $size = shift;
556my $unit = shift;
557my $ret = 0;
558
559#print FLOG "decode_Bsuf input: $size / $unit ";
560if ($size =~ /KB$/i) {
561 $size =~ s/KB$//i;
562 $size *= 1024;
563} elsif ($size =~ /MB$/i) {
564 $size =~ s/MB$//i;
565 $size *= 1048576;
566} elsif ($size =~ /GB$/i) {
567 $size =~ s/GB$//i;
568 $size *= 1073741824;
569} elsif ($size =~ /TB$/i) {
570 $size =~ s/TB$//i;
571 $size *= 1099511627776;
572} else {
573 # Nothing to do
574}
575$ret = $size / $unit;
576#print FLOG " - output : $size => $ret\n";
577return($ret);
578}
579
580
581# Based on Version 2.4 27-Sep-1996 Charles Bailey bailey@genetics.upenn.edu
582# in Basename.pm
583
584sub basename {
585
586my($fullname) = shift;
587
588my($dirpath,$basename);
589
590($dirpath,$basename) = ($fullname =~ m#^(.*/)?(.*)#s);
591
592return($basename);
593}
594
595sub myexit {
596
597my $val=shift;
598
599close(FLOG);
600exit($val);
601}
602
603sub which_type {
604
605my $device = shift;
606my $type = "";
607
608open (FDISK, "$fdisk -l $device |") || die "Unable to read from $fdisk";
609while (<FDISK>) {
610 if ($_ =~ /EFI GPT/) {
611 $type= "gpt";
612 print FLOG "Found a GPT partition format\n";
613 last;
614 }
615}
616close(FDISK);
617open (PARTED, "$parted -s $device print|") || die "Unable to read from $fdisk";
618while (<PARTED>) {
619 if ($_ =~ /Disk label type: msdos/) {
620 $type= "msdos";
621 print FLOG "Found a msdos partition format\n";
622 last;
623 }
624}
625close(FDISK);
626return ($type);
627}
628
629sub mysyn {
630 print "Syntax: $0 [-l] device | [-s] partition\n";
631 myexit(-1);
632}
Note: See TracBrowser for help on using the repository browser.