modules/zlib/src/gzlib.c

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

     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  */
     6 #include "gzguts.h"
     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
    18 /* Local functions */
    19 local void gz_reset OF((gz_statep));
    20 local gzFile gz_open OF((const void *, int, const char *));
    22 #if defined UNDER_CE
    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.
    28    The string pointed to shall not be modified by the application, but may be
    29    overwritten by a subsequent call to gz_strwinerror
    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];
    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         }
    56         if (chars > sizeof (buf) - 1) {
    57             chars = sizeof (buf) - 1;
    58             msgbuf[chars] = 0;
    59         }
    61         wcstombs(buf, msgbuf, chars + 1);
    62         LocalFree(msgbuf);
    63     }
    64     else {
    65         sprintf(buf, "unknown win32 error (%ld)", error);
    66     }
    68     SetLastError(lasterr);
    69     return buf;
    70 }
    72 #endif /* UNDER_CE */
    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 }
    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
   106     /* check input */
   107     if (path == NULL)
   108         return NULL;
   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 */
   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     }
   175     /* must provide an "r", "w", or "a" */
   176     if (state->mode == GZ_NONE) {
   177         free(state);
   178         return NULL;
   179     }
   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     }
   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
   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)));
   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 */
   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     }
   260     /* initialize stream */
   261     gz_reset(state);
   263     /* return stream */
   264     return (gzFile)state;
   265 }
   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 }
   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 }
   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;
   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 }
   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
   313 /* -- see zlib.h -- */
   314 int ZEXPORT gzbuffer(file, size)
   315     gzFile file;
   316     unsigned size;
   317 {
   318     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;
   327     /* make sure we haven't already allocated memory */
   328     if (state->size != 0)
   329         return -1;
   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 }
   338 /* -- see zlib.h -- */
   339 int ZEXPORT gzrewind(file)
   340     gzFile file;
   341 {
   342     gz_statep state;
   344     /* get internal structure */
   345     if (file == NULL)
   346         return -1;
   347     state = (gz_statep)file;
   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;
   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 }
   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;
   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;
   378     /* check that there's no error */
   379     if (state->err != Z_OK && state->err != Z_BUF_ERROR)
   380         return -1;
   382     /* can only seek from start or relative to current position */
   383     if (whence != SEEK_SET && whence != SEEK_CUR)
   384         return -1;
   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;
   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     }
   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     }
   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     }
   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 }
   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;
   446     ret = gzseek64(file, (z_off64_t)offset, whence);
   447     return ret == (z_off_t)ret ? (z_off_t)ret : -1;
   448 }
   450 /* -- see zlib.h -- */
   451 z_off64_t ZEXPORT gztell64(file)
   452     gzFile file;
   453 {
   454     gz_statep state;
   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;
   463     /* return position */
   464     return state->x.pos + (state->seek ? state->skip : 0);
   465 }
   467 /* -- see zlib.h -- */
   468 z_off_t ZEXPORT gztell(file)
   469     gzFile file;
   470 {
   471     z_off64_t ret;
   473     ret = gztell64(file);
   474     return ret == (z_off_t)ret ? (z_off_t)ret : -1;
   475 }
   477 /* -- see zlib.h -- */
   478 z_off64_t ZEXPORT gzoffset64(file)
   479     gzFile file;
   480 {
   481     z_off64_t offset;
   482     gz_statep state;
   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;
   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 }
   500 /* -- see zlib.h -- */
   501 z_off_t ZEXPORT gzoffset(file)
   502     gzFile file;
   503 {
   504     z_off64_t ret;
   506     ret = gzoffset64(file);
   507     return ret == (z_off_t)ret ? (z_off_t)ret : -1;
   508 }
   510 /* -- see zlib.h -- */
   511 int ZEXPORT gzeof(file)
   512     gzFile file;
   513 {
   514     gz_statep state;
   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;
   523     /* return end-of-file state */
   524     return state->mode == GZ_READ ? state->past : 0;
   525 }
   527 /* -- see zlib.h -- */
   528 const char * ZEXPORT gzerror(file, errnum)
   529     gzFile file;
   530     int *errnum;
   531 {
   532     gz_statep state;
   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;
   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 }
   548 /* -- see zlib.h -- */
   549 void ZEXPORT gzclearerr(file)
   550     gzFile file;
   551 {
   552     gz_statep state;
   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;
   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 }
   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     }
   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;
   591     /* set error code, and if no message, then done */
   592     state->err = err;
   593     if (msg == NULL)
   594         return;
   596     /* for an out of memory error, return literal string when requested */
   597     if (err == Z_MEM_ERROR)
   598         return;
   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 }
   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;
   626     p = 1;
   627     do {
   628         q = p;
   629         p <<= 1;
   630         p++;
   631     } while (p > q);
   632     return q >> 1;
   633 }
   634 #endif

mercurial