Subversion Repositories Kolibri OS

Rev

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

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