Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

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