• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /netgear-WNDR4500v2-V1.0.0.60_1.0.38/ap/gpl/timemachine/netatalk-2.2.5/contrib/shell_utils/
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 (" 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 @NETATALK_VERSION@\)\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