xref: /aosp_15_r20/external/pdfium/third_party/libtiff/tif_flush.c (revision 3ac0a46f773bac49fa9476ec2b1cf3f8da5ec3a4)
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 
TIFFFlush(TIFF * tif)30 int TIFFFlush(TIFF *tif)
31 {
32     if (tif->tif_mode == O_RDONLY)
33         return 1;
34 
35     if (!TIFFFlushData(tif))
36         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     if ((tif->tif_flags & TIFF_DIRTYSTRIP) &&
44         !(tif->tif_flags & TIFF_DIRTYDIRECT) && tif->tif_mode == O_RDWR)
45     {
46         if (TIFFForceStrileArrayWriting(tif))
47             return 1;
48     }
49 
50     if ((tif->tif_flags & (TIFF_DIRTYDIRECT | TIFF_DIRTYSTRIP)) &&
51         !TIFFRewriteDirectory(tif))
52         return (0);
53 
54     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  */
TIFFForceStrileArrayWriting(TIFF * tif)76 int TIFFForceStrileArrayWriting(TIFF *tif)
77 {
78     static const char module[] = "TIFFForceStrileArrayWriting";
79     const int isTiled = TIFFIsTiled(tif);
80 
81     if (tif->tif_mode == O_RDONLY)
82     {
83         TIFFErrorExtR(tif, tif->tif_name, "File opened in read-only mode");
84         return 0;
85     }
86     if (tif->tif_diroff == 0)
87     {
88         TIFFErrorExtR(tif, module, "Directory has not yet been written");
89         return 0;
90     }
91     if ((tif->tif_flags & TIFF_DIRTYDIRECT) != 0)
92     {
93         TIFFErrorExtR(tif, module,
94                       "Directory has changes other than the strile arrays. "
95                       "TIFFRewriteDirectory() should be called instead");
96         return 0;
97     }
98 
99     if (!(tif->tif_flags & TIFF_DIRTYSTRIP))
100     {
101         if (!(tif->tif_dir.td_stripoffset_entry.tdir_tag != 0 &&
102               tif->tif_dir.td_stripoffset_entry.tdir_count == 0 &&
103               tif->tif_dir.td_stripoffset_entry.tdir_type == 0 &&
104               tif->tif_dir.td_stripoffset_entry.tdir_offset.toff_long8 == 0 &&
105               tif->tif_dir.td_stripbytecount_entry.tdir_tag != 0 &&
106               tif->tif_dir.td_stripbytecount_entry.tdir_count == 0 &&
107               tif->tif_dir.td_stripbytecount_entry.tdir_type == 0 &&
108               tif->tif_dir.td_stripbytecount_entry.tdir_offset.toff_long8 == 0))
109         {
110             TIFFErrorExtR(tif, module,
111                           "Function not called together with "
112                           "TIFFDeferStrileArrayWriting()");
113             return 0;
114         }
115 
116         if (tif->tif_dir.td_stripoffset_p == NULL && !TIFFSetupStrips(tif))
117             return 0;
118     }
119 
120     if (_TIFFRewriteField(tif,
121                           isTiled ? TIFFTAG_TILEOFFSETS : TIFFTAG_STRIPOFFSETS,
122                           TIFF_LONG8, tif->tif_dir.td_nstrips,
123                           tif->tif_dir.td_stripoffset_p) &&
124         _TIFFRewriteField(
125             tif, isTiled ? TIFFTAG_TILEBYTECOUNTS : TIFFTAG_STRIPBYTECOUNTS,
126             TIFF_LONG8, tif->tif_dir.td_nstrips,
127             tif->tif_dir.td_stripbytecount_p))
128     {
129         tif->tif_flags &= ~TIFF_DIRTYSTRIP;
130         tif->tif_flags &= ~TIFF_BEENWRITING;
131         return 1;
132     }
133 
134     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  */
TIFFFlushData(TIFF * tif)146 int TIFFFlushData(TIFF *tif)
147 {
148     if ((tif->tif_flags & TIFF_BEENWRITING) == 0)
149         return (1);
150     if (tif->tif_flags & TIFF_POSTENCODE)
151     {
152         tif->tif_flags &= ~TIFF_POSTENCODE;
153         if (!(*tif->tif_postencode)(tif))
154             return (0);
155     }
156     return (TIFFFlushData1(tif));
157 }
158