1 /* 2 * Copyright (c) 1988-1997 Sam Leffler 3 * Copyright (c) 1991-1997 Silicon Graphics, Inc. 4 * 5 * Permission to use, copy, modify, distribute, and sell this software and 6 * its documentation for any purpose is hereby granted without fee, provided 7 * that (i) the above copyright notices and this permission notice appear in 8 * all copies of the software and related documentation, and (ii) the names of 9 * Sam Leffler and Silicon Graphics may not be used in any advertising or 10 * publicity relating to the software without the specific, prior written 11 * permission of Sam Leffler and Silicon Graphics. 12 * 13 * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND, 14 * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY 15 * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. 16 * 17 * IN NO EVENT SHALL SAM LEFFLER OR SILICON GRAPHICS BE LIABLE FOR 18 * ANY SPECIAL, INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, 19 * OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 20 * WHETHER OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF 21 * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE 22 * OF THIS SOFTWARE. 23 */ 24 25 /* 26 * TIFF Library. 27 */ 28 29 #include <precomp.h> 30 31 int 32 TIFFFlush(TIFF* tif) 33 { 34 if( tif->tif_mode == O_RDONLY ) 35 return 1; 36 37 if (!TIFFFlushData(tif)) 38 return (0); 39 40 /* In update (r+) mode we try to detect the case where 41 only the strip/tile map has been altered, and we try to 42 rewrite only that portion of the directory without 43 making any other changes */ 44 45 if( (tif->tif_flags & TIFF_DIRTYSTRIP) 46 && !(tif->tif_flags & TIFF_DIRTYDIRECT) 47 && tif->tif_mode == O_RDWR ) 48 { 49 if( TIFFForceStrileArrayWriting(tif) ) 50 return 1; 51 } 52 53 if ((tif->tif_flags & (TIFF_DIRTYDIRECT|TIFF_DIRTYSTRIP)) 54 && !TIFFRewriteDirectory(tif)) 55 return (0); 56 57 return (1); 58 } 59 60 /* 61 * This is an advanced writing function that must be used in a particular 62 * sequence, and together with TIFFDeferStrileArrayWriting(), 63 * to make its intended effect. Its aim is to force the writing of 64 * the [Strip/Tile][Offsets/ByteCounts] arrays at the end of the file, when 65 * they have not yet been rewritten. 66 * 67 * The typical sequence of calls is: 68 * TIFFOpen() 69 * [ TIFFCreateDirectory(tif) ] 70 * Set fields with calls to TIFFSetField(tif, ...) 71 * TIFFDeferStrileArrayWriting(tif) 72 * TIFFWriteCheck(tif, ...) 73 * TIFFWriteDirectory(tif) 74 * ... potentially create other directories and come back to the above directory 75 * TIFFForceStrileArrayWriting(tif) 76 * 77 * Returns 1 in case of success, 0 otherwise. 78 */ 79 int TIFFForceStrileArrayWriting(TIFF* tif) 80 { 81 static const char module[] = "TIFFForceStrileArrayWriting"; 82 const int isTiled = TIFFIsTiled(tif); 83 84 if (tif->tif_mode == O_RDONLY) 85 { 86 TIFFErrorExt(tif->tif_clientdata, tif->tif_name, 87 "File opened in read-only mode"); 88 return 0; 89 } 90 if( tif->tif_diroff == 0 ) 91 { 92 TIFFErrorExt(tif->tif_clientdata, module, 93 "Directory has not yet been written"); 94 return 0; 95 } 96 if( (tif->tif_flags & TIFF_DIRTYDIRECT) != 0 ) 97 { 98 TIFFErrorExt(tif->tif_clientdata, module, 99 "Directory has changes other than the strile arrays. " 100 "TIFFRewriteDirectory() should be called instead"); 101 return 0; 102 } 103 104 if( !(tif->tif_flags & TIFF_DIRTYSTRIP) ) 105 { 106 if( !(tif->tif_dir.td_stripoffset_entry.tdir_tag != 0 && 107 tif->tif_dir.td_stripoffset_entry.tdir_count == 0 && 108 tif->tif_dir.td_stripoffset_entry.tdir_type == 0 && 109 tif->tif_dir.td_stripoffset_entry.tdir_offset.toff_long8 == 0 && 110 tif->tif_dir.td_stripbytecount_entry.tdir_tag != 0 && 111 tif->tif_dir.td_stripbytecount_entry.tdir_count == 0 && 112 tif->tif_dir.td_stripbytecount_entry.tdir_type == 0 && 113 tif->tif_dir.td_stripbytecount_entry.tdir_offset.toff_long8 == 0) ) 114 { 115 TIFFErrorExt(tif->tif_clientdata, module, 116 "Function not called together with " 117 "TIFFDeferStrileArrayWriting()"); 118 return 0; 119 } 120 121 if (tif->tif_dir.td_stripoffset_p == NULL && !TIFFSetupStrips(tif)) 122 return 0; 123 } 124 125 if( _TIFFRewriteField( tif, 126 isTiled ? TIFFTAG_TILEOFFSETS : 127 TIFFTAG_STRIPOFFSETS, 128 TIFF_LONG8, 129 tif->tif_dir.td_nstrips, 130 tif->tif_dir.td_stripoffset_p ) 131 && _TIFFRewriteField( tif, 132 isTiled ? TIFFTAG_TILEBYTECOUNTS : 133 TIFFTAG_STRIPBYTECOUNTS, 134 TIFF_LONG8, 135 tif->tif_dir.td_nstrips, 136 tif->tif_dir.td_stripbytecount_p ) ) 137 { 138 tif->tif_flags &= ~TIFF_DIRTYSTRIP; 139 tif->tif_flags &= ~TIFF_BEENWRITING; 140 return 1; 141 } 142 143 return 0; 144 } 145 146 /* 147 * Flush buffered data to the file. 148 * 149 * Frank Warmerdam'2000: I modified this to return 1 if TIFF_BEENWRITING 150 * is not set, so that TIFFFlush() will proceed to write out the directory. 151 * The documentation says returning 1 is an error indicator, but not having 152 * been writing isn't exactly a an error. Hopefully this doesn't cause 153 * problems for other people. 154 */ 155 int 156 TIFFFlushData(TIFF* tif) 157 { 158 if ((tif->tif_flags & TIFF_BEENWRITING) == 0) 159 return (1); 160 if (tif->tif_flags & TIFF_POSTENCODE) { 161 tif->tif_flags &= ~TIFF_POSTENCODE; 162 if (!(*tif->tif_postencode)(tif)) 163 return (0); 164 } 165 return (TIFFFlushData1(tif)); 166 } 167 168 /* vim: set ts=8 sts=8 sw=8 noet: */ 169 /* 170 * Local Variables: 171 * mode: c 172 * c-basic-offset: 8 173 * fill-column: 78 174 * End: 175 */ 176