xref: /aosp_15_r20/external/zstd/zlibWrapper/gzwrite.c (revision 01826a4963a0d8a59bc3812d29bdf0fb76416722)
1*01826a49SYabin Cui /* gzwrite.c contains minimal changes required to be compiled with zlibWrapper:
2*01826a49SYabin Cui  * - gz_statep was converted to union to work with -Wstrict-aliasing=1      */
3*01826a49SYabin Cui 
4*01826a49SYabin Cui  /* gzwrite.c -- zlib functions for writing gzip files
5*01826a49SYabin Cui  * Copyright (C) 2004-2017 Mark Adler
6*01826a49SYabin Cui  * For conditions of distribution and use, see https://www.zlib.net/zlib_license.html
7*01826a49SYabin Cui  */
8*01826a49SYabin Cui 
9*01826a49SYabin Cui #include <assert.h>
10*01826a49SYabin Cui 
11*01826a49SYabin Cui #include "gzguts.h"
12*01826a49SYabin Cui 
13*01826a49SYabin Cui /* Local functions */
14*01826a49SYabin Cui local int gz_init _Z_OF((gz_statep));
15*01826a49SYabin Cui local int gz_comp _Z_OF((gz_statep, int));
16*01826a49SYabin Cui local int gz_zero _Z_OF((gz_statep, z_off64_t));
17*01826a49SYabin Cui local z_size_t gz_write _Z_OF((gz_statep, voidpc, z_size_t));
18*01826a49SYabin Cui 
19*01826a49SYabin Cui /* Initialize state for writing a gzip file.  Mark initialization by setting
20*01826a49SYabin Cui    state.state->size to non-zero.  Return -1 on a memory allocation failure, or 0 on
21*01826a49SYabin Cui    success. */
gz_init(gz_statep state)22*01826a49SYabin Cui local int gz_init(gz_statep state) {
23*01826a49SYabin Cui     int ret;
24*01826a49SYabin Cui     z_streamp strm = &(state.state->strm);
25*01826a49SYabin Cui 
26*01826a49SYabin Cui     /* allocate input buffer (double size for gzprintf) */
27*01826a49SYabin Cui     state.state->in = (unsigned char*)malloc(state.state->want << 1);
28*01826a49SYabin Cui     if (state.state->in == NULL) {
29*01826a49SYabin Cui         gz_error(state, Z_MEM_ERROR, "out of memory");
30*01826a49SYabin Cui         return -1;
31*01826a49SYabin Cui     }
32*01826a49SYabin Cui 
33*01826a49SYabin Cui     /* only need output buffer and deflate state if compressing */
34*01826a49SYabin Cui     if (!state.state->direct) {
35*01826a49SYabin Cui         /* allocate output buffer */
36*01826a49SYabin Cui         state.state->out = (unsigned char*)malloc(state.state->want);
37*01826a49SYabin Cui         if (state.state->out == NULL) {
38*01826a49SYabin Cui             free(state.state->in);
39*01826a49SYabin Cui             gz_error(state, Z_MEM_ERROR, "out of memory");
40*01826a49SYabin Cui             return -1;
41*01826a49SYabin Cui         }
42*01826a49SYabin Cui 
43*01826a49SYabin Cui         /* allocate deflate memory, set up for gzip compression */
44*01826a49SYabin Cui         strm->zalloc = Z_NULL;
45*01826a49SYabin Cui         strm->zfree = Z_NULL;
46*01826a49SYabin Cui         strm->opaque = Z_NULL;
47*01826a49SYabin Cui         ret = deflateInit2(strm, state.state->level, Z_DEFLATED,
48*01826a49SYabin Cui                            MAX_WBITS + 16, DEF_MEM_LEVEL, state.state->strategy);
49*01826a49SYabin Cui         if (ret != Z_OK) {
50*01826a49SYabin Cui             free(state.state->out);
51*01826a49SYabin Cui             free(state.state->in);
52*01826a49SYabin Cui             gz_error(state, Z_MEM_ERROR, "out of memory");
53*01826a49SYabin Cui             return -1;
54*01826a49SYabin Cui         }
55*01826a49SYabin Cui         strm->next_in = NULL;
56*01826a49SYabin Cui     }
57*01826a49SYabin Cui 
58*01826a49SYabin Cui     /* mark state as initialized */
59*01826a49SYabin Cui     state.state->size = state.state->want;
60*01826a49SYabin Cui 
61*01826a49SYabin Cui     /* initialize write buffer if compressing */
62*01826a49SYabin Cui     if (!state.state->direct) {
63*01826a49SYabin Cui         strm->avail_out = state.state->size;
64*01826a49SYabin Cui         strm->next_out = state.state->out;
65*01826a49SYabin Cui         state.state->x.next = strm->next_out;
66*01826a49SYabin Cui     }
67*01826a49SYabin Cui     return 0;
68*01826a49SYabin Cui }
69*01826a49SYabin Cui 
70*01826a49SYabin Cui /* Compress whatever is at avail_in and next_in and write to the output file.
71*01826a49SYabin Cui    Return -1 if there is an error writing to the output file or if gz_init()
72*01826a49SYabin Cui    fails to allocate memory, otherwise 0.  flush is assumed to be a valid
73*01826a49SYabin Cui    deflate() flush value.  If flush is Z_FINISH, then the deflate() state is
74*01826a49SYabin Cui    reset to start a new gzip stream.  If gz->direct is true, then simply write
75*01826a49SYabin Cui    to the output file without compressing, and ignore flush. */
gz_comp(gz_statep state,int flush)76*01826a49SYabin Cui local int gz_comp(gz_statep state, int flush) {
77*01826a49SYabin Cui     int ret, writ;
78*01826a49SYabin Cui     unsigned have, put, max = ((unsigned)-1 >> 2) + 1;
79*01826a49SYabin Cui     z_streamp strm = &(state.state->strm);
80*01826a49SYabin Cui 
81*01826a49SYabin Cui     /* allocate memory if this is the first time through */
82*01826a49SYabin Cui     if (state.state->size == 0 && gz_init(state) == -1)
83*01826a49SYabin Cui         return -1;
84*01826a49SYabin Cui 
85*01826a49SYabin Cui     /* write directly if requested */
86*01826a49SYabin Cui     if (state.state->direct) {
87*01826a49SYabin Cui         while (strm->avail_in) {
88*01826a49SYabin Cui             put = strm->avail_in > max ? max : strm->avail_in;
89*01826a49SYabin Cui             writ = (int)write(state.state->fd, strm->next_in, put);
90*01826a49SYabin Cui             if (writ < 0) {
91*01826a49SYabin Cui                 gz_error(state, Z_ERRNO, zstrerror());
92*01826a49SYabin Cui                 return -1;
93*01826a49SYabin Cui             }
94*01826a49SYabin Cui             strm->avail_in -= (unsigned)writ;
95*01826a49SYabin Cui             strm->next_in += writ;
96*01826a49SYabin Cui         }
97*01826a49SYabin Cui         return 0;
98*01826a49SYabin Cui     }
99*01826a49SYabin Cui 
100*01826a49SYabin Cui     /* run deflate() on provided input until it produces no more output */
101*01826a49SYabin Cui     ret = Z_OK;
102*01826a49SYabin Cui     do {
103*01826a49SYabin Cui         /* write out current buffer contents if full, or if flushing, but if
104*01826a49SYabin Cui            doing Z_FINISH then don't write until we get to Z_STREAM_END */
105*01826a49SYabin Cui         if (strm->avail_out == 0 || (flush != Z_NO_FLUSH &&
106*01826a49SYabin Cui             (flush != Z_FINISH || ret == Z_STREAM_END))) {
107*01826a49SYabin Cui             while (strm->next_out > state.state->x.next) {
108*01826a49SYabin Cui                 put = strm->next_out - state.state->x.next > (int)max ? max :
109*01826a49SYabin Cui                       (unsigned)(strm->next_out - state.state->x.next);
110*01826a49SYabin Cui                 writ = (int)write(state.state->fd, state.state->x.next, put);
111*01826a49SYabin Cui                 if (writ < 0) {
112*01826a49SYabin Cui                     gz_error(state, Z_ERRNO, zstrerror());
113*01826a49SYabin Cui                     return -1;
114*01826a49SYabin Cui                 }
115*01826a49SYabin Cui                 state.state->x.next += writ;
116*01826a49SYabin Cui             }
117*01826a49SYabin Cui             if (strm->avail_out == 0) {
118*01826a49SYabin Cui                 strm->avail_out = state.state->size;
119*01826a49SYabin Cui                 strm->next_out = state.state->out;
120*01826a49SYabin Cui                 state.state->x.next = state.state->out;
121*01826a49SYabin Cui             }
122*01826a49SYabin Cui         }
123*01826a49SYabin Cui 
124*01826a49SYabin Cui         /* compress */
125*01826a49SYabin Cui         have = strm->avail_out;
126*01826a49SYabin Cui         ret = deflate(strm, flush);
127*01826a49SYabin Cui         if (ret == Z_STREAM_ERROR) {
128*01826a49SYabin Cui             gz_error(state, Z_STREAM_ERROR,
129*01826a49SYabin Cui                       "internal error: deflate stream corrupt");
130*01826a49SYabin Cui             return -1;
131*01826a49SYabin Cui         }
132*01826a49SYabin Cui         have -= strm->avail_out;
133*01826a49SYabin Cui     } while (have);
134*01826a49SYabin Cui 
135*01826a49SYabin Cui     /* if that completed a deflate stream, allow another to start */
136*01826a49SYabin Cui     if (flush == Z_FINISH)
137*01826a49SYabin Cui         deflateReset(strm);
138*01826a49SYabin Cui 
139*01826a49SYabin Cui     /* all done, no errors */
140*01826a49SYabin Cui     return 0;
141*01826a49SYabin Cui }
142*01826a49SYabin Cui 
143*01826a49SYabin Cui /* Compress len zeros to output.  Return -1 on a write error or memory
144*01826a49SYabin Cui    allocation failure by gz_comp(), or 0 on success. */
gz_zero(gz_statep state,z_off64_t len)145*01826a49SYabin Cui local int gz_zero(gz_statep state, z_off64_t len) {
146*01826a49SYabin Cui     int first;
147*01826a49SYabin Cui     unsigned n;
148*01826a49SYabin Cui     z_streamp strm = &(state.state->strm);
149*01826a49SYabin Cui 
150*01826a49SYabin Cui     /* consume whatever's left in the input buffer */
151*01826a49SYabin Cui     if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1)
152*01826a49SYabin Cui         return -1;
153*01826a49SYabin Cui 
154*01826a49SYabin Cui     /* compress len zeros (len guaranteed > 0) */
155*01826a49SYabin Cui     first = 1;
156*01826a49SYabin Cui     while (len) {
157*01826a49SYabin Cui         n = GT_OFF(state.state->size) || (z_off64_t)state.state->size > len ?
158*01826a49SYabin Cui             (unsigned)len : state.state->size;
159*01826a49SYabin Cui         if (first) {
160*01826a49SYabin Cui             memset(state.state->in, 0, n);
161*01826a49SYabin Cui             first = 0;
162*01826a49SYabin Cui         }
163*01826a49SYabin Cui         strm->avail_in = n;
164*01826a49SYabin Cui         strm->next_in = state.state->in;
165*01826a49SYabin Cui         state.state->x.pos += n;
166*01826a49SYabin Cui         if (gz_comp(state, Z_NO_FLUSH) == -1)
167*01826a49SYabin Cui             return -1;
168*01826a49SYabin Cui         len -= n;
169*01826a49SYabin Cui     }
170*01826a49SYabin Cui     return 0;
171*01826a49SYabin Cui }
172*01826a49SYabin Cui 
173*01826a49SYabin Cui /* Write len bytes from buf to file.  Return the number of bytes written.  If
174*01826a49SYabin Cui    the returned value is less than len, then there was an error. */
gz_write(gz_statep state,voidpc buf,z_size_t len)175*01826a49SYabin Cui local z_size_t gz_write(gz_statep state, voidpc buf, z_size_t len) {
176*01826a49SYabin Cui     z_size_t put = len;
177*01826a49SYabin Cui 
178*01826a49SYabin Cui     /* if len is zero, avoid unnecessary operations */
179*01826a49SYabin Cui     if (len == 0)
180*01826a49SYabin Cui         return 0;
181*01826a49SYabin Cui 
182*01826a49SYabin Cui     /* allocate memory if this is the first time through */
183*01826a49SYabin Cui     if (state.state->size == 0 && gz_init(state) == -1)
184*01826a49SYabin Cui         return 0;
185*01826a49SYabin Cui 
186*01826a49SYabin Cui     /* check for seek request */
187*01826a49SYabin Cui     if (state.state->seek) {
188*01826a49SYabin Cui         state.state->seek = 0;
189*01826a49SYabin Cui         if (gz_zero(state, state.state->skip) == -1)
190*01826a49SYabin Cui             return 0;
191*01826a49SYabin Cui     }
192*01826a49SYabin Cui 
193*01826a49SYabin Cui     /* for small len, copy to input buffer, otherwise compress directly */
194*01826a49SYabin Cui     if (len < state.state->size) {
195*01826a49SYabin Cui         /* copy to input buffer, compress when full */
196*01826a49SYabin Cui         do {
197*01826a49SYabin Cui             z_size_t have, copy;
198*01826a49SYabin Cui 
199*01826a49SYabin Cui             if (state.state->strm.avail_in == 0)
200*01826a49SYabin Cui                 state.state->strm.next_in = state.state->in;
201*01826a49SYabin Cui             have = (unsigned)((state.state->strm.next_in + state.state->strm.avail_in) -
202*01826a49SYabin Cui                               state.state->in);
203*01826a49SYabin Cui             copy = state.state->size - have;
204*01826a49SYabin Cui             if (copy > len)
205*01826a49SYabin Cui                 copy = len;
206*01826a49SYabin Cui             memcpy(state.state->in + have, buf, copy);
207*01826a49SYabin Cui             state.state->strm.avail_in += copy;
208*01826a49SYabin Cui             state.state->x.pos += copy;
209*01826a49SYabin Cui             buf = (const char *)buf + copy;
210*01826a49SYabin Cui             len -= copy;
211*01826a49SYabin Cui             if (len && gz_comp(state, Z_NO_FLUSH) == -1)
212*01826a49SYabin Cui                 return 0;
213*01826a49SYabin Cui         } while (len);
214*01826a49SYabin Cui     }
215*01826a49SYabin Cui     else {
216*01826a49SYabin Cui         /* consume whatever's left in the input buffer */
217*01826a49SYabin Cui         if (state.state->strm.avail_in && gz_comp(state, Z_NO_FLUSH) == -1)
218*01826a49SYabin Cui             return 0;
219*01826a49SYabin Cui 
220*01826a49SYabin Cui         /* directly compress user buffer to file */
221*01826a49SYabin Cui         state.state->strm.next_in = (z_const Bytef *)buf;
222*01826a49SYabin Cui         do {
223*01826a49SYabin Cui             z_size_t n = (unsigned)-1;
224*01826a49SYabin Cui             if (n > len)
225*01826a49SYabin Cui                 n = len;
226*01826a49SYabin Cui             state.state->strm.avail_in = (z_uInt)n;
227*01826a49SYabin Cui             state.state->x.pos += n;
228*01826a49SYabin Cui             if (gz_comp(state, Z_NO_FLUSH) == -1)
229*01826a49SYabin Cui                 return 0;
230*01826a49SYabin Cui             len -= n;
231*01826a49SYabin Cui         } while (len);
232*01826a49SYabin Cui     }
233*01826a49SYabin Cui 
234*01826a49SYabin Cui     /* input was all buffered or compressed */
235*01826a49SYabin Cui     return put;
236*01826a49SYabin Cui }
237*01826a49SYabin Cui 
238*01826a49SYabin Cui /* -- see zlib.h -- */
gzwrite(gzFile file,voidpc buf,unsigned len)239*01826a49SYabin Cui int ZEXPORT gzwrite(gzFile file, voidpc buf, unsigned len) {
240*01826a49SYabin Cui     gz_statep state;
241*01826a49SYabin Cui 
242*01826a49SYabin Cui     /* get internal structure */
243*01826a49SYabin Cui     if (file == NULL)
244*01826a49SYabin Cui         return 0;
245*01826a49SYabin Cui     state.file = file;
246*01826a49SYabin Cui 
247*01826a49SYabin Cui     /* check that we're writing and that there's no error */
248*01826a49SYabin Cui     if (state.state->mode != GZ_WRITE || state.state->err != Z_OK)
249*01826a49SYabin Cui         return 0;
250*01826a49SYabin Cui 
251*01826a49SYabin Cui     /* since an int is returned, make sure len fits in one, otherwise return
252*01826a49SYabin Cui        with an error (this avoids a flaw in the interface) */
253*01826a49SYabin Cui     if ((int)len < 0) {
254*01826a49SYabin Cui         gz_error(state, Z_DATA_ERROR, "requested length does not fit in int");
255*01826a49SYabin Cui         return 0;
256*01826a49SYabin Cui     }
257*01826a49SYabin Cui 
258*01826a49SYabin Cui     /* write len bytes from buf (the return value will fit in an int) */
259*01826a49SYabin Cui     return (int)gz_write(state, buf, len);
260*01826a49SYabin Cui }
261*01826a49SYabin Cui 
262*01826a49SYabin Cui /* -- see zlib.h -- */
gzfwrite(voidpc buf,z_size_t size,z_size_t nitems,gzFile file)263*01826a49SYabin Cui z_size_t ZEXPORT gzfwrite(voidpc buf, z_size_t size, z_size_t nitems,
264*01826a49SYabin Cui                           gzFile file) {
265*01826a49SYabin Cui     z_size_t len;
266*01826a49SYabin Cui     gz_statep state;
267*01826a49SYabin Cui 
268*01826a49SYabin Cui     /* get internal structure */
269*01826a49SYabin Cui     assert(size != 0);
270*01826a49SYabin Cui     if (file == NULL)
271*01826a49SYabin Cui         return 0;
272*01826a49SYabin Cui     state.file = file;
273*01826a49SYabin Cui 
274*01826a49SYabin Cui     /* check that we're writing and that there's no error */
275*01826a49SYabin Cui     if (state.state->mode != GZ_WRITE || state.state->err != Z_OK)
276*01826a49SYabin Cui         return 0;
277*01826a49SYabin Cui 
278*01826a49SYabin Cui     /* compute bytes to read -- error on overflow */
279*01826a49SYabin Cui     len = nitems * size;
280*01826a49SYabin Cui     if (size && (len / size != nitems)) {
281*01826a49SYabin Cui         gz_error(state, Z_STREAM_ERROR, "request does not fit in a size_t");
282*01826a49SYabin Cui         return 0;
283*01826a49SYabin Cui     }
284*01826a49SYabin Cui 
285*01826a49SYabin Cui     /* write len bytes to buf, return the number of full items written */
286*01826a49SYabin Cui     return len ? gz_write(state, buf, len) / size : 0;
287*01826a49SYabin Cui }
288*01826a49SYabin Cui 
289*01826a49SYabin Cui /* -- see zlib.h -- */
gzputc(gzFile file,int c)290*01826a49SYabin Cui int ZEXPORT gzputc(gzFile file, int c) {
291*01826a49SYabin Cui     unsigned have;
292*01826a49SYabin Cui     unsigned char buf[1];
293*01826a49SYabin Cui     gz_statep state;
294*01826a49SYabin Cui     z_streamp strm;
295*01826a49SYabin Cui 
296*01826a49SYabin Cui     /* get internal structure */
297*01826a49SYabin Cui     if (file == NULL)
298*01826a49SYabin Cui         return -1;
299*01826a49SYabin Cui     state.file = file;
300*01826a49SYabin Cui     strm = &(state.state->strm);
301*01826a49SYabin Cui 
302*01826a49SYabin Cui     /* check that we're writing and that there's no error */
303*01826a49SYabin Cui     if (state.state->mode != GZ_WRITE || state.state->err != Z_OK)
304*01826a49SYabin Cui         return -1;
305*01826a49SYabin Cui 
306*01826a49SYabin Cui     /* check for seek request */
307*01826a49SYabin Cui     if (state.state->seek) {
308*01826a49SYabin Cui         state.state->seek = 0;
309*01826a49SYabin Cui         if (gz_zero(state, state.state->skip) == -1)
310*01826a49SYabin Cui             return -1;
311*01826a49SYabin Cui     }
312*01826a49SYabin Cui 
313*01826a49SYabin Cui     /* try writing to input buffer for speed (state.state->size == 0 if buffer not
314*01826a49SYabin Cui        initialized) */
315*01826a49SYabin Cui     if (state.state->size) {
316*01826a49SYabin Cui         if (strm->avail_in == 0)
317*01826a49SYabin Cui             strm->next_in = state.state->in;
318*01826a49SYabin Cui         have = (unsigned)((strm->next_in + strm->avail_in) - state.state->in);
319*01826a49SYabin Cui         if (have < state.state->size) {
320*01826a49SYabin Cui             state.state->in[have] = (unsigned char)c;
321*01826a49SYabin Cui             strm->avail_in++;
322*01826a49SYabin Cui             state.state->x.pos++;
323*01826a49SYabin Cui             return c & 0xff;
324*01826a49SYabin Cui         }
325*01826a49SYabin Cui     }
326*01826a49SYabin Cui 
327*01826a49SYabin Cui     /* no room in buffer or not initialized, use gz_write() */
328*01826a49SYabin Cui     buf[0] = (unsigned char)c;
329*01826a49SYabin Cui     if (gz_write(state, buf, 1) != 1)
330*01826a49SYabin Cui         return -1;
331*01826a49SYabin Cui     return c & 0xff;
332*01826a49SYabin Cui }
333*01826a49SYabin Cui 
334*01826a49SYabin Cui /* -- see zlib.h -- */
gzputs(gzFile file,const char * str)335*01826a49SYabin Cui int ZEXPORT gzputs(gzFile file, const char *str) {
336*01826a49SYabin Cui     int ret;
337*01826a49SYabin Cui     z_size_t len;
338*01826a49SYabin Cui     gz_statep state;
339*01826a49SYabin Cui 
340*01826a49SYabin Cui     /* get internal structure */
341*01826a49SYabin Cui     if (file == NULL)
342*01826a49SYabin Cui         return -1;
343*01826a49SYabin Cui     state.file = file;
344*01826a49SYabin Cui 
345*01826a49SYabin Cui     /* check that we're writing and that there's no error */
346*01826a49SYabin Cui     if (state.state->mode != GZ_WRITE || state.state->err != Z_OK)
347*01826a49SYabin Cui         return -1;
348*01826a49SYabin Cui 
349*01826a49SYabin Cui     /* write string */
350*01826a49SYabin Cui     len = strlen(str);
351*01826a49SYabin Cui     ret = (int)gz_write(state, str, len);
352*01826a49SYabin Cui     return ret == 0 && len != 0 ? -1 : ret;
353*01826a49SYabin Cui }
354*01826a49SYabin Cui 
355*01826a49SYabin Cui #if defined(STDC) || defined(Z_HAVE_STDARG_H)
356*01826a49SYabin Cui #include <stdarg.h>
357*01826a49SYabin Cui 
358*01826a49SYabin Cui /* -- see zlib.h -- */
gzvprintf(gzFile file,const char * format,va_list va)359*01826a49SYabin Cui int ZEXPORTVA gzvprintf(gzFile file, const char *format, va_list va) {
360*01826a49SYabin Cui     int len;
361*01826a49SYabin Cui     unsigned left;
362*01826a49SYabin Cui     char *next;
363*01826a49SYabin Cui     gz_statep state;
364*01826a49SYabin Cui     z_streamp strm;
365*01826a49SYabin Cui 
366*01826a49SYabin Cui     /* get internal structure */
367*01826a49SYabin Cui     if (file == NULL)
368*01826a49SYabin Cui         return Z_STREAM_ERROR;
369*01826a49SYabin Cui     state.file = file;
370*01826a49SYabin Cui     strm = &(state.state->strm);
371*01826a49SYabin Cui 
372*01826a49SYabin Cui     /* check that we're writing and that there's no error */
373*01826a49SYabin Cui     if (state.state->mode != GZ_WRITE || state.state->err != Z_OK)
374*01826a49SYabin Cui         return Z_STREAM_ERROR;
375*01826a49SYabin Cui 
376*01826a49SYabin Cui     /* make sure we have some buffer space */
377*01826a49SYabin Cui     if (state.state->size == 0 && gz_init(state) == -1)
378*01826a49SYabin Cui         return state.state->err;
379*01826a49SYabin Cui 
380*01826a49SYabin Cui     /* check for seek request */
381*01826a49SYabin Cui     if (state.state->seek) {
382*01826a49SYabin Cui         state.state->seek = 0;
383*01826a49SYabin Cui         if (gz_zero(state, state.state->skip) == -1)
384*01826a49SYabin Cui             return state.state->err;
385*01826a49SYabin Cui     }
386*01826a49SYabin Cui 
387*01826a49SYabin Cui     /* do the printf() into the input buffer, put length in len -- the input
388*01826a49SYabin Cui        buffer is double-sized just for this function, so there is guaranteed to
389*01826a49SYabin Cui        be state.state->size bytes available after the current contents */
390*01826a49SYabin Cui     if (strm->avail_in == 0)
391*01826a49SYabin Cui         strm->next_in = state.state->in;
392*01826a49SYabin Cui     next = (char *)(state.state->in + (strm->next_in - state.state->in) + strm->avail_in);
393*01826a49SYabin Cui     next[state.state->size - 1] = 0;
394*01826a49SYabin Cui #ifdef NO_vsnprintf
395*01826a49SYabin Cui #  ifdef HAS_vsprintf_void
396*01826a49SYabin Cui     (void)vsprintf(next, format, va);
397*01826a49SYabin Cui     for (len = 0; len < state.state->size; len++)
398*01826a49SYabin Cui         if (next[len] == 0) break;
399*01826a49SYabin Cui #  else
400*01826a49SYabin Cui     len = vsprintf(next, format, va);
401*01826a49SYabin Cui #  endif
402*01826a49SYabin Cui #else
403*01826a49SYabin Cui #  ifdef HAS_vsnprintf_void
404*01826a49SYabin Cui     (void)vsnprintf(next, state.state->size, format, va);
405*01826a49SYabin Cui     len = strlen(next);
406*01826a49SYabin Cui #  else
407*01826a49SYabin Cui     len = vsnprintf(next, state.state->size, format, va);
408*01826a49SYabin Cui #  endif
409*01826a49SYabin Cui #endif
410*01826a49SYabin Cui 
411*01826a49SYabin Cui     /* check that printf() results fit in buffer */
412*01826a49SYabin Cui     if (len == 0 || (unsigned)len >= state.state->size || next[state.state->size - 1] != 0)
413*01826a49SYabin Cui         return 0;
414*01826a49SYabin Cui 
415*01826a49SYabin Cui     /* update buffer and position, compress first half if past that */
416*01826a49SYabin Cui     strm->avail_in += (unsigned)len;
417*01826a49SYabin Cui     state.state->x.pos += len;
418*01826a49SYabin Cui     if (strm->avail_in >= state.state->size) {
419*01826a49SYabin Cui         left = strm->avail_in - state.state->size;
420*01826a49SYabin Cui         strm->avail_in = state.state->size;
421*01826a49SYabin Cui         if (gz_comp(state, Z_NO_FLUSH) == -1)
422*01826a49SYabin Cui             return state.state->err;
423*01826a49SYabin Cui         memcpy(state.state->in, state.state->in + state.state->size, left);
424*01826a49SYabin Cui         strm->next_in = state.state->in;
425*01826a49SYabin Cui         strm->avail_in = left;
426*01826a49SYabin Cui     }
427*01826a49SYabin Cui     return len;
428*01826a49SYabin Cui }
429*01826a49SYabin Cui 
gzprintf(gzFile file,const char * format,...)430*01826a49SYabin Cui int ZEXPORTVA gzprintf(gzFile file, const char *format, ...) {
431*01826a49SYabin Cui     va_list va;
432*01826a49SYabin Cui     int ret;
433*01826a49SYabin Cui 
434*01826a49SYabin Cui     va_start(va, format);
435*01826a49SYabin Cui     ret = gzvprintf(file, format, va);
436*01826a49SYabin Cui     va_end(va);
437*01826a49SYabin Cui     return ret;
438*01826a49SYabin Cui }
439*01826a49SYabin Cui 
440*01826a49SYabin Cui #else /* !STDC && !Z_HAVE_STDARG_H */
441*01826a49SYabin Cui 
442*01826a49SYabin Cui /* -- see zlib.h -- */
gzprintf(gzFile file,const char * format,int a1,int a2,int a3,int a4,int a5,int a6,int a7,int a8,int a9,int a10,int a11,int a12,int a13,int a14,int a15,int a16,int a17,int a18,int a19,int a20)443*01826a49SYabin Cui int ZEXPORTVA gzprintf(gzFile file, const char *format, int a1, int a2, int a3,
444*01826a49SYabin Cui                        int a4, int a5, int a6, int a7, int a8, int a9, int a10,
445*01826a49SYabin Cui                        int a11, int a12, int a13, int a14, int a15, int a16,
446*01826a49SYabin Cui                        int a17, int a18, int a19, int a20) {
447*01826a49SYabin Cui     unsigned len, left;
448*01826a49SYabin Cui     char *next;
449*01826a49SYabin Cui     gz_statep state;
450*01826a49SYabin Cui     z_streamp strm;
451*01826a49SYabin Cui 
452*01826a49SYabin Cui     /* get internal structure */
453*01826a49SYabin Cui     if (file == NULL)
454*01826a49SYabin Cui         return Z_STREAM_ERROR;
455*01826a49SYabin Cui     state = (gz_statep)file;
456*01826a49SYabin Cui     strm = &(state.state->strm);
457*01826a49SYabin Cui 
458*01826a49SYabin Cui     /* check that can really pass pointer in ints */
459*01826a49SYabin Cui     if (sizeof(int) != sizeof(void *))
460*01826a49SYabin Cui         return Z_STREAM_ERROR;
461*01826a49SYabin Cui 
462*01826a49SYabin Cui     /* check that we're writing and that there's no error */
463*01826a49SYabin Cui     if (state.state->mode != GZ_WRITE || state.state->err != Z_OK)
464*01826a49SYabin Cui         return Z_STREAM_ERROR;
465*01826a49SYabin Cui 
466*01826a49SYabin Cui     /* make sure we have some buffer space */
467*01826a49SYabin Cui     if (state.state->size == 0 && gz_init(state) == -1)
468*01826a49SYabin Cui         return state.state->error;
469*01826a49SYabin Cui 
470*01826a49SYabin Cui     /* check for seek request */
471*01826a49SYabin Cui     if (state.state->seek) {
472*01826a49SYabin Cui         state.state->seek = 0;
473*01826a49SYabin Cui         if (gz_zero(state, state.state->skip) == -1)
474*01826a49SYabin Cui             return state.state->error;
475*01826a49SYabin Cui     }
476*01826a49SYabin Cui 
477*01826a49SYabin Cui     /* do the printf() into the input buffer, put length in len -- the input
478*01826a49SYabin Cui        buffer is double-sized just for this function, so there is guaranteed to
479*01826a49SYabin Cui        be state.state->size bytes available after the current contents */
480*01826a49SYabin Cui     if (strm->avail_in == 0)
481*01826a49SYabin Cui         strm->next_in = state.state->in;
482*01826a49SYabin Cui     next = (char *)(strm->next_in + strm->avail_in);
483*01826a49SYabin Cui     next[state.state->size - 1] = 0;
484*01826a49SYabin Cui #ifdef NO_snprintf
485*01826a49SYabin Cui #  ifdef HAS_sprintf_void
486*01826a49SYabin Cui     sprintf(next, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12,
487*01826a49SYabin Cui             a13, a14, a15, a16, a17, a18, a19, a20);
488*01826a49SYabin Cui     for (len = 0; len < size; len++)
489*01826a49SYabin Cui         if (next[len] == 0)
490*01826a49SYabin Cui             break;
491*01826a49SYabin Cui #  else
492*01826a49SYabin Cui     len = sprintf(next, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11,
493*01826a49SYabin Cui                   a12, a13, a14, a15, a16, a17, a18, a19, a20);
494*01826a49SYabin Cui #  endif
495*01826a49SYabin Cui #else
496*01826a49SYabin Cui #  ifdef HAS_snprintf_void
497*01826a49SYabin Cui     snprintf(next, state.state->size, format, a1, a2, a3, a4, a5, a6, a7, a8, a9,
498*01826a49SYabin Cui              a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20);
499*01826a49SYabin Cui     len = strlen(next);
500*01826a49SYabin Cui #  else
501*01826a49SYabin Cui     len = snprintf(next, state.state->size, format, a1, a2, a3, a4, a5, a6, a7, a8,
502*01826a49SYabin Cui                    a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20);
503*01826a49SYabin Cui #  endif
504*01826a49SYabin Cui #endif
505*01826a49SYabin Cui 
506*01826a49SYabin Cui     /* check that printf() results fit in buffer */
507*01826a49SYabin Cui     if (len == 0 || len >= state.state->size || next[state.state->size - 1] != 0)
508*01826a49SYabin Cui         return 0;
509*01826a49SYabin Cui 
510*01826a49SYabin Cui     /* update buffer and position, compress first half if past that */
511*01826a49SYabin Cui     strm->avail_in += len;
512*01826a49SYabin Cui     state.state->x.pos += len;
513*01826a49SYabin Cui     if (strm->avail_in >= state.state->size) {
514*01826a49SYabin Cui         left = strm->avail_in - state.state->size;
515*01826a49SYabin Cui         strm->avail_in = state.state->size;
516*01826a49SYabin Cui         if (gz_comp(state, Z_NO_FLUSH) == -1)
517*01826a49SYabin Cui             return state.state->err;
518*01826a49SYabin Cui         memcpy(state.state->in, state.state->in + state.state->size, left);
519*01826a49SYabin Cui         strm->next_in = state.state->in;
520*01826a49SYabin Cui         strm->avail_in = left;
521*01826a49SYabin Cui     }
522*01826a49SYabin Cui     return (int)len;
523*01826a49SYabin Cui }
524*01826a49SYabin Cui 
525*01826a49SYabin Cui #endif
526*01826a49SYabin Cui 
527*01826a49SYabin Cui /* -- see zlib.h -- */
gzflush(gzFile file,int flush)528*01826a49SYabin Cui int ZEXPORT gzflush(gzFile file, int flush) {
529*01826a49SYabin Cui     gz_statep state;
530*01826a49SYabin Cui 
531*01826a49SYabin Cui     /* get internal structure */
532*01826a49SYabin Cui     if (file == NULL)
533*01826a49SYabin Cui         return Z_STREAM_ERROR;
534*01826a49SYabin Cui     state.file = file;
535*01826a49SYabin Cui 
536*01826a49SYabin Cui     /* check that we're writing and that there's no error */
537*01826a49SYabin Cui     if (state.state->mode != GZ_WRITE || state.state->err != Z_OK)
538*01826a49SYabin Cui         return Z_STREAM_ERROR;
539*01826a49SYabin Cui 
540*01826a49SYabin Cui     /* check flush parameter */
541*01826a49SYabin Cui     if (flush < 0 || flush > Z_FINISH)
542*01826a49SYabin Cui         return Z_STREAM_ERROR;
543*01826a49SYabin Cui 
544*01826a49SYabin Cui     /* check for seek request */
545*01826a49SYabin Cui     if (state.state->seek) {
546*01826a49SYabin Cui         state.state->seek = 0;
547*01826a49SYabin Cui         if (gz_zero(state, state.state->skip) == -1)
548*01826a49SYabin Cui             return state.state->err;
549*01826a49SYabin Cui     }
550*01826a49SYabin Cui 
551*01826a49SYabin Cui     /* compress remaining data with requested flush */
552*01826a49SYabin Cui     (void)gz_comp(state, flush);
553*01826a49SYabin Cui     return state.state->err;
554*01826a49SYabin Cui }
555*01826a49SYabin Cui 
556*01826a49SYabin Cui /* -- see zlib.h -- */
gzsetparams(gzFile file,int level,int strategy)557*01826a49SYabin Cui int ZEXPORT gzsetparams(gzFile file, int level, int strategy) {
558*01826a49SYabin Cui     gz_statep state;
559*01826a49SYabin Cui     z_streamp strm;
560*01826a49SYabin Cui 
561*01826a49SYabin Cui     /* get internal structure */
562*01826a49SYabin Cui     if (file == NULL)
563*01826a49SYabin Cui         return Z_STREAM_ERROR;
564*01826a49SYabin Cui     state.file = file;
565*01826a49SYabin Cui     strm = &(state.state->strm);
566*01826a49SYabin Cui 
567*01826a49SYabin Cui     /* check that we're writing and that there's no error */
568*01826a49SYabin Cui     if (state.state->mode != GZ_WRITE || state.state->err != Z_OK)
569*01826a49SYabin Cui         return Z_STREAM_ERROR;
570*01826a49SYabin Cui 
571*01826a49SYabin Cui     /* if no change is requested, then do nothing */
572*01826a49SYabin Cui     if (level == state.state->level && strategy == state.state->strategy)
573*01826a49SYabin Cui         return Z_OK;
574*01826a49SYabin Cui 
575*01826a49SYabin Cui     /* check for seek request */
576*01826a49SYabin Cui     if (state.state->seek) {
577*01826a49SYabin Cui         state.state->seek = 0;
578*01826a49SYabin Cui         if (gz_zero(state, state.state->skip) == -1)
579*01826a49SYabin Cui             return state.state->err;
580*01826a49SYabin Cui     }
581*01826a49SYabin Cui 
582*01826a49SYabin Cui     /* change compression parameters for subsequent input */
583*01826a49SYabin Cui     if (state.state->size) {
584*01826a49SYabin Cui         /* flush previous input with previous parameters before changing */
585*01826a49SYabin Cui         if (strm->avail_in && gz_comp(state, Z_BLOCK) == -1)
586*01826a49SYabin Cui             return state.state->err;
587*01826a49SYabin Cui         deflateParams(strm, level, strategy);
588*01826a49SYabin Cui     }
589*01826a49SYabin Cui     state.state->level = level;
590*01826a49SYabin Cui     state.state->strategy = strategy;
591*01826a49SYabin Cui     return Z_OK;
592*01826a49SYabin Cui }
593*01826a49SYabin Cui 
594*01826a49SYabin Cui /* -- see zlib.h -- */
gzclose_w(gzFile file)595*01826a49SYabin Cui int ZEXPORT gzclose_w(gzFile file) {
596*01826a49SYabin Cui     int ret = Z_OK;
597*01826a49SYabin Cui     gz_statep state;
598*01826a49SYabin Cui 
599*01826a49SYabin Cui     /* get internal structure */
600*01826a49SYabin Cui     if (file == NULL)
601*01826a49SYabin Cui         return Z_STREAM_ERROR;
602*01826a49SYabin Cui     state.file = file;
603*01826a49SYabin Cui 
604*01826a49SYabin Cui     /* check that we're writing */
605*01826a49SYabin Cui     if (state.state->mode != GZ_WRITE)
606*01826a49SYabin Cui         return Z_STREAM_ERROR;
607*01826a49SYabin Cui 
608*01826a49SYabin Cui     /* check for seek request */
609*01826a49SYabin Cui     if (state.state->seek) {
610*01826a49SYabin Cui         state.state->seek = 0;
611*01826a49SYabin Cui         if (gz_zero(state, state.state->skip) == -1)
612*01826a49SYabin Cui             ret = state.state->err;
613*01826a49SYabin Cui     }
614*01826a49SYabin Cui 
615*01826a49SYabin Cui     /* flush, free memory, and close file */
616*01826a49SYabin Cui     if (gz_comp(state, Z_FINISH) == -1)
617*01826a49SYabin Cui         ret = state.state->err;
618*01826a49SYabin Cui     if (state.state->size) {
619*01826a49SYabin Cui         if (!state.state->direct) {
620*01826a49SYabin Cui             (void)deflateEnd(&(state.state->strm));
621*01826a49SYabin Cui             free(state.state->out);
622*01826a49SYabin Cui         }
623*01826a49SYabin Cui         free(state.state->in);
624*01826a49SYabin Cui     }
625*01826a49SYabin Cui     gz_error(state, Z_OK, NULL);
626*01826a49SYabin Cui     free(state.state->path);
627*01826a49SYabin Cui     if (close(state.state->fd) == -1)
628*01826a49SYabin Cui         ret = Z_ERRNO;
629*01826a49SYabin Cui     free(state.state);
630*01826a49SYabin Cui     return ret;
631*01826a49SYabin Cui }
632