1#!/usr/bin/perl 2# 3# AppleSingle/AppleDouble dump 4# 5# (c) 2009-2010 by HAT <hat@fa2.so-net.ne.jp> 6# 7# This program is free software; you can redistribute it and/or modify 8# it under the terms of the GNU General Public License as published by 9# the Free Software Foundation; either version 2 of the License, or 10# (at your option) any later version. 11# 12# This program is distributed in the hope that it will be useful, 13# but WITHOUT ANY WARRANTY; without even the implied warranty of 14# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15# GNU General Public License for more details. 16# 17 18# 19# References: 20# 21# Applesingle and AppleDouble format internals (version 1) 22# http://users.phg-online.de/tk/netatalk/doc/Apple/v1/ 23# 24# AppleSingle/AppleDouble Formats for Foreign Files Developer's Note (version2) 25# http://users.phg-online.de/tk/netatalk/doc/Apple/v2/AppleSingle_AppleDouble.pdf 26# 27# Inside Macintosh: Macintosh Toolbox Essentials / 28# Chapter 7 - Finder Interface / Finder Interface Reference 29# http://developer.apple.com/legacy/mac/library/documentation/mac/toolbox/Toolbox-463.html 30# 31# Finder Interface Reference 32# http://developer.apple.com/legacy/mac/library/documentation/Carbon/Reference/Finder_Interface/Reference/reference.html 33# 34# Technical Note TN1150 HFS Plus Volume Format 35# http://developer.apple.com/mac/library/technotes/tn/tn1150.html#FinderInfo 36# 37# CarbonHeaders source 38# http://www.opensource.apple.com/source/CarbonHeaders/CarbonHeaders-8A428/Finder.h 39# http://www.opensource.apple.com/source/CarbonHeaders/CarbonHeaders-9A581/Finder.h 40# 41# Xcode 3.2.1 42# /usr/bin/SetFile 43# /usr/bin/GetFileInfo 44# 45# Mac OS X 10.6.2 kernel source 46# http://www.opensource.apple.com/source/xnu/xnu-1486.2.11/bsd/vfs/vfs_xattr.c 47# 48 49use File::Basename; 50use File::Spec; 51use bigint; # require perl >= 5.8 52 53# parse command line ----------------------------------------------- 54 55$finderinfo = 0; # 0: unknown 1: file 2: directory 56while ($arg = shift @ARGV) 57{ 58 if ($arg =~ /^(-h|-help|--help)$/ ) { 59 printf ("usage: %s [-a] FILE|DIR\n" ,basename($0)); 60 printf (" or: %s -f FILE\n" ,basename($0)); 61 printf (" or: %s -d FILE\n" ,basename($0)); 62 printf (" or: %s -h|-help|--help\n" ,basename($0)); 63 printf (" or: %s -v|-version|--version\n" ,basename($0)); 64 printf ("Dump AppleSingle/AppleDouble format file.\n"); 65 printf ("\n"); 66 printf (" -a (default) Dump a AppleSingle/AppleDouble file for FILE or DIR\n"); 67 printf (" automatically.\n"); 68 printf (" Extrapolate FinderInfo type from absolute path.\n"); 69 printf (" If FILE is not AppleSingle/AppleDouble format,\n"); 70 printf (" look for '.AppleDouble/FILE' and '._FILE'.\n"); 71 printf (" If DIR, look for 'DIR/.AppleDouble/.Parent' and '._DIR'.\n"); 72 printf (" -f Dump FILE. Assume FinderInfo to be FileInfo.\n"); 73 printf (" -d Dump FILE. Assume FinderInfo to be DirInfo.\n"); 74 printf (" -h,-help,--help Display this help and exit\n"); 75 printf (" -v,-version,--version Show version and exit\n"); 76 printf ("\n"); 77 printf ("There is no way to detect whether FinderInfo is FileInfo or DirInfo.\n"); 78 printf ("By default, %s examins whether file or directory,\n" ,basename($0)); 79 printf ("a parent directory is .AppleDouble, filename is ._*, filename is .Parent,\n"); 80 printf ("and so on.\n"); 81 printf ("If setting option -f or -d, %s assume FinderInfo and doesn't look for\n"); 82 printf ("another file.\n"); 83 exit 1; 84 } elsif ($arg =~ /^(-v|-version|--version)$/ ) { 85 printf ("%s \(Netatalk 2.2.5\)\n", basename($0)); 86 exit 1; 87 } elsif ($arg eq "-a") { 88 $finderinfo = 0; 89 } elsif ($arg eq "-f") { 90 $finderinfo = 1; 91 } elsif ($arg eq "-d") { 92 $finderinfo = 2; 93 } elsif ($arg =~ /^-/) { 94 printf (STDERR "%s: invalid option %s\n", basename($0), $arg); 95 printf (STDERR "Try \`%s\ -h' for more information.\n", basename($0)); 96 exit 1; 97 } else { 98 $afile = $arg; 99 } 100} 101 102if (!($afile)) { 103 printf (STDERR "missing file operand.\n"); 104 exit 1; 105} 106if (!( -e $afile)) { 107 printf (STDERR "\"%s\" not found.\n", $afile); 108 exit 1; 109} 110 111# detect FinderInfo, and search AppleSingle/AppleDouble file -------------- 112 113$abspath = File::Spec->rel2abs($afile); 114($basename, $path, $ext) = fileparse($abspath); 115 116if ( $finderinfo != 0 ) { 117 ; 118} elsif ( -f $afile ) { 119 if ( $basename eq ".Parent") { 120 $finderinfo = 2; 121 } elsif ( $path =~ /\/.AppleDouble\/$/ ) { 122 $finderinfo =1; 123 } elsif ( $basename =~ /^._/ ) { 124 if ( -f $path.substr($basename, 2) ) { 125 $finderinfo =1; 126 } elsif ( -d $path.substr($basename, 2) ) { 127 $finderinfo =2; 128 } 129 } 130 if (!open(INFILE, "<$afile")) { 131 printf (STDERR "cannot open %s\n", $afile); 132 exit 1; 133 } 134 read(INFILE,$buf,4); 135 $val = unpack("N", $buf ); 136 close(INFILE); 137 if ($val == 0x00051600 || $val == 0x00051607) { 138 ; 139 } else { 140 printf ("\"%s\" is not AppleSingle/AppleDouble format.\n", $afile); 141 $finderinfo = 1; 142 $netatalkfile = $path.".AppleDouble/".$basename; 143 $osxfile = $path."._".$basename; 144 145 if (( -e $netatalkfile ) && !( -e $osxfile )) { 146 $afile = $netatalkfile; 147 } elsif (!( -e $netatalkfile ) && ( -e $osxfile )) { 148 $afile = $osxfile; 149 } elsif (( -e $netatalkfile ) && ( -e $osxfile )) { 150 printf ("\"%s\" found.\n", $netatalkfile); 151 printf ("\"%s\" found.\n", $osxfile); 152 printf ("Specify which of file.\n"); 153 exit 1; 154 } else { 155 printf ("\"%s\" not found.\n", $netatalkfile); 156 printf ("\"%s\" not found.\n", $osxfile); 157 exit 1; 158 } 159 } 160} elsif ( -d $afile) { 161 printf ("\"%s\" is a directory.\n", $afile); 162 $finderinfo =2; 163 $netatalkfile = $path.$basename."/.AppleDouble/.Parent"; 164 $osxfile = $path."._".$basename; 165 166 if (( -e $netatalkfile ) && !( -e $osxfile )) { 167 $afile = $netatalkfile; 168 } elsif (!( -e $netatalkfile ) && ( -e $osxfile )) { 169 $afile = $osxfile; 170 } elsif (( -e $netatalkfile ) && ( -e $osxfile )) { 171 printf ("\"%s\" found.\n", $netatalkfile); 172 printf ("\"%s\" found.\n", $osxfile); 173 printf ("Specify which of file.\n"); 174 exit 1; 175 } else { 176 printf ("\"%s\" not found.\n", $netatalkfile); 177 printf ("\"%s\" not found.\n", $osxfile); 178 exit 1; 179 } 180} else { 181 printf (STDERR "unknown error: %s\n", $afile); 182 exit 1; 183} 184 185if (!open(INFILE, "<$afile")) { 186 printf (STDERR "cannot open %s\n", $afile); 187 exit 1; 188} 189printf ("%s:\n\n", $afile); 190 191# Magic Number ----------------------------------------------- 192 193print "-------------------------------------------------------------------------------\n"; 194 195read(INFILE,$buf,4); 196$val = unpack("N", $buf ); 197printf("MagicNumber: %08X", $val); 198if ( $val == 0x00051600 ) { 199 printf(" : AppleSingle"); 200} 201elsif ( $val == 0x00051607 ) { 202 printf(" : AppleDouble"); 203} 204else { 205 printf(" : Unknown" ); 206} 207print "\n"; 208 209# Version Number --------------------------------------------- 210 211read(INFILE,$buf,4); 212$version = unpack("N", $buf ); 213printf("Version : %08X", $version); 214if ( $version == 0x00010000 ) { 215 printf(" : Version 1"); 216} elsif ( $version == 0x00020000 ) { 217 printf(" : Version 2"); 218} else { 219 printf(" : Unknown" ); 220} 221print "\n"; 222 223# v1:Home file system / v2:Filler ---------------------------- 224 225read(INFILE,$buf,16); 226if ( $version == 0x00010000 ) { 227 print "HomeFileSys:"; 228} else { 229 print "Filler :"; 230} 231hexdump($buf, 16, 16, " "); 232 233# Number of entities ----------------------------------------- 234 235read(INFILE,$buf,2); 236$entnum = unpack("n", $buf ); 237printf("Num. of ent: %04X ", $entnum); 238printf(" : %d", $entnum); 239print "\n"; 240 241# data ------------------------------------------------------- 242 243for ( $num = 0 ; $num < $entnum ; $num++) { 244 245 seek(INFILE, ($num * 12 + 26), 0); 246 247# Entry --------------------------------------------------- 248 249 read(INFILE,$buf,4); 250 $entid = unpack("N", $buf ); 251 print "\n-------------------------------------------------------------------------------\n"; 252 printf("Entry ID : %08X", $entid); 253 if ( $entid == 1 ) { printf(" : Data Fork"); } 254 elsif ( $entid == 2 ) { printf(" : Resource Fork"); } 255 elsif ( $entid == 3 ) { printf(" : Real Name"); } 256 elsif ( $entid == 4 ) { printf(" : Comment"); } 257 elsif ( $entid == 5 ) { printf(" : Icon, B&W"); } 258 elsif ( $entid == 6 ) { printf(" : Icon Color"); } 259 elsif ( $entid == 7 ) { printf(" : File Info"); } 260 elsif ( $entid == 8 ) { printf(" : File Dates Info"); } 261 elsif ( $entid == 9 ) { printf(" : Finder Info"); } 262 elsif ( $entid == 10 ) { printf(" : Macintosh File Info"); } 263 elsif ( $entid == 11 ) { printf(" : ProDOS File Info"); } 264 elsif ( $entid == 12 ) { printf(" : MS-DOS File Info"); } 265 elsif ( $entid == 13 ) { printf(" : Short Name"); } 266 elsif ( $entid == 14 ) { printf(" : AFP File Info"); } 267 elsif ( $entid == 15 ) { printf(" : Directory ID"); } 268 elsif ( $entid == 0x8053567E ) { printf(" : CNID (Netatalk Extended)"); } 269 elsif ( $entid == 0x8053594E ) { printf(" : DB stamp (Netatalk Extended)"); } 270 elsif ( $entid == 0x80444556 ) { printf(" : dev (Netatalk Extended)"); } 271 elsif ( $entid == 0x80494E4F ) { printf(" : inode (Netatalk Extended)"); } 272 else { printf(" : Unknown"); } 273 print "\n"; 274 275# Offset ------------------------------------------------- 276 277 read(INFILE,$buf,4); 278 $ofst = unpack("N", $buf ); 279 printf("Offset : %08X", $ofst); 280 printf(" : %d ", $ofst); 281 282# Length ------------------------------------------------- 283 284 read(INFILE,$buf,4); 285 $len = unpack("N", $buf ); 286 printf("\nLength : %08X", $len); 287 printf(" : %d", $len); 288 $quo = $len >> 4; 289 $rem = $len & 0xF; 290 print "\n"; 291 292# Dump for each Entry ID -------------------------------- 293 294# if ( $entid == 1 ) { ; } # Data Fork 295# if ( $entid == 2 ) { ; } # Resource Fork 296# if ( $entid == 3 ) { ; } # Real Name 297# if ( $entid == 4 ) { ; } # Comment 298# if ( $entid == 5 ) { ; } # Icon, B&W 299# if ( $entid == 6 ) { ; } # Icon Color 300# if ( $entid == 7 ) { ; } # File Info 301 if ( $entid == 8 ) { filedatesdump($ofst,$len); } 302 elsif ( $entid == 9 ) { finderinfodump($ofst,$len); } 303# if ( $entid == 10 ) { ; } # Macintosh File Info 304# if ( $entid == 11 ) { ; } # ProDOS File Info 305# if ( $entid == 12 ) { ; } # MS-DOS File Info 306# if ( $entid == 13 ) { ; } # Short Name 307# if ( $entid == 14 ) { ; } # AFP File Info 308 elsif ( $entid == 15 ) { print "\n"; bedump($ofst,$len); } # Directory ID 309 elsif ( $entid == 0x8053567E ) { print "\n"; bedump($ofst,$len); } # CNID (Netatalk Extended) 310 elsif ( $entid == 0x8053594E ) { print "\n"; bedump($ofst,$len); ledump($ofst,$len); } # DB stamp (Netatalk Extended) 311 elsif ( $entid == 0x80444556 ) { print "\n"; bedump($ofst,$len); ledump($ofst,$len); } # dev (Netatalk Extended) 312 elsif ( $entid == 0x80494E4F ) { print "\n"; bedump($ofst,$len); ledump($ofst,$len); } # inode (Netatalk Extended) 313 314# RAW Dump --------------------------------------------------- 315 316 if ( ($quo > 0) || ($rem > 0)) { 317 print "\n"; 318 print "-RAW DUMP--: 0 1 2 3 4 5 6 7 8 9 A B C D E F : (ASCII)\n"; 319 } 320 321 seek(INFILE, $ofst, 0); 322 rawdump($quo, $rem); 323 324} 325 326close(INFILE); 327exit 0; 328 329#sub ----------------------------------------------------------- 330 331sub filedatesdump { 332 my ($ofst, $len) = @_; 333 my ($datedata); 334 my ($i); 335 my ($datestr); 336 337 @datetype =('create ', 'modify ', 'backup ', 'access '); 338 339 seek(INFILE, $ofst, 0); 340 341 print "\n"; 342 printf ("-DATE------: : (GMT) : (Local)\n"); 343 344 for ( $i = 0 ; $i < 4 ; $i++) { 345 read(INFILE,$buf,4); 346 $datedata = unpack("N", $buf ); 347 if ($datedata < 0x80000000) { 348 $datestr = gmtime( $datedata + 946684800) 349 ." : " 350 .localtime( $datedata + 946684800); 351 } elsif ($datedata == 0x80000000) { 352 $datestr = "Unknown or Initial"; 353 } else { 354 $datestr = gmtime( $datedata - 3348282496) 355 ." : " 356 .localtime( $datedata - 3348282496); 357 } 358 printf ("%s : %08X : %s\n",$datetype[$i], $datedata, $datestr); 359 } 360} 361 362sub finderinfodump { 363 my ($ofst, $len) = @_; 364 365 seek(INFILE, $ofst, 0); 366 367 if ($finderinfo == 0) { 368 print "\n"; 369 print "-NOTE------: cannot detect whether FInfo or DInfo. assume FInfo.\n"; 370 } 371 372 if ($finderinfo == 0 || $finderinfo == 1) { 373 filefinderinfodump(); 374 } elsif ($finderinfo == 2) { 375 dirfinderinfodump(); 376 } else { 377 print STDERR "unknown FinderInfo type\n" 378 } 379 380 if ($len > 32) { eadump(); } 381} 382 383sub filefinderinfodump { 384 385 print "\n"; 386 print "-FInfo-----:\n"; 387 388 read(INFILE,$buf,4); 389 print "Type : "; 390 hexdump($buf, 4, 4, ""); 391 392 read(INFILE,$buf,4); 393 print "Creator : "; 394 hexdump($buf, 4, 4, ""); 395 396 flagsdump(); 397 398 read(INFILE,$buf,2); 399 $val = unpack("n", $buf ); 400 printf("Location v : %04X", $val); 401 printf(" : %d\n", $val>0x7FFF?$val-0x10000:$val); 402 403 read(INFILE,$buf,2); 404 $val = unpack("n", $buf ); 405 printf("Location h : %04X", $val); 406 printf(" : %d\n", $val>0x7FFF?$val-0x10000:$val); 407 408 read(INFILE,$buf,2); 409 print "Fldr : "; 410 hexdump($buf, 2, 4, ""); 411 412 print "\n"; 413 print "-FXInfo----:\n"; 414 415 read(INFILE,$buf,2); 416 $val = unpack("n", $buf ); 417 printf("Rsvd|IconID: %04X", $val); 418 printf(" : %d\n", $val>0x7FFF?$val-0x10000:$val); 419 420 read(INFILE,$buf,2); 421 print "Rsvd : "; 422 hexdump($buf, 2, 4, ""); 423 read(INFILE,$buf,2); 424 print "Rsvd : "; 425 hexdump($buf, 2, 4, ""); 426 read(INFILE,$buf,2); 427 print "Rsvd : "; 428 hexdump($buf, 2, 4, ""); 429 430 xflagsdump(); 431 432 read(INFILE,$buf,2); 433 $val = unpack("n", $buf ); 434 printf("Rsvd|commnt: %04X", $val); 435 printf(" : %d\n", $val>0x7FFF?$val-0x10000:$val); 436 437 read(INFILE,$buf,4); 438 $val = unpack("N", $buf ); 439 printf("PutAway : %08X", $val); 440 printf(" : %d\n", $val>0x7FFFFFFF?$val-0x100000000:$val); # Why SInt32? 441 442} 443 444sub dirfinderinfodump { 445 446 print "\n"; 447 print "-DInfo-----:\n"; 448 449 read(INFILE,$buf,2); 450 $val = unpack("n", $buf ); 451 printf("Rect top : %04X", $val); 452 printf(" : %d\n", $val>0x7FFF?$val-0x10000:$val); 453 454 read(INFILE,$buf,2); 455 $val = unpack("n", $buf ); 456 printf("Rect left : %04X", $val); 457 printf(" : %d\n", $val>0x7FFF?$val-0x10000:$val); 458 459 read(INFILE,$buf,2); 460 $val = unpack("n", $buf ); 461 printf("Rect bottom: %04X", $val); 462 printf(" : %d\n", $val>0x7FFF?$val-0x10000:$val); 463 464 read(INFILE,$buf,2); 465 $val = unpack("n", $buf ); 466 printf("Rect right : %04X", $val); 467 printf(" : %d\n", $val>0x7FFF?$val-0x10000:$val); 468 469 flagsdump(); 470 471 read(INFILE,$buf,2); 472 $val = unpack("n", $buf ); 473 printf("Location v : %04X", $val); 474 printf(" : %d\n", $val>0x7FFF?$val-0x10000:$val); 475 476 read(INFILE,$buf,2); 477 $val = unpack("n", $buf ); 478 printf("Location h : %04X", $val); 479 printf(" : %d\n", $val>0x7FFF?$val-0x10000:$val); 480 481 read(INFILE,$buf,2); 482 print "View : "; 483 hexdump($buf, 2, 4, ""); 484 485 print "\n"; 486 print "-DXInfo----:\n"; 487 488 read(INFILE,$buf,2); 489 $val = unpack("n", $buf ); 490 printf("Scroll v : %04X", $val); 491 printf(" : %d\n", $val>0x7FFF?$val-0x10000:$val); 492 493 read(INFILE,$buf,2); 494 $val = unpack("n", $buf ); 495 printf("Scroll h : %04X", $val); 496 printf(" : %d\n", $val>0x7FFF?$val-0x10000:$val); 497 498 read(INFILE,$buf,4); 499 $val = unpack("N", $buf ); 500 printf("Rsvd|OpnChn: %08X", $val); 501 printf(" : %d\n", $val>0x7FFFFFFF?$val-0x100000000:$val); # Why SInt32? 502 503 xflagsdump(); 504 505 read(INFILE,$buf,2); 506 print "Comment : "; 507 hexdump($buf, 2, 4, ""); 508 509 read(INFILE,$buf,4); 510 $val = unpack("N", $buf ); 511 printf("PutAway : %08X", $val); 512 printf(" : %d\n", $val>0x7FFFFFFF?$val-0x100000000:$val); # Why SInt32? 513 514} 515sub flagsdump { 516 517 @colortype =('none', 'gray', 'green', 'purple', 'blue', 'yellow', 'red', 'orange'); 518 519 read(INFILE,$buf,2); 520 $flags = unpack("n", $buf ); 521 printf ("isAlias : %d\n", ($flags >> 15) & 1); 522 printf ("Invisible : %d\n", ($flags >> 14) & 1); 523 printf ("hasBundle : %d\n", ($flags >> 13) & 1); 524 printf ("nameLocked : %d\n", ($flags >> 12) & 1); 525 printf ("Stationery : %d\n", ($flags >> 11) & 1); 526 printf ("CustomIcon : %d\n", ($flags >> 10) & 1); 527 printf ("Reserved : %d\n", ($flags >> 9) & 1); 528 printf ("Inited : %d\n", ($flags >> 8) & 1); 529 printf ("NoINITS : %d\n", ($flags >> 7) & 1); 530 printf ("Shared : %d\n", ($flags >> 6) & 1); 531 printf ("SwitchLaunc: %d\n", ($flags >> 5) & 1); 532 printf ("Hidden Ext : %d\n", ($flags >> 4) & 1); 533 printf ("color : %d%d%d : %s\n", ($flags >> 3) & 1, 534 ($flags >> 2) & 1, 535 ($flags >> 1) & 1, 536 @colortype[($flags & 0xE)>>1]); 537 printf ("isOnDesk : %d\n", ($flags >> 0) & 1); 538 539} 540 541sub xflagsdump { 542 543 read(INFILE,$buf,2); 544 $flags = unpack("n", $buf ); 545 546 if (($flags >> 15) == 1) { 547 print "Script : "; 548 hexdump($buf, 1, 4, ""); 549 } else { 550 printf ("AreInvalid : %d\n", ($flags >> 15) & 1); 551 printf ("unknown bit: %d\n", ($flags >> 14) & 1); 552 printf ("unknown bit: %d\n", ($flags >> 13) & 1); 553 printf ("unknown bit: %d\n", ($flags >> 12) & 1); 554 printf ("unknown bit: %d\n", ($flags >> 11) & 1); 555 printf ("unknown bit: %d\n", ($flags >> 10) & 1); 556 printf ("unknown bit: %d\n", ($flags >> 9) & 1); 557 } 558 559 printf ("CustomBadge: %d\n", ($flags >> 8) & 1); 560 printf ("ObjctIsBusy: %d\n", ($flags >> 7) & 1); 561 printf ("unknown bit: %d\n", ($flags >> 6) & 1); 562 printf ("unknown bit: %d\n", ($flags >> 5) & 1); 563 printf ("unknown bit: %d\n", ($flags >> 4) & 1); 564 printf ("unknown bit: %d\n", ($flags >> 3) & 1); 565 printf ("RoutingInfo: %d\n", ($flags >> 2) & 1); 566 printf ("unknown bit: %d\n", ($flags >> 1) & 1); 567 printf ("unknown bit: %d\n", ($flags >> 0) & 1); 568 569} 570 571sub eadump { 572 573 print "\n"; 574 print "-EA--------:\n"; 575 576 read(INFILE,$buf,2); 577 print "pad : "; 578 hexdump($buf, 2, 4, ""); 579 580 read(INFILE,$buf,4); 581 print "magic : "; 582 hexdump($buf, 4, 4, ""); 583 584 read(INFILE,$buf,4); 585 $ea_debug_tag = unpack("N", $buf ); 586 printf("debug_tag : %08X", $ea_debug_tag); 587 printf(" : %d\n", $ea_debug_tag); 588 589 read(INFILE,$buf,4); 590 $ea_total_size = unpack("N", $buf ); 591 printf("total_size : %08X", $ea_total_size); 592 printf(" : %d\n", $ea_total_size); 593 594 read(INFILE,$buf,4); 595 $ea_data_start = unpack("N", $buf ); 596 printf("data_start : %08X", $ea_data_start); 597 printf(" : %d\n", $ea_data_start); 598 599 read(INFILE,$buf,4); 600 $ea_data_length = unpack("N", $buf ); 601 printf("data_length: %08X", $ea_data_length); 602 printf(" : %d\n", $ea_data_length); 603 604 read(INFILE,$buf,4); 605 print "reserved[0]: "; 606 hexdump($buf, 4, 4, ""); 607 608 read(INFILE,$buf,4); 609 print "reserved[1]: "; 610 hexdump($buf, 4, 4, ""); 611 612 read(INFILE,$buf,4); 613 print "reserved[2]: "; 614 hexdump($buf, 4, 4, ""); 615 616 read(INFILE,$buf,2); 617 print "flags : "; 618 hexdump($buf, 2, 4, ""); 619 620 read(INFILE,$buf,2); 621 $ea_num_attrs = unpack("n", $buf ); 622 printf("num_attrs : %04X", $ea_num_attrs); 623 printf(" : %d\n", $ea_num_attrs); 624 625 $pos = tell(INFILE); 626 627 for ($i = 0 ; $i < $ea_num_attrs ; $i++) { 628 629 $pos = (($pos & 0x3) == 0) ? ($pos) : ((($pos >> 2) + 1) << 2); 630 seek(INFILE, $pos, 0); 631 632 print "-EA ENTRY--:\n"; 633 634 read(INFILE,$buf,4); 635 $ea_offset = unpack("N", $buf ); 636 printf("offset : %08X", $ea_offset); 637 printf(" : %d\n", $ea_offset); 638 639 read(INFILE,$buf,4); 640 $ea_length = unpack("N", $buf ); 641 printf("length : %08X", $ea_length); 642 printf(" : %d\n", $ea_length); 643 644 read(INFILE,$buf,2); 645 print "flags : "; 646 hexdump($buf, 2, 4, ""); 647 648 read(INFILE,$buf,1); 649 $ea_namelen = unpack("C", $buf ); 650 printf("namelen : %02X", $ea_namelen); 651 printf(" : %d\n", $ea_namelen); 652 653 $ea_namequo = $ea_namelen >> 4; 654 $ea_namerem = $ea_namelen & 0xF; 655 print "-EA NAME---: 0 1 2 3 4 5 6 7 8 9 A B C D E F : (ASCII)\n"; 656 rawdump($ea_namequo, $ea_namerem); 657 658 $pos = tell(INFILE); 659 660 seek(INFILE, $ea_offset, 0); 661 $ea_quo = $ea_length >> 4; 662 $ea_rem = $ea_length & 0xF; 663 print "-EA VALUE--: 0 1 2 3 4 5 6 7 8 9 A B C D E F : (ASCII)\n"; 664 rawdump($ea_quo, $ea_rem); 665 } 666} 667 668sub bedump { 669 my ($ofst, $len) = @_; 670 my ($i); 671 my ($value); 672 673 seek(INFILE, $ofst, 0); 674 675 printf("%2dbit-BE : ", $len * 8 ); 676 677 $value = 0; 678 for ( $i=0 ; $i < $len ; $i++ ) { 679 read(INFILE,$buf,1); 680 $bytedata[$i] = unpack("C", $buf ); 681 $value += $bytedata[$i] << (($len - $i -1) * 8) ; 682 } 683 684 for ( $i=0 ; $i < $len ; $i++ ) { 685 printf("%02X", $bytedata[$i]); 686 } 687 688 printf(" : %s", $value); 689 print "\n"; 690 691} 692 693sub ledump { 694 my ($ofst, $len) = @_; 695 my ($i); 696 my ($value); 697 698 seek(INFILE, $ofst, 0); 699 700 printf("%2dbit-LE : ", $len * 8 ); 701 702 $value = 0; 703 for ( $i=0 ; $i < $len ; $i++ ) { 704 read(INFILE,$buf,1); 705 $bytedata[$len - $i - 1] = unpack("C", $buf ); 706 $value += $bytedata[$len - $i -1] << ($i * 8) ; 707 } 708 709 for ( $i=0 ; $i < $len ; $i++ ) { 710 printf("%02X", $bytedata[$i]); 711 } 712 713 printf(" : %s", $value); 714 print "\n"; 715 716} 717 718sub rawdump { 719 my ($quo, $rem) = @_; 720 my ($addrs, $line, $buf); 721 722 $addrs = 0; 723 for ( $line = 0 ; $line < $quo ; $line++) { 724 read(INFILE, $buf, 16); 725 printf ( "%08X :", $addrs); 726 hexdump($buf, 16, 16, " "); 727 $addrs = $addrs + 0x10; 728 } 729 if ( $rem != 0 ) { 730 read(INFILE, $buf, $rem); 731 printf ( "%08X :", $addrs); 732 hexdump($buf, $rem, 16, " "); 733 } 734 735} 736 737sub hexdump { 738 my ($buf, $len, $col, $delimit) = @_; 739 my ($i); 740 741 $hexstr = ""; 742 $ascstr = ""; 743 744 for ( $i=0 ; $i < $len ; $i++ ) { 745 $val = substr($buf, $i, 1); 746 $ascval = ord($val); 747 $hexstr .= sprintf("%s%02X", $delimit, $ascval); 748 749 if (($ascval < 32) || ( $ascval > 126 )) { 750 $val = "."; 751 } 752 $ascstr .= $val; 753 } 754 for ( ; $i < $col ; $i++) { 755 $hexstr .= " ".$delimit; 756 $ascstr .= " "; 757 } 758 759 printf("%s : %s", $hexstr,$ascstr); 760 761 print "\n"; 762} 763 764#EOF 765