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

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

remove fdisk error messages on ia64 that end up on screen during restore - such as GPT not supported ...

  • Property svn:keywords set to Id
File size: 14.2 KB
Line 
1#!/usr/bin/perl -w
2#
3# $Id: parted2fdisk.pl 1857 2008-01-11 14:28:40Z 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 2>/dev/null |") || 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 2>/dev/null") || 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 2>/dev/null |") || 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 2>/dev/null |") || 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 =~ /K[B]*$/i) {
561 $size =~ s/K[B]*$//i;
562 $size *= 1024;
563} elsif ($size =~ /M[B]*$/i) {
564 $size =~ s/M[B]*$//i;
565 $size *= 1048576;
566} elsif ($size =~ /G[B]*$/i) {
567 $size =~ s/G[B]*$//i;
568 $size *= 1073741824;
569} elsif ($size =~ /T[B]*$/i) {
570 $size =~ s/T[B]*$//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 2>/dev/null |") || 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.