1212397c6Schristos /* gzwrite.c -- zlib functions for writing gzip files
2*4b169a6bSchristos * Copyright (C) 2004-2019 Mark Adler
3212397c6Schristos * For conditions of distribution and use, see copyright notice in zlib.h
4212397c6Schristos */
5212397c6Schristos
6212397c6Schristos #include "gzguts.h"
7212397c6Schristos
8212397c6Schristos /* Local functions */
9212397c6Schristos local int gz_init OF((gz_statep));
10212397c6Schristos local int gz_comp OF((gz_statep, int));
11212397c6Schristos local int gz_zero OF((gz_statep, z_off64_t));
12796c32c9Schristos local z_size_t gz_write OF((gz_statep, voidpc, z_size_t));
13212397c6Schristos
14212397c6Schristos /* Initialize state for writing a gzip file. Mark initialization by setting
15796c32c9Schristos state->size to non-zero. Return -1 on a memory allocation failure, or 0 on
16796c32c9Schristos success. */
gz_init(state)17212397c6Schristos local int gz_init(state)
18212397c6Schristos gz_statep state;
19212397c6Schristos {
20212397c6Schristos int ret;
21212397c6Schristos z_streamp strm = &(state->strm);
22212397c6Schristos
23796c32c9Schristos /* allocate input buffer (double size for gzprintf) */
24796c32c9Schristos state->in = (unsigned char *)malloc(state->want << 1);
25212397c6Schristos if (state->in == NULL) {
26212397c6Schristos gz_error(state, Z_MEM_ERROR, "out of memory");
27212397c6Schristos return -1;
28212397c6Schristos }
29212397c6Schristos
30212397c6Schristos /* only need output buffer and deflate state if compressing */
31212397c6Schristos if (!state->direct) {
32212397c6Schristos /* allocate output buffer */
33ba340e45Schristos state->out = (unsigned char *)malloc(state->want);
34212397c6Schristos if (state->out == NULL) {
35212397c6Schristos free(state->in);
36212397c6Schristos gz_error(state, Z_MEM_ERROR, "out of memory");
37212397c6Schristos return -1;
38212397c6Schristos }
39212397c6Schristos
40212397c6Schristos /* allocate deflate memory, set up for gzip compression */
41212397c6Schristos strm->zalloc = Z_NULL;
42212397c6Schristos strm->zfree = Z_NULL;
43212397c6Schristos strm->opaque = Z_NULL;
44212397c6Schristos ret = deflateInit2(strm, state->level, Z_DEFLATED,
45212397c6Schristos MAX_WBITS + 16, DEF_MEM_LEVEL, state->strategy);
46212397c6Schristos if (ret != Z_OK) {
47212397c6Schristos free(state->out);
48212397c6Schristos free(state->in);
49212397c6Schristos gz_error(state, Z_MEM_ERROR, "out of memory");
50212397c6Schristos return -1;
51212397c6Schristos }
52796c32c9Schristos strm->next_in = NULL;
53212397c6Schristos }
54212397c6Schristos
55212397c6Schristos /* mark state as initialized */
56212397c6Schristos state->size = state->want;
57212397c6Schristos
58212397c6Schristos /* initialize write buffer if compressing */
59212397c6Schristos if (!state->direct) {
60212397c6Schristos strm->avail_out = state->size;
61212397c6Schristos strm->next_out = state->out;
62212397c6Schristos state->x.next = strm->next_out;
63212397c6Schristos }
64212397c6Schristos return 0;
65212397c6Schristos }
66212397c6Schristos
67212397c6Schristos /* Compress whatever is at avail_in and next_in and write to the output file.
68796c32c9Schristos Return -1 if there is an error writing to the output file or if gz_init()
69796c32c9Schristos fails to allocate memory, otherwise 0. flush is assumed to be a valid
70796c32c9Schristos deflate() flush value. If flush is Z_FINISH, then the deflate() state is
71796c32c9Schristos reset to start a new gzip stream. If gz->direct is true, then simply write
72796c32c9Schristos to the output file without compressing, and ignore flush. */
gz_comp(state,flush)73212397c6Schristos local int gz_comp(state, flush)
74212397c6Schristos gz_statep state;
75212397c6Schristos int flush;
76212397c6Schristos {
77796c32c9Schristos int ret, writ;
78796c32c9Schristos unsigned have, put, max = ((unsigned)-1 >> 2) + 1;
79212397c6Schristos z_streamp strm = &(state->strm);
80212397c6Schristos
81212397c6Schristos /* allocate memory if this is the first time through */
82212397c6Schristos if (state->size == 0 && gz_init(state) == -1)
83212397c6Schristos return -1;
84212397c6Schristos
85212397c6Schristos /* write directly if requested */
86212397c6Schristos if (state->direct) {
87796c32c9Schristos while (strm->avail_in) {
88796c32c9Schristos put = strm->avail_in > max ? max : strm->avail_in;
89796c32c9Schristos writ = write(state->fd, strm->next_in, put);
90796c32c9Schristos if (writ < 0) {
91212397c6Schristos gz_error(state, Z_ERRNO, zstrerror());
92212397c6Schristos return -1;
93212397c6Schristos }
94796c32c9Schristos strm->avail_in -= (unsigned)writ;
95796c32c9Schristos strm->next_in += writ;
96796c32c9Schristos }
97212397c6Schristos return 0;
98212397c6Schristos }
99212397c6Schristos
100*4b169a6bSchristos /* check for a pending reset */
101*4b169a6bSchristos if (state->reset) {
102*4b169a6bSchristos /* don't start a new gzip member unless there is data to write */
103*4b169a6bSchristos if (strm->avail_in == 0)
104*4b169a6bSchristos return 0;
105*4b169a6bSchristos deflateReset(strm);
106*4b169a6bSchristos state->reset = 0;
107*4b169a6bSchristos }
108*4b169a6bSchristos
109212397c6Schristos /* run deflate() on provided input until it produces no more output */
110212397c6Schristos ret = Z_OK;
111212397c6Schristos do {
112212397c6Schristos /* write out current buffer contents if full, or if flushing, but if
113212397c6Schristos doing Z_FINISH then don't write until we get to Z_STREAM_END */
114212397c6Schristos if (strm->avail_out == 0 || (flush != Z_NO_FLUSH &&
115212397c6Schristos (flush != Z_FINISH || ret == Z_STREAM_END))) {
116796c32c9Schristos while (strm->next_out > state->x.next) {
117796c32c9Schristos put = strm->next_out - state->x.next > (int)max ? max :
118796c32c9Schristos (unsigned)(strm->next_out - state->x.next);
119796c32c9Schristos writ = write(state->fd, state->x.next, put);
120796c32c9Schristos if (writ < 0) {
121212397c6Schristos gz_error(state, Z_ERRNO, zstrerror());
122212397c6Schristos return -1;
123212397c6Schristos }
124796c32c9Schristos state->x.next += writ;
125796c32c9Schristos }
126212397c6Schristos if (strm->avail_out == 0) {
127212397c6Schristos strm->avail_out = state->size;
128212397c6Schristos strm->next_out = state->out;
129796c32c9Schristos state->x.next = state->out;
130212397c6Schristos }
131212397c6Schristos }
132212397c6Schristos
133212397c6Schristos /* compress */
134212397c6Schristos have = strm->avail_out;
135212397c6Schristos ret = deflate(strm, flush);
136212397c6Schristos if (ret == Z_STREAM_ERROR) {
137212397c6Schristos gz_error(state, Z_STREAM_ERROR,
138212397c6Schristos "internal error: deflate stream corrupt");
139212397c6Schristos return -1;
140212397c6Schristos }
141212397c6Schristos have -= strm->avail_out;
142212397c6Schristos } while (have);
143212397c6Schristos
144212397c6Schristos /* if that completed a deflate stream, allow another to start */
145212397c6Schristos if (flush == Z_FINISH)
146*4b169a6bSchristos state->reset = 1;
147212397c6Schristos
148212397c6Schristos /* all done, no errors */
149212397c6Schristos return 0;
150212397c6Schristos }
151212397c6Schristos
152796c32c9Schristos /* Compress len zeros to output. Return -1 on a write error or memory
153796c32c9Schristos allocation failure by gz_comp(), or 0 on success. */
gz_zero(state,len)154212397c6Schristos local int gz_zero(state, len)
155212397c6Schristos gz_statep state;
156212397c6Schristos z_off64_t len;
157212397c6Schristos {
158212397c6Schristos int first;
159212397c6Schristos unsigned n;
160212397c6Schristos z_streamp strm = &(state->strm);
161212397c6Schristos
162212397c6Schristos /* consume whatever's left in the input buffer */
163212397c6Schristos if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1)
164212397c6Schristos return -1;
165212397c6Schristos
166212397c6Schristos /* compress len zeros (len guaranteed > 0) */
167212397c6Schristos first = 1;
168212397c6Schristos while (len) {
169212397c6Schristos n = GT_OFF(state->size) || (z_off64_t)state->size > len ?
170212397c6Schristos (unsigned)len : state->size;
171212397c6Schristos if (first) {
172212397c6Schristos memset(state->in, 0, n);
173212397c6Schristos first = 0;
174212397c6Schristos }
175212397c6Schristos strm->avail_in = n;
176212397c6Schristos strm->next_in = state->in;
177212397c6Schristos state->x.pos += n;
178212397c6Schristos if (gz_comp(state, Z_NO_FLUSH) == -1)
179212397c6Schristos return -1;
180212397c6Schristos len -= n;
181212397c6Schristos }
182212397c6Schristos return 0;
183212397c6Schristos }
184212397c6Schristos
185796c32c9Schristos /* Write len bytes from buf to file. Return the number of bytes written. If
186796c32c9Schristos the returned value is less than len, then there was an error. */
gz_write(state,buf,len)187796c32c9Schristos local z_size_t gz_write(state, buf, len)
188212397c6Schristos gz_statep state;
189796c32c9Schristos voidpc buf;
190796c32c9Schristos z_size_t len;
191796c32c9Schristos {
192796c32c9Schristos z_size_t put = len;
193212397c6Schristos
194212397c6Schristos /* if len is zero, avoid unnecessary operations */
195212397c6Schristos if (len == 0)
196212397c6Schristos return 0;
197212397c6Schristos
198212397c6Schristos /* allocate memory if this is the first time through */
199212397c6Schristos if (state->size == 0 && gz_init(state) == -1)
200212397c6Schristos return 0;
201212397c6Schristos
202212397c6Schristos /* check for seek request */
203212397c6Schristos if (state->seek) {
204212397c6Schristos state->seek = 0;
205212397c6Schristos if (gz_zero(state, state->skip) == -1)
206212397c6Schristos return 0;
207212397c6Schristos }
208212397c6Schristos
209212397c6Schristos /* for small len, copy to input buffer, otherwise compress directly */
210212397c6Schristos if (len < state->size) {
211212397c6Schristos /* copy to input buffer, compress when full */
212212397c6Schristos do {
213ba340e45Schristos unsigned have, copy;
214ba340e45Schristos
215796c32c9Schristos if (state->strm.avail_in == 0)
216796c32c9Schristos state->strm.next_in = state->in;
217796c32c9Schristos have = (unsigned)((state->strm.next_in + state->strm.avail_in) -
218796c32c9Schristos state->in);
219ba340e45Schristos copy = state->size - have;
220ba340e45Schristos if (copy > len)
221*4b169a6bSchristos copy = (unsigned)len;
222ba340e45Schristos memcpy(state->in + have, buf, copy);
223796c32c9Schristos state->strm.avail_in += copy;
224ba340e45Schristos state->x.pos += copy;
225ba340e45Schristos buf = (const char *)buf + copy;
226ba340e45Schristos len -= copy;
227212397c6Schristos if (len && gz_comp(state, Z_NO_FLUSH) == -1)
228212397c6Schristos return 0;
229212397c6Schristos } while (len);
230212397c6Schristos }
231212397c6Schristos else {
232212397c6Schristos /* consume whatever's left in the input buffer */
233796c32c9Schristos if (state->strm.avail_in && gz_comp(state, Z_NO_FLUSH) == -1)
234212397c6Schristos return 0;
235212397c6Schristos
236212397c6Schristos /* directly compress user buffer to file */
237796c32c9Schristos state->strm.next_in = (z_const Bytef *)buf;
238796c32c9Schristos do {
239796c32c9Schristos unsigned n = (unsigned)-1;
240796c32c9Schristos if (n > len)
241*4b169a6bSchristos n = (unsigned)len;
242796c32c9Schristos state->strm.avail_in = n;
243796c32c9Schristos state->x.pos += n;
244212397c6Schristos if (gz_comp(state, Z_NO_FLUSH) == -1)
245212397c6Schristos return 0;
246796c32c9Schristos len -= n;
247796c32c9Schristos } while (len);
248796c32c9Schristos }
249796c32c9Schristos
250796c32c9Schristos /* input was all buffered or compressed */
251796c32c9Schristos return put;
252796c32c9Schristos }
253796c32c9Schristos
254796c32c9Schristos /* -- see zlib.h -- */
gzwrite(file,buf,len)255796c32c9Schristos int ZEXPORT gzwrite(file, buf, len)
256796c32c9Schristos gzFile file;
257796c32c9Schristos voidpc buf;
258796c32c9Schristos unsigned len;
259796c32c9Schristos {
260796c32c9Schristos gz_statep state;
261796c32c9Schristos
262796c32c9Schristos /* get internal structure */
263796c32c9Schristos if (file == NULL)
264796c32c9Schristos return 0;
265796c32c9Schristos state = (gz_statep)file;
266796c32c9Schristos
267796c32c9Schristos /* check that we're writing and that there's no error */
268796c32c9Schristos if (state->mode != GZ_WRITE || state->err != Z_OK)
269796c32c9Schristos return 0;
270796c32c9Schristos
271796c32c9Schristos /* since an int is returned, make sure len fits in one, otherwise return
272796c32c9Schristos with an error (this avoids a flaw in the interface) */
273796c32c9Schristos if ((int)len < 0) {
274796c32c9Schristos gz_error(state, Z_DATA_ERROR, "requested length does not fit in int");
275796c32c9Schristos return 0;
276212397c6Schristos }
277212397c6Schristos
278796c32c9Schristos /* write len bytes from buf (the return value will fit in an int) */
279796c32c9Schristos return (int)gz_write(state, buf, len);
280796c32c9Schristos }
281796c32c9Schristos
282796c32c9Schristos /* -- see zlib.h -- */
gzfwrite(buf,size,nitems,file)283796c32c9Schristos z_size_t ZEXPORT gzfwrite(buf, size, nitems, file)
284796c32c9Schristos voidpc buf;
285796c32c9Schristos z_size_t size;
286796c32c9Schristos z_size_t nitems;
287796c32c9Schristos gzFile file;
288796c32c9Schristos {
289796c32c9Schristos z_size_t len;
290796c32c9Schristos gz_statep state;
291796c32c9Schristos
292796c32c9Schristos /* get internal structure */
293796c32c9Schristos if (file == NULL)
294796c32c9Schristos return 0;
295796c32c9Schristos state = (gz_statep)file;
296796c32c9Schristos
297796c32c9Schristos /* check that we're writing and that there's no error */
298796c32c9Schristos if (state->mode != GZ_WRITE || state->err != Z_OK)
299796c32c9Schristos return 0;
300796c32c9Schristos
301796c32c9Schristos /* compute bytes to read -- error on overflow */
302796c32c9Schristos len = nitems * size;
303796c32c9Schristos if (size && len / size != nitems) {
304796c32c9Schristos gz_error(state, Z_STREAM_ERROR, "request does not fit in a size_t");
305796c32c9Schristos return 0;
306796c32c9Schristos }
307796c32c9Schristos
308796c32c9Schristos /* write len bytes to buf, return the number of full items written */
309796c32c9Schristos return len ? gz_write(state, buf, len) / size : 0;
310212397c6Schristos }
311212397c6Schristos
312212397c6Schristos /* -- see zlib.h -- */
gzputc(file,c)313212397c6Schristos int ZEXPORT gzputc(file, c)
314212397c6Schristos gzFile file;
315212397c6Schristos int c;
316212397c6Schristos {
317ba340e45Schristos unsigned have;
318212397c6Schristos unsigned char buf[1];
319212397c6Schristos gz_statep state;
320212397c6Schristos z_streamp strm;
321212397c6Schristos
322212397c6Schristos /* get internal structure */
323212397c6Schristos if (file == NULL)
324212397c6Schristos return -1;
325212397c6Schristos state = (gz_statep)file;
326212397c6Schristos strm = &(state->strm);
327212397c6Schristos
328212397c6Schristos /* check that we're writing and that there's no error */
329212397c6Schristos if (state->mode != GZ_WRITE || state->err != Z_OK)
330212397c6Schristos return -1;
331212397c6Schristos
332212397c6Schristos /* check for seek request */
333212397c6Schristos if (state->seek) {
334212397c6Schristos state->seek = 0;
335212397c6Schristos if (gz_zero(state, state->skip) == -1)
336212397c6Schristos return -1;
337212397c6Schristos }
338212397c6Schristos
339212397c6Schristos /* try writing to input buffer for speed (state->size == 0 if buffer not
340212397c6Schristos initialized) */
341ba340e45Schristos if (state->size) {
342212397c6Schristos if (strm->avail_in == 0)
343212397c6Schristos strm->next_in = state->in;
344ba340e45Schristos have = (unsigned)((strm->next_in + strm->avail_in) - state->in);
345ba340e45Schristos if (have < state->size) {
346796c32c9Schristos state->in[have] = (unsigned char)c;
347ba340e45Schristos strm->avail_in++;
348212397c6Schristos state->x.pos++;
349212397c6Schristos return c & 0xff;
350212397c6Schristos }
351ba340e45Schristos }
352212397c6Schristos
353212397c6Schristos /* no room in buffer or not initialized, use gz_write() */
354796c32c9Schristos buf[0] = (unsigned char)c;
355796c32c9Schristos if (gz_write(state, buf, 1) != 1)
356212397c6Schristos return -1;
357212397c6Schristos return c & 0xff;
358212397c6Schristos }
359212397c6Schristos
360212397c6Schristos /* -- see zlib.h -- */
gzputs(file,s)361*4b169a6bSchristos int ZEXPORT gzputs(file, s)
362212397c6Schristos gzFile file;
363*4b169a6bSchristos const char *s;
364212397c6Schristos {
365*4b169a6bSchristos z_size_t len, put;
366796c32c9Schristos gz_statep state;
367796c32c9Schristos
368796c32c9Schristos /* get internal structure */
369796c32c9Schristos if (file == NULL)
370796c32c9Schristos return -1;
371796c32c9Schristos state = (gz_statep)file;
372796c32c9Schristos
373796c32c9Schristos /* check that we're writing and that there's no error */
374796c32c9Schristos if (state->mode != GZ_WRITE || state->err != Z_OK)
375796c32c9Schristos return -1;
376212397c6Schristos
377212397c6Schristos /* write string */
378*4b169a6bSchristos len = strlen(s);
379*4b169a6bSchristos if ((int)len < 0 || (unsigned)len != len) {
380*4b169a6bSchristos gz_error(state, Z_STREAM_ERROR, "string length does not fit in int");
381*4b169a6bSchristos return -1;
382*4b169a6bSchristos }
383*4b169a6bSchristos put = gz_write(state, s, len);
384*4b169a6bSchristos return put < len ? -1 : (int)len;
385212397c6Schristos }
386212397c6Schristos
387212397c6Schristos #if defined(STDC) || defined(Z_HAVE_STDARG_H)
388212397c6Schristos #include <stdarg.h>
389212397c6Schristos
390212397c6Schristos /* -- see zlib.h -- */
gzvprintf(gzFile file,const char * format,va_list va)391ba340e45Schristos int ZEXPORTVA gzvprintf(gzFile file, const char *format, va_list va)
392212397c6Schristos {
393796c32c9Schristos int len;
394796c32c9Schristos unsigned left;
395796c32c9Schristos char *next;
396212397c6Schristos gz_statep state;
397212397c6Schristos z_streamp strm;
398212397c6Schristos
399212397c6Schristos /* get internal structure */
400212397c6Schristos if (file == NULL)
401796c32c9Schristos return Z_STREAM_ERROR;
402212397c6Schristos state = (gz_statep)file;
403212397c6Schristos strm = &(state->strm);
404212397c6Schristos
405212397c6Schristos /* check that we're writing and that there's no error */
406212397c6Schristos if (state->mode != GZ_WRITE || state->err != Z_OK)
407796c32c9Schristos return Z_STREAM_ERROR;
408212397c6Schristos
409212397c6Schristos /* make sure we have some buffer space */
410212397c6Schristos if (state->size == 0 && gz_init(state) == -1)
411796c32c9Schristos return state->err;
412212397c6Schristos
413212397c6Schristos /* check for seek request */
414212397c6Schristos if (state->seek) {
415212397c6Schristos state->seek = 0;
416212397c6Schristos if (gz_zero(state, state->skip) == -1)
417796c32c9Schristos return state->err;
418212397c6Schristos }
419212397c6Schristos
420796c32c9Schristos /* do the printf() into the input buffer, put length in len -- the input
421796c32c9Schristos buffer is double-sized just for this function, so there is guaranteed to
422796c32c9Schristos be state->size bytes available after the current contents */
423796c32c9Schristos if (strm->avail_in == 0)
424796c32c9Schristos strm->next_in = state->in;
425796c32c9Schristos next = (char *)(state->in + (strm->next_in - state->in) + strm->avail_in);
426796c32c9Schristos next[state->size - 1] = 0;
427212397c6Schristos #ifdef NO_vsnprintf
428212397c6Schristos # ifdef HAS_vsprintf_void
429796c32c9Schristos (void)vsprintf(next, format, va);
430796c32c9Schristos for (len = 0; len < state->size; len++)
431796c32c9Schristos if (next[len] == 0) break;
432212397c6Schristos # else
433796c32c9Schristos len = vsprintf(next, format, va);
434212397c6Schristos # endif
435212397c6Schristos #else
436212397c6Schristos # ifdef HAS_vsnprintf_void
437796c32c9Schristos (void)vsnprintf(next, state->size, format, va);
438796c32c9Schristos len = strlen(next);
439212397c6Schristos # else
440796c32c9Schristos len = vsnprintf(next, state->size, format, va);
441212397c6Schristos # endif
442212397c6Schristos #endif
443212397c6Schristos
444212397c6Schristos /* check that printf() results fit in buffer */
445796c32c9Schristos if (len == 0 || (unsigned)len >= state->size || next[state->size - 1] != 0)
446212397c6Schristos return 0;
447212397c6Schristos
448796c32c9Schristos /* update buffer and position, compress first half if past that */
449796c32c9Schristos strm->avail_in += (unsigned)len;
450212397c6Schristos state->x.pos += len;
451796c32c9Schristos if (strm->avail_in >= state->size) {
452796c32c9Schristos left = strm->avail_in - state->size;
453796c32c9Schristos strm->avail_in = state->size;
454796c32c9Schristos if (gz_comp(state, Z_NO_FLUSH) == -1)
455796c32c9Schristos return state->err;
456*4b169a6bSchristos memmove(state->in, state->in + state->size, left);
457796c32c9Schristos strm->next_in = state->in;
458796c32c9Schristos strm->avail_in = left;
459796c32c9Schristos }
460212397c6Schristos return len;
461212397c6Schristos }
462212397c6Schristos
gzprintf(gzFile file,const char * format,...)463ba340e45Schristos int ZEXPORTVA gzprintf(gzFile file, const char *format, ...)
464ba340e45Schristos {
465ba340e45Schristos va_list va;
466ba340e45Schristos int ret;
467ba340e45Schristos
468ba340e45Schristos va_start(va, format);
469ba340e45Schristos ret = gzvprintf(file, format, va);
470ba340e45Schristos va_end(va);
471ba340e45Schristos return ret;
472ba340e45Schristos }
473ba340e45Schristos
474212397c6Schristos #else /* !STDC && !Z_HAVE_STDARG_H */
475212397c6Schristos
476212397c6Schristos /* -- 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)477212397c6Schristos int ZEXPORTVA gzprintf (file, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10,
478212397c6Schristos a11, a12, a13, a14, a15, a16, a17, a18, a19, a20)
479212397c6Schristos gzFile file;
480212397c6Schristos const char *format;
481212397c6Schristos int a1, a2, a3, a4, a5, a6, a7, a8, a9, a10,
482212397c6Schristos a11, a12, a13, a14, a15, a16, a17, a18, a19, a20;
483212397c6Schristos {
484796c32c9Schristos unsigned len, left;
485796c32c9Schristos char *next;
486212397c6Schristos gz_statep state;
487212397c6Schristos z_streamp strm;
488212397c6Schristos
489212397c6Schristos /* get internal structure */
490212397c6Schristos if (file == NULL)
491796c32c9Schristos return Z_STREAM_ERROR;
492212397c6Schristos state = (gz_statep)file;
493212397c6Schristos strm = &(state->strm);
494212397c6Schristos
495212397c6Schristos /* check that can really pass pointer in ints */
496212397c6Schristos if (sizeof(int) != sizeof(void *))
497796c32c9Schristos return Z_STREAM_ERROR;
498212397c6Schristos
499212397c6Schristos /* check that we're writing and that there's no error */
500212397c6Schristos if (state->mode != GZ_WRITE || state->err != Z_OK)
501796c32c9Schristos return Z_STREAM_ERROR;
502212397c6Schristos
503212397c6Schristos /* make sure we have some buffer space */
504212397c6Schristos if (state->size == 0 && gz_init(state) == -1)
505796c32c9Schristos return state->error;
506212397c6Schristos
507212397c6Schristos /* check for seek request */
508212397c6Schristos if (state->seek) {
509212397c6Schristos state->seek = 0;
510212397c6Schristos if (gz_zero(state, state->skip) == -1)
511796c32c9Schristos return state->error;
512212397c6Schristos }
513212397c6Schristos
514796c32c9Schristos /* do the printf() into the input buffer, put length in len -- the input
515796c32c9Schristos buffer is double-sized just for this function, so there is guaranteed to
516796c32c9Schristos be state->size bytes available after the current contents */
517796c32c9Schristos if (strm->avail_in == 0)
518796c32c9Schristos strm->next_in = state->in;
519796c32c9Schristos next = (char *)(strm->next_in + strm->avail_in);
520796c32c9Schristos next[state->size - 1] = 0;
521212397c6Schristos #ifdef NO_snprintf
522212397c6Schristos # ifdef HAS_sprintf_void
523796c32c9Schristos sprintf(next, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12,
524796c32c9Schristos a13, a14, a15, a16, a17, a18, a19, a20);
525212397c6Schristos for (len = 0; len < size; len++)
526796c32c9Schristos if (next[len] == 0)
527796c32c9Schristos break;
528212397c6Schristos # else
529796c32c9Schristos len = sprintf(next, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11,
530796c32c9Schristos a12, a13, a14, a15, a16, a17, a18, a19, a20);
531212397c6Schristos # endif
532212397c6Schristos #else
533212397c6Schristos # ifdef HAS_snprintf_void
534796c32c9Schristos snprintf(next, state->size, format, a1, a2, a3, a4, a5, a6, a7, a8, a9,
535796c32c9Schristos a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20);
536796c32c9Schristos len = strlen(next);
537212397c6Schristos # else
538796c32c9Schristos len = snprintf(next, state->size, format, a1, a2, a3, a4, a5, a6, a7, a8,
539796c32c9Schristos a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20);
540212397c6Schristos # endif
541212397c6Schristos #endif
542212397c6Schristos
543212397c6Schristos /* check that printf() results fit in buffer */
544796c32c9Schristos if (len == 0 || len >= state->size || next[state->size - 1] != 0)
545212397c6Schristos return 0;
546212397c6Schristos
547796c32c9Schristos /* update buffer and position, compress first half if past that */
548796c32c9Schristos strm->avail_in += len;
549212397c6Schristos state->x.pos += len;
550796c32c9Schristos if (strm->avail_in >= state->size) {
551796c32c9Schristos left = strm->avail_in - state->size;
552796c32c9Schristos strm->avail_in = state->size;
553796c32c9Schristos if (gz_comp(state, Z_NO_FLUSH) == -1)
554796c32c9Schristos return state->err;
555*4b169a6bSchristos memmove(state->in, state->in + state->size, left);
556796c32c9Schristos strm->next_in = state->in;
557796c32c9Schristos strm->avail_in = left;
558796c32c9Schristos }
559796c32c9Schristos return (int)len;
560212397c6Schristos }
561212397c6Schristos
562212397c6Schristos #endif
563212397c6Schristos
564212397c6Schristos /* -- see zlib.h -- */
gzflush(file,flush)565212397c6Schristos int ZEXPORT gzflush(file, flush)
566212397c6Schristos gzFile file;
567212397c6Schristos int flush;
568212397c6Schristos {
569212397c6Schristos gz_statep state;
570212397c6Schristos
571212397c6Schristos /* get internal structure */
572212397c6Schristos if (file == NULL)
573796c32c9Schristos return Z_STREAM_ERROR;
574212397c6Schristos state = (gz_statep)file;
575212397c6Schristos
576212397c6Schristos /* check that we're writing and that there's no error */
577212397c6Schristos if (state->mode != GZ_WRITE || state->err != Z_OK)
578212397c6Schristos return Z_STREAM_ERROR;
579212397c6Schristos
580212397c6Schristos /* check flush parameter */
581212397c6Schristos if (flush < 0 || flush > Z_FINISH)
582212397c6Schristos return Z_STREAM_ERROR;
583212397c6Schristos
584212397c6Schristos /* check for seek request */
585212397c6Schristos if (state->seek) {
586212397c6Schristos state->seek = 0;
587212397c6Schristos if (gz_zero(state, state->skip) == -1)
588796c32c9Schristos return state->err;
589212397c6Schristos }
590212397c6Schristos
591212397c6Schristos /* compress remaining data with requested flush */
592796c32c9Schristos (void)gz_comp(state, flush);
593212397c6Schristos return state->err;
594212397c6Schristos }
595212397c6Schristos
596212397c6Schristos /* -- see zlib.h -- */
gzsetparams(file,level,strategy)597212397c6Schristos int ZEXPORT gzsetparams(file, level, strategy)
598212397c6Schristos gzFile file;
599212397c6Schristos int level;
600212397c6Schristos int strategy;
601212397c6Schristos {
602212397c6Schristos gz_statep state;
603212397c6Schristos z_streamp strm;
604212397c6Schristos
605212397c6Schristos /* get internal structure */
606212397c6Schristos if (file == NULL)
607212397c6Schristos return Z_STREAM_ERROR;
608212397c6Schristos state = (gz_statep)file;
609212397c6Schristos strm = &(state->strm);
610212397c6Schristos
611212397c6Schristos /* check that we're writing and that there's no error */
612212397c6Schristos if (state->mode != GZ_WRITE || state->err != Z_OK)
613212397c6Schristos return Z_STREAM_ERROR;
614212397c6Schristos
615212397c6Schristos /* if no change is requested, then do nothing */
616212397c6Schristos if (level == state->level && strategy == state->strategy)
617212397c6Schristos return Z_OK;
618212397c6Schristos
619212397c6Schristos /* check for seek request */
620212397c6Schristos if (state->seek) {
621212397c6Schristos state->seek = 0;
622212397c6Schristos if (gz_zero(state, state->skip) == -1)
623796c32c9Schristos return state->err;
624212397c6Schristos }
625212397c6Schristos
626212397c6Schristos /* change compression parameters for subsequent input */
627212397c6Schristos if (state->size) {
628212397c6Schristos /* flush previous input with previous parameters before changing */
629796c32c9Schristos if (strm->avail_in && gz_comp(state, Z_BLOCK) == -1)
630212397c6Schristos return state->err;
631212397c6Schristos deflateParams(strm, level, strategy);
632212397c6Schristos }
633212397c6Schristos state->level = level;
634212397c6Schristos state->strategy = strategy;
635212397c6Schristos return Z_OK;
636212397c6Schristos }
637212397c6Schristos
638212397c6Schristos /* -- see zlib.h -- */
gzclose_w(file)639212397c6Schristos int ZEXPORT gzclose_w(file)
640212397c6Schristos gzFile file;
641212397c6Schristos {
642212397c6Schristos int ret = Z_OK;
643212397c6Schristos gz_statep state;
644212397c6Schristos
645212397c6Schristos /* get internal structure */
646212397c6Schristos if (file == NULL)
647212397c6Schristos return Z_STREAM_ERROR;
648212397c6Schristos state = (gz_statep)file;
649212397c6Schristos
650212397c6Schristos /* check that we're writing */
651212397c6Schristos if (state->mode != GZ_WRITE)
652212397c6Schristos return Z_STREAM_ERROR;
653212397c6Schristos
654212397c6Schristos /* check for seek request */
655212397c6Schristos if (state->seek) {
656212397c6Schristos state->seek = 0;
657212397c6Schristos if (gz_zero(state, state->skip) == -1)
658212397c6Schristos ret = state->err;
659212397c6Schristos }
660212397c6Schristos
661212397c6Schristos /* flush, free memory, and close file */
662212397c6Schristos if (gz_comp(state, Z_FINISH) == -1)
663212397c6Schristos ret = state->err;
664ba340e45Schristos if (state->size) {
665212397c6Schristos if (!state->direct) {
666212397c6Schristos (void)deflateEnd(&(state->strm));
667212397c6Schristos free(state->out);
668212397c6Schristos }
669212397c6Schristos free(state->in);
670212397c6Schristos }
671212397c6Schristos gz_error(state, Z_OK, NULL);
672212397c6Schristos free(state->path);
673212397c6Schristos if (close(state->fd) == -1)
674212397c6Schristos ret = Z_ERRNO;
675212397c6Schristos free(state);
676212397c6Schristos return ret;
677212397c6Schristos }
678