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