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