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