The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/contrib/zstd/zlibWrapper/gzlib.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

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

Cache object: c566e2f4b3f54a8e74cdf0cb2983c190


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.