Line data Source code
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 : #include "tiffiop.h" 29 : 30 52856 : int TIFFFlush(TIFF *tif) 31 : { 32 52856 : if (tif->tif_mode == O_RDONLY) 33 0 : return 1; 34 : 35 52856 : if (!TIFFFlushData(tif)) 36 12 : return (0); 37 : 38 : /* In update (r+) mode we try to detect the case where 39 : only the strip/tile map has been altered, and we try to 40 : rewrite only that portion of the directory without 41 : making any other changes */ 42 : 43 52842 : if ((tif->tif_flags & TIFF_DIRTYSTRIP) && 44 34592 : !(tif->tif_flags & TIFF_DIRTYDIRECT) && tif->tif_mode == O_RDWR) 45 : { 46 7530 : if (TIFFForceStrileArrayWriting(tif)) 47 7530 : return 1; 48 : } 49 : 50 72404 : if ((tif->tif_flags & (TIFF_DIRTYDIRECT | TIFF_DIRTYSTRIP)) && 51 27091 : !TIFFRewriteDirectory(tif)) 52 20 : return (0); 53 : 54 45293 : return (1); 55 : } 56 : 57 : /* 58 : * This is an advanced writing function that must be used in a particular 59 : * sequence, and together with TIFFDeferStrileArrayWriting(), 60 : * to make its intended effect. Its aim is to force the writing of 61 : * the [Strip/Tile][Offsets/ByteCounts] arrays at the end of the file, when 62 : * they have not yet been rewritten. 63 : * 64 : * The typical sequence of calls is: 65 : * TIFFOpen() 66 : * [ TIFFCreateDirectory(tif) ] 67 : * Set fields with calls to TIFFSetField(tif, ...) 68 : * TIFFDeferStrileArrayWriting(tif) 69 : * TIFFWriteCheck(tif, ...) 70 : * TIFFWriteDirectory(tif) 71 : * ... potentially create other directories and come back to the above directory 72 : * TIFFForceStrileArrayWriting(tif) 73 : * 74 : * Returns 1 in case of success, 0 otherwise. 75 : */ 76 7853 : int TIFFForceStrileArrayWriting(TIFF *tif) 77 : { 78 : static const char module[] = "TIFFForceStrileArrayWriting"; 79 7853 : const int isTiled = TIFFIsTiled(tif); 80 : 81 7853 : if (tif->tif_mode == O_RDONLY) 82 : { 83 0 : TIFFErrorExtR(tif, tif->tif_name, "File opened in read-only mode"); 84 0 : return 0; 85 : } 86 7853 : if (tif->tif_diroff == 0) 87 : { 88 0 : TIFFErrorExtR(tif, module, "Directory has not yet been written"); 89 0 : return 0; 90 : } 91 7853 : if ((tif->tif_flags & TIFF_DIRTYDIRECT) != 0) 92 : { 93 0 : TIFFErrorExtR(tif, module, 94 : "Directory has changes other than the strile arrays. " 95 : "TIFFRewriteDirectory() should be called instead"); 96 0 : return 0; 97 : } 98 : 99 7853 : if (!(tif->tif_flags & TIFF_DIRTYSTRIP)) 100 : { 101 323 : if (!(tif->tif_dir.td_stripoffset_entry.tdir_tag != 0 && 102 323 : tif->tif_dir.td_stripoffset_entry.tdir_count == 0 && 103 323 : tif->tif_dir.td_stripoffset_entry.tdir_type == 0 && 104 323 : tif->tif_dir.td_stripoffset_entry.tdir_offset.toff_long8 == 0 && 105 323 : tif->tif_dir.td_stripbytecount_entry.tdir_tag != 0 && 106 323 : tif->tif_dir.td_stripbytecount_entry.tdir_count == 0 && 107 323 : tif->tif_dir.td_stripbytecount_entry.tdir_type == 0 && 108 323 : tif->tif_dir.td_stripbytecount_entry.tdir_offset.toff_long8 == 0)) 109 : { 110 0 : TIFFErrorExtR(tif, module, 111 : "Function not called together with " 112 : "TIFFDeferStrileArrayWriting()"); 113 0 : return 0; 114 : } 115 : 116 323 : if (tif->tif_dir.td_stripoffset_p == NULL && !TIFFSetupStrips(tif)) 117 0 : return 0; 118 : } 119 : 120 7853 : if (_TIFFRewriteField(tif, 121 : isTiled ? TIFFTAG_TILEOFFSETS : TIFFTAG_STRIPOFFSETS, 122 7853 : TIFF_LONG8, tif->tif_dir.td_nstrips, 123 15706 : tif->tif_dir.td_stripoffset_p) && 124 7853 : _TIFFRewriteField( 125 : tif, isTiled ? TIFFTAG_TILEBYTECOUNTS : TIFFTAG_STRIPBYTECOUNTS, 126 7853 : TIFF_LONG8, tif->tif_dir.td_nstrips, 127 7853 : tif->tif_dir.td_stripbytecount_p)) 128 : { 129 7853 : tif->tif_flags &= ~TIFF_DIRTYSTRIP; 130 7853 : tif->tif_flags &= ~TIFF_BEENWRITING; 131 7853 : return 1; 132 : } 133 : 134 0 : return 0; 135 : } 136 : 137 : /* 138 : * Flush buffered data to the file. 139 : * 140 : * Frank Warmerdam'2000: I modified this to return 1 if TIFF_BEENWRITING 141 : * is not set, so that TIFFFlush() will proceed to write out the directory. 142 : * The documentation says returning 1 is an error indicator, but not having 143 : * been writing isn't exactly a an error. Hopefully this doesn't cause 144 : * problems for other people. 145 : */ 146 52878 : int TIFFFlushData(TIFF *tif) 147 : { 148 52878 : if ((tif->tif_flags & TIFF_BEENWRITING) == 0) 149 18044 : return (1); 150 34834 : if (tif->tif_flags & TIFF_POSTENCODE) 151 : { 152 11 : tif->tif_flags &= ~TIFF_POSTENCODE; 153 11 : if (!(*tif->tif_postencode)(tif)) 154 0 : return (0); 155 : } 156 34834 : return (TIFFFlushData1(tif)); 157 : }