1 /* $Id: tif_open.c,v 1.31 2006/03/16 12:23:02 dron 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 /*
28  * TIFF Library.
29  */
30 #include "tiffiop.h"
31 
32 static const long typemask[13] = {
33 	(long)0L,		/* TIFF_NOTYPE */
34 	(long)0x000000ffL,	/* TIFF_BYTE */
35 	(long)0xffffffffL,	/* TIFF_ASCII */
36 	(long)0x0000ffffL,	/* TIFF_SHORT */
37 	(long)0xffffffffL,	/* TIFF_LONG */
38 	(long)0xffffffffL,	/* TIFF_RATIONAL */
39 	(long)0x000000ffL,	/* TIFF_SBYTE */
40 	(long)0x000000ffL,	/* TIFF_UNDEFINED */
41 	(long)0x0000ffffL,	/* TIFF_SSHORT */
42 	(long)0xffffffffL,	/* TIFF_SLONG */
43 	(long)0xffffffffL,	/* TIFF_SRATIONAL */
44 	(long)0xffffffffL,	/* TIFF_FLOAT */
45 	(long)0xffffffffL,	/* TIFF_DOUBLE */
46 };
47 static const int bigTypeshift[13] = {
48 	0,		/* TIFF_NOTYPE */
49 	24,		/* TIFF_BYTE */
50 	0,		/* TIFF_ASCII */
51 	16,		/* TIFF_SHORT */
52 	0,		/* TIFF_LONG */
53 	0,		/* TIFF_RATIONAL */
54 	24,		/* TIFF_SBYTE */
55 	24,		/* TIFF_UNDEFINED */
56 	16,		/* TIFF_SSHORT */
57 	0,		/* TIFF_SLONG */
58 	0,		/* TIFF_SRATIONAL */
59 	0,		/* TIFF_FLOAT */
60 	0,		/* TIFF_DOUBLE */
61 };
62 static const int litTypeshift[13] = {
63 	0,		/* TIFF_NOTYPE */
64 	0,		/* TIFF_BYTE */
65 	0,		/* TIFF_ASCII */
66 	0,		/* TIFF_SHORT */
67 	0,		/* TIFF_LONG */
68 	0,		/* TIFF_RATIONAL */
69 	0,		/* TIFF_SBYTE */
70 	0,		/* TIFF_UNDEFINED */
71 	0,		/* TIFF_SSHORT */
72 	0,		/* TIFF_SLONG */
73 	0,		/* TIFF_SRATIONAL */
74 	0,		/* TIFF_FLOAT */
75 	0,		/* TIFF_DOUBLE */
76 };
77 
78 /*
79  * Dummy functions to fill the omitted client procedures.
80  */
81 static int
_tiffDummyMapProc(thandle_t fd,tdata_t * pbase,toff_t * psize)82 _tiffDummyMapProc(thandle_t fd, tdata_t* pbase, toff_t* psize)
83 {
84 	(void) fd; (void) pbase; (void) psize;
85 	return (0);
86 }
87 
88 static void
_tiffDummyUnmapProc(thandle_t fd,tdata_t base,toff_t size)89 _tiffDummyUnmapProc(thandle_t fd, tdata_t base, toff_t size)
90 {
91 	(void) fd; (void) base; (void) size;
92 }
93 
94 /*
95  * Initialize the shift & mask tables, and the
96  * byte swapping state according to the file
97  * contents and the machine architecture.
98  */
99 static void
TIFFInitOrder(TIFF * tif,int magic)100 TIFFInitOrder(TIFF* tif, int magic)
101 {
102 	tif->tif_typemask = typemask;
103 	if (magic == TIFF_BIGENDIAN) {
104 		tif->tif_typeshift = bigTypeshift;
105 #ifndef WORDS_BIGENDIAN
106 		tif->tif_flags |= TIFF_SWAB;
107 #endif
108 	} else {
109 		tif->tif_typeshift = litTypeshift;
110 #ifdef WORDS_BIGENDIAN
111 		tif->tif_flags |= TIFF_SWAB;
112 #endif
113 	}
114 }
115 
116 int
_TIFFgetMode(const char * mode,const char * module)117 _TIFFgetMode(const char* mode, const char* module)
118 {
119 	int m = -1;
120 
121 	switch (mode[0]) {
122 	case 'r':
123 		m = O_RDONLY;
124 		if (mode[1] == '+')
125 			m = O_RDWR;
126 		break;
127 	case 'w':
128 	case 'a':
129 		m = O_RDWR|O_CREAT;
130 		if (mode[0] == 'w')
131 			m |= O_TRUNC;
132 		break;
133 	default:
134 		TIFFErrorExt(0, module, "\"%s\": Bad mode", mode);
135 		break;
136 	}
137 	return (m);
138 }
139 
140 TIFF*
TIFFClientOpen(const char * name,const char * mode,thandle_t clientdata,TIFFReadWriteProc readproc,TIFFReadWriteProc writeproc,TIFFSeekProc seekproc,TIFFCloseProc closeproc,TIFFSizeProc sizeproc,TIFFMapFileProc mapproc,TIFFUnmapFileProc unmapproc)141 TIFFClientOpen(
142 	const char* name, const char* mode,
143 	thandle_t clientdata,
144 	TIFFReadWriteProc readproc,
145 	TIFFReadWriteProc writeproc,
146 	TIFFSeekProc seekproc,
147 	TIFFCloseProc closeproc,
148 	TIFFSizeProc sizeproc,
149 	TIFFMapFileProc mapproc,
150 	TIFFUnmapFileProc unmapproc
151 )
152 {
153 	static const char module[] = "TIFFClientOpen";
154 	TIFF *tif;
155 	int m;
156 	const char* cp;
157 
158 	m = _TIFFgetMode(mode, module);
159 	if (m == -1)
160 		goto bad2;
161 	tif = (TIFF *)_TIFFmalloc(sizeof (TIFF) + strlen(name) + 1);
162 	if (tif == NULL) {
163 		TIFFErrorExt(clientdata, module, "%s: Out of memory (TIFF structure)", name);
164 		goto bad2;
165 	}
166 	_TIFFmemset(tif, 0, sizeof (*tif));
167 	tif->tif_name = (char *)tif + sizeof (TIFF);
168 	strcpy(tif->tif_name, name);
169 	tif->tif_mode = m &~ (O_CREAT|O_TRUNC);
170 	tif->tif_curdir = (tdir_t) -1;		/* non-existent directory */
171 	tif->tif_curoff = 0;
172 	tif->tif_curstrip = (tstrip_t) -1;	/* invalid strip */
173 	tif->tif_row = (uint32) -1;		/* read/write pre-increment */
174 	tif->tif_clientdata = clientdata;
175 	if (!readproc || !writeproc || !seekproc || !closeproc || !sizeproc) {
176 		TIFFErrorExt(clientdata, module,
177 			  "One of the client procedures is NULL pointer.");
178 		goto bad2;
179 	}
180 	tif->tif_readproc = readproc;
181 	tif->tif_writeproc = writeproc;
182 	tif->tif_seekproc = seekproc;
183 	tif->tif_closeproc = closeproc;
184 	tif->tif_sizeproc = sizeproc;
185         if (mapproc)
186 		tif->tif_mapproc = mapproc;
187 	else
188 		tif->tif_mapproc = _tiffDummyMapProc;
189 	if (unmapproc)
190 		tif->tif_unmapproc = unmapproc;
191 	else
192 		tif->tif_unmapproc = _tiffDummyUnmapProc;
193 	_TIFFSetDefaultCompressionState(tif);	/* setup default state */
194 	/*
195 	 * Default is to return data MSB2LSB and enable the
196 	 * use of memory-mapped files and strip chopping when
197 	 * a file is opened read-only.
198 	 */
199 	tif->tif_flags = FILLORDER_MSB2LSB;
200 	if (m == O_RDONLY )
201             tif->tif_flags |= TIFF_MAPPED;
202 
203 #ifdef STRIPCHOP_DEFAULT
204 	if (m == O_RDONLY || m == O_RDWR)
205 		tif->tif_flags |= STRIPCHOP_DEFAULT;
206 #endif
207 
208 	/*
209 	 * Process library-specific flags in the open mode string.
210 	 * The following flags may be used to control intrinsic library
211 	 * behaviour that may or may not be desirable (usually for
212 	 * compatibility with some application that claims to support
213 	 * TIFF but only supports some braindead idea of what the
214 	 * vendor thinks TIFF is):
215 	 *
216 	 * 'l'		use little-endian byte order for creating a file
217 	 * 'b'		use big-endian byte order for creating a file
218 	 * 'L'		read/write information using LSB2MSB bit order
219 	 * 'B'		read/write information using MSB2LSB bit order
220 	 * 'H'		read/write information using host bit order
221 	 * 'M'		enable use of memory-mapped files when supported
222 	 * 'm'		disable use of memory-mapped files
223 	 * 'C'		enable strip chopping support when reading
224 	 * 'c'		disable strip chopping support
225 	 * 'h'		read TIFF header only, do not load the first IFD
226 	 *
227 	 * The use of the 'l' and 'b' flags is strongly discouraged.
228 	 * These flags are provided solely because numerous vendors,
229 	 * typically on the PC, do not correctly support TIFF; they
230 	 * only support the Intel little-endian byte order.  This
231 	 * support is not configured by default because it supports
232 	 * the violation of the TIFF spec that says that readers *MUST*
233 	 * support both byte orders.  It is strongly recommended that
234 	 * you not use this feature except to deal with busted apps
235 	 * that write invalid TIFF.  And even in those cases you should
236 	 * bang on the vendors to fix their software.
237 	 *
238 	 * The 'L', 'B', and 'H' flags are intended for applications
239 	 * that can optimize operations on data by using a particular
240 	 * bit order.  By default the library returns data in MSB2LSB
241 	 * bit order for compatibiltiy with older versions of this
242 	 * library.  Returning data in the bit order of the native cpu
243 	 * makes the most sense but also requires applications to check
244 	 * the value of the FillOrder tag; something they probably do
245 	 * not do right now.
246 	 *
247 	 * The 'M' and 'm' flags are provided because some virtual memory
248 	 * systems exhibit poor behaviour when large images are mapped.
249 	 * These options permit clients to control the use of memory-mapped
250 	 * files on a per-file basis.
251 	 *
252 	 * The 'C' and 'c' flags are provided because the library support
253 	 * for chopping up large strips into multiple smaller strips is not
254 	 * application-transparent and as such can cause problems.  The 'c'
255 	 * option permits applications that only want to look at the tags,
256 	 * for example, to get the unadulterated TIFF tag information.
257 	 */
258 	for (cp = mode; *cp; cp++)
259 		switch (*cp) {
260 		case 'b':
261 #ifndef WORDS_BIGENDIAN
262 		    if (m&O_CREAT)
263 				tif->tif_flags |= TIFF_SWAB;
264 #endif
265 			break;
266 		case 'l':
267 #ifdef WORDS_BIGENDIAN
268 			if ((m&O_CREAT))
269 				tif->tif_flags |= TIFF_SWAB;
270 #endif
271 			break;
272 		case 'B':
273 			tif->tif_flags = (tif->tif_flags &~ TIFF_FILLORDER) |
274 			    FILLORDER_MSB2LSB;
275 			break;
276 		case 'L':
277 			tif->tif_flags = (tif->tif_flags &~ TIFF_FILLORDER) |
278 			    FILLORDER_LSB2MSB;
279 			break;
280 		case 'H':
281 			tif->tif_flags = (tif->tif_flags &~ TIFF_FILLORDER) |
282 			    HOST_FILLORDER;
283 			break;
284 		case 'M':
285 			if (m == O_RDONLY)
286 				tif->tif_flags |= TIFF_MAPPED;
287 			break;
288 		case 'm':
289 			if (m == O_RDONLY)
290 				tif->tif_flags &= ~TIFF_MAPPED;
291 			break;
292 		case 'C':
293 			if (m == O_RDONLY)
294 				tif->tif_flags |= TIFF_STRIPCHOP;
295 			break;
296 		case 'c':
297 			if (m == O_RDONLY)
298 				tif->tif_flags &= ~TIFF_STRIPCHOP;
299 			break;
300 		case 'h':
301 			tif->tif_flags |= TIFF_HEADERONLY;
302 			break;
303 		}
304 	/*
305 	 * Read in TIFF header.
306 	 */
307 	if (tif->tif_mode & O_TRUNC ||
308 	    !ReadOK(tif, &tif->tif_header, sizeof (TIFFHeader))) {
309 		if (tif->tif_mode == O_RDONLY) {
310 			TIFFErrorExt(tif->tif_clientdata, name, "Cannot read TIFF header");
311 			goto bad;
312 		}
313 		/*
314 		 * Setup header and write.
315 		 */
316 #ifdef WORDS_BIGENDIAN
317 		tif->tif_header.tiff_magic = tif->tif_flags & TIFF_SWAB
318 		    ? TIFF_LITTLEENDIAN : TIFF_BIGENDIAN;
319 #else
320 		tif->tif_header.tiff_magic = tif->tif_flags & TIFF_SWAB
321 		    ? TIFF_BIGENDIAN : TIFF_LITTLEENDIAN;
322 #endif
323 		tif->tif_header.tiff_version = TIFF_VERSION;
324 		if (tif->tif_flags & TIFF_SWAB)
325 			TIFFSwabShort(&tif->tif_header.tiff_version);
326 		tif->tif_header.tiff_diroff = 0;	/* filled in later */
327 
328 
329                 /*
330                  * The doc for "fopen" for some STD_C_LIBs says that if you
331                  * open a file for modify ("+"), then you must fseek (or
332                  * fflush?) between any freads and fwrites.  This is not
333                  * necessary on most systems, but has been shown to be needed
334                  * on Solaris.
335                  */
336                 TIFFSeekFile( tif, 0, SEEK_SET );
337 
338 		if (!WriteOK(tif, &tif->tif_header, sizeof (TIFFHeader))) {
339 			TIFFErrorExt(tif->tif_clientdata, name, "Error writing TIFF header");
340 			goto bad;
341 		}
342 		/*
343 		 * Setup the byte order handling.
344 		 */
345 		TIFFInitOrder(tif, tif->tif_header.tiff_magic);
346 		/*
347 		 * Setup default directory.
348 		 */
349 		if (!TIFFDefaultDirectory(tif))
350 			goto bad;
351 		tif->tif_diroff = 0;
352 		tif->tif_dirlist = NULL;
353 		tif->tif_dirnumber = 0;
354 		return (tif);
355 	}
356 	/*
357 	 * Setup the byte order handling.
358 	 */
359 	if (tif->tif_header.tiff_magic != TIFF_BIGENDIAN &&
360 	    tif->tif_header.tiff_magic != TIFF_LITTLEENDIAN
361 #if MDI_SUPPORT
362 	    &&
363 #if HOST_BIGENDIAN
364 	    tif->tif_header.tiff_magic != MDI_BIGENDIAN
365 #else
366 	    tif->tif_header.tiff_magic != MDI_LITTLEENDIAN
367 #endif
368 	    ) {
369 		TIFFErrorExt(tif->tif_clientdata, name,  "Not a TIFF or MDI file, bad magic number %d (0x%x)",
370 #else
371 	    ) {
372 		TIFFErrorExt(tif->tif_clientdata, name,  "Not a TIFF file, bad magic number %d (0x%x)",
373 #endif
374 		    tif->tif_header.tiff_magic,
375 		    tif->tif_header.tiff_magic);
376 		goto bad;
377 	}
378 	TIFFInitOrder(tif, tif->tif_header.tiff_magic);
379 	/*
380 	 * Swap header if required.
381 	 */
382 	if (tif->tif_flags & TIFF_SWAB) {
383 		TIFFSwabShort(&tif->tif_header.tiff_version);
384 		TIFFSwabLong(&tif->tif_header.tiff_diroff);
385 	}
386 	/*
387 	 * Now check version (if needed, it's been byte-swapped).
388 	 * Note that this isn't actually a version number, it's a
389 	 * magic number that doesn't change (stupid).
390 	 */
391 	if (tif->tif_header.tiff_version == TIFF_BIGTIFF_VERSION) {
392 		TIFFErrorExt(tif->tif_clientdata, name,
393                           "This is a BigTIFF file.  This format not supported\n"
394                           "by this version of libtiff." );
395 		goto bad;
396 	}
397 	if (tif->tif_header.tiff_version != TIFF_VERSION) {
398 		TIFFErrorExt(tif->tif_clientdata, name,
399 		    "Not a TIFF file, bad version number %d (0x%x)",
400 		    tif->tif_header.tiff_version,
401 		    tif->tif_header.tiff_version);
402 		goto bad;
403 	}
404 	tif->tif_flags |= TIFF_MYBUFFER;
405 	tif->tif_rawcp = tif->tif_rawdata = 0;
406 	tif->tif_rawdatasize = 0;
407 
408 	/*
409 	 * Sometimes we do not want to read the first directory (for example,
410 	 * it may be broken) and want to proceed to other directories. I this
411 	 * case we use the TIFF_HEADERONLY flag to open file and return
412 	 * immediately after reading TIFF header.
413 	 */
414 	if (tif->tif_flags & TIFF_HEADERONLY)
415 		return (tif);
416 
417 	/*
418 	 * Setup initial directory.
419 	 */
420 	switch (mode[0]) {
421 	case 'r':
422 		tif->tif_nextdiroff = tif->tif_header.tiff_diroff;
423 		/*
424 		 * Try to use a memory-mapped file if the client
425 		 * has not explicitly suppressed usage with the
426 		 * 'm' flag in the open mode (see above).
427 		 */
428 		if ((tif->tif_flags & TIFF_MAPPED) &&
429 	!TIFFMapFileContents(tif, (tdata_t*) &tif->tif_base, &tif->tif_size))
430 			tif->tif_flags &= ~TIFF_MAPPED;
431 		if (TIFFReadDirectory(tif)) {
432 			tif->tif_rawcc = -1;
433 			tif->tif_flags |= TIFF_BUFFERSETUP;
434 			return (tif);
435 		}
436 		break;
437 	case 'a':
438 		/*
439 		 * New directories are automatically append
440 		 * to the end of the directory chain when they
441 		 * are written out (see TIFFWriteDirectory).
442 		 */
443 		if (!TIFFDefaultDirectory(tif))
444 			goto bad;
445 		return (tif);
446 	}
447 bad:
448 	tif->tif_mode = O_RDONLY;	/* XXX avoid flush */
449         TIFFCleanup(tif);
450 bad2:
451 	return ((TIFF*)0);
452 }
453 
454 /*
455  * Query functions to access private data.
456  */
457 
458 /*
459  * Return open file's name.
460  */
461 const char *
462 TIFFFileName(TIFF* tif)
463 {
464 	return (tif->tif_name);
465 }
466 
467 /*
468  * Set the file name.
469  */
470 const char *
471 TIFFSetFileName(TIFF* tif, const char *name)
472 {
473 	const char* old_name = tif->tif_name;
474 	tif->tif_name = (char *)name;
475 	return (old_name);
476 }
477 
478 /*
479  * Return open file's I/O descriptor.
480  */
481 int
482 TIFFFileno(TIFF* tif)
483 {
484 	return (tif->tif_fd);
485 }
486 
487 /*
488  * Set open file's I/O descriptor, and return previous value.
489  */
490 int
491 TIFFSetFileno(TIFF* tif, int fd)
492 {
493         int old_fd = tif->tif_fd;
494 	tif->tif_fd = fd;
495 	return old_fd;
496 }
497 
498 /*
499  * Return open file's clientdata.
500  */
501 thandle_t
502 TIFFClientdata(TIFF* tif)
503 {
504 	return (tif->tif_clientdata);
505 }
506 
507 /*
508  * Set open file's clientdata, and return previous value.
509  */
510 thandle_t
511 TIFFSetClientdata(TIFF* tif, thandle_t newvalue)
512 {
513 	thandle_t m = tif->tif_clientdata;
514 	tif->tif_clientdata = newvalue;
515 	return m;
516 }
517 
518 /*
519  * Return read/write mode.
520  */
521 int
522 TIFFGetMode(TIFF* tif)
523 {
524 	return (tif->tif_mode);
525 }
526 
527 /*
528  * Return read/write mode.
529  */
530 int
531 TIFFSetMode(TIFF* tif, int mode)
532 {
533 	int old_mode = tif->tif_mode;
534 	tif->tif_mode = mode;
535 	return (old_mode);
536 }
537 
538 /*
539  * Return nonzero if file is organized in
540  * tiles; zero if organized as strips.
541  */
542 int
543 TIFFIsTiled(TIFF* tif)
544 {
545 	return (isTiled(tif));
546 }
547 
548 /*
549  * Return current row being read/written.
550  */
551 uint32
552 TIFFCurrentRow(TIFF* tif)
553 {
554 	return (tif->tif_row);
555 }
556 
557 /*
558  * Return index of the current directory.
559  */
560 tdir_t
561 TIFFCurrentDirectory(TIFF* tif)
562 {
563 	return (tif->tif_curdir);
564 }
565 
566 /*
567  * Return current strip.
568  */
569 tstrip_t
570 TIFFCurrentStrip(TIFF* tif)
571 {
572 	return (tif->tif_curstrip);
573 }
574 
575 /*
576  * Return current tile.
577  */
578 ttile_t
579 TIFFCurrentTile(TIFF* tif)
580 {
581 	return (tif->tif_curtile);
582 }
583 
584 /*
585  * Return nonzero if the file has byte-swapped data.
586  */
587 int
588 TIFFIsByteSwapped(TIFF* tif)
589 {
590 	return ((tif->tif_flags & TIFF_SWAB) != 0);
591 }
592 
593 /*
594  * Return nonzero if the data is returned up-sampled.
595  */
596 int
597 TIFFIsUpSampled(TIFF* tif)
598 {
599 	return (isUpSampled(tif));
600 }
601 
602 /*
603  * Return nonzero if the data is returned in MSB-to-LSB bit order.
604  */
605 int
606 TIFFIsMSB2LSB(TIFF* tif)
607 {
608 	return (isFillOrder(tif, FILLORDER_MSB2LSB));
609 }
610 
611 /*
612  * Return nonzero if given file was written in big-endian order.
613  */
614 int
615 TIFFIsBigEndian(TIFF* tif)
616 {
617 	return (tif->tif_header.tiff_magic == TIFF_BIGENDIAN);
618 }
619 
620 /*
621  * Return pointer to file read method.
622  */
623 TIFFReadWriteProc
624 TIFFGetReadProc(TIFF* tif)
625 {
626 	return (tif->tif_readproc);
627 }
628 
629 /*
630  * Return pointer to file write method.
631  */
632 TIFFReadWriteProc
633 TIFFGetWriteProc(TIFF* tif)
634 {
635 	return (tif->tif_writeproc);
636 }
637 
638 /*
639  * Return pointer to file seek method.
640  */
641 TIFFSeekProc
642 TIFFGetSeekProc(TIFF* tif)
643 {
644 	return (tif->tif_seekproc);
645 }
646 
647 /*
648  * Return pointer to file close method.
649  */
650 TIFFCloseProc
651 TIFFGetCloseProc(TIFF* tif)
652 {
653 	return (tif->tif_closeproc);
654 }
655 
656 /*
657  * Return pointer to file size requesting method.
658  */
659 TIFFSizeProc
660 TIFFGetSizeProc(TIFF* tif)
661 {
662 	return (tif->tif_sizeproc);
663 }
664 
665 /*
666  * Return pointer to memory mapping method.
667  */
668 TIFFMapFileProc
669 TIFFGetMapFileProc(TIFF* tif)
670 {
671 	return (tif->tif_mapproc);
672 }
673 
674 /*
675  * Return pointer to memory unmapping method.
676  */
677 TIFFUnmapFileProc
678 TIFFGetUnmapFileProc(TIFF* tif)
679 {
680 	return (tif->tif_unmapproc);
681 }
682 
683 /* vim: set ts=8 sts=8 sw=8 noet: */
684