Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | Download | RSS feed

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