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