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