roentgen b75cab
/* $Id: tif_open.c,v 1.46 2010-12-06 16:54:54 faxguy Exp $ */
roentgen b75cab
roentgen b75cab
/*
roentgen b75cab
 * Copyright (c) 1988-1997 Sam Leffler
roentgen b75cab
 * Copyright (c) 1991-1997 Silicon Graphics, Inc.
roentgen b75cab
 *
roentgen b75cab
 * Permission to use, copy, modify, distribute, and sell this software and 
roentgen b75cab
 * its documentation for any purpose is hereby granted without fee, provided
roentgen b75cab
 * that (i) the above copyright notices and this permission notice appear in
roentgen b75cab
 * all copies of the software and related documentation, and (ii) the names of
roentgen b75cab
 * Sam Leffler and Silicon Graphics may not be used in any advertising or
roentgen b75cab
 * publicity relating to the software without the specific, prior written
roentgen b75cab
 * permission of Sam Leffler and Silicon Graphics.
roentgen b75cab
 * 
roentgen b75cab
 * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, 
roentgen b75cab
 * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY 
roentgen b75cab
 * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.  
roentgen b75cab
 * 
roentgen b75cab
 * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
roentgen b75cab
 * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
roentgen b75cab
 * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
roentgen b75cab
 * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF 
roentgen b75cab
 * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE 
roentgen b75cab
 * OF THIS SOFTWARE.
roentgen b75cab
 */
roentgen b75cab
roentgen b75cab
/*
roentgen b75cab
 * TIFF Library.
roentgen b75cab
 */
roentgen b75cab
#include "tiffiop.h"
roentgen b75cab
roentgen b75cab
/*
roentgen b75cab
 * Dummy functions to fill the omitted client procedures.
roentgen b75cab
 */
