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