Blame libtiff/tif_dirwrite.c

Packit 994f1a
/* $Id: tif_dirwrite.c,v 1.37.2.7 2010-06-08 18:50:42 bfriesen Exp $ */
Packit 994f1a
Packit 994f1a
/*
Packit 994f1a
 * Copyright (c) 1988-1997 Sam Leffler
Packit 994f1a
 * Copyright (c) 1991-1997 Silicon Graphics, Inc.
Packit 994f1a
 *
Packit 994f1a
 * Permission to use, copy, modify, distribute, and sell this software and 
Packit 994f1a
 * its documentation for any purpose is hereby granted without fee, provided
Packit 994f1a
 * that (i) the above copyright notices and this permission notice appear in
Packit 994f1a
 * all copies of the software and related documentation, and (ii) the names of
Packit 994f1a
 * Sam Leffler and Silicon Graphics may not be used in any advertising or
Packit 994f1a
 * publicity relating to the software without the specific, prior written
Packit 994f1a
 * permission of Sam Leffler and Silicon Graphics.
Packit 994f1a
 * 
Packit 994f1a
 * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, 
Packit 994f1a
 * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY 
Packit 994f1a
 * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.  
Packit 994f1a
 * 
Packit 994f1a
 * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR
Packit 994f1a
 * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND,
Packit 994f1a
 * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
Packit 994f1a
 * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF 
Packit 994f1a
 * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE 
Packit 994f1a
 * OF THIS SOFTWARE.
Packit 994f1a
 */
Packit 994f1a
Packit 994f1a
/*
Packit 994f1a
 * TIFF Library.
Packit 994f1a
 *
Packit 994f1a
 * Directory Write Support Routines.
Packit 994f1a
 */
Packit 994f1a
#include "tiffiop.h"
Packit 994f1a
Packit 994f1a
#ifdef HAVE_IEEEFP
Packit 994f1a
# define	TIFFCvtNativeToIEEEFloat(tif, n, fp)
Packit 994f1a
# define	TIFFCvtNativeToIEEEDouble(tif, n, dp)
Packit 994f1a
#else
Packit 994f1a
extern	void TIFFCvtNativeToIEEEFloat(TIFF*, uint32, float*);
Packit 994f1a
extern	void TIFFCvtNativeToIEEEDouble(TIFF*, uint32, double*);
Packit 994f1a
#endif
Packit 994f1a
Packit 994f1a
static	int TIFFWriteNormalTag(TIFF*, TIFFDirEntry*, const TIFFFieldInfo*);
Packit 994f1a
static	void TIFFSetupShortLong(TIFF*, ttag_t, TIFFDirEntry*, uint32);
Packit 994f1a
static	void TIFFSetupShort(TIFF*, ttag_t, TIFFDirEntry*, uint16);
Packit 994f1a
static	int TIFFSetupShortPair(TIFF*, ttag_t, TIFFDirEntry*);
Packit 994f1a
static	int TIFFWritePerSampleShorts(TIFF*, ttag_t, TIFFDirEntry*);
Packit 994f1a
static	int TIFFWritePerSampleAnys(TIFF*, TIFFDataType, ttag_t, TIFFDirEntry*);
Packit 994f1a
static	int TIFFWriteShortTable(TIFF*, ttag_t, TIFFDirEntry*, uint32, uint16**);
Packit 994f1a
static	int TIFFWriteShortArray(TIFF*, TIFFDirEntry*, uint16*);
Packit 994f1a
static	int TIFFWriteLongArray(TIFF *, TIFFDirEntry*, uint32*);
Packit 994f1a
static	int TIFFWriteRationalArray(TIFF *, TIFFDirEntry*, float*);
Packit 994f1a
static	int TIFFWriteFloatArray(TIFF *, TIFFDirEntry*, float*);
Packit 994f1a
static	int TIFFWriteDoubleArray(TIFF *, TIFFDirEntry*, double*);
Packit 994f1a
static	int TIFFWriteByteArray(TIFF*, TIFFDirEntry*, char*);
Packit 994f1a
static	int TIFFWriteAnyArray(TIFF*,
Packit 994f1a
	    TIFFDataType, ttag_t, TIFFDirEntry*, uint32, double*);
Packit 994f1a
static	int TIFFWriteTransferFunction(TIFF*, TIFFDirEntry*);
Packit 994f1a
static	int TIFFWriteInkNames(TIFF*, TIFFDirEntry*);
Packit 994f1a
static	int TIFFWriteData(TIFF*, TIFFDirEntry*, char*);
Packit 994f1a
static	int TIFFLinkDirectory(TIFF*);
Packit 994f1a
Packit 994f1a
#define	WriteRationalPair(type, tag1, v1, tag2, v2) {		\
Packit 994f1a
	TIFFWriteRational((tif), (type), (tag1), (dir), (v1))	\
Packit 994f1a
	TIFFWriteRational((tif), (type), (tag2), (dir)+1, (v2))	\
Packit 994f1a
	(dir)++;						\
Packit 994f1a
}
Packit 994f1a
#define	TIFFWriteRational(tif, type, tag, dir, v)		\
Packit 994f1a
	(dir)->tdir_tag = (tag);				\
Packit 994f1a
	(dir)->tdir_type = (type);				\
Packit 994f1a
	(dir)->tdir_count = 1;					\
Packit 994f1a
	if (!TIFFWriteRationalArray((tif), (dir), &(v)))	\
Packit 994f1a
		goto bad;
Packit 994f1a
Packit 994f1a
/*
Packit 994f1a
 * Write the contents of the current directory
Packit 994f1a
 * to the specified file.  This routine doesn't
Packit 994f1a
 * handle overwriting a directory with auxiliary
Packit 994f1a
 * storage that's been changed.
Packit 994f1a
 */
