static tsize_t TIFFReadRawStrip1(TIFF* tif, tstrip_t strip, tdata_t buf, tsize_t size, const char* module) { TIFFDirectory *td = &tif->tif_dir; assert((tif->tif_flags&TIFF_NOREADRAW)==0); if (!isMapped(tif)) { tsize_t cc; if (!SeekOK(tif, td->td_stripoffset[strip])) { TIFFErrorExt(tif->tif_clientdata, module, "%s: Seek error at scanline %lu, strip %lu", tif->tif_name, (unsigned long) tif->tif_row, (unsigned long) strip); return (-1); } cc = TIFFReadFile(tif, buf, size); if (cc != size) { TIFFErrorExt(tif->tif_clientdata, module, "%s: Read error at scanline %lu; got %lu bytes, expected %lu", tif->tif_name, (unsigned long) tif->tif_row, (unsigned long) cc, (unsigned long) size); return (-1); } } else { if (td->td_stripoffset[strip] + size > tif->tif_size) { TIFFErrorExt(tif->tif_clientdata, module, "%s: Read error at scanline %lu, strip %lu; got %lu bytes, expected %lu", tif->tif_name, (unsigned long) tif->tif_row, (unsigned long) strip, (unsigned long) tif->tif_size - td->td_stripoffset[strip], (unsigned long) size); return (-1); } _TIFFmemcpy(buf, tif->tif_base + td->td_stripoffset[strip], size); } return (size); }
static tsize_t TIFFReadRawStrip1(TIFF* tif, tstrip_t strip, tdata_t buf, tsize_t size, const char* module) { TIFFDirectory *td = &tif->tif_dir; if (!isMapped(tif)) { tsize_t cc; if (!SeekOK(tif, td->td_stripoffset[strip])) { TIFFError(module, "%s: Seek error at scanline %lu, strip %lu", tif->tif_name, (u_long) tif->tif_row, (u_long) strip); return (-1); } cc = TIFFReadFile(tif, buf, size); if (cc != size) { TIFFError(module, "%s: Read error at scanline %lu; got %lu bytes, expected %lu", tif->tif_name, (u_long) tif->tif_row, (u_long) cc, (u_long) size); // return (-1); //<DP> To decode some nasty images } } else { if (td->td_stripoffset[strip] + size > tif->tif_size) { TIFFError(module, "%s: Read error at scanline %lu, strip %lu; got %lu bytes, expected %lu", tif->tif_name, (u_long) tif->tif_row, (u_long) strip, (u_long) tif->tif_size - td->td_stripoffset[strip], (u_long) size); return (-1); } _TIFFmemcpy(buf, tif->tif_base + td->td_stripoffset[strip], size); } return (size); }
static tmsize_t TIFFReadRawStrip1(TIFF* tif, uint32 strip, void* buf, tmsize_t size, const char* module) { TIFFDirectory *td = &tif->tif_dir; if (!_TIFFFillStriles( tif )) return ((tmsize_t)(-1)); assert((tif->tif_flags&TIFF_NOREADRAW)==0); if (!isMapped(tif)) { tmsize_t cc; if (!SeekOK(tif, td->td_stripoffset[strip])) { TIFFErrorExt(tif->tif_clientdata, module, "Seek error at scanline %lu, strip %lu", (unsigned long) tif->tif_row, (unsigned long) strip); return ((tmsize_t)(-1)); } cc = TIFFReadFile(tif, buf, size); if (cc != size) { #if defined(__WIN32__) && (defined(_MSC_VER) || defined(__MINGW32__)) TIFFErrorExt(tif->tif_clientdata, module, "Read error at scanline %lu; got %I64u bytes, expected %I64u", (unsigned long) tif->tif_row, (unsigned __int64) cc, (unsigned __int64) size); #else TIFFErrorExt(tif->tif_clientdata, module, "Read error at scanline %lu; got %llu bytes, expected %llu", (unsigned long) tif->tif_row, (unsigned long long) cc, (unsigned long long) size); #endif return ((tmsize_t)(-1)); } } else { tmsize_t ma = 0; tmsize_t n; if ((td->td_stripoffset[strip] > (uint64)TIFF_TMSIZE_T_MAX)|| ((ma=(tmsize_t)td->td_stripoffset[strip])>tif->tif_size)) { n=0; } else if( ma > TIFF_TMSIZE_T_MAX - size ) { n=0; } else { tmsize_t mb=ma+size; if (mb>tif->tif_size) n=tif->tif_size-ma; else n=size; } if (n!=size) { #if defined(__WIN32__) && (defined(_MSC_VER) || defined(__MINGW32__)) TIFFErrorExt(tif->tif_clientdata, module, "Read error at scanline %lu, strip %lu; got %I64u bytes, expected %I64u", (unsigned long) tif->tif_row, (unsigned long) strip, (unsigned __int64) n, (unsigned __int64) size); #else TIFFErrorExt(tif->tif_clientdata, module, "Read error at scanline %lu, strip %lu; got %llu bytes, expected %llu", (unsigned long) tif->tif_row, (unsigned long) strip, (unsigned long long) n, (unsigned long long) size); #endif return ((tmsize_t)(-1)); } _TIFFmemcpy(buf, tif->tif_base + ma, size); } return (size); }
/* Read 'size' bytes in tif_rawdata buffer starting at offset 'rawdata_offset' * Returns 1 in case of success, 0 otherwise. */ static int TIFFReadAndRealloc( TIFF* tif, tmsize_t size, tmsize_t rawdata_offset, int is_strip, uint32 strip_or_tile, const char* module ) { #if SIZEOF_SIZE_T == 8 tmsize_t threshold = INITIAL_THRESHOLD; #endif tmsize_t already_read = 0; /* On 64 bit processes, read first a maximum of 1 MB, then 10 MB, etc */ /* so as to avoid allocating too much memory in case the file is too */ /* short. We could ask for the file size, but this might be */ /* expensive with some I/O layers (think of reading a gzipped file) */ /* Restrict to 64 bit processes, so as to avoid reallocs() */ /* on 32 bit processes where virtual memory is scarce. */ while( already_read < size ) { tmsize_t bytes_read; tmsize_t to_read = size - already_read; #if SIZEOF_SIZE_T == 8 if( to_read >= threshold && threshold < MAX_THRESHOLD && already_read + to_read + rawdata_offset > tif->tif_rawdatasize ) { to_read = threshold; threshold *= THRESHOLD_MULTIPLIER; } #endif if (already_read + to_read + rawdata_offset > tif->tif_rawdatasize) { uint8* new_rawdata; assert((tif->tif_flags & TIFF_MYBUFFER) != 0); tif->tif_rawdatasize = (tmsize_t)TIFFroundup_64( (uint64)already_read + to_read + rawdata_offset, 1024); if (tif->tif_rawdatasize==0) { TIFFErrorExt(tif->tif_clientdata, module, "Invalid buffer size"); return 0; } new_rawdata = (uint8*) _TIFFrealloc( tif->tif_rawdata, tif->tif_rawdatasize); if( new_rawdata == 0 ) { TIFFErrorExt(tif->tif_clientdata, module, "No space for data buffer at scanline %lu", (unsigned long) tif->tif_row); _TIFFfree(tif->tif_rawdata); tif->tif_rawdata = 0; tif->tif_rawdatasize = 0; return 0; } tif->tif_rawdata = new_rawdata; } bytes_read = TIFFReadFile(tif, tif->tif_rawdata + rawdata_offset + already_read, to_read); already_read += bytes_read; if (bytes_read != to_read) { memset( tif->tif_rawdata + rawdata_offset + already_read, 0, tif->tif_rawdatasize - rawdata_offset - already_read ); #if defined(__WIN32__) && (defined(_MSC_VER) || defined(__MINGW32__)) if( is_strip ) { TIFFErrorExt(tif->tif_clientdata, module, "Read error at scanline %lu; got %I64u bytes, " "expected %I64u", (unsigned long) tif->tif_row, (unsigned __int64) already_read, (unsigned __int64) size); } else { TIFFErrorExt(tif->tif_clientdata, module, "Read error at row %lu, col %lu, tile %lu; " "got %I64u bytes, expected %I64u", (unsigned long) tif->tif_row, (unsigned long) tif->tif_col, (unsigned long) strip_or_tile, (unsigned __int64) already_read, (unsigned __int64) size); } #else if( is_strip ) { TIFFErrorExt(tif->tif_clientdata, module, "Read error at scanline %lu; got %llu bytes, " "expected %llu", (unsigned long) tif->tif_row, (unsigned long long) already_read, (unsigned long long) size); } else { TIFFErrorExt(tif->tif_clientdata, module, "Read error at row %lu, col %lu, tile %lu; " "got %llu bytes, expected %llu", (unsigned long) tif->tif_row, (unsigned long) tif->tif_col, (unsigned long) strip_or_tile, (unsigned long long) already_read, (unsigned long long) size); } #endif return 0; } } return 1; }
static tmsize_t TIFFReadRawTile1(TIFF* tif, uint32 tile, void* buf, tmsize_t size, const char* module) { TIFFDirectory *td = &tif->tif_dir; if (!_TIFFFillStriles( tif )) return ((tmsize_t)(-1)); assert((tif->tif_flags&TIFF_NOREADRAW)==0); if (!isMapped(tif)) { tmsize_t cc; if (!SeekOK(tif, td->td_stripoffset[tile])) { TIFFErrorExt(tif->tif_clientdata, module, "Seek error at row %lu, col %lu, tile %lu", (unsigned long) tif->tif_row, (unsigned long) tif->tif_col, (unsigned long) tile); return ((tmsize_t)(-1)); } cc = TIFFReadFile(tif, buf, size); if (cc != size) { #if defined(__WIN32__) && (defined(_MSC_VER) || defined(__MINGW32__)) TIFFErrorExt(tif->tif_clientdata, module, "Read error at row %lu, col %lu; got %I64u bytes, expected %I64u", (unsigned long) tif->tif_row, (unsigned long) tif->tif_col, (unsigned __int64) cc, (unsigned __int64) size); #else TIFFErrorExt(tif->tif_clientdata, module, "Read error at row %lu, col %lu; got %llu bytes, expected %llu", (unsigned long) tif->tif_row, (unsigned long) tif->tif_col, (unsigned long long) cc, (unsigned long long) size); #endif return ((tmsize_t)(-1)); } } else { tmsize_t ma,mb; tmsize_t n; ma=(tmsize_t)td->td_stripoffset[tile]; mb=ma+size; if (((uint64)ma!=td->td_stripoffset[tile])||(ma>tif->tif_size)) n=0; else if ((mb<ma)||(mb<size)||(mb>tif->tif_size)) n=tif->tif_size-ma; else n=size; if (n!=size) { #if defined(__WIN32__) && (defined(_MSC_VER) || defined(__MINGW32__)) TIFFErrorExt(tif->tif_clientdata, module, "Read error at row %lu, col %lu, tile %lu; got %I64u bytes, expected %I64u", (unsigned long) tif->tif_row, (unsigned long) tif->tif_col, (unsigned long) tile, (unsigned __int64) n, (unsigned __int64) size); #else TIFFErrorExt(tif->tif_clientdata, module, "Read error at row %lu, col %lu, tile %lu; got %llu bytes, expected %llu", (unsigned long) tif->tif_row, (unsigned long) tif->tif_col, (unsigned long) tile, (unsigned long long) n, (unsigned long long) size); #endif return ((tmsize_t)(-1)); } _TIFFmemcpy(buf, tif->tif_base + ma, size); } return (size); }
static int TIFFFillStripPartial( TIFF *tif, int strip, tmsize_t read_ahead, int restart ) { static const char module[] = "TIFFFillStripPartial"; register TIFFDirectory *td = &tif->tif_dir; tmsize_t unused_data; uint64 read_offset; tmsize_t cc, to_read; /* tmsize_t bytecountm; */ if (!_TIFFFillStriles( tif ) || !tif->tif_dir.td_stripbytecount) return 0; /* * Expand raw data buffer, if needed, to hold data * strip coming from file (perhaps should set upper * bound on the size of a buffer we'll use?). */ /* bytecountm=(tmsize_t) td->td_stripbytecount[strip]; */ if (read_ahead*2 > tif->tif_rawdatasize) { assert( restart ); tif->tif_curstrip = NOSTRIP; if ((tif->tif_flags & TIFF_MYBUFFER) == 0) { TIFFErrorExt(tif->tif_clientdata, module, "Data buffer too small to hold part of strip %lu", (unsigned long) strip); return (0); } if (!TIFFReadBufferSetup(tif, 0, read_ahead*2)) return (0); } if( restart ) { tif->tif_rawdataloaded = 0; tif->tif_rawdataoff = 0; } /* ** If we are reading more data, move any unused data to the ** start of the buffer. */ if( tif->tif_rawdataloaded > 0 ) unused_data = tif->tif_rawdataloaded - (tif->tif_rawcp - tif->tif_rawdata); else unused_data = 0; if( unused_data > 0 ) { assert((tif->tif_flags&TIFF_BUFFERMMAP)==0); memmove( tif->tif_rawdata, tif->tif_rawcp, unused_data ); } /* ** Seek to the point in the file where more data should be read. */ read_offset = td->td_stripoffset[strip] + tif->tif_rawdataoff + tif->tif_rawdataloaded; if (!SeekOK(tif, read_offset)) { TIFFErrorExt(tif->tif_clientdata, module, "Seek error at scanline %lu, strip %lu", (unsigned long) tif->tif_row, (unsigned long) strip); return 0; } /* ** How much do we want to read? */ to_read = tif->tif_rawdatasize - unused_data; if( (uint64) to_read > td->td_stripbytecount[strip] - tif->tif_rawdataoff - tif->tif_rawdataloaded ) { to_read = (tmsize_t) td->td_stripbytecount[strip] - tif->tif_rawdataoff - tif->tif_rawdataloaded; } assert((tif->tif_flags&TIFF_BUFFERMMAP)==0); cc = TIFFReadFile(tif, tif->tif_rawdata + unused_data, to_read); if (cc != to_read) { #if defined(__WIN32__) && (defined(_MSC_VER) || defined(__MINGW32__)) TIFFErrorExt(tif->tif_clientdata, module, "Read error at scanline %lu; got %I64u bytes, expected %I64u", (unsigned long) tif->tif_row, (unsigned __int64) cc, (unsigned __int64) to_read); #else TIFFErrorExt(tif->tif_clientdata, module, "Read error at scanline %lu; got %llu bytes, expected %llu", (unsigned long) tif->tif_row, (unsigned long long) cc, (unsigned long long) to_read); #endif return 0; } tif->tif_rawdataoff = tif->tif_rawdataoff + tif->tif_rawdataloaded - unused_data ; tif->tif_rawdataloaded = unused_data + to_read; tif->tif_rawcp = tif->tif_rawdata; if (!isFillOrder(tif, td->td_fillorder) && (tif->tif_flags & TIFF_NOBITREV) == 0) { assert((tif->tif_flags&TIFF_BUFFERMMAP)==0); TIFFReverseBits(tif->tif_rawdata + unused_data, to_read ); } /* ** When starting a strip from the beginning we need to ** restart the decoder. */ if( restart ) return TIFFStartStrip(tif, strip); else return 1; }
/* * Function to convert standard TIFF file to BigTIFF file. Loop through all directories in * current file (including subdirectories linked via SubIFD arrays) and create corresponding * new directories with 64-bit arrays. The old 32-bit directories are left in the file as * dead space. The data for directory entries are reused by default. Some directory entries * require new data with 64-bit offsets (e.g. stripe/tile offsets and SubIFD arrays). * * Returns 1 if successful, 0 if cannot convert to BigTIFF (TIFF_NOBIGTIFF set * or 32-bit API called). */ static int TIFFMakeBigTIFF(TIFF *tif) { uint32 dirlink = TIFF_HEADER_DIROFF_S, diroff = tif->tif_header.s.tiff_diroff; toff_t dirlinkB = TIFF_HEADER_DIROFF_B, diroffB; uint16 dircount, dirindex; uint64 dircountB; tsize_t dirsize, dirsizeB; int issubifd = 0; uint32 subifdcnt = 0; uint32 subifdlink; toff_t subifdlinkB; char *data, *dataB; TIFFDirEntry *dir, *dirB; /* * Update flags and file header */ if (noBigTIFF(tif)) { TIFFErrorExt((tif)->tif_clientdata, "TIFFCheckBigTIFF", "File > 2^32 and NO BigTIFF specified"); return (0); } tif->tif_flags |= TIFF_ISBIGTIFF; tif->tif_header.b.tiff_version = TIFF_BIGTIFF_VERSION; tif->tif_header.b.tiff_offsize = 8; tif->tif_header.b.tiff_fill = 0; tif->tif_header.b.tiff_diroff = 0; if (tif->tif_flags & TIFF_SWAB) { TIFFSwabShort(&tif->tif_header.b.tiff_version); TIFFSwabShort(&tif->tif_header.b.tiff_offsize); } if (!SeekOK(tif, 0) || !WriteOK(tif, &tif->tif_header, sizeof(TIFFHeader))) { TIFFErrorExt(tif->tif_clientdata, tif->tif_name, "Error updating TIFF header (%d)", TIFFGetErrno(tif)); return (0); } if (tif->tif_flags & TIFF_SWAB) { TIFFSwabShort(&tif->tif_header.b.tiff_version); TIFFSwabShort(&tif->tif_header.b.tiff_offsize); } /* * Loop through all directories and rewrite as BigTIFF with 64-bit offsets. This * begins with main IFD chain but may divert to SubIFD arrays as needed. */ while (diroff != 0 && diroff != tif->tif_diroff) { if (!SeekOK(tif, diroff) || !ReadOK(tif, &dircount, sizeof(dircount))) { TIFFErrorExt(tif->tif_clientdata, tif->tif_name, "Error reading TIFF directory (%d)", TIFFGetErrno(tif)); return (0); } if (tif->tif_flags & TIFF_SWAB) TIFFSwabShort(&dircount); dircountB = dircount; if (!(data = _TIFFmalloc(dirsize = dircount * TIFFDirEntryLenS)) || !(dataB = _TIFFmalloc(dirsizeB = dircount * TIFFDirEntryLenB))) { TIFFErrorExt(tif->tif_clientdata, tif->tif_name, "Error allocating space for directory"); return (0); } if (!SeekOK(tif, diroff + sizeof(dircount)) || !ReadOK(tif, data, dirsize)) { TIFFErrorExt(tif->tif_clientdata, tif->tif_name, "Error reading TIFF directory (%d)", TIFFGetErrno(tif)); goto error; } diroffB = tif->tif_dataoff; tif->tif_dataoff += sizeof(dircountB) + dirsizeB + sizeof(toff_t); for (dirindex = 0; dirindex < dircount; dirindex++) { dir = (TIFFDirEntry*) (data + dirindex * TIFFDirEntryLenS); dirB = (TIFFDirEntry*) (dataB + dirindex * TIFFDirEntryLenB); if (tif->tif_flags & TIFF_SWAB) { TIFFSwabShort(&dir->s.tdir_tag); TIFFSwabShort(&dir->s.tdir_type); TIFFSwabLong(&dir->s.tdir_count); TIFFSwabLong(&dir->s.tdir_offset); } dirB->b.tdir_tag = dir->s.tdir_tag; dirB->b.tdir_type = dir->s.tdir_type; dirB->b.tdir_count = dir->s.tdir_count; dirB->b.tdir_offset = 0; /* * If data are in directory entry itself, copy data, else (data are pointed * to by directory entry) copy pointer. This is complicated by the fact that * the old entry had 32-bits of space, and the new has 64-bits, so may have * to read data pointed at by the old entry directly into the new entry. */ switch (dir->s.tdir_type) { case TIFF_UNDEFINED: case TIFF_BYTE: case TIFF_SBYTE: case TIFF_ASCII: if (dir->s.tdir_count <= sizeof(dir->s.tdir_offset)) _TIFFmemcpy(&dirB->b.tdir_offset, &dir->s.tdir_offset, dir->s.tdir_count); else if (dir->s.tdir_count <= sizeof(dirB->b.tdir_count)) { TIFFSeekFile(tif, dir->s.tdir_offset, SEEK_SET); TIFFReadFile(tif, &dirB->b.tdir_offset, dir->s.tdir_count); } else dirB->b.tdir_offset = dir->s.tdir_offset; break; case TIFF_SHORT: case TIFF_SSHORT: if (dir->s.tdir_count <= sizeof(dir->s.tdir_offset) / sizeof(uint16)) _TIFFmemcpy(&dirB->b.tdir_offset, &dir->s.tdir_offset, dir->s.tdir_count * sizeof(uint16)); else if (dir->s.tdir_count <= sizeof(dirB->b.tdir_count) / sizeof(uint16)) { TIFFSeekFile(tif, dir->s.tdir_offset, SEEK_SET); TIFFReadFile(tif, &dirB->b.tdir_offset, dir->s.tdir_count * sizeof(uint16)); if (tif->tif_flags & TIFF_SWAB) TIFFSwabArrayOfShort((uint16*) &dirB->b.tdir_offset, dir->s.tdir_count); } else dirB->b.tdir_offset = dir->s.tdir_offset; break; case TIFF_LONG: case TIFF_FLOAT: case TIFF_IFD: if (dir->s.tdir_count <= sizeof(dir->s.tdir_offset) / sizeof(uint32)) _TIFFmemcpy(&dirB->b.tdir_offset, &dir->s.tdir_offset, dir->s.tdir_count * sizeof(uint32)); else if (dir->s.tdir_count <= sizeof(dirB->b.tdir_count) / sizeof(uint32)) { TIFFSeekFile(tif, dir->s.tdir_offset, SEEK_SET); TIFFReadFile(tif, &dirB->b.tdir_offset, dir->s.tdir_count * sizeof(uint32)); if (tif->tif_flags & TIFF_SWAB) TIFFSwabArrayOfLong((uint32*) &dirB->b.tdir_offset, dir->s.tdir_count); } else dirB->b.tdir_offset = dir->s.tdir_offset; break; case TIFF_RATIONAL: case TIFF_SRATIONAL: if (dir->s.tdir_count * 2 <= sizeof(dirB->b.tdir_offset) / sizeof(uint32)) { TIFFSeekFile(tif, dir->s.tdir_offset, SEEK_SET); TIFFReadFile(tif, &dirB->b.tdir_offset, dir->s.tdir_count * 2 * sizeof(uint32)); if (tif->tif_flags & TIFF_SWAB) TIFFSwabArrayOfLong((uint32*) &dirB->b.tdir_offset, dir->s.tdir_count * 2); } else dirB->b.tdir_offset = dir->s.tdir_offset; break; default: dirB->b.tdir_offset = dir->s.tdir_offset; break; } /* * Process special case of SUBIFD; must change data from 32-bit to 64-bit in * case new 64-bit directory offsets need to be added. */ switch (dirB->b.tdir_tag) { case TIFFTAG_SUBIFD: dirB->b.tdir_type = TIFF_IFD8; subifdcnt = dir->s.tdir_count; /* * Set pointer to existing SubIFD array */ if (subifdcnt <= sizeof(dir->s.tdir_offset) / sizeof(uint32)) subifdlink = diroff + sizeof(dircount) + (char*) &dir->s.tdir_offset - (char*) dir; else subifdlink = dir->s.tdir_offset; /* * Initialize new SubIFD array, set pointer to it */ if (subifdcnt <= sizeof(dir->b.tdir_offset) / sizeof(toff_t)) { dir->b.tdir_offset = 0; subifdlinkB = diroffB + sizeof(dircountB) + (char*) &dir->b.tdir_offset - (char*) dirB; } else { toff_t *offB; if (!(offB = _TIFFmalloc(subifdcnt * sizeof(toff_t)))) { TIFFErrorExt(tif->tif_clientdata, tif->tif_name, "Error allocating space for 64-bit SubIFDs"); goto error; } _TIFFmemset(offB, 0, subifdcnt * sizeof(toff_t)); TIFFWriteLong8Array(tif, dirB, offB); _TIFFfree(offB); subifdlinkB = dirB->b.tdir_offset; } break; } if (tif->tif_flags & TIFF_SWAB) { TIFFSwabShort(&dirB->b.tdir_tag); TIFFSwabShort(&dirB->b.tdir_type); TIFFSwabLong8(&dirB->b.tdir_count); TIFFSwabLong8(&dirB->b.tdir_offset); } } /* * Write out new directory and chain to previous */ if (tif->tif_flags & TIFF_SWAB) TIFFSwabLong8(&dircountB); if (!SeekOK(tif, diroffB) || !WriteOK(tif, &dircountB, sizeof(dircountB)) || !SeekOK(tif, diroffB + sizeof(dircountB)) || !WriteOK(tif, dataB, dirsizeB)) { TIFFErrorExt(tif->tif_clientdata, tif->tif_name, "Error writing TIFF directory (%d)", TIFFGetErrno(tif)); goto error; } /* * If directory is SubIFD update array in host directory, else add to * main directory chain */ if (tif->tif_nsubifd && tif->tif_subifdoff == subifdlink) tif->tif_subifdoff = subifdlinkB; if (!issubifd && dirlinkB == TIFF_HEADER_DIROFF_B) tif->tif_header.b.tiff_diroff = diroffB; if (tif->tif_flags & TIFF_SWAB) TIFFSwabLong8(&diroffB); if (!SeekOK(tif, (issubifd ? subifdlinkB++ : dirlinkB)) || !WriteOK(tif, &diroffB, sizeof(diroffB))) { TIFFErrorExt(tif->tif_clientdata, tif->tif_name, "Error writing directory link (%d)", TIFFGetErrno(tif)); goto error; } if (issubifd) subifdcnt--; else { dirlink = diroff + sizeof(dircount) + dirsize; dirlinkB = diroffB + sizeof(dircountB) + dirsizeB; } issubifd = (subifdcnt > 0); if (!SeekOK(tif, (issubifd ? subifdlink++ : dirlink)) || !ReadOK(tif, &diroff, sizeof(diroff))) { TIFFErrorExt(tif->tif_clientdata, tif->tif_name, "Error reading directory link (%d)", TIFFGetErrno(tif)); goto error; } if (tif->tif_flags & TIFF_SWAB) TIFFSwabLong(&diroff); _TIFFfree(dataB); _TIFFfree(data); } /* * Mark end of directory chain */ diroffB = 0; if (dirlinkB == TIFF_HEADER_DIROFF_B) tif->tif_header.b.tiff_diroff = diroffB; if (tif->tif_flags & TIFF_SWAB) TIFFSwabLong8(&diroffB); if (!SeekOK(tif, dirlinkB) || !WriteOK(tif, &diroffB, sizeof(diroffB))) { TIFFErrorExt(tif->tif_clientdata, tif->tif_name, "Error writing directory link (%d)", TIFFGetErrno(tif)); goto error; } return (1); error: _TIFFfree(dataB); _TIFFfree(data); return (0); }