xref: /openbsd-src/lib/libz/gzwrite.c (revision a04ea15dafe6974ae5a5b91b1adc9d00183fc2e9)
136f395ceStb /* gzwrite.c -- zlib functions for writing gzip files
2703d4924Stb  * Copyright (C) 2004-2019 Mark Adler
336f395ceStb  * For conditions of distribution and use, see copyright notice in zlib.h
436f395ceStb  */
536f395ceStb 
636f395ceStb #include "gzguts.h"
736f395ceStb 
836f395ceStb /* Initialize state for writing a gzip file.  Mark initialization by setting
936f395ceStb    state->size to non-zero.  Return -1 on a memory allocation failure, or 0 on
1036f395ceStb    success. */
gz_init(gz_statep state)11*a04ea15dStb local int gz_init(gz_statep state) {
1236f395ceStb     int ret;
1336f395ceStb     z_streamp strm = &(state->strm);
1436f395ceStb 
1536f395ceStb     /* allocate input buffer (double size for gzprintf) */
1636f395ceStb     state->in = (unsigned char *)malloc(state->want << 1);
1736f395ceStb     if (state->in == NULL) {
1836f395ceStb         gz_error(state, Z_MEM_ERROR, "out of memory");
1936f395ceStb         return -1;
2036f395ceStb     }
2136f395ceStb 
2236f395ceStb     /* only need output buffer and deflate state if compressing */
2336f395ceStb     if (!state->direct) {
2436f395ceStb         /* allocate output buffer */
2536f395ceStb         state->out = (unsigned char *)malloc(state->want);
2636f395ceStb         if (state->out == NULL) {
2736f395ceStb             free(state->in);
2836f395ceStb             gz_error(state, Z_MEM_ERROR, "out of memory");
2936f395ceStb             return -1;
3036f395ceStb         }
3136f395ceStb 
3236f395ceStb         /* allocate deflate memory, set up for gzip compression */
3336f395ceStb         strm->zalloc = Z_NULL;
3436f395ceStb         strm->zfree = Z_NULL;
3536f395ceStb         strm->opaque = Z_NULL;
3636f395ceStb         ret = deflateInit2(strm, state->level, Z_DEFLATED,
3736f395ceStb                            MAX_WBITS + 16, DEF_MEM_LEVEL, state->strategy);
3836f395ceStb         if (ret != Z_OK) {
3936f395ceStb             free(state->out);
4036f395ceStb             free(state->in);
4136f395ceStb             gz_error(state, Z_MEM_ERROR, "out of memory");
4236f395ceStb             return -1;
4336f395ceStb         }
4436f395ceStb         strm->next_in = NULL;
4536f395ceStb     }
4636f395ceStb 
4736f395ceStb     /* mark state as initialized */
4836f395ceStb     state->size = state->want;
4936f395ceStb 
5036f395ceStb     /* initialize write buffer if compressing */
5136f395ceStb     if (!state->direct) {
5236f395ceStb         strm->avail_out = state->size;
5336f395ceStb         strm->next_out = state->out;
5436f395ceStb         state->x.next = strm->next_out;
5536f395ceStb     }
5636f395ceStb     return 0;
5736f395ceStb }
5836f395ceStb 
5936f395ceStb /* Compress whatever is at avail_in and next_in and write to the output file.
6036f395ceStb    Return -1 if there is an error writing to the output file or if gz_init()
6136f395ceStb    fails to allocate memory, otherwise 0.  flush is assumed to be a valid
6236f395ceStb    deflate() flush value.  If flush is Z_FINISH, then the deflate() state is
6336f395ceStb    reset to start a new gzip stream.  If gz->direct is true, then simply write
6436f395ceStb    to the output file without compressing, and ignore flush. */
gz_comp(gz_statep state,int flush)65*a04ea15dStb local int gz_comp(gz_statep state, int flush) {
6636f395ceStb     int ret, writ;
6736f395ceStb     unsigned have, put, max = ((unsigned)-1 >> 2) + 1;
6836f395ceStb     z_streamp strm = &(state->strm);
6936f395ceStb 
7036f395ceStb     /* allocate memory if this is the first time through */
7136f395ceStb     if (state->size == 0 && gz_init(state) == -1)
7236f395ceStb         return -1;
7336f395ceStb 
7436f395ceStb     /* write directly if requested */
7536f395ceStb     if (state->direct) {
7636f395ceStb         while (strm->avail_in) {
7736f395ceStb             put = strm->avail_in > max ? max : strm->avail_in;
7836f395ceStb             writ = write(state->fd, strm->next_in, put);
7936f395ceStb             if (writ < 0) {
8036f395ceStb                 gz_error(state, Z_ERRNO, zstrerror());
8136f395ceStb                 return -1;
8236f395ceStb             }
8336f395ceStb             strm->avail_in -= (unsigned)writ;
8436f395ceStb             strm->next_in += writ;
8536f395ceStb         }
8636f395ceStb         return 0;
8736f395ceStb     }
8836f395ceStb 
89703d4924Stb     /* check for a pending reset */
90703d4924Stb     if (state->reset) {
91703d4924Stb         /* don't start a new gzip member unless there is data to write */
92703d4924Stb         if (strm->avail_in == 0)
93703d4924Stb             return 0;
94703d4924Stb         deflateReset(strm);
95703d4924Stb         state->reset = 0;
96703d4924Stb     }
97703d4924Stb 
9836f395ceStb     /* run deflate() on provided input until it produces no more output */
9936f395ceStb     ret = Z_OK;
10036f395ceStb     do {
10136f395ceStb         /* write out current buffer contents if full, or if flushing, but if
10236f395ceStb            doing Z_FINISH then don't write until we get to Z_STREAM_END */
10336f395ceStb         if (strm->avail_out == 0 || (flush != Z_NO_FLUSH &&
10436f395ceStb             (flush != Z_FINISH || ret == Z_STREAM_END))) {
10536f395ceStb             while (strm->next_out > state->x.next) {
10636f395ceStb                 put = strm->next_out - state->x.next > (int)max ? max :
10736f395ceStb                       (unsigned)(strm->next_out - state->x.next);
10836f395ceStb                 writ = write(state->fd, state->x.next, put);
10936f395ceStb                 if (writ < 0) {
11036f395ceStb                     gz_error(state, Z_ERRNO, zstrerror());
11136f395ceStb                     return -1;
11236f395ceStb                 }
11336f395ceStb                 state->x.next += writ;
11436f395ceStb             }
11536f395ceStb             if (strm->avail_out == 0) {
11636f395ceStb                 strm->avail_out = state->size;
11736f395ceStb                 strm->next_out = state->out;
11836f395ceStb                 state->x.next = state->out;
11936f395ceStb             }
12036f395ceStb         }
12136f395ceStb 
12236f395ceStb         /* compress */
12336f395ceStb         have = strm->avail_out;
12436f395ceStb         ret = deflate(strm, flush);
12536f395ceStb         if (ret == Z_STREAM_ERROR) {
12636f395ceStb             gz_error(state, Z_STREAM_ERROR,
12736f395ceStb                       "internal error: deflate stream corrupt");
12836f395ceStb             return -1;
12936f395ceStb         }
13036f395ceStb         have -= strm->avail_out;
13136f395ceStb     } while (have);
13236f395ceStb 
13336f395ceStb     /* if that completed a deflate stream, allow another to start */
13436f395ceStb     if (flush == Z_FINISH)
135703d4924Stb         state->reset = 1;
13636f395ceStb 
13736f395ceStb     /* all done, no errors */
13836f395ceStb     return 0;
13936f395ceStb }
14036f395ceStb 
14136f395ceStb /* Compress len zeros to output.  Return -1 on a write error or memory
14236f395ceStb    allocation failure by gz_comp(), or 0 on success. */
gz_zero(gz_statep state,z_off64_t len)143*a04ea15dStb local int gz_zero(gz_statep state, z_off64_t len) {
14436f395ceStb     int first;
14536f395ceStb     unsigned n;
14636f395ceStb     z_streamp strm = &(state->strm);
14736f395ceStb 
14836f395ceStb     /* consume whatever's left in the input buffer */
14936f395ceStb     if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1)
15036f395ceStb         return -1;
15136f395ceStb 
15236f395ceStb     /* compress len zeros (len guaranteed > 0) */
15336f395ceStb     first = 1;
15436f395ceStb     while (len) {
15536f395ceStb         n = GT_OFF(state->size) || (z_off64_t)state->size > len ?
15636f395ceStb             (unsigned)len : state->size;
15736f395ceStb         if (first) {
15836f395ceStb             memset(state->in, 0, n);
15936f395ceStb             first = 0;
16036f395ceStb         }
16136f395ceStb         strm->avail_in = n;
16236f395ceStb         strm->next_in = state->in;
16336f395ceStb         state->x.pos += n;
16436f395ceStb         if (gz_comp(state, Z_NO_FLUSH) == -1)
16536f395ceStb             return -1;
16636f395ceStb         len -= n;
16736f395ceStb     }
16836f395ceStb     return 0;
16936f395ceStb }
17036f395ceStb 
17136f395ceStb /* Write len bytes from buf to file.  Return the number of bytes written.  If
17236f395ceStb    the returned value is less than len, then there was an error. */
gz_write(gz_statep state,voidpc buf,z_size_t len)173*a04ea15dStb local z_size_t gz_write(gz_statep state, voidpc buf, z_size_t len) {
17436f395ceStb     z_size_t put = len;
17536f395ceStb 
17636f395ceStb     /* if len is zero, avoid unnecessary operations */
17736f395ceStb     if (len == 0)
17836f395ceStb         return 0;
17936f395ceStb 
18036f395ceStb     /* allocate memory if this is the first time through */
18136f395ceStb     if (state->size == 0 && gz_init(state) == -1)
18236f395ceStb         return 0;
18336f395ceStb 
18436f395ceStb     /* check for seek request */
18536f395ceStb     if (state->seek) {
18636f395ceStb         state->seek = 0;
18736f395ceStb         if (gz_zero(state, state->skip) == -1)
18836f395ceStb             return 0;
18936f395ceStb     }
19036f395ceStb 
19136f395ceStb     /* for small len, copy to input buffer, otherwise compress directly */
19236f395ceStb     if (len < state->size) {
19336f395ceStb         /* copy to input buffer, compress when full */
19436f395ceStb         do {
19536f395ceStb             unsigned have, copy;
19636f395ceStb 
19736f395ceStb             if (state->strm.avail_in == 0)
19836f395ceStb                 state->strm.next_in = state->in;
19936f395ceStb             have = (unsigned)((state->strm.next_in + state->strm.avail_in) -
20036f395ceStb                               state->in);
20136f395ceStb             copy = state->size - have;
20236f395ceStb             if (copy > len)
203703d4924Stb                 copy = (unsigned)len;
20436f395ceStb             memcpy(state->in + have, buf, copy);
20536f395ceStb             state->strm.avail_in += copy;
20636f395ceStb             state->x.pos += copy;
20736f395ceStb             buf = (const char *)buf + copy;
20836f395ceStb             len -= copy;
20936f395ceStb             if (len && gz_comp(state, Z_NO_FLUSH) == -1)
21036f395ceStb                 return 0;
21136f395ceStb         } while (len);
21236f395ceStb     }
21336f395ceStb     else {
21436f395ceStb         /* consume whatever's left in the input buffer */
21536f395ceStb         if (state->strm.avail_in && gz_comp(state, Z_NO_FLUSH) == -1)
21636f395ceStb             return 0;
21736f395ceStb 
21836f395ceStb         /* directly compress user buffer to file */
21936f395ceStb         state->strm.next_in = (z_const Bytef *)buf;
22036f395ceStb         do {
22136f395ceStb             unsigned n = (unsigned)-1;
22236f395ceStb             if (n > len)
223703d4924Stb                 n = (unsigned)len;
22436f395ceStb             state->strm.avail_in = n;
22536f395ceStb             state->x.pos += n;
22636f395ceStb             if (gz_comp(state, Z_NO_FLUSH) == -1)
22736f395ceStb                 return 0;
22836f395ceStb             len -= n;
22936f395ceStb         } while (len);
23036f395ceStb     }
23136f395ceStb 
23236f395ceStb     /* input was all buffered or compressed */
23336f395ceStb     return put;
23436f395ceStb }
23536f395ceStb 
23636f395ceStb /* -- see zlib.h -- */
gzwrite(gzFile file,voidpc buf,unsigned len)237*a04ea15dStb int ZEXPORT gzwrite(gzFile file, voidpc buf, unsigned len) {
23836f395ceStb     gz_statep state;
23936f395ceStb 
24036f395ceStb     /* get internal structure */
24136f395ceStb     if (file == NULL)
24236f395ceStb         return 0;
24336f395ceStb     state = (gz_statep)file;
24436f395ceStb 
24536f395ceStb     /* check that we're writing and that there's no error */
24636f395ceStb     if (state->mode != GZ_WRITE || state->err != Z_OK)
24736f395ceStb         return 0;
24836f395ceStb 
24936f395ceStb     /* since an int is returned, make sure len fits in one, otherwise return
25036f395ceStb        with an error (this avoids a flaw in the interface) */
25136f395ceStb     if ((int)len < 0) {
25236f395ceStb         gz_error(state, Z_DATA_ERROR, "requested length does not fit in int");
25336f395ceStb         return 0;
25436f395ceStb     }
25536f395ceStb 
25636f395ceStb     /* write len bytes from buf (the return value will fit in an int) */
25736f395ceStb     return (int)gz_write(state, buf, len);
25836f395ceStb }
25936f395ceStb 
26036f395ceStb /* -- see zlib.h -- */
gzfwrite(voidpc buf,z_size_t size,z_size_t nitems,gzFile file)261*a04ea15dStb z_size_t ZEXPORT gzfwrite(voidpc buf, z_size_t size, z_size_t nitems,
262*a04ea15dStb                           gzFile file) {
26336f395ceStb     z_size_t len;
26436f395ceStb     gz_statep state;
26536f395ceStb 
26636f395ceStb     /* get internal structure */
26736f395ceStb     if (file == NULL)
26836f395ceStb         return 0;
26936f395ceStb     state = (gz_statep)file;
27036f395ceStb 
27136f395ceStb     /* check that we're writing and that there's no error */
27236f395ceStb     if (state->mode != GZ_WRITE || state->err != Z_OK)
27336f395ceStb         return 0;
27436f395ceStb 
27536f395ceStb     /* compute bytes to read -- error on overflow */
27636f395ceStb     len = nitems * size;
27736f395ceStb     if (size && len / size != nitems) {
27836f395ceStb         gz_error(state, Z_STREAM_ERROR, "request does not fit in a size_t");
27936f395ceStb         return 0;
28036f395ceStb     }
28136f395ceStb 
28236f395ceStb     /* write len bytes to buf, return the number of full items written */
28336f395ceStb     return len ? gz_write(state, buf, len) / size : 0;
28436f395ceStb }
28536f395ceStb 
28636f395ceStb /* -- see zlib.h -- */
gzputc(gzFile file,int c)287*a04ea15dStb int ZEXPORT gzputc(gzFile file, int c) {
28836f395ceStb     unsigned have;
28936f395ceStb     unsigned char buf[1];
29036f395ceStb     gz_statep state;
29136f395ceStb     z_streamp strm;
29236f395ceStb 
29336f395ceStb     /* get internal structure */
29436f395ceStb     if (file == NULL)
29536f395ceStb         return -1;
29636f395ceStb     state = (gz_statep)file;
29736f395ceStb     strm = &(state->strm);
29836f395ceStb 
29936f395ceStb     /* check that we're writing and that there's no error */
30036f395ceStb     if (state->mode != GZ_WRITE || state->err != Z_OK)
30136f395ceStb         return -1;
30236f395ceStb 
30336f395ceStb     /* check for seek request */
30436f395ceStb     if (state->seek) {
30536f395ceStb         state->seek = 0;
30636f395ceStb         if (gz_zero(state, state->skip) == -1)
30736f395ceStb             return -1;
30836f395ceStb     }
30936f395ceStb 
31036f395ceStb     /* try writing to input buffer for speed (state->size == 0 if buffer not
31136f395ceStb        initialized) */
31236f395ceStb     if (state->size) {
31336f395ceStb         if (strm->avail_in == 0)
31436f395ceStb             strm->next_in = state->in;
31536f395ceStb         have = (unsigned)((strm->next_in + strm->avail_in) - state->in);
31636f395ceStb         if (have < state->size) {
31736f395ceStb             state->in[have] = (unsigned char)c;
31836f395ceStb             strm->avail_in++;
31936f395ceStb             state->x.pos++;
32036f395ceStb             return c & 0xff;
32136f395ceStb         }
32236f395ceStb     }
32336f395ceStb 
32436f395ceStb     /* no room in buffer or not initialized, use gz_write() */
32536f395ceStb     buf[0] = (unsigned char)c;
32636f395ceStb     if (gz_write(state, buf, 1) != 1)
32736f395ceStb         return -1;
32836f395ceStb     return c & 0xff;
32936f395ceStb }
33036f395ceStb 
33136f395ceStb /* -- see zlib.h -- */
gzputs(gzFile file,const char * s)332*a04ea15dStb int ZEXPORT gzputs(gzFile file, const char *s) {
333703d4924Stb     z_size_t len, put;
33436f395ceStb     gz_statep state;
33536f395ceStb 
33636f395ceStb     /* get internal structure */
33736f395ceStb     if (file == NULL)
33836f395ceStb         return -1;
33936f395ceStb     state = (gz_statep)file;
34036f395ceStb 
34136f395ceStb     /* check that we're writing and that there's no error */
34236f395ceStb     if (state->mode != GZ_WRITE || state->err != Z_OK)
34336f395ceStb         return -1;
34436f395ceStb 
34536f395ceStb     /* write string */
346703d4924Stb     len = strlen(s);
347703d4924Stb     if ((int)len < 0 || (unsigned)len != len) {
348703d4924Stb         gz_error(state, Z_STREAM_ERROR, "string length does not fit in int");
349703d4924Stb         return -1;
350703d4924Stb     }
351703d4924Stb     put = gz_write(state, s, len);
352703d4924Stb     return put < len ? -1 : (int)len;
35336f395ceStb }
35436f395ceStb 
35536f395ceStb #if defined(STDC) || defined(Z_HAVE_STDARG_H)
35636f395ceStb #include <stdarg.h>
35736f395ceStb 
35836f395ceStb /* -- see zlib.h -- */
gzvprintf(gzFile file,const char * format,va_list va)359*a04ea15dStb int ZEXPORTVA gzvprintf(gzFile file, const char *format, va_list va) {
36036f395ceStb     int len;
36136f395ceStb     unsigned left;
36236f395ceStb     char *next;
36336f395ceStb     gz_statep state;
36436f395ceStb     z_streamp strm;
36536f395ceStb 
36636f395ceStb     /* get internal structure */
36736f395ceStb     if (file == NULL)
36836f395ceStb         return Z_STREAM_ERROR;
36936f395ceStb     state = (gz_statep)file;
37036f395ceStb     strm = &(state->strm);
37136f395ceStb 
37236f395ceStb     /* check that we're writing and that there's no error */
37336f395ceStb     if (state->mode != GZ_WRITE || state->err != Z_OK)
37436f395ceStb         return Z_STREAM_ERROR;
37536f395ceStb 
37636f395ceStb     /* make sure we have some buffer space */
37736f395ceStb     if (state->size == 0 && gz_init(state) == -1)
37836f395ceStb         return state->err;
37936f395ceStb 
38036f395ceStb     /* check for seek request */
38136f395ceStb     if (state->seek) {
38236f395ceStb         state->seek = 0;
38336f395ceStb         if (gz_zero(state, state->skip) == -1)
38436f395ceStb             return state->err;
38536f395ceStb     }
38636f395ceStb 
38736f395ceStb     /* do the printf() into the input buffer, put length in len -- the input
38836f395ceStb        buffer is double-sized just for this function, so there is guaranteed to
38936f395ceStb        be state->size bytes available after the current contents */
39036f395ceStb     if (strm->avail_in == 0)
39136f395ceStb         strm->next_in = state->in;
39236f395ceStb     next = (char *)(state->in + (strm->next_in - state->in) + strm->avail_in);
39336f395ceStb     next[state->size - 1] = 0;
39436f395ceStb #ifdef NO_vsnprintf
39536f395ceStb #  ifdef HAS_vsprintf_void
39636f395ceStb     (void)vsprintf(next, format, va);
39736f395ceStb     for (len = 0; len < state->size; len++)
39836f395ceStb         if (next[len] == 0) break;
39936f395ceStb #  else
40036f395ceStb     len = vsprintf(next, format, va);
40136f395ceStb #  endif
40236f395ceStb #else
40336f395ceStb #  ifdef HAS_vsnprintf_void
40436f395ceStb     (void)vsnprintf(next, state->size, format, va);
40536f395ceStb     len = strlen(next);
40636f395ceStb #  else
40736f395ceStb     len = vsnprintf(next, state->size, format, va);
40836f395ceStb #  endif
40936f395ceStb #endif
41036f395ceStb 
41136f395ceStb     /* check that printf() results fit in buffer */
41236f395ceStb     if (len == 0 || (unsigned)len >= state->size || next[state->size - 1] != 0)
41336f395ceStb         return 0;
41436f395ceStb 
41536f395ceStb     /* update buffer and position, compress first half if past that */
41636f395ceStb     strm->avail_in += (unsigned)len;
41736f395ceStb     state->x.pos += len;
41836f395ceStb     if (strm->avail_in >= state->size) {
41936f395ceStb         left = strm->avail_in - state->size;
42036f395ceStb         strm->avail_in = state->size;
42136f395ceStb         if (gz_comp(state, Z_NO_FLUSH) == -1)
42236f395ceStb             return state->err;
423703d4924Stb         memmove(state->in, state->in + state->size, left);
42436f395ceStb         strm->next_in = state->in;
42536f395ceStb         strm->avail_in = left;
42636f395ceStb     }
42736f395ceStb     return len;
42836f395ceStb }
42936f395ceStb 
gzprintf(gzFile file,const char * format,...)430*a04ea15dStb int ZEXPORTVA gzprintf(gzFile file, const char *format, ...) {
43136f395ceStb     va_list va;
43236f395ceStb     int ret;
43336f395ceStb 
43436f395ceStb     va_start(va, format);
43536f395ceStb     ret = gzvprintf(file, format, va);
43636f395ceStb     va_end(va);
43736f395ceStb     return ret;
43836f395ceStb }
43936f395ceStb 
44036f395ceStb #else /* !STDC && !Z_HAVE_STDARG_H */
44136f395ceStb 
44236f395ceStb /* -- 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*a04ea15dStb int ZEXPORTVA gzprintf(gzFile file, const char *format, int a1, int a2, int a3,
444*a04ea15dStb                        int a4, int a5, int a6, int a7, int a8, int a9, int a10,
445*a04ea15dStb                        int a11, int a12, int a13, int a14, int a15, int a16,
446*a04ea15dStb                        int a17, int a18, int a19, int a20) {
44736f395ceStb     unsigned len, left;
44836f395ceStb     char *next;
44936f395ceStb     gz_statep state;
45036f395ceStb     z_streamp strm;
45136f395ceStb 
45236f395ceStb     /* get internal structure */
45336f395ceStb     if (file == NULL)
45436f395ceStb         return Z_STREAM_ERROR;
45536f395ceStb     state = (gz_statep)file;
45636f395ceStb     strm = &(state->strm);
45736f395ceStb 
45836f395ceStb     /* check that can really pass pointer in ints */
45936f395ceStb     if (sizeof(int) != sizeof(void *))
46036f395ceStb         return Z_STREAM_ERROR;
46136f395ceStb 
46236f395ceStb     /* check that we're writing and that there's no error */
46336f395ceStb     if (state->mode != GZ_WRITE || state->err != Z_OK)
46436f395ceStb         return Z_STREAM_ERROR;
46536f395ceStb 
46636f395ceStb     /* make sure we have some buffer space */
46736f395ceStb     if (state->size == 0 && gz_init(state) == -1)
46836f395ceStb         return state->error;
46936f395ceStb 
47036f395ceStb     /* check for seek request */
47136f395ceStb     if (state->seek) {
47236f395ceStb         state->seek = 0;
47336f395ceStb         if (gz_zero(state, state->skip) == -1)
47436f395ceStb             return state->error;
47536f395ceStb     }
47636f395ceStb 
47736f395ceStb     /* do the printf() into the input buffer, put length in len -- the input
47836f395ceStb        buffer is double-sized just for this function, so there is guaranteed to
47936f395ceStb        be state->size bytes available after the current contents */
48036f395ceStb     if (strm->avail_in == 0)
48136f395ceStb         strm->next_in = state->in;
48236f395ceStb     next = (char *)(strm->next_in + strm->avail_in);
48336f395ceStb     next[state->size - 1] = 0;
48436f395ceStb #ifdef NO_snprintf
48536f395ceStb #  ifdef HAS_sprintf_void
48636f395ceStb     sprintf(next, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12,
48736f395ceStb             a13, a14, a15, a16, a17, a18, a19, a20);
48836f395ceStb     for (len = 0; len < size; len++)
48936f395ceStb         if (next[len] == 0)
49036f395ceStb             break;
49136f395ceStb #  else
49236f395ceStb     len = sprintf(next, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11,
49336f395ceStb                   a12, a13, a14, a15, a16, a17, a18, a19, a20);
49436f395ceStb #  endif
49536f395ceStb #else
49636f395ceStb #  ifdef HAS_snprintf_void
49736f395ceStb     snprintf(next, state->size, format, a1, a2, a3, a4, a5, a6, a7, a8, a9,
49836f395ceStb              a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20);
49936f395ceStb     len = strlen(next);
50036f395ceStb #  else
50136f395ceStb     len = snprintf(next, state->size, format, a1, a2, a3, a4, a5, a6, a7, a8,
50236f395ceStb                    a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20);
50336f395ceStb #  endif
50436f395ceStb #endif
50536f395ceStb 
50636f395ceStb     /* check that printf() results fit in buffer */
50736f395ceStb     if (len == 0 || len >= state->size || next[state->size - 1] != 0)
50836f395ceStb         return 0;
50936f395ceStb 
51036f395ceStb     /* update buffer and position, compress first half if past that */
51136f395ceStb     strm->avail_in += len;
51236f395ceStb     state->x.pos += len;
51336f395ceStb     if (strm->avail_in >= state->size) {
51436f395ceStb         left = strm->avail_in - state->size;
51536f395ceStb         strm->avail_in = state->size;
51636f395ceStb         if (gz_comp(state, Z_NO_FLUSH) == -1)
51736f395ceStb             return state->err;
518703d4924Stb         memmove(state->in, state->in + state->size, left);
51936f395ceStb         strm->next_in = state->in;
52036f395ceStb         strm->avail_in = left;
52136f395ceStb     }
52236f395ceStb     return (int)len;
52336f395ceStb }
52436f395ceStb 
52536f395ceStb #endif
52636f395ceStb 
52736f395ceStb /* -- see zlib.h -- */
gzflush(gzFile file,int flush)528*a04ea15dStb int ZEXPORT gzflush(gzFile file, int flush) {
52936f395ceStb     gz_statep state;
53036f395ceStb 
53136f395ceStb     /* get internal structure */
53236f395ceStb     if (file == NULL)
53336f395ceStb         return Z_STREAM_ERROR;
53436f395ceStb     state = (gz_statep)file;
53536f395ceStb 
53636f395ceStb     /* check that we're writing and that there's no error */
53736f395ceStb     if (state->mode != GZ_WRITE || state->err != Z_OK)
53836f395ceStb         return Z_STREAM_ERROR;
53936f395ceStb 
54036f395ceStb     /* check flush parameter */
54136f395ceStb     if (flush < 0 || flush > Z_FINISH)
54236f395ceStb         return Z_STREAM_ERROR;
54336f395ceStb 
54436f395ceStb     /* check for seek request */
54536f395ceStb     if (state->seek) {
54636f395ceStb         state->seek = 0;
54736f395ceStb         if (gz_zero(state, state->skip) == -1)
54836f395ceStb             return state->err;
54936f395ceStb     }
55036f395ceStb 
55136f395ceStb     /* compress remaining data with requested flush */
55236f395ceStb     (void)gz_comp(state, flush);
55336f395ceStb     return state->err;
55436f395ceStb }
55536f395ceStb 
55636f395ceStb /* -- see zlib.h -- */
gzsetparams(gzFile file,int level,int strategy)557*a04ea15dStb int ZEXPORT gzsetparams(gzFile file, int level, int strategy) {
55836f395ceStb     gz_statep state;
55936f395ceStb     z_streamp strm;
56036f395ceStb 
56136f395ceStb     /* get internal structure */
56236f395ceStb     if (file == NULL)
56336f395ceStb         return Z_STREAM_ERROR;
56436f395ceStb     state = (gz_statep)file;
56536f395ceStb     strm = &(state->strm);
56636f395ceStb 
56736f395ceStb     /* check that we're writing and that there's no error */
568*a04ea15dStb     if (state->mode != GZ_WRITE || state->err != Z_OK || state->direct)
56936f395ceStb         return Z_STREAM_ERROR;
57036f395ceStb 
57136f395ceStb     /* if no change is requested, then do nothing */
57236f395ceStb     if (level == state->level && strategy == state->strategy)
57336f395ceStb         return Z_OK;
57436f395ceStb 
57536f395ceStb     /* check for seek request */
57636f395ceStb     if (state->seek) {
57736f395ceStb         state->seek = 0;
57836f395ceStb         if (gz_zero(state, state->skip) == -1)
57936f395ceStb             return state->err;
58036f395ceStb     }
58136f395ceStb 
58236f395ceStb     /* change compression parameters for subsequent input */
58336f395ceStb     if (state->size) {
58436f395ceStb         /* flush previous input with previous parameters before changing */
58536f395ceStb         if (strm->avail_in && gz_comp(state, Z_BLOCK) == -1)
58636f395ceStb             return state->err;
58736f395ceStb         deflateParams(strm, level, strategy);
58836f395ceStb     }
58936f395ceStb     state->level = level;
59036f395ceStb     state->strategy = strategy;
59136f395ceStb     return Z_OK;
59236f395ceStb }
59336f395ceStb 
59436f395ceStb /* -- see zlib.h -- */
gzclose_w(gzFile file)595*a04ea15dStb int ZEXPORT gzclose_w(gzFile file) {
59636f395ceStb     int ret = Z_OK;
59736f395ceStb     gz_statep state;
59836f395ceStb 
59936f395ceStb     /* get internal structure */
60036f395ceStb     if (file == NULL)
60136f395ceStb         return Z_STREAM_ERROR;
60236f395ceStb     state = (gz_statep)file;
60336f395ceStb 
60436f395ceStb     /* check that we're writing */
60536f395ceStb     if (state->mode != GZ_WRITE)
60636f395ceStb         return Z_STREAM_ERROR;
60736f395ceStb 
60836f395ceStb     /* check for seek request */
60936f395ceStb     if (state->seek) {
61036f395ceStb         state->seek = 0;
61136f395ceStb         if (gz_zero(state, state->skip) == -1)
61236f395ceStb             ret = state->err;
61336f395ceStb     }
61436f395ceStb 
61536f395ceStb     /* flush, free memory, and close file */
61636f395ceStb     if (gz_comp(state, Z_FINISH) == -1)
61736f395ceStb         ret = state->err;
61836f395ceStb     if (state->size) {
61936f395ceStb         if (!state->direct) {
62036f395ceStb             (void)deflateEnd(&(state->strm));
62136f395ceStb             free(state->out);
62236f395ceStb         }
62336f395ceStb         free(state->in);
62436f395ceStb     }
62536f395ceStb     gz_error(state, Z_OK, NULL);
62636f395ceStb     free(state->path);
62736f395ceStb     if (close(state->fd) == -1)
62836f395ceStb         ret = Z_ERRNO;
62936f395ceStb     free(state);
63036f395ceStb     return ret;
63136f395ceStb }
632