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

Cache object: e344ae3140db3be49517759396680382


[ 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.