source: MondoRescue/branches/2.2.8/mindi/parted2fdisk.pl@ 2789

Last change on this file since 2789 was 2789, checked in by Bruno Cornec, 13 years ago

r2159@localhost (orig r2158): bruno | 2009-03-05 20:01:54 +0100

  • Fixes for ia64 support from Giuseppe Grassi <giuseppe.grassi2_at_italtel.it>:
    • the m) fake output is expected in fdisk.log so printing that on stdout instead of parted2fdisk log file
    • parted2fdisk supports now lack of partition given in 't' command
    • parted2fdisk supports now LVM type of partitions correctly (using a parted flag)
    • init links now /dev/tty to /dev/ttyS0 to have a working serial support on ia64


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