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