/* * Append the data to the specified strip. * * NB: We don't check that there's space in the * file (i.e. that strips do not overlap). */ static int TIFFAppendToStrip(TIFF* tif, tstrip_t strip, tidata_t data, tsize_t cc) { TIFFDirectory *td = &tif->tif_dir; static const char module[] = "TIFFAppendToStrip"; if (td->td_stripoffset[strip] == 0 || tif->tif_curoff == 0) { /* * No current offset, set the current strip. */ if (td->td_stripoffset[strip] != 0) { if (!SeekOK(tif, td->td_stripoffset[strip])) { TIFFError(module, "%s: Seek error at scanline %lu", tif->tif_name, (u_long) tif->tif_row); return (0); } } else td->td_stripoffset[strip] = TIFFSeekFile(tif, (toff_t) 0, SEEK_END); tif->tif_curoff = td->td_stripoffset[strip]; } if (!WriteOK(tif, data, cc)) { TIFFError(module, "%s: Write error at scanline %lu", tif->tif_name, (u_long) tif->tif_row); return (0); } tif->tif_curoff += cc; td->td_stripbytecount[strip] += cc; return (1); }
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)) { 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); } if (!ReadOK(tif, buf, size)) { TIFFError(module, "%s: Read error at scanline %lu", tif->tif_name, (u_long) tif->tif_row); return (-1); } } else { if (td->td_stripoffset[strip] + size > tif->tif_size) { TIFFError(module, "%s: Seek error at scanline %lu, strip %lu", tif->tif_name, (u_long) tif->tif_row, (u_long) strip); return (-1); } memcpy(buf, tif->tif_base + td->td_stripoffset[strip], size); } return (size); }
/* * Append the data to the specified strip. */ static int TIFFAppendToStrip(TIFF *tif, tstrip_t strip, tidata_t data, tsize_t cc) { static const char module[] = "TIFFAppendToStrip"; TIFFDirectory *td = &tif->tif_dir; if (td->td_stripoffset[strip] == 0 || tif->tif_curoff == 0) { assert(td->td_nstrips > 0); if (td->td_stripbytecount[strip] != 0 && td->td_stripoffset[strip] != 0 && td->td_stripbytecount[strip] >= cc) { /* * There is already tile data on disk, and the new tile * data we have to will fit in the same space. The only * aspect of this that is risky is that there could be * more data to append to this strip before we are done * depending on how we are getting called. */ if (!SeekOK(tif, td->td_stripoffset[strip])) { TIFFErrorExt(tif->tif_clientdata, module, "Seek error at scanline %lu", (unsigned long)tif->tif_row); return (0); } } else { /* * Seek to end of file, and set that as our location to * write this strip. */ td->td_stripoffset[strip] = TIFFSeekFile(tif, 0, SEEK_END); } tif->tif_curoff = td->td_stripoffset[strip]; /* * We are starting a fresh strip/tile, so set the size to zero. */ td->td_stripbytecount[strip] = 0; } if (!WriteOK(tif, data, cc)) { TIFFErrorExt(tif->tif_clientdata, module, "Write error at scanline %lu", (unsigned long) tif->tif_row); return (0); } tif->tif_curoff = tif->tif_curoff + cc; td->td_stripbytecount[strip] += cc; 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) { TIFFErrorExt(tif->tif_clientdata, module, "Read error at row %lu, col %lu; got " TIFF_UINT64_FORMAT " bytes, expected " TIFF_UINT64_FORMAT, (unsigned long) tif->tif_row, (unsigned long) tif->tif_col, (TIFF_UINT64_T) cc, (TIFF_UINT64_T) size); 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) { TIFFErrorExt(tif->tif_clientdata, module, "Read error at row %lu, col %lu, tile %lu; got " TIFF_UINT64_FORMAT " bytes, expected " TIFF_UINT64_FORMAT, (unsigned long) tif->tif_row, (unsigned long) tif->tif_col, (unsigned long) tile, (TIFF_UINT64_T) n, (TIFF_UINT64_T) size); return ((tmsize_t)(-1)); } _TIFFmemcpy(buf, tif->tif_base + ma, size); } return (size); }
static tsize_t TIFFReadRawTile1(TIFF* tif, ttile_t tile, 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[tile])) { TIFFErrorExt(tif->tif_clientdata, module, "%s: Seek error at row %ld, col %ld, tile %ld", tif->tif_name, (long) tif->tif_row, (long) tif->tif_col, (long) tile); return ((tsize_t) -1); } cc = TIFFReadFile(tif, buf, size); if (cc != size) { TIFFErrorExt(tif->tif_clientdata, module, "%s: Read error at row %ld, col %ld; got %lu bytes, expected %lu", tif->tif_name, (long) tif->tif_row, (long) tif->tif_col, (unsigned long) cc, (unsigned long) size); return ((tsize_t) -1); } } else { if (td->td_stripoffset[tile] + size > tif->tif_size) { TIFFErrorExt(tif->tif_clientdata, module, "%s: Read error at row %ld, col %ld, tile %ld; got %lu bytes, expected %lu", tif->tif_name, (long) tif->tif_row, (long) tif->tif_col, (long) tile, (unsigned long) tif->tif_size - td->td_stripoffset[tile], (unsigned long) size); return ((tsize_t) -1); } _TIFFmemcpy(buf, tif->tif_base + td->td_stripoffset[tile], size); } return (size); }
/* * 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->s.tdir_type) { case TIFF_SHORT: case TIFF_SSHORT: TIFFSwabArrayOfShort((uint16*) cp, TDIRGetEntryCount(tif,dir)); break; case TIFF_LONG: case TIFF_SLONG: case TIFF_IFD: case TIFF_FLOAT: TIFFSwabArrayOfLong((uint32*) cp, TDIRGetEntryCount(tif,dir)); break; case TIFF_LONG8: case TIFF_SLONG8: case TIFF_IFD8: TIFFSwabArrayOfLong8((uint64*) cp, TDIRGetEntryCount(tif,dir)); break; case TIFF_RATIONAL: case TIFF_SRATIONAL: TIFFSwabArrayOfLong((uint32*) cp, 2 * TDIRGetEntryCount(tif,dir)); break; case TIFF_DOUBLE: TIFFSwabArrayOfDouble((double*) cp, TDIRGetEntryCount(tif,dir)); break; } } TDIRSetEntryOff(tif,dir,tif->tif_dataoff); cc = TDIRGetEntryCount(tif,dir) * TIFFDataWidth((TIFFDataType) dir->s.tdir_type); if (SeekOK(tif, tif->tif_dataoff) && 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\" (%d)", _TIFFFieldWithTag(tif, dir->s.tdir_tag)->field_name, TIFFGetErrno(tif)); return (0); }
/* * Fetch a contiguous directory item. */ static tsize_t TIFFFetchData(TIFF* tif, TIFFDirEntry* dir, char* cp) { int w = tiffDataWidth[dir->tdir_type]; tsize_t cc = dir->tdir_count * w; if (!isMapped(tif)) { if (!SeekOK(tif, dir->tdir_offset)) goto bad; if (!ReadOK(tif, cp, cc)) goto bad; } else { if (dir->tdir_offset + cc > tif->tif_size) goto bad; _TIFFmemcpy(cp, tif->tif_base + dir->tdir_offset, 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; } } return (cc); bad: TIFFError(tif->tif_name, "Error fetching data for field \"%s\"", _TIFFFieldWithTag(tif, dir->tdir_tag)->field_name); return ((tsize_t) 0); }
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, (unsigned long) tif->tif_row, (unsigned 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, (unsigned long) tif->tif_row, (unsigned long) cc, (unsigned long) size); return (-1); } } 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, (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 TIFFReadRawTile1(TIFF* tif, ttile_t tile, tdata_t buf, tsize_t size, const char* module) { TIFFDirectory *td = &tif->tif_dir; if (!isMapped(tif)) { if (!SeekOK(tif, td->td_stripoffset[tile])) { TIFFError(module, "%s: Seek error at row %ld, col %ld, tile %ld", tif->tif_name, (long) tif->tif_row, (long) tif->tif_col, (long) tile); return ((tsize_t) -1); } if (!ReadOK(tif, buf, size)) { TIFFError(module, "%s: Read error at row %ld, col %ld", tif->tif_name, (long) tif->tif_row, (long) tif->tif_col); return ((tsize_t) -1); } } else { if (td->td_stripoffset[tile] + size > tif->tif_size) { TIFFError(module, "%s: Seek error at row %ld, col %ld, tile %ld", tif->tif_name, (long) tif->tif_row, (long) tif->tif_col, (long) tile); return ((tsize_t) -1); } memcpy(buf, tif->tif_base + td->td_stripoffset[tile], size); } return (size); }
/* * 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); }
static tmsize_t TIFFReadRawStripOrTile2(TIFF* tif, uint32 strip_or_tile, int is_strip, tmsize_t size, const char* module) { TIFFDirectory *td = &tif->tif_dir; assert( !isMapped(tif) ); assert((tif->tif_flags&TIFF_NOREADRAW)==0); if (!SeekOK(tif, td->td_stripoffset[strip_or_tile])) { if( is_strip ) { TIFFErrorExt(tif->tif_clientdata, module, "Seek error at scanline %lu, strip %lu", (unsigned long) tif->tif_row, (unsigned long) strip_or_tile); } else { 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) strip_or_tile); } return ((tmsize_t)(-1)); } if( !TIFFReadAndRealloc( tif, size, 0, is_strip, strip_or_tile, module ) ) { return ((tmsize_t)(-1)); } return (size); }
/* * Append the data to the specified strip. */ static int TIFFAppendToStrip(TIFF* tif, uint32 strip, uint8* data, tmsize_t cc) { static const char module[] = "TIFFAppendToStrip"; TIFFDirectory *td = &tif->tif_dir; uint64 m; int64 old_byte_count = -1; if (td->td_stripoffset[strip] == 0 || tif->tif_curoff == 0) { assert(td->td_nstrips > 0); if( td->td_stripbytecount[strip] != 0 && td->td_stripoffset[strip] != 0 && td->td_stripbytecount[strip] >= (uint64) cc ) { /* * There is already tile data on disk, and the new tile * data we have will fit in the same space. The only * aspect of this that is risky is that there could be * more data to append to this strip before we are done * depending on how we are getting called. */ if (!SeekOK(tif, td->td_stripoffset[strip])) { TIFFErrorExt(tif->tif_clientdata, module, "Seek error at scanline %lu", (unsigned long)tif->tif_row); return (0); } } else { /* * Seek to end of file, and set that as our location to * write this strip. */ td->td_stripoffset[strip] = TIFFSeekFile(tif, 0, SEEK_END); tif->tif_flags |= TIFF_DIRTYSTRIP; } tif->tif_curoff = td->td_stripoffset[strip]; /* * We are starting a fresh strip/tile, so set the size to zero. */ old_byte_count = td->td_stripbytecount[strip]; td->td_stripbytecount[strip] = 0; } m = tif->tif_curoff+cc; if (!(tif->tif_flags&TIFF_BIGTIFF)) m = (uint32)m; if ((m<tif->tif_curoff)||(m<(uint64)cc)) { TIFFErrorExt(tif->tif_clientdata, module, "Maximum TIFF file size exceeded"); return (0); } if (!WriteOK(tif, data, cc)) { TIFFErrorExt(tif->tif_clientdata, module, "Write error at scanline %lu", (unsigned long) tif->tif_row); return (0); } tif->tif_curoff = m; td->td_stripbytecount[strip] += cc; if( (int64) td->td_stripbytecount[strip] != old_byte_count ) tif->tif_flags |= TIFF_DIRTYSTRIP; return (1); }
/* * 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 (TIFFGetHdrDirOff(tif,tif->tif_header) == tif->tif_diroff) { TIFFSetHdrDirOff(tif,tif->tif_header,0); tif->tif_diroff = 0; 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); } } else { toff_t nextdir, off; toff_t nextdiroff; /* 32-bit or 64-bit directory offset */ nextdir = TIFFGetHdrDirOff(tif,tif->tif_header); do { uint16 dircount; if (!SeekOK(tif, nextdir) || !ReadOK(tif, &dircount, sizeof (dircount))) { TIFFErrorExt(tif->tif_clientdata, module, "Error fetching directory count (%d)", TIFFGetErrno(tif)); return (0); } if (tif->tif_flags & TIFF_SWAB) TIFFSwabShort(&dircount); (void) TIFFSeekFile(tif, TIFFGetDirCnt(tif,dircount) * TDIREntryLen(tif), SEEK_CUR); if (!ReadOK(tif, &nextdiroff, TIFFDirOffLen(tif))) { TIFFErrorExt(tif->tif_clientdata, module, "Error fetching directory link (%d)", TIFFGetErrno(tif)); return (0); } if (tif->tif_flags & TIFF_SWAB) TIFFSwabDirOff(tif,&nextdiroff); nextdir = TIFFGetDirOff(tif,nextdiroff); } while (nextdir != tif->tif_diroff && nextdir != 0); off = TIFFSeekFile(tif, 0, SEEK_CUR); /* get current offset */ (void) TIFFSeekFile(tif, off - TIFFDirOffLen(tif), SEEK_SET); tif->tif_diroff = 0; if (!WriteOK(tif, &(tif->tif_diroff), TIFFDirOffLen(tif))) { TIFFErrorExt(tif->tif_clientdata, module, "Error writing directory link (%d)", TIFFGetErrno(tif)); return (0); } } /* ** Now use TIFFWriteDirectory() normally. */ return TIFFWriteDirectory( tif ); }
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); }
/* * Append the data to the specified strip. */ static int TIFFAppendToStrip(TIFF* tif, tstrip_t strip, tidata_t data, tsize_t cc) { TIFFDirectory* td = &tif->tif_dir; static const char module[] = "TIFFAppendToStrip"; if (td->td_stripoffset[strip] == 0 || tif->tif_curoff == 0) { /* * No current offset, set the current strip. */ assert(td->td_nstrips > 0); if (td->td_stripoffset[strip] != 0) { /* * Prevent overlapping of the data chunks. We need * this to enable in place updating of the compressed * images. Larger blocks will be moved at the end of * the file without any optimization of the spare * space, so such scheme is not too much effective. */ if (td->td_stripbytecountsorted) { if (strip == td->td_nstrips - 1 || td->td_stripoffset[strip + 1] < td->td_stripoffset[strip] + cc) { td->td_stripoffset[strip] = TIFFSeekFile(tif, (toff_t)0, SEEK_END); } } else { tstrip_t i; for (i = 0; i < td->td_nstrips; i++) { if (td->td_stripoffset[i] > td->td_stripoffset[strip] && td->td_stripoffset[i] < td->td_stripoffset[strip] + cc) { td->td_stripoffset[strip] = TIFFSeekFile(tif, (toff_t)0, SEEK_END); } } } if (!SeekOK(tif, td->td_stripoffset[strip])) { TIFFError(module, "%s: Seek error at scanline %lu", tif->tif_name, (unsigned long)tif->tif_row); return (0); } } else td->td_stripoffset[strip] = TIFFSeekFile(tif, (toff_t) 0, SEEK_END); tif->tif_curoff = td->td_stripoffset[strip]; } if (!WriteOK(tif, data, cc)) { TIFFError(module, "%s: Write error at scanline %lu", tif->tif_name, (unsigned long) tif->tif_row); return (0); } tif->tif_curoff += cc; td->td_stripbytecount[strip] += cc; return (1); }
/* * Link the current directory into the * directory chain for the file. */ static int TIFFLinkDirectory(TIFF* tif) { static const char module[] = "TIFFLinkDirectory"; toff_t currdir, nextdir; toff_t diroff, nextdiroff; /* 32-bit or 64-bit dir offsets */ /* * New directory will go at end of file; if file not BigTIFF and * size is beyond 2^32, convert to BigTIFF now. */ tif->tif_diroff = ((TIFFSeekFile(tif, 0, SEEK_END) + 1) & ~(toff_t) 1); if (!isBigTIFF(tif) && isBigOff(tif->tif_diroff)) { if (!TIFFMakeBigTIFF(tif)) return (0); tif->tif_diroff = ((TIFFSeekFile(tif, 0, SEEK_END) + 1) & ~(toff_t) 1); } TIFFSetDirOff(tif,diroff,tif->tif_diroff); if (tif->tif_flags & TIFF_SWAB) TIFFSwabDirOff(tif,&diroff); /* * Handle SubIFDs */ if (tif->tif_flags & TIFF_INSUBIFD) { (void) TIFFSeekFile(tif, tif->tif_subifdoff, SEEK_SET); if (!WriteOK(tif, &diroff, TIFFDirOffLen(tif))) { TIFFErrorExt(tif->tif_clientdata, module, "%s: Error writing SubIFD directory link (%d)", tif->tif_name, TIFFGetErrno(tif)); 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 += TIFFDirOffLen(tif); else tif->tif_flags &= ~TIFF_INSUBIFD; return (1); } /* * First directory, overwrite offset in header. */ nextdir = TIFFGetHdrDirOff(tif,tif->tif_header); if (nextdir == 0) { TIFFSetHdrDirOff(tif,tif->tif_header, tif->tif_diroff); if (!SeekOK(tif, 0) || !WriteOK(tif, &tif->tif_header, sizeof(TIFFHeader)) ) { TIFFErrorExt(tif->tif_clientdata, tif->tif_name, "Error writing TIFF header (%d)", TIFFGetErrno(tif)); return (0); } return (1); } /* * Not the first directory, search to the last and append. */ do { uint64 dircount; /* 16-bit or 64-bit directory count */ if (!SeekOK(tif, nextdir) || !ReadOK(tif, &dircount, TIFFDirCntLen(tif))) { TIFFErrorExt(tif->tif_clientdata, module, "Error fetching directory count (%d)", TIFFGetErrno(tif)); return (0); } if (tif->tif_flags & TIFF_SWAB) TIFFSwabDirCnt(tif,&dircount); currdir = nextdir + TIFFDirCntLen(tif) + TIFFGetDirCnt(tif,dircount) * TDIREntryLen(tif); TIFFSeekFile(tif, currdir, SEEK_SET); if (!ReadOK(tif, &nextdiroff, TIFFDirOffLen(tif)) ) { TIFFErrorExt(tif->tif_clientdata, module, "Error fetching directory link (%d)", TIFFGetErrno(tif)); return (0); } if (tif->tif_flags & TIFF_SWAB) TIFFSwabDirOff(tif,&nextdiroff); nextdir = TIFFGetDirOff(tif,nextdiroff); } while (nextdir != 0); TIFFSeekFile(tif, currdir, SEEK_SET); if (!WriteOK(tif, &diroff, TIFFDirOffLen(tif)) ) { TIFFErrorExt(tif->tif_clientdata, module, "Error writing directory link (%d)", TIFFGetErrno(tif)); return (0); } return (1); }
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; }
/* * Read the next TIFF directory from a file * and convert it to the internal format. * We read directories sequentially. */ int TIFFReadDirectory(TIFF* tif) { register TIFFDirEntry* dp; register int n; register TIFFDirectory* td; TIFFDirEntry* dir; int iv; long v; double dv; const TIFFFieldInfo* fip; int fix; uint16 dircount; toff_t nextdiroff; char* cp; int diroutoforderwarning = 0; tif->tif_diroff = tif->tif_nextdiroff; if (tif->tif_diroff == 0) /* no more directories */ return (0); /* * Cleanup any previous compression state. */ (*tif->tif_cleanup)(tif); tif->tif_curdir++; nextdiroff = 0; if (!isMapped(tif)) { if (!SeekOK(tif, tif->tif_diroff)) { TIFFError(tif->tif_name, "Seek error accessing TIFF directory"); return (0); } if (!ReadOK(tif, &dircount, sizeof (uint16))) { TIFFError(tif->tif_name, "Can not read TIFF directory count"); return (0); } if (tif->tif_flags & TIFF_SWAB) TIFFSwabShort(&dircount); dir = (TIFFDirEntry *)CheckMalloc(tif, dircount * sizeof (TIFFDirEntry), "to read TIFF directory"); if (dir == NULL) return (0); if (!ReadOK(tif, dir, dircount*sizeof (TIFFDirEntry))) { TIFFError(tif->tif_name, "Can not read TIFF directory"); goto bad; } /* * Read offset to next directory for sequential scans. */ (void) ReadOK(tif, &nextdiroff, sizeof (uint32)); } else { toff_t off = tif->tif_diroff; if (off + sizeof (uint16) > tif->tif_size) { TIFFError(tif->tif_name, "Can not read TIFF directory count"); return (0); } else _TIFFmemcpy(&dircount, tif->tif_base + off, sizeof (uint16)); off += sizeof (uint16); if (tif->tif_flags & TIFF_SWAB) TIFFSwabShort(&dircount); dir = (TIFFDirEntry *)CheckMalloc(tif, dircount * sizeof (TIFFDirEntry), "to read TIFF directory"); if (dir == NULL) return (0); if (off + dircount*sizeof (TIFFDirEntry) > tif->tif_size) { TIFFError(tif->tif_name, "Can not read TIFF directory"); goto bad; } else _TIFFmemcpy(dir, tif->tif_base + off, dircount*sizeof (TIFFDirEntry)); off += dircount* sizeof (TIFFDirEntry); if (off + sizeof (uint32) <= tif->tif_size) _TIFFmemcpy(&nextdiroff, tif->tif_base+off, sizeof (uint32)); } if (tif->tif_flags & TIFF_SWAB) TIFFSwabLong(&nextdiroff); tif->tif_nextdiroff = nextdiroff; tif->tif_flags &= ~TIFF_BEENWRITING; /* reset before new dir */ /* * Setup default value and then make a pass over * the fields to check type and tag information, * and to extract info required to size data * structures. A second pass is made afterwards * to read in everthing not taken in the first pass. */ td = &tif->tif_dir; /* free any old stuff and reinit */ TIFFFreeDirectory(tif); TIFFDefaultDirectory(tif); /* * Electronic Arts writes gray-scale TIFF files * without a PlanarConfiguration directory entry. * Thus we setup a default value here, even though * the TIFF spec says there is no default value. */ TIFFSetField(tif, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG); /* * Sigh, we must make a separate pass through the * directory for the following reason: * * We must process the Compression tag in the first pass * in order to merge in codec-private tag definitions (otherwise * we may get complaints about unknown tags). However, the * Compression tag may be dependent on the SamplesPerPixel * tag value because older TIFF specs permited Compression * to be written as a SamplesPerPixel-count tag entry. * Thus if we don't first figure out the correct SamplesPerPixel * tag value then we may end up ignoring the Compression tag * value because it has an incorrect count value (if the * true value of SamplesPerPixel is not 1). * * It sure would have been nice if Aldus had really thought * this stuff through carefully. */ for (dp = dir, n = dircount; n > 0; n--, dp++) { if (tif->tif_flags & TIFF_SWAB) { TIFFSwabArrayOfShort(&dp->tdir_tag, 2); TIFFSwabArrayOfLong(&dp->tdir_count, 2); } if (dp->tdir_tag == TIFFTAG_SAMPLESPERPIXEL) { if (!TIFFFetchNormalTag(tif, dp)) goto bad; dp->tdir_tag = IGNORE; } } /* * First real pass over the directory. */ fix = 0; for (dp = dir, n = dircount; n > 0; n--, dp++) { /* * Find the field information entry for this tag. * Added check for tags to ignore ... [BFC] */ if( TIFFReassignTagToIgnore(TIS_EXTRACT, dp->tdir_tag) ) dp->tdir_tag = IGNORE; if (dp->tdir_tag == IGNORE) continue; /* * Silicon Beach (at least) writes unordered * directory tags (violating the spec). Handle * it here, but be obnoxious (maybe they'll fix it?). */ if (dp->tdir_tag < tif->tif_fieldinfo[fix]->field_tag) { if (!diroutoforderwarning) { TIFFWarning(tif->tif_name, "invalid TIFF directory; tags are not sorted in ascending order"); diroutoforderwarning = 1; } fix = 0; /* O(n^2) */ } while (fix < tif->tif_nfields && tif->tif_fieldinfo[fix]->field_tag < dp->tdir_tag) fix++; if (fix == tif->tif_nfields || tif->tif_fieldinfo[fix]->field_tag != dp->tdir_tag) { TIFFWarning(tif->tif_name, "unknown field with tag %d (0x%x) ignored", dp->tdir_tag, dp->tdir_tag); dp->tdir_tag = IGNORE; fix = 0; /* restart search */ continue; } /* * Null out old tags that we ignore. */ if (tif->tif_fieldinfo[fix]->field_bit == FIELD_IGNORE) { ignore: dp->tdir_tag = IGNORE; continue; } /* * Check data type. */ fip = tif->tif_fieldinfo[fix]; while (dp->tdir_type != (u_short) fip->field_type) { if (fip->field_type == TIFF_ANY) /* wildcard */ break; fip++, fix++; if (fix == tif->tif_nfields || fip->field_tag != dp->tdir_tag) { TIFFWarning(tif->tif_name, "wrong data type %d for \"%s\"; tag ignored", dp->tdir_type, fip[-1].field_name); goto ignore; } } /* * Check count if known in advance. */ if (fip->field_readcount != TIFF_VARIABLE) { uint32 expected = (fip->field_readcount == TIFF_SPP) ? (uint32) td->td_samplesperpixel : (uint32) fip->field_readcount; if (!CheckDirCount(tif, dp, expected)) goto ignore; } switch (dp->tdir_tag) { case TIFFTAG_COMPRESSION: /* * The 5.0 spec says the Compression tag has * one value, while earlier specs say it has * one value per sample. Because of this, we * accept the tag if one value is supplied. */ if (dp->tdir_count == 1) { v = TIFFExtractData(tif, dp->tdir_type, dp->tdir_offset); if (!TIFFSetField(tif, dp->tdir_tag, (int)v)) goto bad; break; } if (!TIFFFetchPerSampleShorts(tif, dp, &iv) || !TIFFSetField(tif, dp->tdir_tag, iv)) goto bad; dp->tdir_tag = IGNORE; break; case TIFFTAG_STRIPOFFSETS: case TIFFTAG_STRIPBYTECOUNTS: case TIFFTAG_TILEOFFSETS: case TIFFTAG_TILEBYTECOUNTS: TIFFSetFieldBit(tif, fip->field_bit); break; case TIFFTAG_IMAGEWIDTH: case TIFFTAG_IMAGELENGTH: case TIFFTAG_IMAGEDEPTH: case TIFFTAG_TILELENGTH: case TIFFTAG_TILEWIDTH: case TIFFTAG_TILEDEPTH: case TIFFTAG_PLANARCONFIG: case TIFFTAG_ROWSPERSTRIP: if (!TIFFFetchNormalTag(tif, dp)) goto bad; dp->tdir_tag = IGNORE; break; case TIFFTAG_EXTRASAMPLES: (void) TIFFFetchExtraSamples(tif, dp); dp->tdir_tag = IGNORE; break; } } /* * Allocate directory structure and setup defaults. */ if (!TIFFFieldSet(tif, FIELD_IMAGEDIMENSIONS)) { MissingRequired(tif, "ImageLength"); goto bad; } if (!TIFFFieldSet(tif, FIELD_PLANARCONFIG)) { MissingRequired(tif, "PlanarConfiguration"); goto bad; } /* * Setup appropriate structures (by strip or by tile) */ if (!TIFFFieldSet(tif, FIELD_TILEDIMENSIONS)) { td->td_nstrips = TIFFNumberOfStrips(tif); td->td_tilewidth = td->td_imagewidth; td->td_tilelength = td->td_rowsperstrip; td->td_tiledepth = td->td_imagedepth; tif->tif_flags &= ~TIFF_ISTILED; } else { td->td_nstrips = TIFFNumberOfTiles(tif); tif->tif_flags |= TIFF_ISTILED; } td->td_stripsperimage = td->td_nstrips; if (td->td_planarconfig == PLANARCONFIG_SEPARATE) td->td_stripsperimage /= td->td_samplesperpixel; if (!TIFFFieldSet(tif, FIELD_STRIPOFFSETS)) { MissingRequired(tif, isTiled(tif) ? "TileOffsets" : "StripOffsets"); goto bad; } /* * Second pass: extract other information. */ for (dp = dir, n = dircount; n > 0; n--, dp++) { if (dp->tdir_tag == IGNORE) continue; switch (dp->tdir_tag) { case TIFFTAG_MINSAMPLEVALUE: case TIFFTAG_MAXSAMPLEVALUE: case TIFFTAG_BITSPERSAMPLE: /* * The 5.0 spec says the Compression tag has * one value, while earlier specs say it has * one value per sample. Because of this, we * accept the tag if one value is supplied. * * The MinSampleValue, MaxSampleValue and * BitsPerSample tags are supposed to be written * as one value/sample, but some vendors incorrectly * write one value only -- so we accept that * as well (yech). */ if (dp->tdir_count == 1) { v = TIFFExtractData(tif, dp->tdir_type, dp->tdir_offset); if (!TIFFSetField(tif, dp->tdir_tag, (int)v)) goto bad; break; } /* fall thru... */ case TIFFTAG_DATATYPE: case TIFFTAG_SAMPLEFORMAT: if (!TIFFFetchPerSampleShorts(tif, dp, &iv) || !TIFFSetField(tif, dp->tdir_tag, iv)) goto bad; break; case TIFFTAG_SMINSAMPLEVALUE: case TIFFTAG_SMAXSAMPLEVALUE: if (!TIFFFetchPerSampleAnys(tif, dp, &dv) || !TIFFSetField(tif, dp->tdir_tag, dv)) goto bad; break; case TIFFTAG_STRIPOFFSETS: case TIFFTAG_TILEOFFSETS: if (!TIFFFetchStripThing(tif, dp, td->td_nstrips, &td->td_stripoffset)) goto bad; break; case TIFFTAG_STRIPBYTECOUNTS: case TIFFTAG_TILEBYTECOUNTS: if (!TIFFFetchStripThing(tif, dp, td->td_nstrips, &td->td_stripbytecount)) goto bad; break; case TIFFTAG_COLORMAP: case TIFFTAG_TRANSFERFUNCTION: /* * TransferFunction can have either 1x or 3x data * values; Colormap can have only 3x items. */ v = 1L<<td->td_bitspersample; if (dp->tdir_tag == TIFFTAG_COLORMAP || dp->tdir_count != (uint32) v) { if (!CheckDirCount(tif, dp, (uint32)(3*v))) break; } v *= sizeof (uint16); cp = CheckMalloc(tif, dp->tdir_count * sizeof (uint16), "to read \"TransferFunction\" tag"); if (cp != NULL) { if (TIFFFetchData(tif, dp, cp)) { /* * This deals with there being only * one array to apply to all samples. */ uint32 c = (uint32)1 << td->td_bitspersample; if (dp->tdir_count == c) v = 0; TIFFSetField(tif, dp->tdir_tag, cp, cp+v, cp+2*v); } _TIFFfree(cp); } break; case TIFFTAG_PAGENUMBER: case TIFFTAG_HALFTONEHINTS: case TIFFTAG_YCBCRSUBSAMPLING: case TIFFTAG_DOTRANGE: (void) TIFFFetchShortPair(tif, dp); break; #ifdef COLORIMETRY_SUPPORT case TIFFTAG_REFERENCEBLACKWHITE: (void) TIFFFetchRefBlackWhite(tif, dp); break; #endif /* BEGIN REV 4.0 COMPATIBILITY */ case TIFFTAG_OSUBFILETYPE: v = 0; switch (TIFFExtractData(tif, dp->tdir_type, dp->tdir_offset)) { case OFILETYPE_REDUCEDIMAGE: v = FILETYPE_REDUCEDIMAGE; break; case OFILETYPE_PAGE: v = FILETYPE_PAGE; break; } if (v) (void) TIFFSetField(tif, TIFFTAG_SUBFILETYPE, (int)v); break; /* END REV 4.0 COMPATIBILITY */ default: (void) TIFFFetchNormalTag(tif, dp); break; } } /* * Verify Palette image has a Colormap. */ if (td->td_photometric == PHOTOMETRIC_PALETTE && !TIFFFieldSet(tif, FIELD_COLORMAP)) { MissingRequired(tif, "Colormap"); goto bad; } /* * Attempt to deal with a missing StripByteCounts tag. */ if (!TIFFFieldSet(tif, FIELD_STRIPBYTECOUNTS)) { /* * Some manufacturers violate the spec by not giving * the size of the strips. In this case, assume there * is one uncompressed strip of data. */ if ((td->td_planarconfig == PLANARCONFIG_CONTIG && td->td_nstrips > 1) || (td->td_planarconfig == PLANARCONFIG_SEPARATE && td->td_nstrips != td->td_samplesperpixel)) { MissingRequired(tif, "StripByteCounts"); goto bad; } TIFFWarning(tif->tif_name, "TIFF directory is missing required \"%s\" field, calculating from imagelength", _TIFFFieldWithTag(tif,TIFFTAG_STRIPBYTECOUNTS)->field_name); EstimateStripByteCounts(tif, dir, dircount); #define BYTECOUNTLOOKSBAD \ ((td->td_stripbytecount[0] == 0 && td->td_stripoffset[0] != 0) || \ (td->td_compression == COMPRESSION_NONE && \ td->td_stripbytecount[0] > TIFFGetFileSize(tif) - td->td_stripoffset[0])) } else if (td->td_nstrips == 1 && BYTECOUNTLOOKSBAD) { /* * Plexus (and others) sometimes give a value * of zero for a tag when they don't know what * the correct value is! Try and handle the * simple case of estimating the size of a one * strip image. */ TIFFWarning(tif->tif_name, "Bogus \"%s\" field, ignoring and calculating from imagelength", _TIFFFieldWithTag(tif,TIFFTAG_STRIPBYTECOUNTS)->field_name); EstimateStripByteCounts(tif, dir, dircount); } if (dir) _TIFFfree((char *)dir); if (!TIFFFieldSet(tif, FIELD_MAXSAMPLEVALUE)) td->td_maxsamplevalue = (uint16)((1L<<td->td_bitspersample)-1); /* * Setup default compression scheme. */ if (!TIFFFieldSet(tif, FIELD_COMPRESSION)) TIFFSetField(tif, TIFFTAG_COMPRESSION, COMPRESSION_NONE); /* * Some manufacturers make life difficult by writing * large amounts of uncompressed data as a single strip. * This is contrary to the recommendations of the spec. * The following makes an attempt at breaking such images * into strips closer to the recommended 8k bytes. A * side effect, however, is that the RowsPerStrip tag * value may be changed. */ if (td->td_nstrips == 1 && td->td_compression == COMPRESSION_NONE && (tif->tif_flags & (TIFF_STRIPCHOP|TIFF_ISTILED)) == TIFF_STRIPCHOP) ChopUpSingleUncompressedStrip(tif); /* * Reinitialize i/o since we are starting on a new directory. */ tif->tif_row = (uint32) -1; tif->tif_curstrip = (tstrip_t) -1; tif->tif_col = (uint32) -1; tif->tif_curtile = (ttile_t) -1; tif->tif_tilesize = TIFFTileSize(tif); tif->tif_scanlinesize = TIFFScanlineSize(tif); return (1); bad: if (dir) _TIFFfree(dir); return (0); }
/* * 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); }
/* * Append the data to the specified strip. */ static int TIFFAppendToStrip(TIFF* tif, tstrip_t strip, tidata_t data, tsize_t cc) { TIFFDirectory *td = &tif->tif_dir; static const char module[] = "TIFFAppendToStrip"; if (_TIFFGetOffset(tif, strip) == 0 || tif->tif_curoff == 0) { /* * No current offset, set the current strip. */ assert(td->td_nstrips > 0); if (_TIFFGetOffset(tif, strip) != 0) { /* * Prevent overlapping of the data chunks. We need * this to enable in place updating of the compressed * images. Larger blocks will be moved at the end of * the file without any optimization of the spare * space, so such scheme is not too much effective. */ if (td->td_stripbytecountsorted) { if (strip == td->td_nstrips - 1 || _TIFFGetOffset(tif, strip + 1) < _TIFFGetOffset(tif, strip) + cc) { _TIFFSetOffset(tif, strip, TIFFSeekFile(tif, (toff_t)0, SEEK_END)); } } else { tstrip_t i; for (i = 0; i < td->td_nstrips; i++) { if (_TIFFGetOffset(tif, i) > _TIFFGetOffset(tif, strip) && _TIFFGetOffset(tif, i) < _TIFFGetOffset(tif, strip) + cc) { _TIFFSetOffset(tif, strip, TIFFSeekFile(tif, (toff_t)0, SEEK_END)); break; } } } /* check if block will overlap offsets or bytes counts arrays */ if ((td->td_stripoffsoff && _TIFFGetOffset(tif, strip) < td->td_stripoffsoff && _TIFFGetOffset(tif, strip) + cc > td->td_stripoffsoff) || (td->td_stripbcsoff && _TIFFGetOffset(tif, strip) < td->td_stripbcsoff && _TIFFGetOffset(tif, strip) + cc > td->td_stripbcsoff)) _TIFFSetOffset(tif, strip, TIFFSeekFile(tif, (toff_t)0, SEEK_END)); if (!SeekOK(tif, _TIFFGetOffset(tif, strip))) { TIFFErrorExt(tif->tif_clientdata, module, "%s: Seek error at scanline %lu", tif->tif_name, (unsigned long)tif->tif_row); return (0); } } else _TIFFSetOffset(tif, strip, TIFFSeekFile(tif, (toff_t) 0, SEEK_END)); tif->tif_curoff = _TIFFGetOffset(tif, strip); } if (!WriteOK(tif, data, cc)) { TIFFErrorExt(tif->tif_clientdata, module, "%s: Write error at scanline %lu (%d)", tif->tif_name, (unsigned long) tif->tif_row, TIFFGetErrno(tif)); return (0); } tif->tif_curoff += cc; _TIFFSetByteCount(tif, strip, _TIFFGetByteCount(tif, strip) + cc); return (1); }
static tmsize_t TIFFReadRawTile1(TIFF* tif, uint32 tile, void* buf, tmsize_t size, const char* module) { TIFFDirectory *td = &tif->tif_dir; 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) 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) 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); }
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; #if defined(__hpux) && defined(__LP64__) #define HDROFF(f) ((toff_t)(unsigned long) &(((TIFFHeader*) 0)->f)) #else #define HDROFF(f) ((toff_t) &(((TIFFHeader*) 0)->f)) #endif TIFFSeekFile(tif, HDROFF(tiff_diroff), SEEK_SET); if (!WriteOK(tif, &(tif->tif_header.tiff_diroff), sizeof (tif->tif_diroff))) { TIFFError(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))) { TIFFError(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))) { TIFFError(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))) { TIFFError(module, "Error writing directory link"); return (0); } } /* ** Now use TIFFWriteDirectory() normally. */ return TIFFWriteDirectory( tif ); }
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 to_read; tmsize_t read_ahead_mod; /* 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]; */ /* Not completely sure where the * 2 comes from, but probably for */ /* an exponentional growth strategy of tif_rawdatasize */ if( read_ahead < TIFF_TMSIZE_T_MAX / 2 ) read_ahead_mod = read_ahead * 2; else read_ahead_mod = read_ahead; if (read_ahead_mod > 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( 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? */ if( read_ahead_mod > tif->tif_rawdatasize ) to_read = read_ahead_mod - unused_data; else 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); if( !TIFFReadAndRealloc( tif, to_read, unused_data, 1, /* is_strip */ 0, /* strip_or_tile */ module) ) { return 0; } tif->tif_rawdataoff = tif->tif_rawdataoff + tif->tif_rawdataloaded - unused_data ; tif->tif_rawdataloaded = unused_data + to_read; tif->tif_rawcc = tif->tif_rawdataloaded; 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 ) { #ifdef JPEG_SUPPORT /* A bit messy since breaks the codec abstraction. Ultimately */ /* there should be a function pointer for that, but it seems */ /* only JPEG is affected. */ /* For JPEG, if there are multiple scans (can generally be known */ /* with the read_ahead used), we need to read the whole strip */ if( tif->tif_dir.td_compression==COMPRESSION_JPEG && (uint64)tif->tif_rawcc < td->td_stripbytecount[strip] ) { if( TIFFJPEGIsFullStripRequired(tif) ) { return TIFFFillStrip(tif, strip); } } #endif return TIFFStartStrip(tif, strip); } else { return 1; } }
/* * 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); #if SUBIFD_SUPPORT if (tif->tif_flags & TIFF_INSUBIFD) { (void) TIFFSeekFile(tif, tif->tif_subifdoff, SEEK_SET); if (!WriteOK(tif, &diroff, sizeof (diroff))) { TIFFError(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); } #endif if (tif->tif_header.tiff_diroff == 0) { /* * First directory, overwrite offset in header. */ tif->tif_header.tiff_diroff = tif->tif_diroff; #define HDROFF(f) ((toff_t) &(((TIFFHeader*) 0)->f)) (void) TIFFSeekFile(tif, HDROFF(tiff_diroff), SEEK_SET); if (!WriteOK(tif, &diroff, sizeof (diroff))) { TIFFError(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))) { TIFFError(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))) { TIFFError(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))) { TIFFError(module, "Error writing directory link"); return (0); } return (1); }
/* * Link the current directory into the * directory chain for the file. */ static int TIFFLinkDirectory(TIFF* tif) { static const char module[] = "TIFFLinkDirectory"; uint32 nextdir; uint32 diroff; tif->tif_diroff = (TIFFSeekFile(tif, (toff_t) 0, SEEK_END)+1) &~ 1; diroff = (uint32) tif->tif_diroff; if (tif->tif_flags & TIFF_SWAB) TIFFSwabLong(&diroff); #if SUBIFD_SUPPORT 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); } #endif if (tif->tif_header.tiff_diroff == 0) { /* * First directory, overwrite offset in header. */ tif->tif_header.tiff_diroff = (uint32) tif->tif_diroff; #define HDROFF(f) ((toff_t) &(((TIFFHeader*) 0)->f)) (void) TIFFSeekFile(tif, HDROFF(tiff_diroff), 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; #if defined(__INTEL_COMPILER) && 1 /* VDM auto patch */ # pragma ivdep # pragma swp # pragma unroll # pragma prefetch # if 0 # pragma simd noassert # endif #endif /* VDM auto patch */ 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); (void) TIFFSeekFile(tif, -(toff_t) sizeof (nextdir), SEEK_CUR); if (!WriteOK(tif, &diroff, sizeof (diroff))) { TIFFErrorExt(tif->tif_clientdata, module, "Error writing directory link"); return (0); } return (1); }