Packit 994f1a
static int
Packit 994f1a
_TIFFWriteDirectory(TIFF* tif, int done)
Packit 994f1a
{
Packit 994f1a
	uint16 dircount;
Packit 994f1a
	toff_t diroff;
Packit 994f1a
	ttag_t tag;
Packit 994f1a
	uint32 nfields;
Packit 994f1a
	tsize_t dirsize;
Packit 994f1a
	char* data;
Packit 994f1a
	TIFFDirEntry* dir;
Packit 994f1a
	TIFFDirectory* td;
Packit 994f1a
	unsigned long b, fields[FIELD_SETLONGS];
Packit 994f1a
	int fi, nfi;
Packit 994f1a
Packit 994f1a
	if (tif->tif_mode == O_RDONLY)
Packit 994f1a
		return (1);
Packit 994f1a
	/*
Packit 994f1a
	 * Clear write state so that subsequent images with
Packit 994f1a
	 * different characteristics get the right buffers
Packit 994f1a
	 * setup for them.
Packit 994f1a
	 */
Packit 994f1a
	if (done)
Packit 994f1a
	{
Packit 994f1a
		if (tif->tif_flags & TIFF_POSTENCODE) {
Packit 994f1a
			tif->tif_flags &= ~TIFF_POSTENCODE;
Packit 994f1a
			if (!(*tif->tif_postencode)(tif)) {
Packit 994f1a
				TIFFErrorExt(tif->tif_clientdata,
Packit 994f1a
					     tif->tif_name,
Packit 994f1a
				"Error post-encoding before directory write");
Packit 994f1a
				return (0);
Packit 994f1a
			}
Packit 994f1a
		}
Packit 994f1a
		(*tif->tif_close)(tif);		/* shutdown encoder */
Packit 994f1a
		/*
Packit 994f1a
		 * Flush any data that might have been written
Packit 994f1a
 		 * by the compression close+cleanup routines.
Packit 994f1a
		 */
Packit 994f1a
		if (tif->tif_rawcc > 0
Packit 994f1a
                    && (tif->tif_flags & TIFF_BEENWRITING) != 0
Packit 994f1a
                    && !TIFFFlushData1(tif)) {
Packit 994f1a
			TIFFErrorExt(tif->tif_clientdata, tif->tif_name,
Packit 994f1a
			    "Error flushing data before directory write");
Packit 994f1a
			return (0);
Packit 994f1a
		}
Packit 994f1a
		if ((tif->tif_flags & TIFF_MYBUFFER) && tif->tif_rawdata) {
Packit 994f1a
			_TIFFfree(tif->tif_rawdata);
Packit 994f1a
			tif->tif_rawdata = NULL;
Packit 994f1a
			tif->tif_rawcc = 0;
Packit 994f1a
			tif->tif_rawdatasize = 0;
Packit 994f1a
		}
Packit 994f1a
		tif->tif_flags &= ~(TIFF_BEENWRITING|TIFF_BUFFERSETUP);
Packit 994f1a
	}
Packit 994f1a
Packit 994f1a
	td = &tif->tif_dir;
Packit 994f1a
	/*
Packit 994f1a
	 * Size the directory so that we can calculate
Packit 994f1a
	 * offsets for the data items that aren't kept
Packit 994f1a
	 * in-place in each field.
Packit 994f1a
	 */
Packit 994f1a
	nfields = 0;
Packit 994f1a
	for (b = 0; b <= FIELD_LAST; b++)
Packit 994f1a
		if (TIFFFieldSet(tif, b) && b != FIELD_CUSTOM)
Packit 994f1a
			nfields += (b < FIELD_SUBFILETYPE ? 2 : 1);
Packit 994f1a
	nfields += td->td_customValueCount;
Packit 994f1a
	dirsize = nfields * sizeof (TIFFDirEntry);
Packit 994f1a
	data = (char*) _TIFFmalloc(dirsize);
Packit 994f1a
	if (data == NULL) {
Packit 994f1a
		TIFFErrorExt(tif->tif_clientdata, tif->tif_name,
Packit 994f1a
			     "Cannot write directory, out of space");
Packit 994f1a
		return (0);
Packit 994f1a
	}
Packit 994f1a
	/*
Packit 994f1a
	 * Directory hasn't been placed yet, put
Packit 994f1a
	 * it at the end of the file and link it
Packit 994f1a
	 * into the existing directory structure.
Packit 994f1a
	 */
Packit 994f1a
	if (tif->tif_diroff == 0 && !TIFFLinkDirectory(tif))
Packit 994f1a
		goto bad;
Packit 994f1a
	tif->tif_dataoff = (toff_t)(
Packit 994f1a
	    tif->tif_diroff + sizeof (uint16) + dirsize + sizeof (toff_t));
Packit 994f1a
	if (tif->tif_dataoff & 1)
Packit 994f1a
		tif->tif_dataoff++;
Packit 994f1a
	(void) TIFFSeekFile(tif, tif->tif_dataoff, SEEK_SET);
Packit 994f1a
	tif->tif_curdir++;
Packit 994f1a
	dir = (TIFFDirEntry*) data;
Packit 994f1a
	/*
Packit 994f1a
	 * Setup external form of directory
Packit 994f1a
	 * entries and write data items.
Packit 994f1a
	 */
Packit 994f1a
	_TIFFmemcpy(fields, td->td_fieldsset, sizeof (fields));
Packit 994f1a
	/*
Packit 994f1a
	 * Write out ExtraSamples tag only if
Packit 994f1a
	 * extra samples are present in the data.
Packit 994f1a
	 */
Packit 994f1a
	if (FieldSet(fields, FIELD_EXTRASAMPLES) && !td->td_extrasamples) {
Packit 994f1a
		ResetFieldBit(fields, FIELD_EXTRASAMPLES);
Packit 994f1a
		nfields--;
Packit 994f1a
		dirsize -= sizeof (TIFFDirEntry);
Packit 994f1a
	}								/*XXX*/
Packit 994f1a
	for (fi = 0, nfi = tif->tif_nfields; nfi > 0; nfi--, fi++) {
Packit 994f1a
		const TIFFFieldInfo* fip = tif->tif_fieldinfo[fi];
Packit 994f1a
Packit 994f1a
		/*
Packit 994f1a
		 * For custom fields, we test to see if the custom field
Packit 994f1a
		 * is set or not.  For normal fields, we just use the
Packit 994f1a
		 * FieldSet test.
Packit 994f1a
		*/
Packit 994f1a
		if( fip->field_bit == FIELD_CUSTOM )
Packit 994f1a
		{
Packit 994f1a
			int ci, is_set = FALSE;
Packit 994f1a
Packit 994f1a
			for( ci = 0; ci < td->td_customValueCount; ci++ )
Packit 994f1a
				is_set |= (td->td_customValues[ci].info == fip);
Packit 994f1a
Packit 994f1a
			if( !is_set )
Packit 994f1a
				continue;
Packit 994f1a
		}
Packit 994f1a
		else if (!FieldSet(fields, fip->field_bit))
Packit 994f1a
			continue;
Packit 994f1a
Packit 994f1a
		/*
Packit 994f1a
		 * Handle other fields.
Packit 994f1a
		 */
Packit 994f1a
		switch (fip->field_bit)
Packit 994f1a
		{
Packit 994f1a
		case FIELD_STRIPOFFSETS:
Packit 994f1a
			/*
Packit 994f1a
			 * We use one field bit for both strip and tile
Packit 994f1a
Packit 994f1a
			 * offsets, and so must be careful in selecting
Packit 994f1a
			 * the appropriate field descriptor (so that tags
Packit 994f1a
			 * are written in sorted order).
Packit 994f1a
			 */
Packit 994f1a
			tag = isTiled(tif) ?
Packit 994f1a
			    TIFFTAG_TILEOFFSETS : TIFFTAG_STRIPOFFSETS;
Packit 994f1a
			if (tag != fip->field_tag)
Packit 994f1a
				continue;
Packit 994f1a
			
Packit 994f1a
			dir->tdir_tag = (uint16) tag;
Packit 994f1a
			dir->tdir_type = (uint16) TIFF_LONG;
Packit 994f1a
			dir->tdir_count = (uint32) td->td_nstrips;
Packit 994f1a
			if (!TIFFWriteLongArray(tif, dir, td->td_stripoffset))
Packit 994f1a
				goto bad;
Packit 994f1a
			break;
Packit 994f1a
		case FIELD_STRIPBYTECOUNTS:
Packit 994f1a
			/*
Packit 994f1a
			 * We use one field bit for both strip and tile
Packit 994f1a
			 * byte counts, and so must be careful in selecting
Packit 994f1a
			 * the appropriate field descriptor (so that tags
Packit 994f1a
			 * are written in sorted order).
Packit 994f1a
			 */
Packit 994f1a
			tag = isTiled(tif) ?
Packit 994f1a
			    TIFFTAG_TILEBYTECOUNTS : TIFFTAG_STRIPBYTECOUNTS;
Packit 994f1a
			if (tag != fip->field_tag)
Packit 994f1a
				continue;
Packit 994f1a
			
Packit 994f1a
			dir->tdir_tag = (uint16) tag;
Packit 994f1a
			dir->tdir_type = (uint16) TIFF_LONG;
Packit 994f1a
			dir->tdir_count = (uint32) td->td_nstrips;
Packit 994f1a
			if (!TIFFWriteLongArray(tif, dir, td->td_stripbytecount))
Packit 994f1a
				goto bad;
Packit 994f1a
			break;
Packit 994f1a
		case FIELD_ROWSPERSTRIP:
Packit 994f1a
			TIFFSetupShortLong(tif, TIFFTAG_ROWSPERSTRIP,
Packit 994f1a
			    dir, td->td_rowsperstrip);
Packit 994f1a
			break;
Packit 994f1a
		case FIELD_COLORMAP:
Packit 994f1a
			if (!TIFFWriteShortTable(tif, TIFFTAG_COLORMAP, dir,
Packit 994f1a
			    3, td->td_colormap))
Packit 994f1a
				goto bad;
Packit 994f1a
			break;
Packit 994f1a
		case FIELD_IMAGEDIMENSIONS:
Packit 994f1a
			TIFFSetupShortLong(tif, TIFFTAG_IMAGEWIDTH,
Packit 994f1a
			    dir++, td->td_imagewidth);
Packit 994f1a
			TIFFSetupShortLong(tif, TIFFTAG_IMAGELENGTH,
Packit 994f1a
			    dir, td->td_imagelength);
Packit 994f1a
			break;
Packit 994f1a
		case FIELD_TILEDIMENSIONS:
Packit 994f1a
			TIFFSetupShortLong(tif, TIFFTAG_TILEWIDTH,
Packit 994f1a
			    dir++, td->td_tilewidth);
Packit 994f1a
			TIFFSetupShortLong(tif, TIFFTAG_TILELENGTH,
Packit 994f1a
			    dir, td->td_tilelength);
Packit 994f1a
			break;
Packit 994f1a
		case FIELD_COMPRESSION:
Packit 994f1a
			TIFFSetupShort(tif, TIFFTAG_COMPRESSION,
Packit 994f1a
			    dir, td->td_compression);
Packit 994f1a
			break;
Packit 994f1a
		case FIELD_PHOTOMETRIC:
Packit 994f1a
			TIFFSetupShort(tif, TIFFTAG_PHOTOMETRIC,
Packit 994f1a
			    dir, td->td_photometric);
Packit 994f1a
			break;
Packit 994f1a
		case FIELD_POSITION:
Packit 994f1a
			WriteRationalPair(TIFF_RATIONAL,
Packit 994f1a
			    TIFFTAG_XPOSITION, td->td_xposition,
Packit 994f1a
			    TIFFTAG_YPOSITION, td->td_yposition);
Packit 994f1a
			break;
Packit 994f1a
		case FIELD_RESOLUTION:
Packit 994f1a
			WriteRationalPair(TIFF_RATIONAL,
Packit 994f1a
			    TIFFTAG_XRESOLUTION, td->td_xresolution,
Packit 994f1a
			    TIFFTAG_YRESOLUTION, td->td_yresolution);
Packit 994f1a
			break;
Packit 994f1a
		case FIELD_BITSPERSAMPLE:
Packit 994f1a
		case FIELD_MINSAMPLEVALUE:
Packit 994f1a
		case FIELD_MAXSAMPLEVALUE:
Packit 994f1a
		case FIELD_SAMPLEFORMAT:
Packit 994f1a
			if (!TIFFWritePerSampleShorts(tif, fip->field_tag, dir))
Packit 994f1a
				goto bad;
Packit 994f1a
			break;
Packit 994f1a
		case FIELD_SMINSAMPLEVALUE:
Packit 994f1a
		case FIELD_SMAXSAMPLEVALUE:
Packit 994f1a
			if (!TIFFWritePerSampleAnys(tif,
Packit 994f1a
			    _TIFFSampleToTagType(tif), fip->field_tag, dir))
Packit 994f1a
				goto bad;
Packit 994f1a
			break;
Packit 994f1a
		case FIELD_PAGENUMBER:
Packit 994f1a
		case FIELD_HALFTONEHINTS:
Packit 994f1a
		case FIELD_YCBCRSUBSAMPLING:
Packit 994f1a
			if (!TIFFSetupShortPair(tif, fip->field_tag, dir))
Packit 994f1a
				goto bad;
Packit 994f1a
			break;
Packit 994f1a
		case FIELD_INKNAMES:
Packit 994f1a
			if (!TIFFWriteInkNames(tif, dir))
Packit 994f1a
				goto bad;
Packit 994f1a
			break;
Packit 994f1a
		case FIELD_TRANSFERFUNCTION:
Packit 994f1a
			if (!TIFFWriteTransferFunction(tif, dir))
Packit 994f1a
				goto bad;
Packit 994f1a
			break;
Packit 994f1a
		case FIELD_SUBIFD:
Packit 994f1a
			/*
Packit 994f1a
			 * XXX: Always write this field using LONG type
Packit 994f1a
			 * for backward compatibility.
Packit 994f1a
			 */
Packit 994f1a
			dir->tdir_tag = (uint16) fip->field_tag;
Packit 994f1a
			dir->tdir_type = (uint16) TIFF_LONG;
Packit 994f1a
			dir->tdir_count = (uint32) td->td_nsubifd;
Packit 994f1a
			if (!TIFFWriteLongArray(tif, dir, td->td_subifd))
Packit 994f1a
				goto bad;
Packit 994f1a
			/*
Packit 994f1a
			 * Total hack: if this directory includes a SubIFD
Packit 994f1a
			 * tag then force the next <n> directories to be
Packit 994f1a
			 * written as ``sub directories'' of this one.  This
Packit 994f1a
			 * is used to write things like thumbnails and
Packit 994f1a
			 * image masks that one wants to keep out of the
Packit 994f1a
			 * normal directory linkage access mechanism.
Packit 994f1a
			 */
Packit 994f1a
			if (dir->tdir_count > 0) {
Packit 994f1a
				tif->tif_flags |= TIFF_INSUBIFD;
Packit 994f1a
				tif->tif_nsubifd = (uint16) dir->tdir_count;
Packit 994f1a
				if (dir->tdir_count > 1)
Packit 994f1a
					tif->tif_subifdoff = dir->tdir_offset;
Packit 994f1a
				else
Packit 994f1a
					tif->tif_subifdoff = (uint32)(
Packit 994f1a
					      tif->tif_diroff
Packit 994f1a
					    + sizeof (uint16)
Packit 994f1a
					    + ((char*)&dir->tdir_offset-data));
Packit 994f1a
			}
Packit 994f1a
			break;
Packit 994f1a
		default:
Packit 994f1a
			/* XXX: Should be fixed and removed. */
Packit 994f1a
			if (fip->field_tag == TIFFTAG_DOTRANGE) {
Packit 994f1a
				if (!TIFFSetupShortPair(tif, fip->field_tag, dir))
Packit 994f1a
					goto bad;
Packit 994f1a
			}
Packit 994f1a
			else if (!TIFFWriteNormalTag(tif, dir, fip))
Packit 994f1a
				goto bad;
Packit 994f1a
			break;
Packit 994f1a
		}
Packit 994f1a
		dir++;
Packit 994f1a
                
Packit 994f1a
		if( fip->field_bit != FIELD_CUSTOM )
Packit 994f1a
			ResetFieldBit(fields, fip->field_bit);
Packit 994f1a
	}
Packit 994f1a
Packit 994f1a
	/*
Packit 994f1a
	 * Write directory.
Packit 994f1a
	 */
Packit 994f1a
	dircount = (uint16) nfields;
Packit 994f1a
	diroff = (uint32) tif->tif_nextdiroff;
Packit 994f1a
	if (tif->tif_flags & TIFF_SWAB) {
Packit 994f1a
		/*
Packit 994f1a
		 * The file's byte order is opposite to the
Packit 994f1a
		 * native machine architecture.  We overwrite
Packit 994f1a
		 * the directory information with impunity
Packit 994f1a
		 * because it'll be released below after we
Packit 994f1a
		 * write it to the file.  Note that all the
Packit 994f1a
		 * other tag construction routines assume that
Packit 994f1a
		 * we do this byte-swapping; i.e. they only
Packit 994f1a
		 * byte-swap indirect data.
Packit 994f1a
		 */
Packit 994f1a
		for (dir = (TIFFDirEntry*) data; dircount; dir++, dircount--) {
Packit 994f1a
			TIFFSwabArrayOfShort(&dir->tdir_tag, 2);
Packit 994f1a
			TIFFSwabArrayOfLong(&dir->tdir_count, 2);
Packit 994f1a
		}
Packit 994f1a
		dircount = (uint16) nfields;
Packit 994f1a
		TIFFSwabShort(&dircount);
Packit 994f1a
		TIFFSwabLong(&diroff);
Packit 994f1a
	}
Packit 994f1a
	(void) TIFFSeekFile(tif, tif->tif_diroff, SEEK_SET);
Packit 994f1a
	if (!WriteOK(tif, &dircount, sizeof (dircount))) {
Packit 994f1a
		TIFFErrorExt(tif->tif_clientdata, tif->tif_name,
Packit 994f1a
			     "Error writing directory count");
Packit 994f1a
		goto bad;
Packit 994f1a
	}
Packit 994f1a
	if (!WriteOK(tif, data, dirsize)) {
Packit 994f1a
		TIFFErrorExt(tif->tif_clientdata, tif->tif_name,
Packit 994f1a
			     "Error writing directory contents");
Packit 994f1a
		goto bad;
Packit 994f1a
	}
Packit 994f1a
	if (!WriteOK(tif, &diroff, sizeof (uint32))) {
Packit 994f1a
		TIFFErrorExt(tif->tif_clientdata, tif->tif_name,
Packit 994f1a
			     "Error writing directory link");
Packit 994f1a
		goto bad;
Packit 994f1a
	}
Packit 994f1a
	if (done) {
Packit 994f1a
		TIFFFreeDirectory(tif);
Packit 994f1a
		tif->tif_flags &= ~TIFF_DIRTYDIRECT;
Packit 994f1a
		(*tif->tif_cleanup)(tif);
Packit 994f1a
Packit 994f1a
		/*
Packit 994f1a
		* Reset directory-related state for subsequent
Packit 994f1a
		* directories.
Packit 994f1a
		*/
Packit 994f1a
		TIFFCreateDirectory(tif);
Packit 994f1a
	}
Packit 994f1a
	_TIFFfree(data);
Packit 994f1a
	return (1);
Packit 994f1a
bad:
Packit 994f1a
	_TIFFfree(data);
Packit 994f1a
	return (0);
Packit 994f1a
}
Packit 994f1a
#undef WriteRationalPair
Packit 994f1a
Packit 994f1a
int
Packit 994f1a
TIFFWriteDirectory(TIFF* tif)
Packit 994f1a
{
Packit 994f1a
	return _TIFFWriteDirectory(tif, TRUE);
Packit 994f1a
}
Packit 994f1a
Packit 994f1a
/*
Packit 994f1a
 * Similar to TIFFWriteDirectory(), writes the directory out
Packit 994f1a
 * but leaves all data structures in memory so that it can be
Packit 994f1a
 * written again.  This will make a partially written TIFF file
Packit 994f1a
 * readable before it is successfully completed/closed.
Packit 994f1a
 */ 
