1 /* $Header: /cvsroot/osrs/libtiff/tools/tiffdump.c,v 1.3 2003/09/02 13:28:09 warmerda Exp $ */
2 
3 /*
4  * Copyright (c) 1988-1997 Sam Leffler
5  * Copyright (c) 1991-1997 Silicon Graphics, Inc.
6  *
7  * Permission to use, copy, modify, distribute, and sell this software and
8  * its documentation for any purpose is hereby granted without fee, provided
9  * that (i) the above copyright notices and this permission notice appear in
10  * all copies of the software and related documentation, and (ii) the names of
11  * Sam Leffler and Silicon Graphics may not be used in any advertising or
12  * publicity relating to the software without the specific, prior written
13  * permission of Sam Leffler and Silicon Graphics.
14  *
15  * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
16  * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
17  * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
18  *
19  * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
20  * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
21  * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
22  * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF
23  * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
24  * OF THIS SOFTWARE.
25  */
26 
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <string.h>
30 
31 #if defined(VMS)
32 #include <unixio.h>
33 #include <file.h>
34 #elif defined(_WINDOWS)
35 #include <io.h>
36 #define	off_t	toff_t
37 #include "tiffio.h"
38 #include <fcntl.h>
39 #elif defined(applec)
40 #define open _open_ /* to avoid conflicts */
41 #include <fcntl.h>
42 #undef open
43 int  open(const char*, int, int);
44 typedef unsigned int off_t;
45 #else /* !VMS && !_WINDOWS && !applec */
46 #ifdef unix
47 #include <sys/types.h>
48 #endif
49 #include <unistd.h>
50 #include <fcntl.h>
51 #endif
52 
53 #if defined(MSDOS)
54 #include <malloc.h>
55 #endif
56 
57 #ifndef O_BINARY
58 #define	O_BINARY	0
59 #endif
60 
61 #include "tiffio.h"
62 
63 char*	appname;
64 char*	curfile;
65 int	swabflag;
66 int	bigendian;
67 int	typeshift[13];		/* data type shift counts */
68 long	typemask[13];		/* data type masks */
69 int	maxitems = 24;		/* maximum indirect data items to print */
70 
71 char*	bytefmt = "%s%#02x";		/* BYTE */
72 char*	sbytefmt = "%s%d";		/* SBYTE */
73 char*	shortfmt = "%s%u";		/* SHORT */
74 char*	sshortfmt = "%s%d";		/* SSHORT */
75 char*	longfmt = "%s%lu";		/* LONG */
76 char*	slongfmt = "%s%ld";		/* SLONG */
77 char*	rationalfmt = "%s%g";		/* RATIONAL */
78 char*	srationalfmt = "%s%g";		/* SRATIONAL */
79 char*	floatfmt = "%s%g";		/* FLOAT */
80 char*	doublefmt = "%s%g";		/* DOUBLE */
81 
82 static	void dump(int, uint32);
83 extern	int optind;
84 extern	char* optarg;
85 
86 void
usage()87 usage()
88 {
89 	fprintf(stderr, "usage: %s [-h] [-o offset] [-m maxitems] file.tif ...\n", appname);
90 	exit(-1);
91 }
92 
93 int
main(int argc,char * argv[])94 main(int argc, char* argv[])
95 {
96 	int one = 1, fd;
97 	int multiplefiles = (argc > 1);
98 	int c;
99 	uint32 diroff = (uint32) 0;
100 	bigendian = (*(char *)&one == 0);
101 
102 	appname = argv[0];
103 	while ((c = getopt(argc, argv, "m:o:h")) != -1) {
104 		switch (c) {
105 		case 'h':			/* print values in hex */
106 			shortfmt = "%s%#x";
107 			sshortfmt = "%s%#x";
108 			longfmt = "%s%#lx";
109 			slongfmt = "%s%#lx";
110 			break;
111 		case 'o':
112 			diroff = (uint32) strtoul(optarg, NULL, 0);
113 			break;
114 		case 'm':
115 			maxitems = strtoul(optarg, NULL, 0);
116 			break;
117 		default:
118 			usage();
119 		}
120 	}
121 	if (optind >= argc)
122 		usage();
123 	for (; optind < argc; optind++) {
124 		fd = open(argv[optind], O_RDONLY|O_BINARY, 0);
125 		if (fd < 0) {
126 			perror(argv[0]);
127 			return (-1);
128 		}
129 		if (multiplefiles)
130 			printf("%s:\n", argv[optind]);
131 		curfile = argv[optind];
132 		swabflag = 0;
133 		dump(fd, diroff);
134 		close(fd);
135 	}
136 	return (0);
137 }
138 
139 static	TIFFHeader hdr;
140 
141 #define	ord(e)	((int)e)
142 
143 /*
144  * Initialize shift & mask tables and byte
145  * swapping state according to the file
146  * byte order.
147  */
148 static void
InitByteOrder(int magic)149 InitByteOrder(int magic)
150 {
151 	typemask[0] = 0;
152 	typemask[ord(TIFF_BYTE)] = 0xff;
153 	typemask[ord(TIFF_SBYTE)] = 0xff;
154 	typemask[ord(TIFF_UNDEFINED)] = 0xff;
155 	typemask[ord(TIFF_SHORT)] = 0xffff;
156 	typemask[ord(TIFF_SSHORT)] = 0xffff;
157 	typemask[ord(TIFF_LONG)] = 0xffffffff;
158 	typemask[ord(TIFF_SLONG)] = 0xffffffff;
159 	typemask[ord(TIFF_RATIONAL)] = 0xffffffff;
160 	typemask[ord(TIFF_SRATIONAL)] = 0xffffffff;
161 	typemask[ord(TIFF_FLOAT)] = 0xffffffff;
162 	typemask[ord(TIFF_DOUBLE)] = 0xffffffff;
163 	typeshift[0] = 0;
164 	typeshift[ord(TIFF_LONG)] = 0;
165 	typeshift[ord(TIFF_SLONG)] = 0;
166 	typeshift[ord(TIFF_RATIONAL)] = 0;
167 	typeshift[ord(TIFF_SRATIONAL)] = 0;
168 	typeshift[ord(TIFF_FLOAT)] = 0;
169 	typeshift[ord(TIFF_DOUBLE)] = 0;
170 	if (magic == TIFF_BIGENDIAN) {
171 		typeshift[ord(TIFF_BYTE)] = 24;
172 		typeshift[ord(TIFF_SBYTE)] = 24;
173 		typeshift[ord(TIFF_SHORT)] = 16;
174 		typeshift[ord(TIFF_SSHORT)] = 16;
175 		swabflag = !bigendian;
176 	} else {
177 		typeshift[ord(TIFF_BYTE)] = 0;
178 		typeshift[ord(TIFF_SBYTE)] = 0;
179 		typeshift[ord(TIFF_SHORT)] = 0;
180 		typeshift[ord(TIFF_SSHORT)] = 0;
181 		swabflag = bigendian;
182 	}
183 }
184 
185 static	uint32 ReadDirectory(int, unsigned, uint32);
186 static	void ReadError(char*);
187 static	void Error(const char*, ...);
188 static	void Fatal(const char*, ...);
189 
190 static void
dump(int fd,uint32 diroff)191 dump(int fd, uint32 diroff)
192 {
193 	unsigned i;
194 
195 	lseek(fd, (off_t) 0, 0);
196 	if (read(fd, (char*) &hdr, sizeof (hdr)) != sizeof (hdr))
197 		ReadError("TIFF header");
198 	/*
199 	 * Setup the byte order handling.
200 	 */
201 	if (hdr.tiff_magic != TIFF_BIGENDIAN && hdr.tiff_magic != TIFF_LITTLEENDIAN)
202 		Fatal("Not a TIFF file, bad magic number %u (%#x)",
203 		    hdr.tiff_magic, hdr.tiff_magic);
204 	InitByteOrder(hdr.tiff_magic);
205 	/*
206 	 * Swap header if required.
207 	 */
208 	if (swabflag) {
209 		TIFFSwabShort(&hdr.tiff_version);
210 		TIFFSwabLong(&hdr.tiff_diroff);
211 	}
212 	/*
213 	 * Now check version (if needed, it's been byte-swapped).
214 	 * Note that this isn't actually a version number, it's a
215 	 * magic number that doesn't change (stupid).
216 	 */
217 	if (hdr.tiff_version != TIFF_VERSION)
218 		Fatal("Not a TIFF file, bad version number %u (%#x)",
219 		    hdr.tiff_version, hdr.tiff_version);
220 	printf("Magic: %#x <%s-endian> Version: %#x\n",
221 	    hdr.tiff_magic,
222 	    hdr.tiff_magic == TIFF_BIGENDIAN ? "big" : "little",
223 	    hdr.tiff_version);
224 	if (diroff == 0)
225 	    diroff = hdr.tiff_diroff;
226 	for (i = 0; diroff != 0; i++) {
227 		if (i > 0)
228 			putchar('\n');
229 		diroff = ReadDirectory(fd, i, diroff);
230 	}
231 }
232 
233 static int datawidth[] = {
234     0,	/* nothing */
235     1,	/* TIFF_BYTE */
236     1,	/* TIFF_ASCII */
237     2,	/* TIFF_SHORT */
238     4,	/* TIFF_LONG */
239     8,	/* TIFF_RATIONAL */
240     1,	/* TIFF_SBYTE */
241     1,	/* TIFF_UNDEFINED */
242     2,	/* TIFF_SSHORT */
243     4,	/* TIFF_SLONG */
244     8,	/* TIFF_SRATIONAL */
245     4,	/* TIFF_FLOAT */
246     8,	/* TIFF_DOUBLE */
247 };
248 #define	NWIDTHS	(sizeof (datawidth) / sizeof (datawidth[0]))
249 static	int TIFFFetchData(int, TIFFDirEntry*, void*);
250 static	void PrintTag(FILE*, uint16);
251 static	void PrintType(FILE*, uint16);
252 static	void PrintData(FILE*, uint16, uint32, unsigned char*);
253 static	void PrintByte(FILE*, const char*, TIFFDirEntry*);
254 static	void PrintShort(FILE*, const char*, TIFFDirEntry*);
255 static	void PrintLong(FILE*, const char*, TIFFDirEntry*);
256 
257 /*
258  * Read the next TIFF directory from a file
259  * and convert it to the internal format.
260  * We read directories sequentially.
261  */
262 static uint32
ReadDirectory(int fd,unsigned ix,uint32 off)263 ReadDirectory(int fd, unsigned ix, uint32 off)
264 {
265 	register TIFFDirEntry *dp;
266 	register int n;
267 	TIFFDirEntry *dir = 0;
268 	uint16 dircount;
269 	int space;
270 	uint32 nextdiroff = 0;
271 
272 	if (off == 0)			/* no more directories */
273 		goto done;
274 	if (lseek(fd, (off_t) off, 0) != off) {
275 		Fatal("Seek error accessing TIFF directory");
276 		goto done;
277 	}
278 	if (read(fd, (char*) &dircount, sizeof (uint16)) != sizeof (uint16)) {
279 		ReadError("directory count");
280 		goto done;
281 	}
282 	if (swabflag)
283 		TIFFSwabShort(&dircount);
284 	dir = (TIFFDirEntry *)_TIFFmalloc(dircount * sizeof (TIFFDirEntry));
285 	if (dir == NULL) {
286 		Fatal("No space for TIFF directory");
287 		goto done;
288 	}
289 	n = read(fd, (char*) dir, dircount*sizeof (*dp));
290 	if (n != dircount*sizeof (*dp)) {
291 		n /= sizeof (*dp);
292 		Error(
293 	    "Could only read %u of %u entries in directory at offset %#lx",
294 		    n, dircount, (unsigned long) off);
295 		dircount = n;
296 	}
297 	if (read(fd, (char*) &nextdiroff, sizeof (uint32)) != sizeof (uint32))
298 		nextdiroff = 0;
299 	if (swabflag)
300 		TIFFSwabLong(&nextdiroff);
301 	printf("Directory %u: offset %lu (%#lx) next %lu (%#lx)\n", ix,
302 	    (unsigned long) off, (unsigned long) off,
303 	    (unsigned long) nextdiroff, (unsigned long) nextdiroff);
304 	for (dp = dir, n = dircount; n > 0; n--, dp++) {
305 		if (swabflag) {
306 			TIFFSwabArrayOfShort(&dp->tdir_tag, 2);
307 			TIFFSwabArrayOfLong(&dp->tdir_count, 2);
308 		}
309 		PrintTag(stdout, dp->tdir_tag);
310 		putchar(' ');
311 		PrintType(stdout, dp->tdir_type);
312 		putchar(' ');
313 		printf("%lu<", (unsigned long) dp->tdir_count);
314 		if (dp->tdir_type >= NWIDTHS) {
315 			printf(">\n");
316 			continue;
317 		}
318 		space = dp->tdir_count * datawidth[dp->tdir_type];
319 		if (space <= 4) {
320 			switch (dp->tdir_type) {
321 			case TIFF_FLOAT:
322 			case TIFF_UNDEFINED:
323 			case TIFF_ASCII: {
324 				unsigned char data[4];
325 				_TIFFmemcpy(data, &dp->tdir_offset, 4);
326 				if (swabflag)
327 					TIFFSwabLong((uint32*) data);
328 				PrintData(stdout,
329 				    dp->tdir_type, dp->tdir_count, data);
330 				break;
331 			}
332 			case TIFF_BYTE:
333 				PrintByte(stdout, bytefmt, dp);
334 				break;
335 			case TIFF_SBYTE:
336 				PrintByte(stdout, sbytefmt, dp);
337 				break;
338 			case TIFF_SHORT:
339 				PrintShort(stdout, shortfmt, dp);
340 				break;
341 			case TIFF_SSHORT:
342 				PrintShort(stdout, sshortfmt, dp);
343 				break;
344 			case TIFF_LONG:
345 				PrintLong(stdout, longfmt, dp);
346 				break;
347 			case TIFF_SLONG:
348 				PrintLong(stdout, slongfmt, dp);
349 				break;
350 			}
351 		} else {
352 			unsigned char *data = (unsigned char *)_TIFFmalloc(space);
353 			if (data) {
354 				if (TIFFFetchData(fd, dp, data))
355 					if (dp->tdir_count > maxitems) {
356 						PrintData(stdout, dp->tdir_type,
357 						    maxitems, data);
358 						printf(" ...");
359 					} else
360 						PrintData(stdout, dp->tdir_type,
361 						    dp->tdir_count, data);
362 				_TIFFfree(data);
363 			} else
364 				Error("No space for data for tag %u",
365 				    dp->tdir_tag);
366 		}
367 		printf(">\n");
368 	}
369 done:
370 	if (dir)
371 		_TIFFfree((char *)dir);
372 	return (nextdiroff);
373 }
374 
375 static	struct tagname {
376 	uint16	tag;
377 	char*	name;
378 } tagnames[] = {
379     { TIFFTAG_SUBFILETYPE,	"SubFileType" },
380     { TIFFTAG_OSUBFILETYPE,	"OldSubFileType" },
381     { TIFFTAG_IMAGEWIDTH,	"ImageWidth" },
382     { TIFFTAG_IMAGELENGTH,	"ImageLength" },
383     { TIFFTAG_BITSPERSAMPLE,	"BitsPerSample" },
384     { TIFFTAG_COMPRESSION,	"Compression" },
385     { TIFFTAG_PHOTOMETRIC,	"Photometric" },
386     { TIFFTAG_THRESHHOLDING,	"Threshholding" },
387     { TIFFTAG_CELLWIDTH,	"CellWidth" },
388     { TIFFTAG_CELLLENGTH,	"CellLength" },
389     { TIFFTAG_FILLORDER,	"FillOrder" },
390     { TIFFTAG_DOCUMENTNAME,	"DocumentName" },
391     { TIFFTAG_IMAGEDESCRIPTION,	"ImageDescription" },
392     { TIFFTAG_MAKE,		"Make" },
393     { TIFFTAG_MODEL,		"Model" },
394     { TIFFTAG_STRIPOFFSETS,	"StripOffsets" },
395     { TIFFTAG_ORIENTATION,	"Orientation" },
396     { TIFFTAG_SAMPLESPERPIXEL,	"SamplesPerPixel" },
397     { TIFFTAG_ROWSPERSTRIP,	"RowsPerStrip" },
398     { TIFFTAG_STRIPBYTECOUNTS,	"StripByteCounts" },
399     { TIFFTAG_MINSAMPLEVALUE,	"MinSampleValue" },
400     { TIFFTAG_MAXSAMPLEVALUE,	"MaxSampleValue" },
401     { TIFFTAG_XRESOLUTION,	"XResolution" },
402     { TIFFTAG_YRESOLUTION,	"YResolution" },
403     { TIFFTAG_PLANARCONFIG,	"PlanarConfig" },
404     { TIFFTAG_PAGENAME,		"PageName" },
405     { TIFFTAG_XPOSITION,	"XPosition" },
406     { TIFFTAG_YPOSITION,	"YPosition" },
407     { TIFFTAG_FREEOFFSETS,	"FreeOffsets" },
408     { TIFFTAG_FREEBYTECOUNTS,	"FreeByteCounts" },
409     { TIFFTAG_GRAYRESPONSEUNIT,	"GrayResponseUnit" },
410     { TIFFTAG_GRAYRESPONSECURVE,"GrayResponseCurve" },
411     { TIFFTAG_GROUP3OPTIONS,	"Group3Options" },
412     { TIFFTAG_GROUP4OPTIONS,	"Group4Options" },
413     { TIFFTAG_RESOLUTIONUNIT,	"ResolutionUnit" },
414     { TIFFTAG_PAGENUMBER,	"PageNumber" },
415     { TIFFTAG_COLORRESPONSEUNIT,"ColorResponseUnit" },
416     { TIFFTAG_TRANSFERFUNCTION,	"TransferFunction" },
417     { TIFFTAG_SOFTWARE,		"Software" },
418     { TIFFTAG_DATETIME,		"DateTime" },
419     { TIFFTAG_ARTIST,		"Artist" },
420     { TIFFTAG_HOSTCOMPUTER,	"HostComputer" },
421     { TIFFTAG_PREDICTOR,	"Predictor" },
422     { TIFFTAG_WHITEPOINT,	"Whitepoint" },
423     { TIFFTAG_PRIMARYCHROMATICITIES,"PrimaryChromaticities" },
424     { TIFFTAG_COLORMAP,		"Colormap" },
425     { TIFFTAG_HALFTONEHINTS,	"HalftoneHints" },
426     { TIFFTAG_TILEWIDTH,	"TileWidth" },
427     { TIFFTAG_TILELENGTH,	"TileLength" },
428     { TIFFTAG_TILEOFFSETS,	"TileOffsets" },
429     { TIFFTAG_TILEBYTECOUNTS,	"TileByteCounts" },
430     { TIFFTAG_BADFAXLINES,	"BadFaxLines" },
431     { TIFFTAG_CLEANFAXDATA,	"CleanFaxData" },
432     { TIFFTAG_CONSECUTIVEBADFAXLINES, "ConsecutiveBadFaxLines" },
433     { TIFFTAG_SUBIFD,		"SubIFD" },
434     { TIFFTAG_INKSET,		"InkSet" },
435     { TIFFTAG_INKNAMES,		"InkNames" },
436     { TIFFTAG_NUMBEROFINKS,	"NumberOfInks" },
437     { TIFFTAG_DOTRANGE,		"DotRange" },
438     { TIFFTAG_TARGETPRINTER,	"TargetPrinter" },
439     { TIFFTAG_EXTRASAMPLES,	"ExtraSamples" },
440     { TIFFTAG_SAMPLEFORMAT,	"SampleFormat" },
441     { TIFFTAG_SMINSAMPLEVALUE,	"SMinSampleValue" },
442     { TIFFTAG_SMAXSAMPLEVALUE,	"SMaxSampleValue" },
443     { TIFFTAG_JPEGPROC,		"JPEGProcessingMode" },
444     { TIFFTAG_JPEGIFOFFSET,	"JPEGInterchangeFormat" },
445     { TIFFTAG_JPEGIFBYTECOUNT,	"JPEGInterchangeFormatLength" },
446     { TIFFTAG_JPEGRESTARTINTERVAL,"JPEGRestartInterval" },
447     { TIFFTAG_JPEGLOSSLESSPREDICTORS,"JPEGLosslessPredictors" },
448     { TIFFTAG_JPEGPOINTTRANSFORM,"JPEGPointTransform" },
449     { TIFFTAG_JPEGTABLES,       "JPEGTables" },
450     { TIFFTAG_JPEGQTABLES,	"JPEGQTables" },
451     { TIFFTAG_JPEGDCTABLES,	"JPEGDCTables" },
452     { TIFFTAG_JPEGACTABLES,	"JPEGACTables" },
453     { TIFFTAG_YCBCRCOEFFICIENTS,"YCbCrCoefficients" },
454     { TIFFTAG_YCBCRSUBSAMPLING,	"YCbCrSubsampling" },
455     { TIFFTAG_YCBCRPOSITIONING,	"YCbCrPositioning" },
456     { TIFFTAG_REFERENCEBLACKWHITE, "ReferenceBlackWhite" },
457     { TIFFTAG_REFPTS,		"IgReferencePoints (Island Graphics)" },
458     { TIFFTAG_REGIONTACKPOINT,	"IgRegionTackPoint (Island Graphics)" },
459     { TIFFTAG_REGIONWARPCORNERS,"IgRegionWarpCorners (Island Graphics)" },
460     { TIFFTAG_REGIONAFFINE,	"IgRegionAffine (Island Graphics)" },
461     { TIFFTAG_MATTEING,		"OBSOLETE Matteing (Silicon Graphics)" },
462     { TIFFTAG_DATATYPE,		"OBSOLETE DataType (Silicon Graphics)" },
463     { TIFFTAG_IMAGEDEPTH,	"ImageDepth (Silicon Graphics)" },
464     { TIFFTAG_TILEDEPTH,	"TileDepth (Silicon Graphics)" },
465     { 32768,			"OLD BOGUS Matteing tag" },
466     { TIFFTAG_COPYRIGHT,	"Copyright" },
467     { TIFFTAG_ICCPROFILE,	"ICC Profile" },
468     { TIFFTAG_JBIGOPTIONS,	"JBIG Options" },
469     { TIFFTAG_STONITS,		"StoNits" },
470 };
471 #define	NTAGS	(sizeof (tagnames) / sizeof (tagnames[0]))
472 
473 static void
PrintTag(FILE * fd,uint16 tag)474 PrintTag(FILE* fd, uint16 tag)
475 {
476 	register struct tagname *tp;
477 
478 	for (tp = tagnames; tp < &tagnames[NTAGS]; tp++)
479 		if (tp->tag == tag) {
480 			fprintf(fd, "%s (%u)", tp->name, tag);
481 			return;
482 		}
483 	fprintf(fd, "%u (%#x)", tag, tag);
484 }
485 
486 static void
PrintType(FILE * fd,uint16 type)487 PrintType(FILE* fd, uint16 type)
488 {
489 	static char *typenames[] = {
490 	    "0",
491 	    "BYTE",
492 	    "ASCII",
493 	    "SHORT",
494 	    "LONG",
495 	    "RATIONAL",
496 	    "SBYTE",
497 	    "UNDEFINED",
498 	    "SSHORT",
499 	    "SLONG",
500 	    "SRATIONAL",
501 	    "FLOAT",
502 	    "DOUBLE"
503 	};
504 #define	NTYPES	(sizeof (typenames) / sizeof (typenames[0]))
505 
506 	if (type < NTYPES)
507 		fprintf(fd, "%s (%u)", typenames[type], type);
508 	else
509 		fprintf(fd, "%u (%#x)", type, type);
510 }
511 #undef	NTYPES
512 
513 static void
PrintByte(FILE * fd,const char * fmt,TIFFDirEntry * dp)514 PrintByte(FILE* fd, const char* fmt, TIFFDirEntry* dp)
515 {
516 	char* sep = "";
517 
518 	if (hdr.tiff_magic != TIFF_LITTLEENDIAN) {
519 		switch ((int)dp->tdir_count) {
520 		case 4: fprintf(fd, fmt, sep, dp->tdir_offset&0xff);
521 			sep = " ";
522 		case 3: fprintf(fd, fmt, sep, (dp->tdir_offset>>8)&0xff);
523 			sep = " ";
524 		case 2: fprintf(fd, fmt, sep, (dp->tdir_offset>>16)&0xff);
525 			sep = " ";
526 		case 1: fprintf(fd, fmt, sep, dp->tdir_offset>>24);
527 		}
528 	} else {
529 		switch ((int)dp->tdir_count) {
530 		case 4: fprintf(fd, fmt, sep, dp->tdir_offset>>24);
531 			sep = " ";
532 		case 3: fprintf(fd, fmt, sep, (dp->tdir_offset>>16)&0xff);
533 			sep = " ";
534 		case 2: fprintf(fd, fmt, sep, (dp->tdir_offset>>8)&0xff);
535 			sep = " ";
536 		case 1: fprintf(fd, fmt, sep, dp->tdir_offset&0xff);
537 		}
538 	}
539 }
540 
541 static void
PrintShort(FILE * fd,const char * fmt,TIFFDirEntry * dp)542 PrintShort(FILE* fd, const char* fmt, TIFFDirEntry* dp)
543 {
544 	char *sep = "";
545 
546 	if (hdr.tiff_magic != TIFF_LITTLEENDIAN) {
547 		switch (dp->tdir_count) {
548 		case 2: fprintf(fd, fmt, sep, dp->tdir_offset&0xffff);
549 			sep = " ";
550 		case 1: fprintf(fd, fmt, sep, dp->tdir_offset>>16);
551 		}
552 	} else {
553 		switch (dp->tdir_count) {
554 		case 2: fprintf(fd, fmt, sep, dp->tdir_offset>>16);
555 			sep = " ";
556 		case 1: fprintf(fd, fmt, sep, dp->tdir_offset&0xffff);
557 		}
558 	}
559 }
560 
561 static void
PrintLong(FILE * fd,const char * fmt,TIFFDirEntry * dp)562 PrintLong(FILE* fd, const char* fmt, TIFFDirEntry* dp)
563 {
564 	fprintf(fd, fmt, "", (long) dp->tdir_offset);
565 }
566 
567 #include <ctype.h>
568 
569 static void
PrintASCII(FILE * fd,uint32 cc,const unsigned char * cp)570 PrintASCII(FILE* fd, uint32 cc, const unsigned char* cp)
571 {
572 	for (; cc > 0; cc--, cp++) {
573 		const char* tp;
574 
575 		if (isprint(*cp)) {
576 			fputc(*cp, fd);
577 			continue;
578 		}
579 		for (tp = "\tt\bb\rr\nn\vv"; *tp; tp++)
580 			if (*tp++ == *cp)
581 				break;
582 		if (*tp)
583 			fprintf(fd, "\\%c", *tp);
584 		else if (*cp)
585 			fprintf(fd, "\\%03o", *cp);
586 		else
587 			fprintf(fd, "\\0");
588 	}
589 }
590 
591 static void
PrintData(FILE * fd,uint16 type,uint32 count,unsigned char * data)592 PrintData(FILE* fd, uint16 type, uint32 count, unsigned char* data)
593 {
594 	char* sep = "";
595 
596 	switch (type) {
597 	case TIFF_BYTE:
598 		while (count-- > 0)
599 			fprintf(fd, bytefmt, sep, *data++), sep = " ";
600 		break;
601 	case TIFF_SBYTE:
602 		while (count-- > 0)
603 			fprintf(fd, sbytefmt, sep, *(char *)data++), sep = " ";
604 		break;
605 	case TIFF_UNDEFINED:
606 		while (count-- > 0)
607 			fprintf(fd, bytefmt, sep, *data++), sep = " ";
608 		break;
609 	case TIFF_ASCII:
610 		PrintASCII(fd, count, data);
611 		break;
612 	case TIFF_SHORT: {
613 		register uint16 *wp = (uint16*)data;
614 		while (count-- > 0)
615 			fprintf(fd, shortfmt, sep, *wp++), sep = " ";
616 		break;
617 	}
618 	case TIFF_SSHORT: {
619 		register int16 *wp = (int16*)data;
620 		while (count-- > 0)
621 			fprintf(fd, sshortfmt, sep, *wp++), sep = " ";
622 		break;
623 	}
624 	case TIFF_LONG: {
625 		register uint32 *lp = (uint32*)data;
626 		while (count-- > 0) {
627 			fprintf(fd, longfmt, sep, (unsigned long) *lp++);
628 			sep = " ";
629 		}
630 		break;
631 	}
632 	case TIFF_SLONG: {
633 		register int32 *lp = (int32*)data;
634 		while (count-- > 0)
635 			fprintf(fd, slongfmt, sep, (long) *lp++), sep = " ";
636 		break;
637 	}
638 	case TIFF_RATIONAL: {
639 		register uint32 *lp = (uint32*)data;
640 		while (count-- > 0) {
641 			if (lp[1] == 0)
642 				fprintf(fd, "%sNan (%lu/%lu)", sep,
643 				    (unsigned long) lp[0],
644 				    (unsigned long) lp[1]);
645 			else
646 				fprintf(fd, rationalfmt, sep,
647 				    (double)lp[0] / (double)lp[1]);
648 			sep = " ";
649 			lp += 2;
650 		}
651 		break;
652 	}
653 	case TIFF_SRATIONAL: {
654 		register int32 *lp = (int32*)data;
655 		while (count-- > 0) {
656 			if (lp[1] == 0)
657 				fprintf(fd, "%sNan (%ld/%ld)", sep,
658 				    (long) lp[0], (long) lp[1]);
659 			else
660 				fprintf(fd, srationalfmt, sep,
661 				    (double)lp[0] / (double)lp[1]);
662 			sep = " ";
663 			lp += 2;
664 		}
665 		break;
666 	}
667 	case TIFF_FLOAT: {
668 		register float *fp = (float *)data;
669 		while (count-- > 0)
670 			fprintf(fd, floatfmt, sep, *fp++), sep = " ";
671 		break;
672 	}
673 	case TIFF_DOUBLE: {
674 		register double *dp = (double *)data;
675 		while (count-- > 0)
676 			fprintf(fd, doublefmt, sep, *dp++), sep = " ";
677 		break;
678 	}
679 	}
680 }
681 
682 /*
683  * Fetch a contiguous directory item.
684  */
685 static int
TIFFFetchData(int fd,TIFFDirEntry * dir,void * cp)686 TIFFFetchData(int fd, TIFFDirEntry* dir, void* cp)
687 {
688 	int cc, w;
689 
690 	w = (dir->tdir_type < NWIDTHS ? datawidth[dir->tdir_type] : 0);
691 	cc = dir->tdir_count * w;
692 	if (lseek(fd, (off_t) dir->tdir_offset, 0) == dir->tdir_offset &&
693 	    read(fd, cp, cc) == cc) {
694 		if (swabflag) {
695 			switch (dir->tdir_type) {
696 			case TIFF_SHORT:
697 			case TIFF_SSHORT:
698 				TIFFSwabArrayOfShort((uint16*) cp,
699 				    dir->tdir_count);
700 				break;
701 			case TIFF_LONG:
702 			case TIFF_SLONG:
703 			case TIFF_FLOAT:
704 				TIFFSwabArrayOfLong((uint32*) cp,
705 				    dir->tdir_count);
706 				break;
707 			case TIFF_RATIONAL:
708 				TIFFSwabArrayOfLong((uint32*) cp,
709 				    2*dir->tdir_count);
710 				break;
711 			case TIFF_DOUBLE:
712 				TIFFSwabArrayOfDouble((double*) cp,
713 				    dir->tdir_count);
714 				break;
715 			}
716 		}
717 		return (cc);
718 	}
719 	Error("Error while reading data for tag %u", dir->tdir_tag);
720 	return (0);
721 }
722 
723 static void
ReadError(char * what)724 ReadError(char* what)
725 {
726 	Fatal("Error while reading %s", what);
727 }
728 
729 #include <stdarg.h>
730 
731 static void
vError(FILE * fd,const char * fmt,va_list ap)732 vError(FILE* fd, const char* fmt, va_list ap)
733 {
734 	fprintf(fd, "%s: ", curfile);
735 	vfprintf(fd, fmt, ap);
736 	fprintf(fd, ".\n");
737 }
738 
739 static void
Error(const char * fmt,...)740 Error(const char* fmt, ...)
741 {
742 	va_list ap;
743 	va_start(ap, fmt);
744 	vError(stderr, fmt, ap);
745 	va_end(ap);
746 }
747 
748 static void
Fatal(const char * fmt,...)749 Fatal(const char* fmt, ...)
750 {
751 	va_list ap;
752 	va_start(ap, fmt);
753 	vError(stderr, fmt, ap);
754 	va_end(ap);
755 	exit(-1);
756 }
757