xref: /reactos/dll/3rdparty/libtiff/tif_flush.c (revision 8a978a17)
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