gzwrite.c
上传用户:shengde
上传日期:2021-02-21
资源大小:638k
文件大小:14k
源码类别:

压缩解压

开发平台:

Visual C++

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