1 /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */
2 /* Copyright (C) 2002,2005 by Duane H. Hesser. All rights reserved.   */
3 /*                                                                    */
4 /* See the file LICENSE.EXIFPROBE for terms of use.                   */
5 /* =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */
6 
7 /* This program reads an arbitrary section of a file from             */
8 /* 'start_offset' to 'end_offset', printing the data as numerical     */
9 /* values in one or more of the requested formats.                    */
10 
11 
12 /* First argument is filename; section to be dumped may be specified  */
13 /* by a second argument "@start:length" or by second and third        */
14 /* arguments "start end".                                             */
15 
16 #ifndef lint
17 static char *ModuleId = "@(#) $Id: dump_section.c,v 1.3 2005/07/24 22:57:36 alex Exp $";
18 #endif
19 
20 #include <stdio.h>
21 /* #include <stdlib.h> */
22 #include <limits.h>
23 #include <string.h>
24 #include <values.h>  /* Needed for MAXINT, no matter what compiler    */
25                      /* may say                                       */
26 
27 #define END_OF_FILE MAXINT
28 #define NAMELENGTH  1024
29 #define TIFF_INTEL      0x4949
30 #define TIFF_MOTOROLA   0x4d4d
31 #define HERE    (unsigned long)0xffffffff
32 
33 extern char *optarg;
34 char *Progname;
35 extern int errno;
36 
37 extern unsigned short read_ushort(FILE *,unsigned short,unsigned long);
38 extern unsigned short to_ushort(unsigned char *,unsigned short);
39 extern unsigned long read_ulong(FILE *,unsigned short,unsigned long);
40 extern unsigned long to_ulong(unsigned char *,unsigned short);
41 
42 
43 
main(int argc,char ** argv)44 main(int argc,char **argv)
45 {
46     char *arg,*infilename,*colon;
47     unsigned long offset = 0UL;
48     unsigned long start_offset = 0UL;
49     unsigned long end_offset = END_OF_FILE;
50     int opt,i;
51     FILE *ifp;
52     unsigned long section_size = 0;
53     unsigned long lvalue;
54     unsigned short svalue;
55     unsigned short byteorder = TIFF_INTEL;
56     unsigned short snumerator,sdenominator;
57     unsigned long lnumerator,ldenominator;
58     double rvalue;
59     int show_bytes = 0;
60     int show_bytes_decimal = 0;
61     int show_bytes_hex = 0;
62     int show_short = 0;
63     int show_short_decimal = 0;
64     int show_short_hex = 0;
65     int show_long = 0;
66     int show_long_decimal = 0;
67     int show_long_hex = 0;
68     int show_rational = 0;
69     int show_long_rational = 0;
70     int show_short_rational = 0;
71 
72     Progname = *argv++;
73     --argc;
74     while(argc > 2 && *argv)
75     {
76         arg = *argv;
77         if(arg && (*arg == '-'))
78         {
79             switch(*++arg)
80             {
81             case 'b': /* bytes */
82                 show_bytes = 1;
83                 if(*++arg == '\0')
84                 {
85                     show_bytes_decimal = 1;
86                     show_bytes_hex = 1;
87                 }
88                 if(strchr(arg,'d'))
89                     show_bytes_decimal = 1;
90                 if(strchr(arg,'h'))
91                     show_bytes_hex = 1;
92                 break;
93             case 's': /* shorts */
94                 show_short = 1;
95                 if(*++arg == '\0')
96                 {
97                     show_short_decimal = 1;
98                     show_short_hex = 1;
99                 }
100                 if(strchr(arg,'d'))
101                     show_short_decimal = 1;
102                 if(strchr(arg,'h'))
103                     show_short_hex = 1;
104                 break;
105             case 'l': /* longs */
106                 show_long = 1;
107                 if(*++arg == '\0')
108                 {
109                     show_long_decimal = 1;
110                     show_long_hex = 1;
111                 }
112                 if(strchr(arg,'d'))
113                     show_long_decimal = 1;
114                 if(strchr(arg,'h'))
115                     show_long_hex = 1;
116                 break;
117             case 'r':
118                 show_rational = 1;
119                 if(*++arg == '\0')
120                 {
121                     show_long_rational = 1;
122                     show_short_rational = 1;
123                 }
124                 if(strchr(arg,'l'))
125                     show_long_rational = 1;
126                 if(strchr(arg,'s'))
127                     show_short_rational = 1;
128                 break;
129             case 'i': /* Intel byteorder */
130                 byteorder = TIFF_INTEL;
131                 break;
132             case 'm': /* Motorola byteorder */
133                 byteorder = TIFF_MOTOROLA;
134                 break;
135 
136             }
137             --argc;
138             ++argv;
139         }
140         else
141             break;
142     }
143 
144     if(argc >= 1)
145     {
146         infilename = *argv;
147         arg = *++argv;
148         if(arg && (*arg == '@'))
149         {
150             start_offset = strtoul(++arg,(char **)0,0);
151             colon = strchr(arg,':');
152             if(colon)
153                 end_offset = start_offset + strtoul(++colon,(char **)0,0) - 1;
154         }
155         else if(arg)
156         {
157             start_offset = strtoul(arg,(char **)0,0);
158             if(*++argv)
159             {
160                 arg = *argv;
161                 end_offset = strtoul(arg,(char **)0,0);
162             }
163         }
164     }
165 
166     printf("input file %s\n",infilename);
167     printf("start_offset = %lu, ",start_offset);
168     section_size =  end_offset - start_offset + 1;
169     if(end_offset == END_OF_FILE)
170         printf("end_offset = end of file\n");
171     else
172         printf("end_offset = %ld, section length = %ld\n",end_offset,section_size);
173     printf("byteorder = %2.2s\n",(char *)&byteorder);
174 
175     if((ifp = fopen(infilename,"r")) != (FILE *)0)
176     {
177         if(show_bytes)
178         {
179             if(show_bytes_decimal)
180             {
181                 fseek(ifp,start_offset,0);
182                 offset = start_offset;
183                 i = 0;
184                 printf("\n=============================================\nUnsigned byte - decimal:\n");
185                 while((offset <= end_offset) && !feof(ifp) && !ferror(ifp))
186                 {
187                     svalue = fgetc(ifp);
188                     printf("%#06lx/%-04lu: %-12u",offset,offset,svalue);
189                     ++offset;
190                     if(++i == 4)
191                     {
192                         putchar('\n');
193                         i = 0;
194                     }
195                 }
196             }
197             if(show_bytes_hex)
198             {
199                 printf("\n=============================================\nUnsigned byte - hex:\n");
200                 fseek(ifp,start_offset,0);
201                 offset = start_offset;
202                 i = 0;
203                 while((offset <= end_offset) && !feof(ifp) && !ferror(ifp))
204                 {
205                     svalue = fgetc(ifp);
206                     printf("%#06lx/%-04lu: %-12#x",offset,offset,svalue);
207                     ++offset;
208                     if(++i == 4)
209                     {
210                         putchar('\n');
211                         i = 0;
212                     }
213                 }
214             }
215         }
216         if(show_short)
217         {
218             if(show_short_decimal)
219             {
220                 offset = start_offset;
221                 i = 0;
222                 printf("\n=============================================\nUnsigned short - decimal:\n");
223                 while((offset <= end_offset) && !feof(ifp) && !ferror(ifp))
224                 {
225                     svalue = read_ushort(ifp,byteorder,offset);
226                     printf("%#06lx/%-04lu: %-12u",offset,offset,svalue);
227                     offset += 2;
228                     if(++i == 4)
229                     {
230                         putchar('\n');
231                         i = 0;
232                     }
233                 }
234             }
235             if(show_short_hex)
236             {
237                 offset = start_offset;
238                 i = 0;
239                 printf("\n=============================================\nUnsigned short - hex:\n");
240                 while((offset <= end_offset) && !feof(ifp) && !ferror(ifp))
241                 {
242                     svalue = read_ushort(ifp,byteorder,offset);
243                     printf("%#06lx/%-04lu: %-12#x",offset,offset,svalue);
244                     offset += 2;
245                     if(++i == 4)
246                     {
247                         putchar('\n');
248                         i = 0;
249                     }
250                 }
251             }
252         }
253         if(show_long)
254         {
255             if(show_long_decimal)
256             {
257                 fseek(ifp,start_offset,0);
258                 offset = start_offset;
259                 i = 0;
260                 printf("\n=============================================\nUnsigned long - decimal:\n");
261                 while((offset <= end_offset) && !feof(ifp) && !ferror(ifp))
262                 {
263                     lvalue = read_ulong(ifp,byteorder,offset);
264                     printf("%#06x/%-04lu: %-12lu",offset,offset,lvalue);
265                     offset += 4;
266                     if(++i == 4)
267                     {
268                         putchar('\n');
269                         i = 0;
270                     }
271                 }
272                 putchar('\n');
273             }
274             if(show_long_hex)
275             {
276                 fseek(ifp,start_offset,0);
277                 offset = start_offset;
278                 i = 0;
279                 printf("\n=============================================\nUnsigned long - hex:\n");
280                 while((offset <= end_offset) && !feof(ifp) && !ferror(ifp))
281                 {
282                     lvalue = read_ulong(ifp,byteorder,offset);
283                     printf("%#06x/%-04lu: %-12#lx",offset,offset,lvalue);
284                     offset += 4;
285                     if(++i == 4)
286                     {
287                         putchar('\n');
288                         i = 0;
289                     }
290                 }
291                 putchar('\n');
292             }
293         }
294 
295         if(show_rational)
296         {
297             if(show_long_rational)
298             {
299                 fseek(ifp,start_offset,0);
300                 offset = start_offset;
301                 i = 0;
302                 printf("\n=============================================\nUnsigned long - rational:\n");
303                 while((offset <= end_offset) && !feof(ifp) && !ferror(ifp))
304                 {
305                     rvalue = 0.0;
306                     lnumerator = read_ulong(ifp,byteorder,offset);
307                     ldenominator = read_ulong(ifp,byteorder,HERE);
308                     if(sdenominator)
309                         rvalue = (double)lnumerator / (double)ldenominator;
310                     printf("%#06x/%-04lu: %-12.8f",offset,offset,rvalue);
311                     offset += 8;
312                     if(++i == 4)
313                     {
314                         putchar('\n');
315                         i = 0;
316                     }
317                 }
318                 putchar('\n');
319             }
320             if(show_short_rational)
321             {
322                 fseek(ifp,start_offset,0);
323                 offset = start_offset;
324                 i = 0;
325                 printf("\n=============================================\nUnsigned short rational:\n");
326                 while((offset <= end_offset) && !feof(ifp) && !ferror(ifp))
327                 {
328                     rvalue = 0.0;
329                     snumerator = read_ushort(ifp,byteorder,offset);
330                     sdenominator = read_ushort(ifp,byteorder,HERE);
331                     if(sdenominator)
332                         rvalue = (double)snumerator / (double)sdenominator;
333                     printf("%#06x/%-04lu: %-12.8f",offset,offset,rvalue);
334                     offset += 4;
335                     if(++i == 4)
336                     {
337                         putchar('\n');
338                         i = 0;
339                     }
340                 }
341                 putchar('\n');
342             }
343         }
344     }
345     else
346     {
347         fprintf(stderr,"%s: could not open input file \"%s\"\n",Progname,infilename);
348         perror("\tbecause");
349         exit(3);
350     }
351     exit(0);
352 }
353 
354 unsigned short
read_ushort(FILE * inptr,unsigned short byteorder,unsigned long offset)355 read_ushort(FILE *inptr,unsigned short byteorder,unsigned long offset)
356 {
357     unsigned char rbuf[2];
358     unsigned long curoffset;
359     unsigned short value = 0;
360     int chpr = 0;
361 
362     if(inptr /*&& !feof(inptr) && !ferror(inptr)*/)
363     {
364         clearerr(inptr);
365         curoffset = ftell(inptr);
366         if((offset != HERE) && (fseek(inptr,offset,0) == -1))
367         {
368             printf(" SEEK FAILED to read unsigned short at offset ");
369             printf("%lu",offset);
370         }
371         else if(fread(rbuf,1,sizeof(unsigned short),inptr) == sizeof(unsigned short))
372             value = to_ushort(rbuf,byteorder);
373         else
374         {
375             printf(" FAILED to read unsigned short value at offset ");
376             if(offset == HERE)
377                 offset = curoffset;
378             chpr += printf("%lu",offset);
379         }
380         if(ferror(inptr))
381         {
382             chpr += printf(" (");
383             printf(strerror(errno));
384             chpr += printf(")");
385             chpr = putchar('\n');
386         }
387         else if(feof(inptr))
388         {
389             printf(" (EOF)");
390             chpr = putchar('\n');
391         }
392     }
393     return(value);
394 }
395 
396 unsigned long
read_ulong(FILE * inptr,unsigned short byteorder,unsigned long offset)397 read_ulong(FILE *inptr,unsigned short byteorder,unsigned long offset)
398 {
399     unsigned char rbuf[4];
400     unsigned long curoffset;
401     unsigned long value = 0;
402     int chpr = 0;
403 
404     if(inptr /* && !feof(inptr) && !ferror(inptr)*/)
405     {
406         clearerr(inptr);
407         curoffset = ftell(inptr);
408         if((offset != HERE) && (fseek(inptr,offset,0) == -1))
409         {
410             printf(" SEEK FAILED to read unsigned 32bit integer at offset ");
411             printf("%lu",offset);
412         }
413         else if(fread(rbuf,1,4,inptr) == 4)
414             value = to_ulong(rbuf,byteorder);
415         else
416         {
417             printf(" FAILED to read unsigned 32bit integer at offset ");
418             if(offset == HERE)
419                 offset = curoffset;
420             chpr += printf("%lu",offset);
421         }
422         if(ferror(inptr))
423         {
424             chpr += printf(" (");
425             printf(strerror(errno));
426             chpr += printf(")");
427             putchar('\n');
428         }
429         else if(feof(inptr))
430         {
431             printf(" (EOF)");
432             chpr = putchar('\n');
433         }
434     }
435     return(value);
436 }
437 
438 unsigned short
to_ushort(unsigned char * buf,unsigned short byteorder)439 to_ushort(unsigned char *buf,unsigned short byteorder)
440 {
441     unsigned short value = 0;
442 
443     if(buf)
444     {
445         value = *(unsigned short *)buf;
446 #ifdef NATIVE_BYTEORDER_BIGENDIAN
447         if(byteorder == TIFF_INTEL)
448             value = (buf[1] << 8) | buf[0];
449 #else
450         if(byteorder == TIFF_MOTOROLA)
451             value = (buf[0] << 8) | buf[1];
452 #endif
453     }
454     return(value);
455 }
456 
457 unsigned long
to_ulong(unsigned char * buf,unsigned short byteorder)458 to_ulong(unsigned char *buf,unsigned short byteorder)
459 {
460     unsigned long value = 0;
461 
462     if(buf)
463     {
464         value = *(unsigned long *)buf;
465 #ifdef NATIVE_BYTEORDER_BIGENDIAN
466         if(byteorder == TIFF_INTEL)
467 #else
468         if(byteorder == TIFF_MOTOROLA)
469 #endif
470             value = (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3];
471     }
472     return((unsigned long)value);
473 }
474 
475