Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  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(state)
  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(state, flush)
  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(state, len)
  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(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;
  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(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;
  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(file, str)
  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 (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;
  396.  
  397.     /* get internal structure */
  398.     if (file == NULL)
  399.         return -1;
  400.     state = (gz_statep)file;
  401.     strm = &(state->strm);
  402.  
  403.     /* check that can really pass pointer in ints */
  404.     if (sizeof(int) != sizeof(void *))
  405.         return 0;
  406.  
  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;
  410.  
  411.     /* make sure we have some buffer space */
  412.     if (state->size == 0 && gz_init(state) == -1)
  413.         return 0;
  414.  
  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.     }
  421.  
  422.     /* consume whatever's left in the input buffer */
  423.     if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1)
  424.         return 0;
  425.  
  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
  450.  
  451.     /* check that printf() results fit in buffer */
  452.     if (len <= 0 || len >= (int)size || state->in[size - 1] != 0)
  453.         return 0;
  454.  
  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. }
  461.  
  462. #endif
  463.  
  464. /* -- see zlib.h -- */
  465. int ZEXPORT gzflush(file, flush)
  466.     gzFile file;
  467.     int flush;
  468. {
  469.     gz_statep state;
  470.  
  471.     /* get internal structure */
  472.     if (file == NULL)
  473.         return -1;
  474.     state = (gz_statep)file;
  475.  
  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;
  479.  
  480.     /* check flush parameter */
  481.     if (flush < 0 || flush > Z_FINISH)
  482.         return Z_STREAM_ERROR;
  483.  
  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.     }
  490.  
  491.     /* compress remaining data with requested flush */
  492.     gz_comp(state, flush);
  493.     return state->err;
  494. }
  495.  
  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;
  504.  
  505.     /* get internal structure */
  506.     if (file == NULL)
  507.         return Z_STREAM_ERROR;
  508.     state = (gz_statep)file;
  509.     strm = &(state->strm);
  510.  
  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;
  514.  
  515.     /* if no change is requested, then do nothing */
  516.     if (level == state->level && strategy == state->strategy)
  517.         return Z_OK;
  518.  
  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.     }
  525.  
  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. }
  537.  
  538. /* -- see zlib.h -- */
  539. int ZEXPORT gzclose_w(file)
  540.     gzFile file;
  541. {
  542.     int ret = Z_OK;
  543.     gz_statep state;
  544.  
  545.     /* get internal structure */
  546.     if (file == NULL)
  547.         return Z_STREAM_ERROR;
  548.     state = (gz_statep)file;
  549.  
  550.     /* check that we're writing */
  551.     if (state->mode != GZ_WRITE)
  552.         return Z_STREAM_ERROR;
  553.  
  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.     }
  560.  
  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. }
  578.