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