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