Packit 994f1a
int
Packit 994f1a
TIFFCheckpointDirectory(TIFF* tif)
Packit 994f1a
{
Packit 994f1a
	int rc;
Packit 994f1a
	/* Setup the strips arrays, if they haven't already been. */
Packit 994f1a
	if (tif->tif_dir.td_stripoffset == NULL)
Packit 994f1a
	    (void) TIFFSetupStrips(tif);
Packit 994f1a
	rc = _TIFFWriteDirectory(tif, FALSE);
Packit 994f1a
	(void) TIFFSetWriteOffset(tif, TIFFSeekFile(tif, 0, SEEK_END));
Packit 994f1a
	return rc;
Packit 994f1a
}
Packit 994f1a
Packit 994f1a
static int
Packit 994f1a
_TIFFWriteCustomDirectory(TIFF* tif, toff_t *pdiroff)
Packit 994f1a
{
Packit 994f1a
	uint16 dircount;
Packit 994f1a
	uint32 nfields;
Packit 994f1a
	tsize_t dirsize;
Packit 994f1a
	char* data;
Packit 994f1a
	TIFFDirEntry* dir;
Packit 994f1a
	TIFFDirectory* td;
Packit 994f1a
	unsigned long b, fields[FIELD_SETLONGS];
Packit 994f1a
	int fi, nfi;
Packit 994f1a
Packit 994f1a
	if (tif->tif_mode == O_RDONLY)
Packit 994f1a
		return (1);
Packit 994f1a
Packit 994f1a
	td = &tif->tif_dir;
Packit 994f1a
	/*
Packit 994f1a
	 * Size the directory so that we can calculate
Packit 994f1a
	 * offsets for the data items that aren't kept
Packit 994f1a
	 * in-place in each field.
Packit 994f1a
	 */
Packit 994f1a
	nfields = 0;
Packit 994f1a
	for (b = 0; b <= FIELD_LAST; b++)
Packit 994f1a
		if (TIFFFieldSet(tif, b) && b != FIELD_CUSTOM)
Packit 994f1a
			nfields += (b < FIELD_SUBFILETYPE ? 2 : 1);
Packit 994f1a
	nfields += td->td_customValueCount;
Packit 994f1a
	dirsize = nfields * sizeof (TIFFDirEntry);
Packit 994f1a
	data = (char*) _TIFFmalloc(dirsize);
Packit 994f1a
	if (data == NULL) {
Packit 994f1a
		TIFFErrorExt(tif->tif_clientdata, tif->tif_name,
Packit 994f1a
			     "Cannot write directory, out of space");
Packit 994f1a
		return (0);
Packit 994f1a
	}
Packit 994f1a
	/*
Packit 994f1a
	 * Put the directory  at the end of the file.
Packit 994f1a
	 */
Packit 994f1a
	tif->tif_diroff = (TIFFSeekFile(tif, (toff_t) 0, SEEK_END)+1) &~ 1;
Packit 994f1a
	tif->tif_dataoff = (toff_t)(
Packit 994f1a
	    tif->tif_diroff + sizeof (uint16) + dirsize + sizeof (toff_t));
Packit 994f1a
	if (tif->tif_dataoff & 1)
Packit 994f1a
		tif->tif_dataoff++;
Packit 994f1a
	(void) TIFFSeekFile(tif, tif->tif_dataoff, SEEK_SET);
Packit 994f1a
	dir = (TIFFDirEntry*) data;
Packit 994f1a
	/*
Packit 994f1a
	 * Setup external form of directory
Packit 994f1a
	 * entries and write data items.
Packit 994f1a
	 */
Packit 994f1a
	_TIFFmemcpy(fields, td->td_fieldsset, sizeof (fields));
Packit 994f1a
Packit 994f1a
	for (fi = 0, nfi = tif->tif_nfields; nfi > 0; nfi--, fi++) {
Packit 994f1a
		const TIFFFieldInfo* fip = tif->tif_fieldinfo[fi];
Packit 994f1a
Packit 994f1a
		/*
Packit 994f1a
		 * For custom fields, we test to see if the custom field
Packit 994f1a
		 * is set or not.  For normal fields, we just use the
Packit 994f1a
		 * FieldSet test.
Packit 994f1a
		*/
Packit 994f1a
		if( fip->field_bit == FIELD_CUSTOM )
Packit 994f1a
		{
Packit 994f1a
			int ci, is_set = FALSE;
Packit 994f1a
Packit 994f1a
			for( ci = 0; ci < td->td_customValueCount; ci++ )
Packit 994f1a
				is_set |= (td->td_customValues[ci].info == fip);
Packit 994f1a
Packit 994f1a
			if( !is_set )
Packit 994f1a
				continue;
Packit 994f1a
		}
Packit 994f1a
		else if (!FieldSet(fields, fip->field_bit))
Packit 994f1a
			continue;
Packit 994f1a
                
Packit 994f1a
		if( fip->field_bit != FIELD_CUSTOM )
Packit 994f1a
			ResetFieldBit(fields, fip->field_bit);
Packit 994f1a
	}
Packit 994f1a
Packit 994f1a
	/*
Packit 994f1a
	 * Write directory.
Packit 994f1a
	 */
Packit 994f1a
	dircount = (uint16) nfields;
Packit 994f1a
	*pdiroff = (uint32) tif->tif_nextdiroff;
Packit 994f1a
	if (tif->tif_flags & TIFF_SWAB) {
Packit 994f1a
		/*
Packit 994f1a
		 * The file's byte order is opposite to the
Packit 994f1a
		 * native machine architecture.  We overwrite
Packit 994f1a
		 * the directory information with impunity
Packit 994f1a
		 * because it'll be released below after we
Packit 994f1a
		 * write it to the file.  Note that all the
Packit 994f1a
		 * other tag construction routines assume that
Packit 994f1a
		 * we do this byte-swapping; i.e. they only
Packit 994f1a
		 * byte-swap indirect data.
Packit 994f1a
		 */
Packit 994f1a
		for (dir = (TIFFDirEntry*) data; dircount; dir++, dircount--) {
Packit 994f1a
			TIFFSwabArrayOfShort(&dir->tdir_tag, 2);
Packit 994f1a
			TIFFSwabArrayOfLong(&dir->tdir_count, 2);
Packit 994f1a
		}
Packit 994f1a
		dircount = (uint16) nfields;
Packit 994f1a
		TIFFSwabShort(&dircount);
Packit 994f1a
		TIFFSwabLong(pdiroff);
Packit 994f1a
	}
Packit 994f1a
	(void) TIFFSeekFile(tif, tif->tif_diroff, SEEK_SET);
Packit 994f1a
	if (!WriteOK(tif, &dircount, sizeof (dircount))) {
Packit 994f1a
		TIFFErrorExt(tif->tif_clientdata, tif->tif_name,
Packit 994f1a
			     "Error writing directory count");
Packit 994f1a
		goto bad;
Packit 994f1a
	}
Packit 994f1a
	if (!WriteOK(tif, data, dirsize)) {
Packit 994f1a
		TIFFErrorExt(tif->tif_clientdata, tif->tif_name,
Packit 994f1a
			     "Error writing directory contents");
Packit 994f1a
		goto bad;
Packit 994f1a
	}
Packit 994f1a
	if (!WriteOK(tif, pdiroff, sizeof (uint32))) {
Packit 994f1a
		TIFFErrorExt(tif->tif_clientdata, tif->tif_name,
Packit 994f1a
			     "Error writing directory link");
Packit 994f1a
		goto bad;
Packit 994f1a
	}
Packit 994f1a
	_TIFFfree(data);
Packit 994f1a
	return (1);
Packit 994f1a
bad:
Packit 994f1a
	_TIFFfree(data);
Packit 994f1a
	return (0);
Packit 994f1a
}
Packit 994f1a
Packit 994f1a
int
Packit 994f1a
TIFFWriteCustomDirectory(TIFF* tif, toff_t *pdiroff)
Packit 994f1a
{
Packit 994f1a
	return _TIFFWriteCustomDirectory(tif, pdiroff);
Packit 994f1a
}
Packit 994f1a
Packit 994f1a
/*
Packit 994f1a
 * Process tags that are not special cased.
Packit 994f1a
 */
