Home | History | Annotate | Download | only in src
      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