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

压缩解压

开发平台:

Visual C++

  1. /* gzlib.c -- zlib functions common to reading and writing gzip files
  2.  * Copyright (C) 2004, 2010 Mark Adler
  3.  * For conditions of distribution and use, see copyright notice in zlib.h
  4.  */
  5. #include "gzguts.h"
  6. #ifdef _LARGEFILE64_SOURCE
  7. #  define LSEEK lseek64
  8. #else
  9. #  define LSEEK lseek
  10. #endif
  11. /* Local functions */
  12. local void gz_reset OF((gz_statep));
  13. local gzFile gz_open OF((const char *, int, const char *));
  14. #if defined UNDER_CE && defined NO_ERRNO_H
  15. /* Map the Windows error number in ERROR to a locale-dependent error message
  16.    string and return a pointer to it.  Typically, the values for ERROR come
  17.    from GetLastError.
  18.    The string pointed to shall not be modified by the application, but may be
  19.    overwritten by a subsequent call to gz_strwinerror
  20.    The gz_strwinerror function does not change the current setting of
  21.    GetLastError. */
  22. char ZEXPORT *gz_strwinerror (error)
  23.      DWORD error;
  24. {
  25.     static char buf[1024];
  26.     wchar_t *msgbuf;
  27.     DWORD lasterr = GetLastError();
  28.     DWORD chars = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM
  29.         | FORMAT_MESSAGE_ALLOCATE_BUFFER,
  30.         NULL,
  31.         error,
  32.         0, /* Default language */
  33.         (LPVOID)&msgbuf,
  34.         0,
  35.         NULL);
  36.     if (chars != 0) {
  37.         /* If there is an rn appended, zap it.  */
  38.         if (chars >= 2
  39.             && msgbuf[chars - 2] == 'r' && msgbuf[chars - 1] == 'n') {
  40.             chars -= 2;
  41.             msgbuf[chars] = 0;
  42.         }
  43.         if (chars > sizeof (buf) - 1) {
  44.             chars = sizeof (buf) - 1;
  45.             msgbuf[chars] = 0;
  46.         }
  47.         wcstombs(buf, msgbuf, chars + 1);
  48.         LocalFree(msgbuf);
  49.     }
  50.     else {
  51.         sprintf(buf, "unknown win32 error (%ld)", error);
  52.     }
  53.     SetLastError(lasterr);
  54.     return buf;
  55. }
  56. #endif /* UNDER_CE && NO_ERRNO_H */
  57. /* Reset gzip file state */
  58. local void gz_reset(state)
  59.     gz_statep state;
  60. {
  61.     if (state->mode == GZ_READ) {   /* for reading ... */
  62.         state->have = 0;            /* no output data available */
  63.         state->eof = 0;             /* not at end of file */
  64.         state->how = LOOK;          /* look for gzip header */
  65.         state->direct = 1;          /* default for empty file */
  66.     }
  67.     state->seek = 0;                /* no seek request pending */
  68.     gz_error(state, Z_OK, NULL);    /* clear error */
  69.     state->pos = 0;                 /* no uncompressed data yet */
  70.     state->strm.avail_in = 0;       /* no input data yet */
  71. }
  72. /* Open a gzip file either by name or file descriptor. */
  73. local gzFile gz_open(path, fd, mode)
  74.     const char *path;
  75.     int fd;
  76.     const char *mode;
  77. {
  78.     gz_statep state;
  79.     /* allocate gzFile structure to return */
  80.     state = malloc(sizeof(gz_state));
  81.     if (state == NULL)
  82.         return NULL;
  83.     state->size = 0;            /* no buffers allocated yet */
  84.     state->want = GZBUFSIZE;    /* requested buffer size */
  85.     state->msg = NULL;          /* no error message yet */
  86.     /* interpret mode */
  87.     state->mode = GZ_NONE;
  88.     state->level = Z_DEFAULT_COMPRESSION;
  89.     state->strategy = Z_DEFAULT_STRATEGY;
  90.     while (*mode) {
  91.         if (*mode >= '0' && *mode <= '9')
  92.             state->level = *mode - '0';
  93.         else
  94.             switch (*mode) {
  95.             case 'r':
  96.                 state->mode = GZ_READ;
  97.                 break;
  98. #ifndef NO_GZCOMPRESS
  99.             case 'w':
  100.                 state->mode = GZ_WRITE;
  101.                 break;
  102.             case 'a':
  103.                 state->mode = GZ_APPEND;
  104.                 break;
  105. #endif
  106.             case '+':       /* can't read and write at the same time */
  107.                 free(state);
  108.                 return NULL;
  109.             case 'b':       /* ignore -- will request binary anyway */
  110.                 break;
  111.             case 'f':
  112.                 state->strategy = Z_FILTERED;
  113.                 break;
  114.             case 'h':
  115.                 state->strategy = Z_HUFFMAN_ONLY;
  116.                 break;
  117.             case 'R':
  118.                 state->strategy = Z_RLE;
  119.                 break;
  120.             case 'F':
  121.                 state->strategy = Z_FIXED;
  122.             default:        /* could consider as an error, but just ignore */
  123.                 ;
  124.             }
  125.         mode++;
  126.     }
  127.     /* must provide an "r", "w", or "a" */
  128.     if (state->mode == GZ_NONE) {
  129.         free(state);
  130.         return NULL;
  131.     }
  132.     /* save the path name for error messages */
  133.     state->path = malloc(strlen(path) + 1);
  134.     if (state->path == NULL) {
  135.         free(state);
  136.         return NULL;
  137.     }
  138.     strcpy(state->path, path);
  139.     /* open the file with the appropriate mode (or just use fd) */
  140.     state->fd = fd != -1 ? fd :
  141.         open(path,
  142. #ifdef O_LARGEFILE
  143.             O_LARGEFILE |
  144. #endif
  145. #ifdef O_BINARY
  146.             O_BINARY |
  147. #endif
  148.             (state->mode == GZ_READ ?
  149.                 O_RDONLY :
  150.                 (O_WRONLY | O_CREAT | (
  151.                     state->mode == GZ_WRITE ?
  152.                         O_TRUNC :
  153.                         O_APPEND))),
  154.             0666);
  155.     if (state->fd == -1) {
  156.         free(state);
  157.         return NULL;
  158.     }
  159.     if (state->mode == GZ_APPEND)
  160.         state->mode = GZ_WRITE;         /* simplify later checks */
  161.     /* save the current position for rewinding (only if reading) */
  162.     if (state->mode == GZ_READ) {
  163.         state->start = LSEEK(state->fd, 0, SEEK_CUR);
  164.         if (state->start == -1) state->start = 0;
  165.     }
  166.     /* initialize stream */
  167.     gz_reset(state);
  168.     /* return stream */
  169.     return (gzFile)state;
  170. }
  171. /* -- see zlib.h -- */
  172. gzFile ZEXPORT gzopen(path, mode)
  173.     const char *path;
  174.     const char *mode;
  175. {
  176.     return gz_open(path, -1, mode);
  177. }
  178. /* -- see zlib.h -- */
  179. gzFile ZEXPORT gzopen64(path, mode)
  180.     const char *path;
  181.     const char *mode;
  182. {
  183.     return gz_open(path, -1, mode);
  184. }
  185. /* -- see zlib.h -- */
  186. gzFile ZEXPORT gzdopen(fd, mode)
  187.     int fd;
  188.     const char *mode;
  189. {
  190.     char *path;         /* identifier for error messages */
  191.     gzFile gz;
  192.     if (fd == -1 || (path = malloc(7 + 3 * sizeof(int))) == NULL)
  193.         return NULL;
  194.     sprintf(path, "<fd:%d>", fd);
  195.     gz = gz_open(path, fd, mode);
  196.     free(path);
  197.     return gz;
  198. }
  199. /* -- see zlib.h -- */
  200. int ZEXPORT gzbuffer(file, size)
  201.     gzFile file;
  202.     unsigned size;
  203. {
  204.     gz_statep state;
  205.     /* get internal structure and check integrity */
  206.     if (file == NULL)
  207.         return -1;
  208.     state = (gz_statep)file;
  209.     if (state->mode != GZ_READ && state->mode != GZ_WRITE)
  210.         return -1;
  211.     /* make sure we haven't already allocated memory */
  212.     if (state->size != 0)
  213.         return -1;
  214.     /* check and set requested size */
  215.     if (size == 0)
  216.         return -1;
  217.     state->want = size;
  218.     return 0;
  219. }
  220. /* -- see zlib.h -- */
  221. int ZEXPORT gzrewind(file)
  222.     gzFile file;
  223. {
  224.     gz_statep state;
  225.     /* get internal structure */
  226.     if (file == NULL)
  227.         return -1;
  228.     state = (gz_statep)file;
  229.     /* check that we're reading and that there's no error */
  230.     if (state->mode != GZ_READ || state->err != Z_OK)
  231.         return -1;
  232.     /* back up and start over */
  233.     if (LSEEK(state->fd, state->start, SEEK_SET) == -1)
  234.         return -1;
  235.     gz_reset(state);
  236.     return 0;
  237. }
  238. /* -- see zlib.h -- */
  239. z_off64_t ZEXPORT gzseek64(file, offset, whence)
  240.     gzFile file;
  241.     z_off64_t offset;
  242.     int whence;
  243. {
  244.     unsigned n;
  245.     z_off64_t ret;
  246.     gz_statep state;
  247.     /* get internal structure and check integrity */
  248.     if (file == NULL)
  249.         return -1;
  250.     state = (gz_statep)file;
  251.     if (state->mode != GZ_READ && state->mode != GZ_WRITE)
  252.         return -1;
  253.     /* check that there's no error */
  254.     if (state->err != Z_OK)
  255.         return -1;
  256.     /* can only seek from start or relative to current position */
  257.     if (whence != SEEK_SET && whence != SEEK_CUR)
  258.         return -1;
  259.     /* normalize offset to a SEEK_CUR specification */
  260.     if (whence == SEEK_SET)
  261.         offset -= state->pos;
  262.     else if (state->seek)
  263.         offset += state->skip;
  264.     state->seek = 0;
  265.     /* if within raw area while reading, just go there */
  266.     if (state->mode == GZ_READ && state->how == COPY &&
  267.         state->pos + offset >= state->raw) {
  268.         ret = LSEEK(state->fd, offset, SEEK_CUR);
  269.         if (ret == -1)
  270.             return -1;
  271.         state->have = 0;
  272.         state->eof = 0;
  273.         state->seek = 0;
  274.         gz_error(state, Z_OK, NULL);
  275.         state->strm.avail_in = 0;
  276.         state->pos += offset;
  277.         return state->pos;
  278.     }
  279.     /* calculate skip amount, rewinding if needed for back seek when reading */
  280.     if (offset < 0) {
  281.         if (state->mode != GZ_READ)         /* writing -- can't go backwards */
  282.             return -1;
  283.         offset += state->pos;
  284.         if (offset < 0)                     /* before start of file! */
  285.             return -1;
  286.         if (gzrewind(file) == -1)           /* rewind, then skip to offset */
  287.             return -1;
  288.     }
  289.     /* if reading, skip what's in output buffer (one less gzgetc() check) */
  290.     if (state->mode == GZ_READ) {
  291.         n = GT_OFF(state->have) || (z_off64_t)state->have > offset ?
  292.             (unsigned)offset : state->have;
  293.         state->have -= n;
  294.         state->next += n;
  295.         state->pos += n;
  296.         offset -= n;
  297.     }
  298.     /* request skip (if not zero) */
  299.     if (offset) {
  300.         state->seek = 1;
  301.         state->skip = offset;
  302.     }
  303.     return state->pos + offset;
  304. }
  305. /* -- see zlib.h -- */
  306. z_off_t ZEXPORT gzseek(file, offset, whence)
  307.     gzFile file;
  308.     z_off_t offset;
  309.     int whence;
  310. {
  311.     z_off64_t ret;
  312.     ret = gzseek64(file, (z_off64_t)offset, whence);
  313.     return ret == (z_off_t)ret ? (z_off_t)ret : -1;
  314. }
  315. /* -- see zlib.h -- */
  316. z_off64_t ZEXPORT gztell64(file)
  317.     gzFile file;
  318. {
  319.     gz_statep state;
  320.     /* get internal structure and check integrity */
  321.     if (file == NULL)
  322.         return -1;
  323.     state = (gz_statep)file;
  324.     if (state->mode != GZ_READ && state->mode != GZ_WRITE)
  325.         return -1;
  326.     /* return position */
  327.     return state->pos + (state->seek ? state->skip : 0);
  328. }
  329. /* -- see zlib.h -- */
  330. z_off_t ZEXPORT gztell(file)
  331.     gzFile file;
  332. {
  333.     z_off64_t ret;
  334.     ret = gztell64(file);
  335.     return ret == (z_off_t)ret ? (z_off_t)ret : -1;
  336. }
  337. /* -- see zlib.h -- */
  338. z_off64_t ZEXPORT gzoffset64(file)
  339.     gzFile file;
  340. {
  341.     z_off64_t offset;
  342.     gz_statep state;
  343.     /* get internal structure and check integrity */
  344.     if (file == NULL)
  345.         return -1;
  346.     state = (gz_statep)file;
  347.     if (state->mode != GZ_READ && state->mode != GZ_WRITE)
  348.         return -1;
  349.     /* compute and return effective offset in file */
  350.     offset = LSEEK(state->fd, 0, SEEK_CUR);
  351.     if (offset == -1)
  352.         return -1;
  353.     if (state->mode == GZ_READ)             /* reading */
  354.         offset -= state->strm.avail_in;     /* don't count buffered input */
  355.     return offset;
  356. }
  357. /* -- see zlib.h -- */
  358. z_off_t ZEXPORT gzoffset(file)
  359.     gzFile file;
  360. {
  361.     z_off64_t ret;
  362.     ret = gzoffset64(file);
  363.     return ret == (z_off_t)ret ? (z_off_t)ret : -1;
  364. }
  365. /* -- see zlib.h -- */
  366. int ZEXPORT gzeof(file)
  367.     gzFile file;
  368. {
  369.     gz_statep state;
  370.     /* get internal structure and check integrity */
  371.     if (file == NULL)
  372.         return 0;
  373.     state = (gz_statep)file;
  374.     if (state->mode != GZ_READ && state->mode != GZ_WRITE)
  375.         return 0;
  376.     /* return end-of-file state */
  377.     return state->mode == GZ_READ ? (state->eof && state->have == 0) : 0;
  378. }
  379. /* -- see zlib.h -- */
  380. const char * ZEXPORT gzerror(file, errnum)
  381.     gzFile file;
  382.     int *errnum;
  383. {
  384.     gz_statep state;
  385.     /* get internal structure and check integrity */
  386.     if (file == NULL)
  387.         return NULL;
  388.     state = (gz_statep)file;
  389.     if (state->mode != GZ_READ && state->mode != GZ_WRITE)
  390.         return NULL;
  391.     /* return error information */
  392.     if (errnum != NULL)
  393.         *errnum = state->err;
  394.     return state->msg == NULL ? "" : state->msg;
  395. }
  396. /* -- see zlib.h -- */
  397. void ZEXPORT gzclearerr(file)
  398.     gzFile file;
  399. {
  400.     gz_statep state;
  401.     /* get internal structure and check integrity */
  402.     if (file == NULL)
  403.         return;
  404.     state = (gz_statep)file;
  405.     if (state->mode != GZ_READ && state->mode != GZ_WRITE)
  406.         return;
  407.     /* clear error and end-of-file */
  408.     if (state->mode == GZ_READ)
  409.         state->eof = 0;
  410.     gz_error(state, Z_OK, NULL);
  411. }
  412. /* Create an error message in allocated memory and set state->err and
  413.    state->msg accordingly.  Free any previous error message already there.  Do
  414.    not try to free or allocate space if the error is Z_MEM_ERROR (out of
  415.    memory).  Simply save the error message as a static string.  If there is an
  416.    allocation failure constructing the error message, then convert the error to
  417.    out of memory. */
  418. void ZEXPORT gz_error(state, err, msg)
  419.     gz_statep state;
  420.     int err;
  421.     const char *msg;
  422. {
  423.     /* free previously allocated message and clear */
  424.     if (state->msg != NULL) {
  425.         if (state->err != Z_MEM_ERROR)
  426.             free(state->msg);
  427.         state->msg = NULL;
  428.     }
  429.     /* set error code, and if no message, then done */
  430.     state->err = err;
  431.     if (msg == NULL)
  432.         return;
  433.     /* for an out of memory error, save as static string */
  434.     if (err == Z_MEM_ERROR) {
  435.         state->msg = (char *)msg;
  436.         return;
  437.     }
  438.     /* construct error message with path */
  439.     if ((state->msg = malloc(strlen(state->path) + strlen(msg) + 3)) == NULL) {
  440.         state->err = Z_MEM_ERROR;
  441.         state->msg = (char *)"out of memory";
  442.         return;
  443.     }
  444.     strcpy(state->msg, state->path);
  445.     strcat(state->msg, ": ");
  446.     strcat(state->msg, msg);
  447.     return;
  448. }
  449. #ifndef INT_MAX
  450. /* portably return maximum value for an int (when limits.h presumed not
  451.    available) -- we need to do this to cover cases where 2's complement not
  452.    used, since C standard permits 1's complement and sign-bit representations,
  453.    otherwise we could just use ((unsigned)-1) >> 1 */
  454. unsigned ZEXPORT gz_intmax()
  455. {
  456.     unsigned p, q;
  457.     p = 1;
  458.     do {
  459.         q = p;
  460.         p <<= 1;
  461.         p++;
  462.     } while (p > q);
  463.     return q >> 1;
  464. }
  465. #endif