Packit 994f1a
static int
Packit 994f1a
TIFFWriteNormalTag(TIFF* tif, TIFFDirEntry* dir, const TIFFFieldInfo* fip)
Packit 994f1a
{
Packit 994f1a
	uint16 wc = (uint16) fip->field_writecount;
Packit 994f1a
	uint32 wc2;
Packit 994f1a
Packit 994f1a
	dir->tdir_tag = (uint16) fip->field_tag;
Packit 994f1a
	dir->tdir_type = (uint16) fip->field_type;
Packit 994f1a
	dir->tdir_count = wc;
Packit 994f1a
	
Packit 994f1a
	switch (fip->field_type) {
Packit 994f1a
	case TIFF_SHORT:
Packit 994f1a
	case TIFF_SSHORT:
Packit 994f1a
		if (fip->field_passcount) {
Packit 994f1a
			uint16* wp;
Packit 994f1a
			if (wc == (uint16) TIFF_VARIABLE2) {
Packit 994f1a
				TIFFGetField(tif, fip->field_tag, &wc2, &wp);
Packit 994f1a
				dir->tdir_count = wc2;
Packit 994f1a
			} else {	/* Assume TIFF_VARIABLE */
Packit 994f1a
				TIFFGetField(tif, fip->field_tag, &wc, &wp);
Packit 994f1a
				dir->tdir_count = wc;
Packit 994f1a
			}
Packit 994f1a
			if (!TIFFWriteShortArray(tif, dir, wp))
Packit 994f1a
				return 0;
Packit 994f1a
		} else {
Packit 994f1a
			if (wc == 1) {
Packit 994f1a
				uint16 sv;
Packit 994f1a
				TIFFGetField(tif, fip->field_tag, &sv;;
Packit 994f1a
				dir->tdir_offset =
Packit 994f1a
					TIFFInsertData(tif, dir->tdir_type, sv);
Packit 994f1a
			} else {
Packit 994f1a
				uint16* wp;
Packit 994f1a
				TIFFGetField(tif, fip->field_tag, &wp);
Packit 994f1a
				if (!TIFFWriteShortArray(tif, dir, wp))
Packit 994f1a
					return 0;
Packit 994f1a
			}
Packit 994f1a
		}
Packit 994f1a
		break;
Packit 994f1a
	case TIFF_LONG:
Packit 994f1a
	case TIFF_SLONG:
Packit 994f1a
	case TIFF_IFD:
Packit 994f1a
		if (fip->field_passcount) {
Packit 994f1a
			uint32* lp;
Packit 994f1a
			if (wc == (uint16) TIFF_VARIABLE2) {
Packit 994f1a
				TIFFGetField(tif, fip->field_tag, &wc2, &lp);
Packit 994f1a
				dir->tdir_count = wc2;
Packit 994f1a
			} else {	/* Assume TIFF_VARIABLE */
Packit 994f1a
				TIFFGetField(tif, fip->field_tag, &wc, &lp);
Packit 994f1a
				dir->tdir_count = wc;
Packit 994f1a
			}
Packit 994f1a
			if (!TIFFWriteLongArray(tif, dir, lp))
Packit 994f1a
				return 0;
Packit 994f1a
		} else {
Packit 994f1a
			if (wc == 1) {
Packit 994f1a
				/* XXX handle LONG->SHORT conversion */
Packit 994f1a
				TIFFGetField(tif, fip->field_tag,
Packit 994f1a
					     &dir->tdir_offset);
Packit 994f1a
			} else {
Packit 994f1a
				uint32* lp;
Packit 994f1a
				TIFFGetField(tif, fip->field_tag, &lp);
Packit 994f1a
				if (!TIFFWriteLongArray(tif, dir, lp))
Packit 994f1a
					return 0;
Packit 994f1a
			}
Packit 994f1a
		}
Packit 994f1a
		break;
Packit 994f1a
	case TIFF_RATIONAL:
Packit 994f1a
	case TIFF_SRATIONAL:
Packit 994f1a
		if (fip->field_passcount) {
Packit 994f1a
			float* fp;
Packit 994f1a
			if (wc == (uint16) TIFF_VARIABLE2) {
Packit 994f1a
				TIFFGetField(tif, fip->field_tag, &wc2, &fp);
Packit 994f1a
				dir->tdir_count = wc2;
Packit 994f1a
			} else {	/* Assume TIFF_VARIABLE */
Packit 994f1a
				TIFFGetField(tif, fip->field_tag, &wc, &fp);
Packit 994f1a
				dir->tdir_count = wc;
Packit 994f1a
			}
Packit 994f1a
			if (!TIFFWriteRationalArray(tif, dir, fp))
Packit 994f1a
				return 0;
Packit 994f1a
		} else {
Packit 994f1a
			if (wc == 1) {
Packit 994f1a
				float fv;
Packit 994f1a
				TIFFGetField(tif, fip->field_tag, &fv;;
Packit 994f1a
				if (!TIFFWriteRationalArray(tif, dir, &fv))
Packit 994f1a
					return 0;
Packit 994f1a
			} else {
Packit 994f1a
				float* fp;
Packit 994f1a
				TIFFGetField(tif, fip->field_tag, &fp);
Packit 994f1a
				if (!TIFFWriteRationalArray(tif, dir, fp))
Packit 994f1a
					return 0;
Packit 994f1a
			}
Packit 994f1a
		}
Packit 994f1a
		break;
Packit 994f1a
	case TIFF_FLOAT:
Packit 994f1a
		if (fip->field_passcount) {
Packit 994f1a
			float* fp;
Packit 994f1a
			if (wc == (uint16) TIFF_VARIABLE2) {
Packit 994f1a
				TIFFGetField(tif, fip->field_tag, &wc2, &fp);
Packit 994f1a
				dir->tdir_count = wc2;
Packit 994f1a
			} else {	/* Assume TIFF_VARIABLE */
Packit 994f1a
				TIFFGetField(tif, fip->field_tag, &wc, &fp);
Packit 994f1a
				dir->tdir_count = wc;
Packit 994f1a
			}
Packit 994f1a
			if (!TIFFWriteFloatArray(tif, dir, fp))
Packit 994f1a
				return 0;
Packit 994f1a
		} else {
Packit 994f1a
			if (wc == 1) {
Packit 994f1a
				float fv;
Packit 994f1a
				TIFFGetField(tif, fip->field_tag, &fv;;
Packit 994f1a
				if (!TIFFWriteFloatArray(tif, dir, &fv))
Packit 994f1a
					return 0;
Packit 994f1a
			} else {
Packit 994f1a
				float* fp;
Packit 994f1a
				TIFFGetField(tif, fip->field_tag, &fp);
Packit 994f1a
				if (!TIFFWriteFloatArray(tif, dir, fp))
Packit 994f1a
					return 0;
Packit 994f1a
			}
Packit 994f1a
		}
Packit 994f1a
		break;
Packit 994f1a
	case TIFF_DOUBLE:
Packit 994f1a
		if (fip->field_passcount) {
Packit 994f1a
			double* dp;
Packit 994f1a
			if (wc == (uint16) TIFF_VARIABLE2) {
Packit 994f1a
				TIFFGetField(tif, fip->field_tag, &wc2, &dp;;
Packit 994f1a
				dir->tdir_count = wc2;
Packit 994f1a
			} else {	/* Assume TIFF_VARIABLE */
Packit 994f1a
				TIFFGetField(tif, fip->field_tag, &wc, &dp;;
Packit 994f1a
				dir->tdir_count = wc;
Packit 994f1a
			}
Packit 994f1a
			if (!TIFFWriteDoubleArray(tif, dir, dp))
Packit 994f1a
				return 0;
Packit 994f1a
		} else {
Packit 994f1a
			if (wc == 1) {
Packit 994f1a
				double dv;
Packit 994f1a
				TIFFGetField(tif, fip->field_tag, &dv;;
Packit 994f1a
				if (!TIFFWriteDoubleArray(tif, dir, &dv))
Packit 994f1a
					return 0;
Packit 994f1a
			} else {
Packit 994f1a
				double* dp;
Packit 994f1a
				TIFFGetField(tif, fip->field_tag, &dp;;
Packit 994f1a
				if (!TIFFWriteDoubleArray(tif, dir, dp))
Packit 994f1a
					return 0;
Packit 994f1a
			}
Packit 994f1a
		}
Packit 994f1a
		break;
Packit 994f1a
	case TIFF_ASCII:
Packit 994f1a
		{ 
Packit 994f1a
                    char* cp;
Packit 994f1a
                    if (fip->field_passcount)
Packit 994f1a
                    {
Packit 994f1a
                        if( wc == (uint16) TIFF_VARIABLE2 )
Packit 994f1a
                            TIFFGetField(tif, fip->field_tag, &wc2, &cp;;
Packit 994f1a
                        else
Packit 994f1a
                            TIFFGetField(tif, fip->field_tag, &wc, &cp;;
Packit 994f1a
                    }
Packit 994f1a
                    else
Packit 994f1a
                        TIFFGetField(tif, fip->field_tag, &cp;;
Packit 994f1a
Packit 994f1a
                    dir->tdir_count = (uint32) (strlen(cp) + 1);
Packit 994f1a
                    if (!TIFFWriteByteArray(tif, dir, cp))
Packit 994f1a
                        return (0);
Packit 994f1a
		}
Packit 994f1a
		break;
Packit 994f1a
Packit 994f1a
        case TIFF_BYTE:
Packit 994f1a
        case TIFF_SBYTE:          
Packit 994f1a
		if (fip->field_passcount) {
Packit 994f1a
			char* cp;
Packit 994f1a
			if (wc == (uint16) TIFF_VARIABLE2) {
Packit 994f1a
				TIFFGetField(tif, fip->field_tag, &wc2, &cp;;
Packit 994f1a
				dir->tdir_count = wc2;
Packit 994f1a
			} else {	/* Assume TIFF_VARIABLE */
Packit 994f1a
				TIFFGetField(tif, fip->field_tag, &wc, &cp;;
Packit 994f1a
				dir->tdir_count = wc;
Packit 994f1a
			}
Packit 994f1a
			if (!TIFFWriteByteArray(tif, dir, cp))
Packit 994f1a
				return 0;
Packit 994f1a
		} else {
Packit 994f1a
			if (wc == 1) {
Packit 994f1a
				char cv;
Packit 994f1a
				TIFFGetField(tif, fip->field_tag, &cv;;
Packit 994f1a
				if (!TIFFWriteByteArray(tif, dir, &cv))
Packit 994f1a
					return 0;
Packit 994f1a
			} else {
Packit 994f1a
				char* cp;
Packit 994f1a
				TIFFGetField(tif, fip->field_tag, &cp;;
Packit 994f1a
				if (!TIFFWriteByteArray(tif, dir, cp))
Packit 994f1a
					return 0;
Packit 994f1a
			}
Packit 994f1a
		}
Packit 994f1a
                break;
Packit 994f1a
Packit 994f1a
	case TIFF_UNDEFINED:
Packit 994f1a
		{ char* cp;
Packit 994f1a
		  if (wc == (unsigned short) TIFF_VARIABLE) {
Packit 994f1a
			TIFFGetField(tif, fip->field_tag, &wc, &cp;;
Packit 994f1a
			dir->tdir_count = wc;
Packit 994f1a
		  } else if (wc == (unsigned short) TIFF_VARIABLE2) {
Packit 994f1a
			TIFFGetField(tif, fip->field_tag, &wc2, &cp;;
Packit 994f1a
			dir->tdir_count = wc2;
Packit 994f1a
		  } else 
Packit 994f1a
			TIFFGetField(tif, fip->field_tag, &cp;;
Packit 994f1a
		  if (!TIFFWriteByteArray(tif, dir, cp))
Packit 994f1a
			return (0);
Packit 994f1a
		}
Packit 994f1a
		break;
Packit 994f1a
Packit 994f1a
        case TIFF_NOTYPE:
Packit 994f1a
                break;
Packit 994f1a
	}
Packit 994f1a
	return (1);
Packit 994f1a
}
Packit 994f1a
Packit 994f1a
/*
Packit 994f1a
 * Setup a directory entry with either a SHORT
Packit 994f1a
 * or LONG type according to the value.
Packit 994f1a
 */
Packit 994f1a
static void
Packit 994f1a
TIFFSetupShortLong(TIFF* tif, ttag_t tag, TIFFDirEntry* dir, uint32 v)
Packit 994f1a
{
Packit 994f1a
	dir->tdir_tag = (uint16) tag;
Packit 994f1a
	dir->tdir_count = 1;
Packit 994f1a
	if (v > 0xffffL) {
Packit 994f1a
		dir->tdir_type = (short) TIFF_LONG;
Packit 994f1a
		dir->tdir_offset = v;
Packit 994f1a
	} else {
Packit 994f1a
		dir->tdir_type = (short) TIFF_SHORT;
Packit 994f1a
		dir->tdir_offset = TIFFInsertData(tif, (int) TIFF_SHORT, v);
Packit 994f1a
	}
Packit 994f1a
}
Packit 994f1a
Packit 994f1a
/*
Packit 994f1a
 * Setup a SHORT directory entry
Packit 994f1a
 */
Packit 994f1a
static void
Packit 994f1a
TIFFSetupShort(TIFF* tif, ttag_t tag, TIFFDirEntry* dir, uint16 v)
Packit 994f1a
{
Packit 994f1a
	dir->tdir_tag = (uint16) tag;
Packit 994f1a
	dir->tdir_count = 1;
Packit 994f1a
	dir->tdir_type = (short) TIFF_SHORT;
Packit 994f1a
	dir->tdir_offset = TIFFInsertData(tif, (int) TIFF_SHORT, v);
Packit 994f1a
}
Packit 994f1a
#undef MakeShortDirent
Packit 994f1a
Packit 994f1a
#define	NITEMS(x)	(sizeof (x) / sizeof (x[0]))
Packit 994f1a
/*
Packit 994f1a
 * Setup a directory entry that references a
Packit 994f1a
 * samples/pixel array of SHORT values and
Packit 994f1a
 * (potentially) write the associated indirect
Packit 994f1a
 * values.
Packit 994f1a
 */
Packit 994f1a
static int
Packit 994f1a
TIFFWritePerSampleShorts(TIFF* tif, ttag_t tag, TIFFDirEntry* dir)
Packit 994f1a
{
Packit 994f1a
	uint16 buf[10], v;
Packit 994f1a
	uint16* w = buf;
Packit 994f1a
	uint16 i, samples = tif->tif_dir.td_samplesperpixel;
Packit 994f1a
	int status;
Packit 994f1a
Packit 994f1a
	if (samples > NITEMS(buf)) {
Packit 994f1a
		w = (uint16*) _TIFFmalloc(samples * sizeof (uint16));
Packit 994f1a
		if (w == NULL) {
Packit 994f1a
			TIFFErrorExt(tif->tif_clientdata, tif->tif_name,
Packit 994f1a
			    "No space to write per-sample shorts");
Packit 994f1a
			return (0);
Packit 994f1a
		}
Packit 994f1a
	}
Packit 994f1a
	TIFFGetField(tif, tag, &v);
Packit 994f1a
	for (i = 0; i < samples; i++)
Packit 994f1a
		w[i] = v;
Packit 994f1a
	
Packit 994f1a
	dir->tdir_tag = (uint16) tag;
Packit 994f1a
	dir->tdir_type = (uint16) TIFF_SHORT;
Packit 994f1a
	dir->tdir_count = samples;
Packit 994f1a
	status = TIFFWriteShortArray(tif, dir, w);
Packit 994f1a
	if (w != buf)
Packit 994f1a
		_TIFFfree((char*) w);
Packit 994f1a
	return (status);
Packit 994f1a
}
Packit 994f1a
Packit 994f1a
/*
Packit 994f1a
 * Setup a directory entry that references a samples/pixel array of ``type''
Packit 994f1a
 * values and (potentially) write the associated indirect values.  The source
Packit 994f1a
 * data from TIFFGetField() for the specified tag must be returned as double.
Packit 994f1a
 */
Packit 994f1a
static int
Packit 994f1a
TIFFWritePerSampleAnys(TIFF* tif,
Packit 994f1a
    TIFFDataType type, ttag_t tag, TIFFDirEntry* dir)
Packit 994f1a
{
Packit 994f1a
	double buf[10], v;
Packit 994f1a
	double* w = buf;
Packit 994f1a
	uint16 i, samples = tif->tif_dir.td_samplesperpixel;
Packit 994f1a
	int status;
Packit 994f1a
Packit 994f1a
	if (samples > NITEMS(buf)) {
Packit 994f1a
		w = (double*) _TIFFmalloc(samples * sizeof (double));
Packit 994f1a
		if (w == NULL) {
Packit 994f1a
			TIFFErrorExt(tif->tif_clientdata, tif->tif_name,
Packit 994f1a
			    "No space to write per-sample values");
Packit 994f1a
			return (0);
Packit 994f1a
		}
Packit 994f1a
	}
Packit 994f1a
	TIFFGetField(tif, tag, &v);
Packit 994f1a
	for (i = 0; i < samples; i++)
Packit 994f1a
		w[i] = v;
Packit 994f1a
	status = TIFFWriteAnyArray(tif, type, tag, dir, samples, w);
Packit 994f1a
	if (w != buf)
Packit 994f1a
		_TIFFfree(w);
Packit 994f1a
	return (status);
Packit 994f1a
}
Packit 994f1a
#undef NITEMS
Packit 994f1a
Packit 994f1a
/*
Packit 994f1a
 * Setup a pair of shorts that are returned by
Packit 994f1a
 * value, rather than as a reference to an array.
Packit 994f1a
 */
Packit 994f1a
static int
Packit 994f1a
TIFFSetupShortPair(TIFF* tif, ttag_t tag, TIFFDirEntry* dir)
Packit 994f1a
{
Packit 994f1a
	uint16 v[2];
Packit 994f1a
Packit 994f1a
	TIFFGetField(tif, tag, &v[0], &v[1]);
Packit 994f1a
Packit 994f1a
	dir->tdir_tag = (uint16) tag;
Packit 994f1a
	dir->tdir_type = (uint16) TIFF_SHORT;
Packit 994f1a
	dir->tdir_count = 2;
Packit 994f1a
	return (TIFFWriteShortArray(tif, dir, v));
Packit 994f1a
}
Packit 994f1a
Packit 994f1a
/*
Packit 994f1a
 * Setup a directory entry for an NxM table of shorts,
Packit 994f1a
 * where M is known to be 2**bitspersample, and write
Packit 994f1a
 * the associated indirect data.
Packit 994f1a
 */
Packit 994f1a
static int
Packit 994f1a
TIFFWriteShortTable(TIFF* tif,
Packit 994f1a
    ttag_t tag, TIFFDirEntry* dir, uint32 n, uint16** table)
Packit 994f1a
{
Packit 994f1a
	uint32 i, off;
Packit 994f1a
Packit 994f1a
	dir->tdir_tag = (uint16) tag;
Packit 994f1a
	dir->tdir_type = (short) TIFF_SHORT;
Packit 994f1a
	/* XXX -- yech, fool TIFFWriteData */
Packit 994f1a
	dir->tdir_count = (uint32) (1L<<tif->tif_dir.td_bitspersample);
Packit 994f1a
	off = tif->tif_dataoff;
Packit 994f1a
	for (i = 0; i < n; i++)
Packit 994f1a
		if (!TIFFWriteData(tif, dir, (char *)table[i]))
Packit 994f1a
			return (0);
Packit 994f1a
	dir->tdir_count *= n;
Packit 994f1a
	dir->tdir_offset = off;
Packit 994f1a
	return (1);
Packit 994f1a
}
Packit 994f1a
Packit 994f1a
/*
Packit 994f1a
 * Write/copy data associated with an ASCII or opaque tag value.
Packit 994f1a
 */
Packit 994f1a
static int
Packit 994f1a
TIFFWriteByteArray(TIFF* tif, TIFFDirEntry* dir, char* cp)
Packit 994f1a
{
Packit 994f1a
	if (dir->tdir_count <= 4) {
Packit 994f1a
		if (tif->tif_header.tiff_magic == TIFF_BIGENDIAN) {
Packit 994f1a
			dir->tdir_offset = (uint32)cp[0] << 24;
Packit 994f1a
			if (dir->tdir_count >= 2)
Packit 994f1a
				dir->tdir_offset |= (uint32)cp[1] << 16;
Packit 994f1a
			if (dir->tdir_count >= 3)
Packit 994f1a
				dir->tdir_offset |= (uint32)cp[2] << 8;
Packit 994f1a
			if (dir->tdir_count == 4)
Packit 994f1a
				dir->tdir_offset |= cp[3];
Packit 994f1a
		} else {
Packit 994f1a
			dir->tdir_offset = cp[0];
Packit 994f1a
			if (dir->tdir_count >= 2)
Packit 994f1a
				dir->tdir_offset |= (uint32) cp[1] << 8;
Packit 994f1a
			if (dir->tdir_count >= 3)
Packit 994f1a
				dir->tdir_offset |= (uint32) cp[2] << 16;
Packit 994f1a
			if (dir->tdir_count == 4)
Packit 994f1a
				dir->tdir_offset |= (uint32) cp[3] << 24;
Packit 994f1a
		}
Packit 994f1a
		return 1;
Packit 994f1a
	} else
Packit 994f1a
		return TIFFWriteData(tif, dir, cp);
Packit 994f1a
}
Packit 994f1a
Packit 994f1a
/*
Packit 994f1a
 * Setup a directory entry of an array of SHORT
Packit 994f1a
 * or SSHORT and write the associated indirect values.
Packit 994f1a
 */
Packit 994f1a
static int
Packit 994f1a
TIFFWriteShortArray(TIFF* tif, TIFFDirEntry* dir, uint16* v)
Packit 994f1a
{
Packit 994f1a
	if (dir->tdir_count <= 2) {
Packit 994f1a
		if (tif->tif_header.tiff_magic == TIFF_BIGENDIAN) {
Packit 994f1a
			dir->tdir_offset = (uint32) v[0] << 16;
Packit 994f1a
			if (dir->tdir_count == 2)
Packit 994f1a
				dir->tdir_offset |= v[1] & 0xffff;
Packit 994f1a
		} else {
Packit 994f1a
			dir->tdir_offset = v[0] & 0xffff;
Packit 994f1a
			if (dir->tdir_count == 2)
Packit 994f1a
				dir->tdir_offset |= (uint32) v[1] << 16;
Packit 994f1a
		}
Packit 994f1a
		return (1);
Packit 994f1a
	} else
Packit 994f1a
		return (TIFFWriteData(tif, dir, (char*) v));
Packit 994f1a
}
Packit 994f1a
Packit 994f1a
/*
Packit 994f1a
 * Setup a directory entry of an array of LONG
Packit 994f1a
 * or SLONG and write the associated indirect values.
Packit 994f1a
 */
Packit 994f1a
static int
Packit 994f1a
TIFFWriteLongArray(TIFF* tif, TIFFDirEntry* dir, uint32* v)
Packit 994f1a
{
Packit 994f1a
	if (dir->tdir_count == 1) {
Packit 994f1a
		dir->tdir_offset = v[0];
Packit 994f1a
		return (1);
Packit 994f1a
	} else
Packit 994f1a
		return (TIFFWriteData(tif, dir, (char*) v));
Packit 994f1a
}
Packit 994f1a
Packit 994f1a
/*
Packit 994f1a
 * Setup a directory entry of an array of RATIONAL
Packit 994f1a
 * or SRATIONAL and write the associated indirect values.
Packit 994f1a
 */
Packit 994f1a
static int
Packit 994f1a
TIFFWriteRationalArray(TIFF* tif, TIFFDirEntry* dir, float* v)
Packit 994f1a
{
Packit 994f1a
	uint32 i;
Packit 994f1a
	uint32* t;
Packit 994f1a
	int status;
Packit 994f1a
Packit 994f1a
	t = (uint32*) _TIFFmalloc(2 * dir->tdir_count * sizeof (uint32));
Packit 994f1a
	if (t == NULL) {
Packit 994f1a
		TIFFErrorExt(tif->tif_clientdata, tif->tif_name,
Packit 994f1a
		    "No space to write RATIONAL array");
Packit 994f1a
		return (0);
Packit 994f1a
	}
Packit 994f1a
	for (i = 0; i < dir->tdir_count; i++) {
Packit 994f1a
		float fv = v[i];
Packit 994f1a
		int sign = 1;
Packit 994f1a
		uint32 den;
Packit 994f1a
Packit 994f1a
		if (fv < 0) {
Packit 994f1a
			if (dir->tdir_type == TIFF_RATIONAL) {
Packit 994f1a
				TIFFWarningExt(tif->tif_clientdata,
Packit 994f1a
					       tif->tif_name,
Packit 994f1a
	"\"%s\": Information lost writing value (%g) as (unsigned) RATIONAL",
Packit 994f1a
				_TIFFFieldWithTag(tif,dir->tdir_tag)->field_name,
Packit 994f1a
						fv);
Packit 994f1a
				fv = 0;
Packit 994f1a
			} else
Packit 994f1a
				fv = -fv, sign = -1;
Packit 994f1a
		}
Packit 994f1a
		den = 1L;
Packit 994f1a
		if (fv > 0) {
Packit 994f1a
			while (fv < 1L<<(31-3) && den < 1L<<(31-3))
Packit 994f1a
				fv *= 1<<3, den *= 1L<<3;
Packit 994f1a
		}
Packit 994f1a
		t[2*i+0] = (uint32) (sign * (fv + 0.5));
Packit 994f1a
		t[2*i+1] = den;
Packit 994f1a
	}
Packit 994f1a
	status = TIFFWriteData(tif, dir, (char *)t);
Packit 994f1a
	_TIFFfree((char*) t);
Packit 994f1a
	return (status);
Packit 994f1a
}
Packit 994f1a
Packit 994f1a
static int
Packit 994f1a
TIFFWriteFloatArray(TIFF* tif, TIFFDirEntry* dir, float* v)
Packit 994f1a
{
Packit 994f1a
	TIFFCvtNativeToIEEEFloat(tif, dir->tdir_count, v);
Packit 994f1a
	if (dir->tdir_count == 1) {
Packit 994f1a
		dir->tdir_offset = *(uint32*) &v[0];
Packit 994f1a
		return (1);
Packit 994f1a
	} else
Packit 994f1a
		return (TIFFWriteData(tif, dir, (char*) v));
Packit 994f1a
}
Packit 994f1a
Packit 994f1a
static int
Packit 994f1a
TIFFWriteDoubleArray(TIFF* tif, TIFFDirEntry* dir, double* v)
Packit 994f1a
{
Packit 994f1a
	TIFFCvtNativeToIEEEDouble(tif, dir->tdir_count, v);
Packit 994f1a
	return (TIFFWriteData(tif, dir, (char*) v));
Packit 994f1a
}
Packit 994f1a
Packit 994f1a
/*
Packit 994f1a
 * Write an array of ``type'' values for a specified tag (i.e. this is a tag
Packit 994f1a
 * which is allowed to have different types, e.g. SMaxSampleType).
Packit 994f1a
 * Internally the data values are represented as double since a double can
Packit 994f1a
 * hold any of the TIFF tag types (yes, this should really be an abstract
Packit 994f1a
 * type tany_t for portability).  The data is converted into the specified
Packit 994f1a
 * type in a temporary buffer and then handed off to the appropriate array
Packit 994f1a
 * writer.
Packit 994f1a
 */
Packit 994f1a
static int
Packit 994f1a
TIFFWriteAnyArray(TIFF* tif,
Packit 994f1a
    TIFFDataType type, ttag_t tag, TIFFDirEntry* dir, uint32 n, double* v)
Packit 994f1a
{
Packit 994f1a
	char buf[10 * sizeof(double)];
Packit 994f1a
	char* w = buf;
Packit 994f1a
	int i, status = 0;
Packit 994f1a
Packit 994f1a
	if (n * TIFFDataWidth(type) > sizeof buf) {
Packit 994f1a
		w = (char*) _TIFFmalloc(n * TIFFDataWidth(type));
Packit 994f1a
		if (w == NULL) {
Packit 994f1a
			TIFFErrorExt(tif->tif_clientdata, tif->tif_name,
Packit 994f1a
				     "No space to write array");
Packit 994f1a
			return (0);
Packit 994f1a
		}
Packit 994f1a
	}
Packit 994f1a
Packit 994f1a
	dir->tdir_tag = (uint16) tag;
Packit 994f1a
	dir->tdir_type = (uint16) type;
Packit 994f1a
	dir->tdir_count = n;
Packit 994f1a
Packit 994f1a
	switch (type) {
Packit 994f1a
	case TIFF_BYTE:
Packit 994f1a
		{ 
Packit 994f1a
			uint8* bp = (uint8*) w;
Packit 994f1a
			for (i = 0; i < (int) n; i++)
Packit 994f1a
				bp[i] = (uint8) v[i];
Packit 994f1a
			if (!TIFFWriteByteArray(tif, dir, (char*) bp))
Packit 994f1a
				goto out;
Packit 994f1a
		}
Packit 994f1a
		break;
Packit 994f1a
	case TIFF_SBYTE:
Packit 994f1a
		{ 
Packit 994f1a
			int8* bp = (int8*) w;
Packit 994f1a
			for (i = 0; i < (int) n; i++)
Packit 994f1a
				bp[i] = (int8) v[i];
Packit 994f1a
			if (!TIFFWriteByteArray(tif, dir, (char*) bp))
Packit 994f1a
				goto out;
Packit 994f1a
		}
Packit 994f1a
		break;
Packit 994f1a
	case TIFF_SHORT:
Packit 994f1a
		{
Packit 994f1a
			uint16* bp = (uint16*) w;
Packit 994f1a
			for (i = 0; i < (int) n; i++)
Packit 994f1a
				bp[i] = (uint16) v[i];
Packit 994f1a
			if (!TIFFWriteShortArray(tif, dir, (uint16*)bp))
Packit 994f1a
				goto out;
Packit 994f1a
		}
Packit 994f1a
		break;
Packit 994f1a
	case TIFF_SSHORT:
Packit 994f1a
		{ 
Packit 994f1a
			int16* bp = (int16*) w;
Packit 994f1a
			for (i = 0; i < (int) n; i++)
Packit 994f1a
				bp[i] = (int16) v[i];
Packit 994f1a
			if (!TIFFWriteShortArray(tif, dir, (uint16*)bp))
Packit 994f1a
				goto out;
Packit 994f1a
		}
Packit 994f1a
		break;
Packit 994f1a
	case TIFF_LONG:
Packit 994f1a
		{
Packit 994f1a
			uint32* bp = (uint32*) w;
Packit 994f1a
			for (i = 0; i < (int) n; i++)
Packit 994f1a
				bp[i] = (uint32) v[i];
Packit 994f1a
			if (!TIFFWriteLongArray(tif, dir, bp))
Packit 994f1a
				goto out;
Packit 994f1a
		}
Packit 994f1a
		break;
Packit 994f1a
	case TIFF_SLONG:
Packit 994f1a
		{
Packit 994f1a
			int32* bp = (int32*) w;
Packit 994f1a
			for (i = 0; i < (int) n; i++)
Packit 994f1a
				bp[i] = (int32) v[i];
Packit 994f1a
			if (!TIFFWriteLongArray(tif, dir, (uint32*) bp))
Packit 994f1a
				goto out;
Packit 994f1a
		}
Packit 994f1a
		break;
Packit 994f1a
	case TIFF_FLOAT:
Packit 994f1a
		{ 
Packit 994f1a
			float* bp = (float*) w;
Packit 994f1a
			for (i = 0; i < (int) n; i++)
Packit 994f1a
				bp[i] = (float) v[i];
Packit 994f1a
			if (!TIFFWriteFloatArray(tif, dir, bp))
Packit 994f1a
				goto out;
Packit 994f1a
		}
Packit 994f1a
		break;
Packit 994f1a
	case TIFF_DOUBLE:
Packit 994f1a
                {
Packit 994f1a
                    if( !TIFFWriteDoubleArray(tif, dir, v))
Packit 994f1a
                        goto out;
Packit 994f1a
                }
Packit 994f1a
		break;
Packit 994f1a
	default:
Packit 994f1a
		/* TIFF_NOTYPE */
Packit 994f1a
		/* TIFF_ASCII */
Packit 994f1a
		/* TIFF_UNDEFINED */
Packit 994f1a
		/* TIFF_RATIONAL */
Packit 994f1a
		/* TIFF_SRATIONAL */
Packit 994f1a
		goto out;
Packit 994f1a
	}
Packit 994f1a
	status = 1;
Packit 994f1a
 out:
Packit 994f1a
	if (w != buf)
Packit 994f1a
		_TIFFfree(w);
Packit 994f1a
	return (status);
Packit 994f1a
}
Packit 994f1a
Packit 994f1a
static int
Packit 994f1a
TIFFWriteTransferFunction(TIFF* tif, TIFFDirEntry* dir)
Packit 994f1a
{
Packit 994f1a
	TIFFDirectory* td = &tif->tif_dir;
Packit 994f1a
	tsize_t n = (1L<<td->td_bitspersample) * sizeof (uint16);
Packit 994f1a
	uint16** tf = td->td_transferfunction;
Packit 994f1a
	int ncols;
Packit 994f1a
Packit 994f1a
	/*
Packit 994f1a
	 * Check if the table can be written as a single column,
Packit 994f1a
	 * or if it must be written as 3 columns.  Note that we
Packit 994f1a
	 * write a 3-column tag if there are 2 samples/pixel and
Packit 994f1a
	 * a single column of data won't suffice--hmm.
Packit 994f1a
	 */
Packit 994f1a
	switch (td->td_samplesperpixel - td->td_extrasamples) {
Packit 994f1a
	default:	if (_TIFFmemcmp(tf[0], tf[2], n)) { ncols = 3; break; }
Packit 994f1a
	case 2:		if (_TIFFmemcmp(tf[0], tf[1], n)) { ncols = 3; break; }
Packit 994f1a
	case 1: case 0:	ncols = 1;
Packit 994f1a
	}
Packit 994f1a
	return (TIFFWriteShortTable(tif,
Packit 994f1a
	    TIFFTAG_TRANSFERFUNCTION, dir, ncols, tf));
Packit 994f1a
}
Packit 994f1a
Packit 994f1a
static int
Packit 994f1a
TIFFWriteInkNames(TIFF* tif, TIFFDirEntry* dir)
Packit 994f1a
{
Packit 994f1a
	TIFFDirectory* td = &tif->tif_dir;
Packit 994f1a
Packit 994f1a
	dir->tdir_tag = TIFFTAG_INKNAMES;
Packit 994f1a
	dir->tdir_type = (short) TIFF_ASCII;
Packit 994f1a
	dir->tdir_count = td->td_inknameslen;
Packit 994f1a
	return (TIFFWriteByteArray(tif, dir, td->td_inknames));
Packit 994f1a
}
Packit 994f1a
Packit 994f1a
/*
Packit 994f1a
 * Write a contiguous directory item.
Packit 994f1a
 */
Packit 994f1a
static int
Packit 994f1a
TIFFWriteData(TIFF* tif, TIFFDirEntry* dir, char* cp)
Packit 994f1a
{
Packit 994f1a
	tsize_t cc;
Packit 994f1a
Packit 994f1a
	if (tif->tif_flags & TIFF_SWAB) {
Packit 994f1a
		switch (dir->tdir_type) {
Packit 994f1a
		case TIFF_SHORT:
Packit 994f1a
		case TIFF_SSHORT:
Packit 994f1a
			TIFFSwabArrayOfShort((uint16*) cp, dir->tdir_count);
Packit 994f1a
			break;
Packit 994f1a
		case TIFF_LONG:
Packit 994f1a
		case TIFF_SLONG:
Packit 994f1a
		case TIFF_FLOAT:
Packit 994f1a
			TIFFSwabArrayOfLong((uint32*) cp, dir->tdir_count);
Packit 994f1a
			break;
Packit 994f1a
		case TIFF_RATIONAL:
Packit 994f1a
		case TIFF_SRATIONAL:
Packit 994f1a
			TIFFSwabArrayOfLong((uint32*) cp, 2*dir->tdir_count);
Packit 994f1a
			break;
Packit 994f1a
		case TIFF_DOUBLE:
Packit 994f1a
			TIFFSwabArrayOfDouble((double*) cp, dir->tdir_count);
Packit 994f1a
			break;
Packit 994f1a
		}
Packit 994f1a
	}
Packit 994f1a
	dir->tdir_offset = tif->tif_dataoff;
Packit 994f1a
	cc = dir->tdir_count * TIFFDataWidth((TIFFDataType) dir->tdir_type);
Packit 994f1a
	if (SeekOK(tif, dir->tdir_offset) &&
Packit 994f1a
	    WriteOK(tif, cp, cc)) {
Packit 994f1a
		tif->tif_dataoff += (cc + 1) & ~1;
Packit 994f1a
		return (1);
Packit 994f1a
	}
Packit 994f1a
	TIFFErrorExt(tif->tif_clientdata, tif->tif_name,
Packit 994f1a
		     "Error writing data for field \"%s\"",
Packit 994f1a
	_TIFFFieldWithTag(tif, dir->tdir_tag)->field_name);
Packit 994f1a
	return (0);
Packit 994f1a
}
Packit 994f1a
Packit 994f1a
/*
Packit 994f1a
 * Similar to TIFFWriteDirectory(), but if the directory has already
Packit 994f1a
 * been written once, it is relocated to the end of the file, in case it
Packit 994f1a
 * has changed in size.  Note that this will result in the loss of the 
Packit 994f1a
 * previously used directory space. 
Packit 994f1a
 */ 
Packit 994f1a
Packit 994f1a
int 
Packit 994f1a
TIFFRewriteDirectory( TIFF *tif )
Packit 994f1a
{
Packit 994f1a
    static const char module[] = "TIFFRewriteDirectory";
Packit 994f1a
Packit 994f1a
    /* We don't need to do anything special if it hasn't been written. */
Packit 994f1a
    if( tif->tif_diroff == 0 )
Packit 994f1a
        return TIFFWriteDirectory( tif );
Packit 994f1a
Packit 994f1a
    /*
Packit 994f1a
    ** Find and zero the pointer to this directory, so that TIFFLinkDirectory
Packit 994f1a
    ** will cause it to be added after this directories current pre-link.
Packit 994f1a
    */
Packit 994f1a
    
Packit 994f1a
    /* Is it the first directory in the file? */
Packit 994f1a
    if (tif->tif_header.tiff_diroff == tif->tif_diroff) 
Packit 994f1a
    {
Packit 994f1a
        tif->tif_header.tiff_diroff = 0;
Packit 994f1a
        tif->tif_diroff = 0;
Packit 994f1a
Packit 994f1a
        TIFFSeekFile(tif, (toff_t)(TIFF_MAGIC_SIZE+TIFF_VERSION_SIZE),
Packit 994f1a
		     SEEK_SET);
Packit 994f1a
        if (!WriteOK(tif, &(tif->tif_header.tiff_diroff), 
Packit 994f1a
                     sizeof (tif->tif_diroff))) 
Packit 994f1a
        {
Packit 994f1a
			TIFFErrorExt(tif->tif_clientdata, tif->tif_name,
Packit 994f1a
				     "Error updating TIFF header");
Packit 994f1a
            return (0);
Packit 994f1a
        }
Packit 994f1a
    }
Packit 994f1a
    else
Packit 994f1a
    {
Packit 994f1a
        toff_t  nextdir, off;
Packit 994f1a
Packit 994f1a
	nextdir = tif->tif_header.tiff_diroff;
Packit 994f1a
	do {
Packit 994f1a
		uint16 dircount;
Packit 994f1a
Packit 994f1a
		if (!SeekOK(tif, nextdir) ||
Packit 994f1a
		    !ReadOK(tif, &dircount, sizeof (dircount))) {
Packit 994f1a
			TIFFErrorExt(tif->tif_clientdata, module,
Packit 994f1a
				     "Error fetching directory count");
Packit 994f1a
			return (0);
Packit 994f1a
		}
Packit 994f1a
		if (tif->tif_flags & TIFF_SWAB)
Packit 994f1a
			TIFFSwabShort(&dircount);
Packit 994f1a
		(void) TIFFSeekFile(tif,
Packit 994f1a
		    dircount * sizeof (TIFFDirEntry), SEEK_CUR);
Packit 994f1a
		if (!ReadOK(tif, &nextdir, sizeof (nextdir))) {
Packit 994f1a
			TIFFErrorExt(tif->tif_clientdata, module,
Packit 994f1a
				     "Error fetching directory link");
Packit 994f1a
			return (0);
Packit 994f1a
		}
Packit 994f1a
		if (tif->tif_flags & TIFF_SWAB)
Packit 994f1a
			TIFFSwabLong(&nextdir);
Packit 994f1a
	} while (nextdir != tif->tif_diroff && nextdir != 0);
Packit 994f1a
        off = TIFFSeekFile(tif, 0, SEEK_CUR); /* get current offset */
Packit 994f1a
        (void) TIFFSeekFile(tif, off - (toff_t)sizeof(nextdir), SEEK_SET);
Packit 994f1a
        tif->tif_diroff = 0;
Packit 994f1a
	if (!WriteOK(tif, &(tif->tif_diroff), sizeof (nextdir))) {
Packit 994f1a
		TIFFErrorExt(tif->tif_clientdata, module,
Packit 994f1a
			     "Error writing directory link");
Packit 994f1a
		return (0);
Packit 994f1a
	}
Packit 994f1a
    }
Packit 994f1a
Packit 994f1a
    /*
Packit 994f1a
    ** Now use TIFFWriteDirectory() normally.
Packit 994f1a
    */
Packit 994f1a
Packit 994f1a
    return TIFFWriteDirectory( tif );
Packit 994f1a
}
Packit 994f1a
Packit 994f1a
Packit 994f1a
/*
Packit 994f1a
 * Link the current directory into the directory chain for the file.
Packit 994f1a
 */
Packit 994f1a
static int
Packit 994f1a
TIFFLinkDirectory(TIFF* tif)
Packit 994f1a
{
Packit 994f1a
	static const char module[] = "TIFFLinkDirectory";
Packit 994f1a
	toff_t nextdir;
Packit 994f1a
	toff_t diroff, off;
Packit 994f1a
Packit 994f1a
	tif->tif_diroff = (TIFFSeekFile(tif, (toff_t) 0, SEEK_END)+1) &~ 1;
Packit 994f1a
	diroff = tif->tif_diroff;
Packit 994f1a
	if (tif->tif_flags & TIFF_SWAB)
Packit 994f1a
		TIFFSwabLong(&diroff);
Packit 994f1a
Packit 994f1a
	/*
Packit 994f1a
	 * Handle SubIFDs
Packit 994f1a
	 */
Packit 994f1a
        if (tif->tif_flags & TIFF_INSUBIFD) {
Packit 994f1a
		(void) TIFFSeekFile(tif, tif->tif_subifdoff, SEEK_SET);
Packit 994f1a
		if (!WriteOK(tif, &diroff, sizeof (diroff))) {
Packit 994f1a
			TIFFErrorExt(tif->tif_clientdata, module,
Packit 994f1a
				     "%s: Error writing SubIFD directory link",
Packit 994f1a
				     tif->tif_name);
Packit 994f1a
			return (0);
Packit 994f1a
		}
Packit 994f1a
		/*
Packit 994f1a
		 * Advance to the next SubIFD or, if this is
Packit 994f1a
		 * the last one configured, revert back to the
Packit 994f1a
		 * normal directory linkage.
Packit 994f1a
		 */
Packit 994f1a
		if (--tif->tif_nsubifd)
Packit 994f1a
			tif->tif_subifdoff += sizeof (diroff);
Packit 994f1a
		else
Packit 994f1a
			tif->tif_flags &= ~TIFF_INSUBIFD;
Packit 994f1a
		return (1);
Packit 994f1a
	}
Packit 994f1a
Packit 994f1a
	if (tif->tif_header.tiff_diroff == 0) {
Packit 994f1a
		/*
Packit 994f1a
		 * First directory, overwrite offset in header.
Packit 994f1a
		 */
Packit 994f1a
		tif->tif_header.tiff_diroff = tif->tif_diroff;
Packit 994f1a
		(void) TIFFSeekFile(tif,
Packit 994f1a
				    (toff_t)(TIFF_MAGIC_SIZE+TIFF_VERSION_SIZE),
Packit 994f1a
                                    SEEK_SET);
Packit 994f1a
		if (!WriteOK(tif, &diroff, sizeof (diroff))) {
Packit 994f1a
			TIFFErrorExt(tif->tif_clientdata, tif->tif_name,
Packit 994f1a
				     "Error writing TIFF header");
Packit 994f1a
			return (0);
Packit 994f1a
		}
Packit 994f1a
		return (1);
Packit 994f1a
	}
Packit 994f1a
	/*
Packit 994f1a
	 * Not the first directory, search to the last and append.
Packit 994f1a
	 */
Packit 994f1a
	nextdir = tif->tif_header.tiff_diroff;
Packit 994f1a
	do {
Packit 994f1a
		uint16 dircount;
Packit 994f1a
Packit 994f1a
		if (!SeekOK(tif, nextdir) ||
Packit 994f1a
		    !ReadOK(tif, &dircount, sizeof (dircount))) {
Packit 994f1a
			TIFFErrorExt(tif->tif_clientdata, module,
Packit 994f1a
				     "Error fetching directory count");
Packit 994f1a
			return (0);
Packit 994f1a
		}
Packit 994f1a
		if (tif->tif_flags & TIFF_SWAB)
Packit 994f1a
			TIFFSwabShort(&dircount);
Packit 994f1a
		(void) TIFFSeekFile(tif,
Packit 994f1a
		    dircount * sizeof (TIFFDirEntry), SEEK_CUR);
Packit 994f1a
		if (!ReadOK(tif, &nextdir, sizeof (nextdir))) {
Packit 994f1a
			TIFFErrorExt(tif->tif_clientdata, module,
Packit 994f1a
				     "Error fetching directory link");
Packit 994f1a
			return (0);
Packit 994f1a
		}
Packit 994f1a
		if (tif->tif_flags & TIFF_SWAB)
Packit 994f1a
			TIFFSwabLong(&nextdir);
Packit 994f1a
	} while (nextdir != 0);
Packit 994f1a
        off = TIFFSeekFile(tif, 0, SEEK_CUR); /* get current offset */
Packit 994f1a
        (void) TIFFSeekFile(tif, off - (toff_t)sizeof(nextdir), SEEK_SET);
Packit 994f1a
	if (!WriteOK(tif, &diroff, sizeof (diroff))) {
Packit 994f1a
		TIFFErrorExt(tif->tif_clientdata, module,
Packit 994f1a
			     "Error writing directory link");
Packit 994f1a
		return (0);
Packit 994f1a
	}
Packit 994f1a
	return (1);
Packit 994f1a
}
Packit 994f1a
Packit 994f1a
/* vim: set ts=8 sts=8 sw=8 noet: */
Packit 994f1a
/*
Packit 994f1a
 * Local Variables:
Packit 994f1a
 * mode: c
Packit 994f1a
 * c-basic-offset: 8
Packit 994f1a
 * fill-column: 78
Packit 994f1a
 * End:
Packit 994f1a
 */