"hl kwb">$partmap_end) {$part->{start} =$partmap_end+1;$part->{size} =$end-$part->{start};}}sub adjustEnd($$) {my($hd, $part) =@_;}subread($$) {my($hd, $sector) =@_;my$tmp;local*F; partition_table_raw::openit($hd,*F)or die"failed to open device";
c::lseek_sector(fileno(F),$sector,0)or die"reading of partition in sector$sectorfailed";sysread F,$tmp, psizeof($bz_format)or die"error while reading bz \(Block Zero\) in sector$sector";my%info;@info{@$bz_fields} =unpack$bz_format, $tmp;my$i;foreach$i(0..$info{bzDrvrCnt}-1) {sysread F,$tmp, psizeof($dd_format)or die"error while reading driver data in sector$sector";my%dd;@dd{@$dd_fields} =unpack$dd_format, $tmp;push@{$info{ddMap}}, \%dd;}#- check magic number$info{bzSig} ==$magicor die"bad magic number";my$numparts;
c::lseek_sector(fileno(F),$sector,516)or die"reading of partition in sector$sectorfailed";sysread F,$tmp,4or die"error while reading partition info in sector$sector";$numparts=unpack"N",$tmp;my$partmapsize;
c::lseek_sector(fileno(F),$sector,524)or die"reading of partition in sector$sectorfailed";sysread F,$tmp,4or die"error while reading partition info in sector$sector";$partmapsize= ((unpack"N",$tmp) *$info{bzBlkSize}) / psizeof($p_format);
c::lseek_sector(fileno(F),$sector,512)or die"reading of partition in sector$sectorfailed";my@pt;for($i=0;$i<$partmapsize;$i++) {my$part;sysread F,$part, psizeof($p_format)or die"error while reading partition info in sector$sector";push@pt,map{my%h;@h{@$p_fields} =unpack$p_format, $part;if($i<$numparts&&$h{pSig}eq$pmagic) {$h{size} = ($h{pPBlocks} *$info{bzBlkSize}) /512;$h{start} = ($h{pPBlockStart} *$info{bzBlkSize}) /512;if($h{pType} =~/^Apple_UNIX_SVR2/i) {$h{pName} =~/swap/i ? ($h{type} =0x82) : ($h{type} =0x83);}elsif($h{pType} =~/^Apple_Free/i) {#- need to locate a 1MB partition to setup a bootstrap onif(defined$freepart_start&&$freepart_size>=1) {#- already found a suitable partition}else{$freepart_start=$h{start};$freepart_size=$h{size}/2048;$freepart_device=$hd;$freepart_part="/dev/".$hd->{device} . ($i+1);log::l("free apple partition found on drive /dev/$freepart_device->{device}, block$freepart_start,size$freepart_size");}next;#$h{type} = 0x0;}elsif($h{pType} =~/^Apple_HFS/i) {$h{type} =0x402;if(defined$macos_part) {#- swag at identifying MacOS - 1st HFS partition}else{$macos_part="/dev/".$hd->{device} . ($i+1);log::l("found MacOS at partition$macos_part");}}elsif($h{pType} =~/^Apple_Partition_Map/i) {$h{type} =0x401;$h{isMap} =1;}elsif($h{pType} =~/^Apple_Bootstrap/i) {$h{type} =0x401;$h{isBoot} =1;if(defined$bootstrap_part) {#found a bootstrap already - use it, but log the findlog::l("found another apple bootstrap at partition /dev/$hd->{device}". ($i+1));}else{$bootstrap_part="/dev/".$hd->{device} . ($i+1);log::l("found apple bootstrap at partition$bootstrap_part");}}else{$h{type} =0x401;$h{isDriver} =1;};# Let's see if this partition is a driver.foreach(@{$info{ddMap}}) {$_->{ddBlock} ==$h{pPBlockStart}and$h{isDriver} =1;}}
\%h;} [$part];};[@pt], \%info;}subwrite($$$;$) {my($hd, $sector, $pt, $info) =@_;#- handle testing for writing partition table on file only!local*F;if($::testing) {my$file="/tmp/partition_table_$hd->{device}";open F,">$file"or die"error opening test file$file";}else{
partition_table_raw::openit($hd,*F,2)or die"error opening device$hd->{device} for writing";
c::lseek_sector(fileno(F),$sector,0)orreturn0;}# Find the partition map.my@partstowrite;my$part=$pt->[0];(defined$part->{isMap})or die"the first partition is not the partition map";push@partstowrite, $part;# Now go thru the partitions, sort and fill gaps.my$last;while($part) {$last=$part;$part= &partition_table::next($hd, $part);$partorlast;if($last->{start} +$last->{size} <$part->{start}) {#There is a gap between partitions. Fill it and move on.push@partstowrite,{
type =>0x0,
start =>$last->{start} +$last->{size},
size =>$part->{start} - ($last->{start} +$last->{size}),};}push@partstowrite, $part;};# now, fill a gap at the end if there is one.if($last->{start} +$last->{size} <$hd->{totalsectors}) {push@partstowrite,{
type =>0x0,
start =>$last->{start} +$last->{size},
size =>$hd->{totalsectors} - ($last->{start} +$last->{size}),};}# Since we didn't create any new drivers, let's try and match up our driver records with out partitons and see if any are missing.$info->{bzDrvrCnt} =0;my@ddstowrite;my$dd;foreach$dd(@{$info->{ddMap}}) {foreach(@partstowrite) {if($dd->{ddBlock} ==$_->{pPBlockStart}) {push@ddstowrite, $dd;$info->{bzDrvrCnt}++;last;}}}# Now let's write our first block.syswrite F,pack($bz_format, @$info{@$bz_fields}), psizeof($bz_format)orreturn0;# ...and now the driver information.foreach(@ddstowrite) {syswrite F,pack($dd_format, @$_{@$dd_fields}), psizeof($dd_format)orreturn0;}# zero the rest of the data in the first block.foreach(1.. (494- ((@ddstowrite) *8))) {syswrite F,"\0",1orreturn0;}#c::lseek_sector(fileno(F), $sector, 512) or return 0;# Now, we iterate thru the partstowrite and write them.foreach(@partstowrite) {if(!defined$_->{pSig}) {# The values we need to write to disk are not defined. Let's make them up.$_->{pSig} =$pmagic;$_->{pSigPad} =0;$_->{pPBlockStart} = ($_->{start} *512) /$info->{bzBlkSize};$_->{pPBlocks} = ($_->{size} *512) /$info->{bzBlkSize};$_->{pLBlockStart} =0;$_->{pLBlocks} =$_->{pPBlocks};$_->{pBootBlock} =0;$_->{pBootBytes} =0;$_->{pAddrs1} =0;$_->{pAddrs2} =0;$_->{pAddrs3} =0;$_->{pAddrs4} =0;$_->{pChecksum} =0;$_->{pProcID} ="\0";$_->{pBootArgs} ="\0";$_->{pReserved} ="\0";if($_->{type} ==0x402) {$_->{pType} ="Apple_HFS";$_->{pName} ="MacOS";$_->{pFlags} =0x4000037F;}elsif($_->{type} ==0x401&&$_->{start} ==1) {$_->{pType} ="Apple_Partition_Map";$_->{pName} ="Apple";$_->{pFlags} =0x33;}elsif($_->{type} ==0x401) {$_->{pType} ="Apple_Bootstrap";$_->{pName} ="bootstrap";$_->{pFlags} =0x33;$_->{isBoot} =1;}elsif($_->{type} ==0x82) {$_->{pType} ="Apple_UNIX_SVR2";$_->{pName} ="swap";$_->{pFlags} =0x33;}elsif($_->{type} ==0x83) {$_->{pType} ="Apple_UNIX_SVR2";$_->{pName} ="Linux Native";$_->{pFlags} =0x33;}elsif($_->{type} ==0x0) {$_->{pType} ="Apple_Free";$_->{pName} ="Extra";$_->{pFlags} =0x31;}};$_->{pMapEntry} =@partstowrite;syswrite F,pack($p_format, @$_{@$p_fields}), psizeof($p_format)orreturn0;}
sync();1;}sub info {my($hd) =@_;# - Build the first block of the drive.my$info= {
bzSig =>$magic,
bzBlkSize =>512,
bzBlkCnt =>$hd->{totalsectors},
bzDevType =>0,
bzDevID =>0,
bzReserved =>0,
bzDrvrCnt =>0,};$info;}sub clear_raw {my($hd) =@_;my@oldraw= @{$hd->{primary}{raw}};my$pt= { raw => [ ({}) x 63], info => info($hd) };#- handle special case for partition 1 which is the partition map.$pt->{raw}[0] = {
type =>0x401,
start =>1,
size =>63,
isMap =>1,};# $pt->{raw}[1] = {# type => 0x0,# start => 64,# size => $hd->{totalsectors} - 64,# isMap => 0,# };push@{$pt->{normal}},$pt->{raw}[0];# push @{$pt->{normal}}, $pt->{raw}[1];#- Recover any Apple Drivers, if any.my$i=1;foreach(@oldraw) {if(defined$_->{isDriver}) {$pt->{raw}[$i] =$_;push@{$pt->{normal}},$pt->{raw}[$i];$i++;}};@{$pt->{info}{ddMap}} = @{$hd->{primary}{info}{ddMap}};$pt;}1;