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