modules/zlib/src/gzwrite.c

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

     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  */
     6 #include "gzguts.h"
     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));
    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(state)
    16     gz_statep state;
    17 {
    18     int ret;
    19     z_streamp strm = &(state->strm);
    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     }
    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         }
    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     }
    52     /* mark state as initialized */
    53     state->size = state->want;
    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 }
    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(state, flush)
    71     gz_statep state;
    72     int flush;
    73 {
    74     int ret, got;
    75     unsigned have;
    76     z_streamp strm = &(state->strm);
    78     /* allocate memory if this is the first time through */
    79     if (state->size == 0 && gz_init(state) == -1)
    80         return -1;
    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     }
    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         }
   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);
   124     /* if that completed a deflate stream, allow another to start */
   125     if (flush == Z_FINISH)
   126         deflateReset(strm);
   128     /* all done, no errors */
   129     return 0;
   130 }
   132 /* Compress len zeros to output.  Return -1 on error, 0 on success. */
   133 local int gz_zero(state, len)
   134     gz_statep state;
   135     z_off64_t len;
   136 {
   137     int first;
   138     unsigned n;
   139     z_streamp strm = &(state->strm);
   141     /* consume whatever's left in the input buffer */
   142     if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1)
   143         return -1;
   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 }
   164 /* -- see zlib.h -- */
   165 int ZEXPORT gzwrite(file, buf, len)
   166     gzFile file;
   167     voidpc buf;
   168     unsigned len;
   169 {
   170     unsigned put = len;
   171     gz_statep state;
   172     z_streamp strm;
   174     /* get internal structure */
   175     if (file == NULL)
   176         return 0;
   177     state = (gz_statep)file;
   178     strm = &(state->strm);
   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;
   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     }
   191     /* if len is zero, avoid unnecessary operations */
   192     if (len == 0)
   193         return 0;
   195     /* allocate memory if this is the first time through */
   196     if (state->size == 0 && gz_init(state) == -1)
   197         return 0;
   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     }
   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;
   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;
   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     }
   240     /* input was all buffered or compressed (put will fit in int) */
   241     return (int)put;
   242 }
   244 /* -- see zlib.h -- */
   245 int ZEXPORT gzputc(file, c)
   246     gzFile file;
   247     int c;
   248 {
   249     unsigned have;
   250     unsigned char buf[1];
   251     gz_statep state;
   252     z_streamp strm;
   254     /* get internal structure */
   255     if (file == NULL)
   256         return -1;
   257     state = (gz_statep)file;
   258     strm = &(state->strm);
   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;
   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     }
   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     }
   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 }
   292 /* -- see zlib.h -- */
   293 int ZEXPORT gzputs(file, str)
   294     gzFile file;
   295     const char *str;
   296 {
   297     int ret;
   298     unsigned len;
   300     /* write string */
   301     len = (unsigned)strlen(str);
   302     ret = gzwrite(file, str, len);
   303     return ret == 0 && len != 0 ? -1 : ret;
   304 }
   306 #if defined(STDC) || defined(Z_HAVE_STDARG_H)
   307 #include <stdarg.h>
   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;
   316     /* get internal structure */
   317     if (file == NULL)
   318         return -1;
   319     state = (gz_statep)file;
   320     strm = &(state->strm);
   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;
   326     /* make sure we have some buffer space */
   327     if (state->size == 0 && gz_init(state) == -1)
   328         return 0;
   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     }
   337     /* consume whatever's left in the input buffer */
   338     if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1)
   339         return 0;
   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
   361     /* check that printf() results fit in buffer */
   362     if (len <= 0 || len >= (int)size || state->in[size - 1] != 0)
   363         return 0;
   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 }
   372 int ZEXPORTVA gzprintf(gzFile file, const char *format, ...)
   373 {
   374     va_list va;
   375     int ret;
   377     va_start(va, format);
   378     ret = gzvprintf(file, format, va);
   379     va_end(va);
   380     return ret;
   381 }
   383 #else /* !STDC && !Z_HAVE_STDARG_H */
   385 /* -- see zlib.h -- */
   386 int ZEXPORTVA gzprintf (file, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10,
   387                        a11, a12, a13, a14, a15, a16, a17, a18, a19, a20)
   388     gzFile file;
   389     const char *format;
   390     int a1, a2, a3, a4, a5, a6, a7, a8, a9, a10,
   391         a11, a12, a13, a14, a15, a16, a17, a18, a19, a20;
   392 {
   393     int size, len;
   394     gz_statep state;
   395     z_streamp strm;
   397     /* get internal structure */
   398     if (file == NULL)
   399         return -1;
   400     state = (gz_statep)file;
   401     strm = &(state->strm);
   403     /* check that can really pass pointer in ints */
   404     if (sizeof(int) != sizeof(void *))
   405         return 0;
   407     /* check that we're writing and that there's no error */
   408     if (state->mode != GZ_WRITE || state->err != Z_OK)
   409         return 0;
   411     /* make sure we have some buffer space */
   412     if (state->size == 0 && gz_init(state) == -1)
   413         return 0;
   415     /* check for seek request */
   416     if (state->seek) {
   417         state->seek = 0;
   418         if (gz_zero(state, state->skip) == -1)
   419             return 0;
   420     }
   422     /* consume whatever's left in the input buffer */
   423     if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1)
   424         return 0;
   426     /* do the printf() into the input buffer, put length in len */
   427     size = (int)(state->size);
   428     state->in[size - 1] = 0;
   429 #ifdef NO_snprintf
   430 #  ifdef HAS_sprintf_void
   431     sprintf((char *)(state->in), format, a1, a2, a3, a4, a5, a6, a7, a8,
   432             a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20);
   433     for (len = 0; len < size; len++)
   434         if (state->in[len] == 0) break;
   435 #  else
   436     len = sprintf((char *)(state->in), format, a1, a2, a3, a4, a5, a6, a7, a8,
   437                   a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20);
   438 #  endif
   439 #else
   440 #  ifdef HAS_snprintf_void
   441     snprintf((char *)(state->in), size, format, a1, a2, a3, a4, a5, a6, a7, a8,
   442              a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20);
   443     len = strlen((char *)(state->in));
   444 #  else
   445     len = snprintf((char *)(state->in), size, format, a1, a2, a3, a4, a5, a6,
   446                    a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18,
   447                    a19, a20);
   448 #  endif
   449 #endif
   451     /* check that printf() results fit in buffer */
   452     if (len <= 0 || len >= (int)size || state->in[size - 1] != 0)
   453         return 0;
   455     /* update buffer and position, defer compression until needed */
   456     strm->avail_in = (unsigned)len;
   457     strm->next_in = state->in;
   458     state->x.pos += len;
   459     return len;
   460 }
   462 #endif
   464 /* -- see zlib.h -- */
   465 int ZEXPORT gzflush(file, flush)
   466     gzFile file;
   467     int flush;
   468 {
   469     gz_statep state;
   471     /* get internal structure */
   472     if (file == NULL)
   473         return -1;
   474     state = (gz_statep)file;
   476     /* check that we're writing and that there's no error */
   477     if (state->mode != GZ_WRITE || state->err != Z_OK)
   478         return Z_STREAM_ERROR;
   480     /* check flush parameter */
   481     if (flush < 0 || flush > Z_FINISH)
   482         return Z_STREAM_ERROR;
   484     /* check for seek request */
   485     if (state->seek) {
   486         state->seek = 0;
   487         if (gz_zero(state, state->skip) == -1)
   488             return -1;
   489     }
   491     /* compress remaining data with requested flush */
   492     gz_comp(state, flush);
   493     return state->err;
   494 }
   496 /* -- see zlib.h -- */
   497 int ZEXPORT gzsetparams(file, level, strategy)
   498     gzFile file;
   499     int level;
   500     int strategy;
   501 {
   502     gz_statep state;
   503     z_streamp strm;
   505     /* get internal structure */
   506     if (file == NULL)
   507         return Z_STREAM_ERROR;
   508     state = (gz_statep)file;
   509     strm = &(state->strm);
   511     /* check that we're writing and that there's no error */
   512     if (state->mode != GZ_WRITE || state->err != Z_OK)
   513         return Z_STREAM_ERROR;
   515     /* if no change is requested, then do nothing */
   516     if (level == state->level && strategy == state->strategy)
   517         return Z_OK;
   519     /* check for seek request */
   520     if (state->seek) {
   521         state->seek = 0;
   522         if (gz_zero(state, state->skip) == -1)
   523             return -1;
   524     }
   526     /* change compression parameters for subsequent input */
   527     if (state->size) {
   528         /* flush previous input with previous parameters before changing */
   529         if (strm->avail_in && gz_comp(state, Z_PARTIAL_FLUSH) == -1)
   530             return state->err;
   531         deflateParams(strm, level, strategy);
   532     }
   533     state->level = level;
   534     state->strategy = strategy;
   535     return Z_OK;
   536 }
   538 /* -- see zlib.h -- */
   539 int ZEXPORT gzclose_w(file)
   540     gzFile file;
   541 {
   542     int ret = Z_OK;
   543     gz_statep state;
   545     /* get internal structure */
   546     if (file == NULL)
   547         return Z_STREAM_ERROR;
   548     state = (gz_statep)file;
   550     /* check that we're writing */
   551     if (state->mode != GZ_WRITE)
   552         return Z_STREAM_ERROR;
   554     /* check for seek request */
   555     if (state->seek) {
   556         state->seek = 0;
   557         if (gz_zero(state, state->skip) == -1)
   558             ret = state->err;
   559     }
   561     /* flush, free memory, and close file */
   562     if (gz_comp(state, Z_FINISH) == -1)
   563         ret = state->err;
   564     if (state->size) {
   565         if (!state->direct) {
   566             (void)deflateEnd(&(state->strm));
   567             free(state->out);
   568         }
   569         free(state->in);
   570     }
   571     gz_error(state, Z_OK, NULL);
   572     free(state->path);
   573     if (close(state->fd) == -1)
   574         ret = Z_ERRNO;
   575     free(state);
   576     return ret;
   577 }

mercurial