roentgen b75cab
static int
roentgen b75cab
_tiffDummyMapProc(thandle_t fd, void** pbase, toff_t* psize)
roentgen b75cab
{
roentgen b75cab
	(void) fd; (void) pbase; (void) psize;
roentgen b75cab
	return (0);
roentgen b75cab
}
roentgen b75cab
roentgen b75cab
static void
roentgen b75cab
_tiffDummyUnmapProc(thandle_t fd, void* base, toff_t size)
roentgen b75cab
{
roentgen b75cab
	(void) fd; (void) base; (void) size;
roentgen b75cab
}
roentgen b75cab
roentgen b75cab
int
roentgen b75cab
_TIFFgetMode(const char* mode, const char* module)
roentgen b75cab
{
roentgen b75cab
	int m = -1;
roentgen b75cab
roentgen b75cab
	switch (mode[0]) {
roentgen b75cab
	case 'r':
roentgen b75cab
		m = O_RDONLY;
roentgen b75cab
		if (mode[1] == '+')
roentgen b75cab
			m = O_RDWR;
roentgen b75cab
		break;
roentgen b75cab
	case 'w':
roentgen b75cab
	case 'a':
roentgen b75cab
		m = O_RDWR|O_CREAT;
roentgen b75cab
		if (mode[0] == 'w')
roentgen b75cab
			m |= O_TRUNC;
roentgen b75cab
		break;
roentgen b75cab
	default:
roentgen b75cab
		TIFFErrorExt(0, module, "\"%s\": Bad mode", mode);
roentgen b75cab
		break;
roentgen b75cab
	}
roentgen b75cab
	return (m);
roentgen b75cab
}
roentgen b75cab
roentgen b75cab
TIFF*
roentgen b75cab
TIFFClientOpen(
roentgen b75cab
	const char* name, const char* mode,
roentgen b75cab
	thandle_t clientdata,
roentgen b75cab
	TIFFReadWriteProc readproc,
roentgen b75cab
	TIFFReadWriteProc writeproc,
roentgen b75cab
	TIFFSeekProc seekproc,
roentgen b75cab
	TIFFCloseProc closeproc,
roentgen b75cab
	TIFFSizeProc sizeproc,
roentgen b75cab
	TIFFMapFileProc mapproc,
roentgen b75cab
	TIFFUnmapFileProc unmapproc
roentgen b75cab
)
roentgen b75cab
{
roentgen b75cab
	static const char module[] = "TIFFClientOpen";
roentgen b75cab
	TIFF *tif;
roentgen b75cab
	int m;
roentgen b75cab
	const char* cp;
roentgen b75cab
roentgen b75cab
	/* The following are configuration checks. They should be redundant, but should not
roentgen b75cab
	 * compile to any actual code in an optimised release build anyway. If any of them
roentgen b75cab
	 * fail, (makefile-based or other) configuration is not correct */
roentgen b75cab
	assert(sizeof(uint8)==1);
roentgen b75cab
	assert(sizeof(int8)==1);
roentgen b75cab
	assert(sizeof(uint16)==2);
roentgen b75cab
	assert(sizeof(int16)==2);
roentgen b75cab
	assert(sizeof(uint32)==4);
roentgen b75cab
	assert(sizeof(int32)==4);
roentgen b75cab
	assert(sizeof(uint64)==8);
roentgen b75cab
	assert(sizeof(int64)==8);
roentgen b75cab
	assert(sizeof(tmsize_t)==sizeof(void*));
roentgen b75cab
	{
roentgen b75cab
		union{
roentgen b75cab
			uint8 a8[2];
roentgen b75cab
			uint16 a16;
roentgen b75cab
		} n;
roentgen b75cab
		n.a8[0]=1;
roentgen b75cab
		n.a8[1]=0;
roentgen b75cab
		#ifdef WORDS_BIGENDIAN
roentgen b75cab
		assert(n.a16==256);
roentgen b75cab
		#else
roentgen b75cab
		assert(n.a16==1);
roentgen b75cab
		#endif
roentgen b75cab
	}
roentgen b75cab
roentgen b75cab
	m = _TIFFgetMode(mode, module);
roentgen b75cab
	if (m == -1)
roentgen b75cab
		goto bad2;
roentgen b75cab
	tif = (TIFF *)_TIFFmalloc((tmsize_t)(sizeof (TIFF) + strlen(name) + 1));
roentgen b75cab
	if (tif == NULL) {
roentgen b75cab
		TIFFErrorExt(clientdata, module, "%s: Out of memory (TIFF structure)", name);
roentgen b75cab
		goto bad2;
roentgen b75cab
	}
roentgen b75cab
	_TIFFmemset(tif, 0, sizeof (*tif));
roentgen b75cab
	tif->tif_name = (char *)tif + sizeof (TIFF);
roentgen b75cab
	strcpy(tif->tif_name, name);
roentgen b75cab
	tif->tif_mode = m &~ (O_CREAT|O_TRUNC);
roentgen b75cab
	tif->tif_curdir = (uint16) -1;		/* non-existent directory */
roentgen b75cab
	tif->tif_curoff = 0;
roentgen b75cab
	tif->tif_curstrip = (uint32) -1;	/* invalid strip */
roentgen b75cab
	tif->tif_row = (uint32) -1;		/* read/write pre-increment */
roentgen b75cab
	tif->tif_clientdata = clientdata;
roentgen b75cab
	if (!readproc || !writeproc || !seekproc || !closeproc || !sizeproc) {
roentgen b75cab
		TIFFErrorExt(clientdata, module,
roentgen b75cab
		    "One of the client procedures is NULL pointer.");
roentgen b75cab
		goto bad2;
roentgen b75cab
	}
roentgen b75cab
	tif->tif_readproc = readproc;
roentgen b75cab
	tif->tif_writeproc = writeproc;
roentgen b75cab
	tif->tif_seekproc = seekproc;
roentgen b75cab
	tif->tif_closeproc = closeproc;
roentgen b75cab
	tif->tif_sizeproc = sizeproc;
roentgen b75cab
	if (mapproc)
roentgen b75cab
		tif->tif_mapproc = mapproc;
roentgen b75cab
	else
roentgen b75cab
		tif->tif_mapproc = _tiffDummyMapProc;
roentgen b75cab
	if (unmapproc)
roentgen b75cab
		tif->tif_unmapproc = unmapproc;
roentgen b75cab
	else
roentgen b75cab
		tif->tif_unmapproc = _tiffDummyUnmapProc;
roentgen b75cab
	_TIFFSetDefaultCompressionState(tif);    /* setup default state */
roentgen b75cab
	/*
roentgen b75cab
	 * Default is to return data MSB2LSB and enable the
roentgen b75cab
	 * use of memory-mapped files and strip chopping when
roentgen b75cab
	 * a file is opened read-only.
roentgen b75cab
	 */
roentgen b75cab
	tif->tif_flags = FILLORDER_MSB2LSB;
roentgen b75cab
	if (m == O_RDONLY )
roentgen b75cab
		tif->tif_flags |= TIFF_MAPPED;
roentgen b75cab
roentgen b75cab
	#ifdef STRIPCHOP_DEFAULT
roentgen b75cab
	if (m == O_RDONLY || m == O_RDWR)
roentgen b75cab
		tif->tif_flags |= STRIPCHOP_DEFAULT;
roentgen b75cab
	#endif
roentgen b75cab
roentgen b75cab
	/*
roentgen b75cab
	 * Process library-specific flags in the open mode string.
roentgen b75cab
	 * The following flags may be used to control intrinsic library
roentgen b75cab
	 * behaviour that may or may not be desirable (usually for
roentgen b75cab
	 * compatibility with some application that claims to support
roentgen b75cab
	 * TIFF but only supports some braindead idea of what the
roentgen b75cab
	 * vendor thinks TIFF is):
roentgen b75cab
	 *
roentgen b75cab
	 * 'l' use little-endian byte order for creating a file
roentgen b75cab
	 * 'b' use big-endian byte order for creating a file
roentgen b75cab
	 * 'L' read/write information using LSB2MSB bit order
roentgen b75cab
	 * 'B' read/write information using MSB2LSB bit order
roentgen b75cab
	 * 'H' read/write information using host bit order
roentgen b75cab
	 * 'M' enable use of memory-mapped files when supported
roentgen b75cab
	 * 'm' disable use of memory-mapped files
roentgen b75cab
	 * 'C' enable strip chopping support when reading
roentgen b75cab
	 * 'c' disable strip chopping support
roentgen b75cab
	 * 'h' read TIFF header only, do not load the first IFD
roentgen b75cab
	 * '4' ClassicTIFF for creating a file (default)
roentgen b75cab
	 * '8' BigTIFF for creating a file
roentgen b75cab
	 *
roentgen b75cab
	 * The use of the 'l' and 'b' flags is strongly discouraged.
roentgen b75cab
	 * These flags are provided solely because numerous vendors,
roentgen b75cab
	 * typically on the PC, do not correctly support TIFF; they
roentgen b75cab
	 * only support the Intel little-endian byte order.  This
roentgen b75cab
	 * support is not configured by default because it supports
roentgen b75cab
	 * the violation of the TIFF spec that says that readers *MUST*
roentgen b75cab
	 * support both byte orders.  It is strongly recommended that
roentgen b75cab
	 * you not use this feature except to deal with busted apps
roentgen b75cab
	 * that write invalid TIFF.  And even in those cases you should
roentgen b75cab
	 * bang on the vendors to fix their software.
roentgen b75cab
	 *
roentgen b75cab
	 * The 'L', 'B', and 'H' flags are intended for applications
roentgen b75cab
	 * that can optimize operations on data by using a particular
roentgen b75cab
	 * bit order.  By default the library returns data in MSB2LSB
roentgen b75cab
	 * bit order for compatibiltiy with older versions of this
roentgen b75cab
	 * library.  Returning data in the bit order of the native cpu
roentgen b75cab
	 * makes the most sense but also requires applications to check
roentgen b75cab
	 * the value of the FillOrder tag; something they probably do
roentgen b75cab
	 * not do right now.
roentgen b75cab
	 *
roentgen b75cab
	 * The 'M' and 'm' flags are provided because some virtual memory
roentgen b75cab
	 * systems exhibit poor behaviour when large images are mapped.
roentgen b75cab
	 * These options permit clients to control the use of memory-mapped
roentgen b75cab
	 * files on a per-file basis.
roentgen b75cab
	 *
roentgen b75cab
	 * The 'C' and 'c' flags are provided because the library support
roentgen b75cab
	 * for chopping up large strips into multiple smaller strips is not
roentgen b75cab
	 * application-transparent and as such can cause problems.  The 'c'
roentgen b75cab
	 * option permits applications that only want to look at the tags,
roentgen b75cab
	 * for example, to get the unadulterated TIFF tag information.
roentgen b75cab
	 */
roentgen b75cab
	for (cp = mode; *cp; cp++)
roentgen b75cab
		switch (*cp) {
roentgen b75cab
			case 'b':
roentgen b75cab
				#ifndef WORDS_BIGENDIAN
roentgen b75cab
				if (m&O_CREAT)
roentgen b75cab
					tif->tif_flags |= TIFF_SWAB;
roentgen b75cab
				#endif
roentgen b75cab
				break;
roentgen b75cab
			case 'l':
roentgen b75cab
				#ifdef WORDS_BIGENDIAN
roentgen b75cab
				if ((m&O_CREAT))
roentgen b75cab
					tif->tif_flags |= TIFF_SWAB;
roentgen b75cab
				#endif
roentgen b75cab
				break;
roentgen b75cab
			case 'B':
roentgen b75cab
				tif->tif_flags = (tif->tif_flags &~ TIFF_FILLORDER) |
roentgen b75cab
				    FILLORDER_MSB2LSB;
roentgen b75cab
				break;
roentgen b75cab
			case 'L':
roentgen b75cab
				tif->tif_flags = (tif->tif_flags &~ TIFF_FILLORDER) |
roentgen b75cab
				    FILLORDER_LSB2MSB;
roentgen b75cab
				break;
roentgen b75cab
			case 'H':
roentgen b75cab
				tif->tif_flags = (tif->tif_flags &~ TIFF_FILLORDER) |
roentgen b75cab
				    HOST_FILLORDER;
roentgen b75cab
				break;
roentgen b75cab
			case 'M':
roentgen b75cab
				if (m == O_RDONLY)
roentgen b75cab
					tif->tif_flags |= TIFF_MAPPED;
roentgen b75cab
				break;
roentgen b75cab
			case 'm':
roentgen b75cab
				if (m == O_RDONLY)
roentgen b75cab
					tif->tif_flags &= ~TIFF_MAPPED;
roentgen b75cab
				break;
roentgen b75cab
			case 'C':
roentgen b75cab
				if (m == O_RDONLY)
roentgen b75cab
					tif->tif_flags |= TIFF_STRIPCHOP;
roentgen b75cab
				break;
roentgen b75cab
			case 'c':
roentgen b75cab
				if (m == O_RDONLY)
roentgen b75cab
					tif->tif_flags &= ~TIFF_STRIPCHOP;
roentgen b75cab
				break;
roentgen b75cab
			case 'h':
roentgen b75cab
				tif->tif_flags |= TIFF_HEADERONLY;
roentgen b75cab
				break;
roentgen b75cab
			case '8':
roentgen b75cab
				if (m&O_CREAT)
roentgen b75cab
					tif->tif_flags |= TIFF_BIGTIFF;
roentgen b75cab
				break;
roentgen b75cab
		}
roentgen b75cab
	/*
roentgen b75cab
	 * Read in TIFF header.
roentgen b75cab
	 */
roentgen b75cab
	if ((m & O_TRUNC) ||
roentgen b75cab
	    !ReadOK(tif, &tif->tif_header, sizeof (TIFFHeaderClassic))) {
roentgen b75cab
		if (tif->tif_mode == O_RDONLY) {
roentgen b75cab
			TIFFErrorExt(tif->tif_clientdata, name,
roentgen b75cab
			    "Cannot read TIFF header");
roentgen b75cab
			goto bad;
roentgen b75cab
		}
roentgen b75cab
		/*
roentgen b75cab
		 * Setup header and write.
roentgen b75cab
		 */
roentgen b75cab
		#ifdef WORDS_BIGENDIAN
roentgen b75cab
		tif->tif_header.common.tiff_magic = tif->tif_flags & TIFF_SWAB
roentgen b75cab
		    ? TIFF_LITTLEENDIAN : TIFF_BIGENDIAN;
roentgen b75cab
		#else
roentgen b75cab
		tif->tif_header.common.tiff_magic = tif->tif_flags & TIFF_SWAB
roentgen b75cab
		    ? TIFF_BIGENDIAN : TIFF_LITTLEENDIAN;
roentgen b75cab
		#endif
roentgen b75cab
		if (!(tif->tif_flags&TIFF_BIGTIFF))
roentgen b75cab
		{
roentgen b75cab
			tif->tif_header.common.tiff_version = TIFF_VERSION_CLASSIC;
roentgen b75cab
			tif->tif_header.classic.tiff_diroff = 0;
roentgen b75cab
			if (tif->tif_flags & TIFF_SWAB)
roentgen b75cab
				TIFFSwabShort(&tif->tif_header.common.tiff_version);
roentgen b75cab
			tif->tif_header_size = sizeof(TIFFHeaderClassic);
roentgen b75cab
		}
roentgen b75cab
		else
roentgen b75cab
		{
roentgen b75cab
			tif->tif_header.common.tiff_version = TIFF_VERSION_BIG;
roentgen b75cab
			tif->tif_header.big.tiff_offsetsize = 8;
roentgen b75cab
			tif->tif_header.big.tiff_unused = 0;
roentgen b75cab
			tif->tif_header.big.tiff_diroff = 0;
roentgen b75cab
			if (tif->tif_flags & TIFF_SWAB)
roentgen b75cab
			{
roentgen b75cab
				TIFFSwabShort(&tif->tif_header.common.tiff_version);
roentgen b75cab
				TIFFSwabShort(&tif->tif_header.big.tiff_offsetsize);
roentgen b75cab
			}
roentgen b75cab
			tif->tif_header_size = sizeof (TIFFHeaderBig);
roentgen b75cab
		}
roentgen b75cab
		/*
roentgen b75cab
		 * The doc for "fopen" for some STD_C_LIBs says that if you
roentgen b75cab
		 * open a file for modify ("+"), then you must fseek (or
roentgen b75cab
		 * fflush?) between any freads and fwrites.  This is not
roentgen b75cab
		 * necessary on most systems, but has been shown to be needed
roentgen b75cab
		 * on Solaris.
roentgen b75cab
		 */
roentgen b75cab
		TIFFSeekFile( tif, 0, SEEK_SET );
roentgen b75cab
		if (!WriteOK(tif, &tif->tif_header, (tmsize_t)(tif->tif_header_size))) {
roentgen b75cab
			TIFFErrorExt(tif->tif_clientdata, name,
roentgen b75cab
			    "Error writing TIFF header");
roentgen b75cab
			goto bad;
roentgen b75cab
		}
roentgen b75cab
		/*
roentgen b75cab
		 * Setup the byte order handling.
roentgen b75cab
		 */
roentgen b75cab
		if (tif->tif_header.common.tiff_magic == TIFF_BIGENDIAN) {
roentgen b75cab
			#ifndef WORDS_BIGENDIAN
roentgen b75cab
			tif->tif_flags |= TIFF_SWAB;
roentgen b75cab
			#endif
roentgen b75cab
		} else {
roentgen b75cab
			#ifdef WORDS_BIGENDIAN
roentgen b75cab
			tif->tif_flags |= TIFF_SWAB;
roentgen b75cab
			#endif
roentgen b75cab
		}
roentgen b75cab
		/*
roentgen b75cab
		 * Setup default directory.
roentgen b75cab
		 */
roentgen b75cab
		if (!TIFFDefaultDirectory(tif))
roentgen b75cab
			goto bad;
roentgen b75cab
		tif->tif_diroff = 0;
roentgen b75cab
		tif->tif_dirlist = NULL;
roentgen b75cab
		tif->tif_dirlistsize = 0;
roentgen b75cab
		tif->tif_dirnumber = 0;
roentgen b75cab
		return (tif);
roentgen b75cab
	}
roentgen b75cab
	/*
roentgen b75cab
	 * Setup the byte order handling.
roentgen b75cab
	 */
roentgen b75cab
	if (tif->tif_header.common.tiff_magic != TIFF_BIGENDIAN &&
roentgen b75cab
	    tif->tif_header.common.tiff_magic != TIFF_LITTLEENDIAN
roentgen b75cab
	    #if MDI_SUPPORT
roentgen b75cab
	    &&
roentgen b75cab
	    #if HOST_BIGENDIAN
roentgen b75cab
	    tif->tif_header.common.tiff_magic != MDI_BIGENDIAN
roentgen b75cab
	    #else
roentgen b75cab
	    tif->tif_header.common.tiff_magic != MDI_LITTLEENDIAN
roentgen b75cab
	    #endif
roentgen b75cab
	    ) {
roentgen b75cab
		TIFFErrorExt(tif->tif_clientdata, name,
roentgen b75cab
		    "Not a TIFF or MDI file, bad magic number %d (0x%x)",
roentgen b75cab
	    #else
roentgen b75cab
	    ) {
roentgen b75cab
		TIFFErrorExt(tif->tif_clientdata, name,
roentgen b75cab
		    "Not a TIFF file, bad magic number %d (0x%x)",
roentgen b75cab
	    #endif
roentgen b75cab
		    tif->tif_header.common.tiff_magic,
roentgen b75cab
		    tif->tif_header.common.tiff_magic);
roentgen b75cab
		goto bad;
roentgen b75cab
	}
roentgen b75cab
	if (tif->tif_header.common.tiff_magic == TIFF_BIGENDIAN) {
roentgen b75cab
		#ifndef WORDS_BIGENDIAN
roentgen b75cab
		tif->tif_flags |= TIFF_SWAB;
roentgen b75cab
		#endif
roentgen b75cab
	} else {
roentgen b75cab
		#ifdef WORDS_BIGENDIAN
roentgen b75cab
		tif->tif_flags |= TIFF_SWAB;
roentgen b75cab
		#endif
roentgen b75cab
	}
roentgen b75cab
	if (tif->tif_flags & TIFF_SWAB) 
roentgen b75cab
		TIFFSwabShort(&tif->tif_header.common.tiff_version);
roentgen b75cab
	if ((tif->tif_header.common.tiff_version != TIFF_VERSION_CLASSIC)&&
roentgen b75cab
	    (tif->tif_header.common.tiff_version != TIFF_VERSION_BIG)) {
roentgen b75cab
		TIFFErrorExt(tif->tif_clientdata, name,
roentgen b75cab
		    "Not a TIFF file, bad version number %d (0x%x)",
roentgen b75cab
		    tif->tif_header.common.tiff_version,
roentgen b75cab
		    tif->tif_header.common.tiff_version);
roentgen b75cab
		goto bad;
roentgen b75cab
	}
roentgen b75cab
	if (tif->tif_header.common.tiff_version == TIFF_VERSION_CLASSIC)
roentgen b75cab
	{
roentgen b75cab
		if (tif->tif_flags & TIFF_SWAB)
roentgen b75cab
			TIFFSwabLong(&tif->tif_header.classic.tiff_diroff);
roentgen b75cab
		tif->tif_header_size = sizeof(TIFFHeaderClassic);
roentgen b75cab
	}
roentgen b75cab
	else
roentgen b75cab
	{
roentgen b75cab
		if (!ReadOK(tif, ((uint8*)(&tif->tif_header) + sizeof(TIFFHeaderClassic)), (sizeof(TIFFHeaderBig)-sizeof(TIFFHeaderClassic))))
roentgen b75cab
		{
roentgen b75cab
			TIFFErrorExt(tif->tif_clientdata, name,
roentgen b75cab
			    "Cannot read TIFF header");
roentgen b75cab
			goto bad;
roentgen b75cab
		}
roentgen b75cab
		if (tif->tif_flags & TIFF_SWAB)
roentgen b75cab
		{
roentgen b75cab
			TIFFSwabShort(&tif->tif_header.big.tiff_offsetsize);
roentgen b75cab
			TIFFSwabLong8(&tif->tif_header.big.tiff_diroff);
roentgen b75cab
		}
roentgen b75cab
		if (tif->tif_header.big.tiff_offsetsize != 8)
roentgen b75cab
		{
roentgen b75cab
			TIFFErrorExt(tif->tif_clientdata, name,
roentgen b75cab
			    "Not a TIFF file, bad BigTIFF offsetsize %d (0x%x)",
roentgen b75cab
			    tif->tif_header.big.tiff_offsetsize,
roentgen b75cab
			    tif->tif_header.big.tiff_offsetsize);
roentgen b75cab
			goto bad;
roentgen b75cab
		}
roentgen b75cab
		if (tif->tif_header.big.tiff_unused != 0)
roentgen b75cab
		{
roentgen b75cab
			TIFFErrorExt(tif->tif_clientdata, name,
roentgen b75cab
			    "Not a TIFF file, bad BigTIFF unused %d (0x%x)",
roentgen b75cab
			    tif->tif_header.big.tiff_unused,
roentgen b75cab
			    tif->tif_header.big.tiff_unused);
roentgen b75cab
			goto bad;
roentgen b75cab
		}
roentgen b75cab
		tif->tif_header_size = sizeof(TIFFHeaderBig);
roentgen b75cab
		tif->tif_flags |= TIFF_BIGTIFF;
roentgen b75cab
	}
roentgen b75cab
	tif->tif_flags |= TIFF_MYBUFFER;
roentgen b75cab
	tif->tif_rawcp = tif->tif_rawdata = 0;
roentgen b75cab
	tif->tif_rawdatasize = 0;
roentgen b75cab
        tif->tif_rawdataoff = 0;
roentgen b75cab
        tif->tif_rawdataloaded = 0;
roentgen b75cab
roentgen b75cab
	switch (mode[0]) {
roentgen b75cab
		case 'r':
roentgen b75cab
			if (!(tif->tif_flags&TIFF_BIGTIFF))
roentgen b75cab
				tif->tif_nextdiroff = tif->tif_header.classic.tiff_diroff;
roentgen b75cab
			else
roentgen b75cab
				tif->tif_nextdiroff = tif->tif_header.big.tiff_diroff;
roentgen b75cab
			/*
roentgen b75cab
			 * Try to use a memory-mapped file if the client
roentgen b75cab
			 * has not explicitly suppressed usage with the
roentgen b75cab
			 * 'm' flag in the open mode (see above).
roentgen b75cab
			 */
roentgen b75cab
			if (tif->tif_flags & TIFF_MAPPED)
roentgen b75cab
			{
roentgen b75cab
				toff_t n;
roentgen b75cab
				if (TIFFMapFileContents(tif,(void**)(&tif->tif_base),&n))
roentgen b75cab
				{
roentgen b75cab
					tif->tif_size=(tmsize_t)n;
roentgen b75cab
					assert((toff_t)tif->tif_size==n);
roentgen b75cab
				}
roentgen b75cab
				else
roentgen b75cab
					tif->tif_flags &= ~TIFF_MAPPED;
roentgen b75cab
			}
roentgen b75cab
			/*
roentgen b75cab
			 * Sometimes we do not want to read the first directory (for example,
roentgen b75cab
			 * it may be broken) and want to proceed to other directories. I this
roentgen b75cab
			 * case we use the TIFF_HEADERONLY flag to open file and return
roentgen b75cab
			 * immediately after reading TIFF header.
roentgen b75cab
			 */
roentgen b75cab
			if (tif->tif_flags & TIFF_HEADERONLY)
roentgen b75cab
				return (tif);
roentgen b75cab
roentgen b75cab
			/*
roentgen b75cab
			 * Setup initial directory.
roentgen b75cab
			 */
roentgen b75cab
			if (TIFFReadDirectory(tif)) {
roentgen b75cab
				tif->tif_rawcc = (tmsize_t)-1;
roentgen b75cab
				tif->tif_flags |= TIFF_BUFFERSETUP;
roentgen b75cab
				return (tif);
roentgen b75cab
			}
roentgen b75cab
			break;
roentgen b75cab
		case 'a':
roentgen b75cab
			/*
roentgen b75cab
			 * New directories are automatically append
roentgen b75cab
			 * to the end of the directory chain when they
roentgen b75cab
			 * are written out (see TIFFWriteDirectory).
roentgen b75cab
			 */
roentgen b75cab
			if (!TIFFDefaultDirectory(tif))
roentgen b75cab
				goto bad;
roentgen b75cab
			return (tif);
roentgen b75cab
	}
roentgen b75cab
bad:
roentgen b75cab
	tif->tif_mode = O_RDONLY;	/* XXX avoid flush */
roentgen b75cab
        TIFFCleanup(tif);
roentgen b75cab
bad2:
roentgen b75cab
	return ((TIFF*)0);
roentgen b75cab
}
roentgen b75cab
roentgen b75cab
/*
roentgen b75cab
 * Query functions to access private data.
roentgen b75cab
 */
roentgen b75cab
roentgen b75cab
/*
roentgen b75cab
 * Return open file's name.
roentgen b75cab
 */
roentgen b75cab
const char *
roentgen b75cab
TIFFFileName(TIFF* tif)
roentgen b75cab
{
roentgen b75cab
	return (tif->tif_name);
roentgen b75cab
}
roentgen b75cab
roentgen b75cab
/*
roentgen b75cab
 * Set the file name.
roentgen b75cab
 */
roentgen b75cab
const char *
roentgen b75cab
TIFFSetFileName(TIFF* tif, const char *name)
roentgen b75cab
{
roentgen b75cab
	const char* old_name = tif->tif_name;
roentgen b75cab
	tif->tif_name = (char *)name;
roentgen b75cab
	return (old_name);
roentgen b75cab
}
roentgen b75cab
roentgen b75cab
/*
roentgen b75cab
 * Return open file's I/O descriptor.
roentgen b75cab
 */
roentgen b75cab
int
roentgen b75cab
TIFFFileno(TIFF* tif)
roentgen b75cab
{
roentgen b75cab
	return (tif->tif_fd);
roentgen b75cab
}
roentgen b75cab
roentgen b75cab
/*
roentgen b75cab
 * Set open file's I/O descriptor, and return previous value.
roentgen b75cab
 */
roentgen b75cab
int
roentgen b75cab
TIFFSetFileno(TIFF* tif, int fd)
roentgen b75cab
{
roentgen b75cab
        int old_fd = tif->tif_fd;
roentgen b75cab
	tif->tif_fd = fd;
roentgen b75cab
	return old_fd;
roentgen b75cab
}
roentgen b75cab
roentgen b75cab
/*
roentgen b75cab
 * Return open file's clientdata.
roentgen b75cab
 */
roentgen b75cab
thandle_t
roentgen b75cab
TIFFClientdata(TIFF* tif)
roentgen b75cab
{
roentgen b75cab
	return (tif->tif_clientdata);
roentgen b75cab
}
roentgen b75cab
roentgen b75cab
/*
roentgen b75cab
 * Set open file's clientdata, and return previous value.
roentgen b75cab
 */
roentgen b75cab
thandle_t
roentgen b75cab
TIFFSetClientdata(TIFF* tif, thandle_t newvalue)
roentgen b75cab
{
roentgen b75cab
	thandle_t m = tif->tif_clientdata;
roentgen b75cab
	tif->tif_clientdata = newvalue;
roentgen b75cab
	return m;
roentgen b75cab
}
roentgen b75cab
roentgen b75cab
/*
roentgen b75cab
 * Return read/write mode.
roentgen b75cab
 */
roentgen b75cab
int
roentgen b75cab
TIFFGetMode(TIFF* tif)
roentgen b75cab
{
roentgen b75cab
	return (tif->tif_mode);
roentgen b75cab
}
roentgen b75cab
roentgen b75cab
/*
roentgen b75cab
 * Return read/write mode.
roentgen b75cab
 */
roentgen b75cab
int
roentgen b75cab
TIFFSetMode(TIFF* tif, int mode)
roentgen b75cab
{
roentgen b75cab
	int old_mode = tif->tif_mode;
roentgen b75cab
	tif->tif_mode = mode;
roentgen b75cab
	return (old_mode);
roentgen b75cab
}
roentgen b75cab
roentgen b75cab
/*
roentgen b75cab
 * Return nonzero if file is organized in
roentgen b75cab
 * tiles; zero if organized as strips.
roentgen b75cab
 */
roentgen b75cab
int
roentgen b75cab
TIFFIsTiled(TIFF* tif)
roentgen b75cab
{
roentgen b75cab
	return (isTiled(tif));
roentgen b75cab
}
roentgen b75cab
roentgen b75cab
/*
roentgen b75cab
 * Return current row being read/written.
roentgen b75cab
 */
roentgen b75cab
uint32
roentgen b75cab
TIFFCurrentRow(TIFF* tif)
roentgen b75cab
{
roentgen b75cab
	return (tif->tif_row);
roentgen b75cab
}
roentgen b75cab
roentgen b75cab
/*
roentgen b75cab
 * Return index of the current directory.
roentgen b75cab
 */
roentgen b75cab
uint16
roentgen b75cab
TIFFCurrentDirectory(TIFF* tif)
roentgen b75cab
{
roentgen b75cab
	return (tif->tif_curdir);
roentgen b75cab
}
roentgen b75cab
roentgen b75cab
/*
roentgen b75cab
 * Return current strip.
roentgen b75cab
 */
roentgen b75cab
uint32
roentgen b75cab
TIFFCurrentStrip(TIFF* tif)
roentgen b75cab
{
roentgen b75cab
	return (tif->tif_curstrip);
roentgen b75cab
}
roentgen b75cab
roentgen b75cab
/*
roentgen b75cab
 * Return current tile.
roentgen b75cab
 */
roentgen b75cab
uint32
roentgen b75cab
TIFFCurrentTile(TIFF* tif)
roentgen b75cab
{
roentgen b75cab
	return (tif->tif_curtile);
roentgen b75cab
}
roentgen b75cab
roentgen b75cab
/*
roentgen b75cab
 * Return nonzero if the file has byte-swapped data.
roentgen b75cab
 */
roentgen b75cab
int
roentgen b75cab
TIFFIsByteSwapped(TIFF* tif)
roentgen b75cab
{
roentgen b75cab
	return ((tif->tif_flags & TIFF_SWAB) != 0);
roentgen b75cab
}
roentgen b75cab
roentgen b75cab
/*
roentgen b75cab
 * Return nonzero if the data is returned up-sampled.
roentgen b75cab
 */
roentgen b75cab
int
roentgen b75cab
TIFFIsUpSampled(TIFF* tif)
roentgen b75cab
{
roentgen b75cab
	return (isUpSampled(tif));
roentgen b75cab
}
roentgen b75cab
roentgen b75cab
/*
roentgen b75cab
 * Return nonzero if the data is returned in MSB-to-LSB bit order.
roentgen b75cab
 */
roentgen b75cab
int
roentgen b75cab
TIFFIsMSB2LSB(TIFF* tif)
roentgen b75cab
{
roentgen b75cab
	return (isFillOrder(tif, FILLORDER_MSB2LSB));
roentgen b75cab
}
roentgen b75cab
roentgen b75cab
/*
roentgen b75cab
 * Return nonzero if given file was written in big-endian order.
roentgen b75cab
 */
roentgen b75cab
int
roentgen b75cab
TIFFIsBigEndian(TIFF* tif)
roentgen b75cab
{
roentgen b75cab
	return (tif->tif_header.common.tiff_magic == TIFF_BIGENDIAN);
roentgen b75cab
}
roentgen b75cab
roentgen b75cab
/*
roentgen b75cab
 * Return pointer to file read method.
roentgen b75cab
 */
roentgen b75cab
TIFFReadWriteProc
roentgen b75cab
TIFFGetReadProc(TIFF* tif)
roentgen b75cab
{
roentgen b75cab
	return (tif->tif_readproc);
roentgen b75cab
}
roentgen b75cab
roentgen b75cab
/*
roentgen b75cab
 * Return pointer to file write method.
roentgen b75cab
 */
roentgen b75cab
TIFFReadWriteProc
roentgen b75cab
TIFFGetWriteProc(TIFF* tif)
roentgen b75cab
{
roentgen b75cab
	return (tif->tif_writeproc);
roentgen b75cab
}
roentgen b75cab
roentgen b75cab
/*
roentgen b75cab
 * Return pointer to file seek method.
roentgen b75cab
 */
roentgen b75cab
TIFFSeekProc
roentgen b75cab
TIFFGetSeekProc(TIFF* tif)
roentgen b75cab
{
roentgen b75cab
	return (tif->tif_seekproc);
roentgen b75cab
}
roentgen b75cab
roentgen b75cab
/*
roentgen b75cab
 * Return pointer to file close method.
roentgen b75cab
 */
roentgen b75cab
TIFFCloseProc
roentgen b75cab
TIFFGetCloseProc(TIFF* tif)
roentgen b75cab
{
roentgen b75cab
	return (tif->tif_closeproc);
roentgen b75cab
}
roentgen b75cab
roentgen b75cab
/*
roentgen b75cab
 * Return pointer to file size requesting method.
roentgen b75cab
 */
roentgen b75cab
TIFFSizeProc
roentgen b75cab
TIFFGetSizeProc(TIFF* tif)
roentgen b75cab
{
roentgen b75cab
	return (tif->tif_sizeproc);
roentgen b75cab
}
roentgen b75cab
roentgen b75cab
/*
roentgen b75cab
 * Return pointer to memory mapping method.
roentgen b75cab
 */
roentgen b75cab
TIFFMapFileProc
roentgen b75cab
TIFFGetMapFileProc(TIFF* tif)
roentgen b75cab
{
roentgen b75cab
	return (tif->tif_mapproc);
roentgen b75cab
}
roentgen b75cab
roentgen b75cab
/*
roentgen b75cab
 * Return pointer to memory unmapping method.
roentgen b75cab
 */
roentgen b75cab
TIFFUnmapFileProc
roentgen b75cab
TIFFGetUnmapFileProc(TIFF* tif)
roentgen b75cab
{
roentgen b75cab
	return (tif->tif_unmapproc);
roentgen b75cab
}
roentgen b75cab
roentgen b75cab
/* vim: set ts=8 sts=8 sw=8 noet: */
roentgen b75cab
/*
roentgen b75cab
 * Local Variables:
roentgen b75cab
 * mode: c
roentgen b75cab
 * c-basic-offset: 8
roentgen b75cab
 * fill-column: 78
roentgen b75cab
 * End:
roentgen b75cab
 */