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