Home | History | Annotate | Line # | Download | only in zlib
gzlib.c revision 1.1.1.1
      1  1.1  christos /* gzlib.c -- zlib functions common to reading and writing gzip files
      2  1.1  christos  * Copyright (C) 2004, 2010, 2011, 2012, 2013, 2016 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__) && !defined(__MINGW32__)
      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     z_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.1  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.1  christos                 break;
    166  1.1  christos             case 'T':
    167  1.1  christos                 state->direct = 1;
    168  1.1  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 WIDECHAR
    192  1.1  christos     if (fd == -2) {
    193  1.1  christos         len = wcstombs(NULL, path, 0);
    194  1.1  christos         if (len == (z_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.1  christos         len = strlen((const char *)path);
    200  1.1  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 WIDECHAR
    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.1  christos #if !defined(NO_snprintf) && !defined(NO_vsnprintf)
    214  1.1  christos         (void)snprintf(state->path, len + 1, "%s", (const char *)path);
    215  1.1  christos #else
    216  1.1  christos         strcpy(state->path, path);
    217  1.1  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 WIDECHAR
    243  1.1  christos         fd == -2 ? _wopen(path, oflag, 0666) :
    244  1.1  christos #endif
    245  1.1  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         LSEEK(state->fd, 0, SEEK_END);  /* so gzoffset() is correct */
    253  1.1  christos         state->mode = GZ_WRITE;         /* simplify later checks */
    254  1.1  christos     }
    255  1.1  christos 
    256  1.1  christos     /* save the current position for rewinding (only if reading) */
    257  1.1  christos     if (state->mode == GZ_READ) {
    258  1.1  christos         state->start = LSEEK(state->fd, 0, SEEK_CUR);
    259  1.1  christos         if (state->start == -1) state->start = 0;
    260  1.1  christos     }
    261  1.1  christos 
    262  1.1  christos     /* initialize stream */
    263  1.1  christos     gz_reset(state);
    264  1.1  christos 
    265  1.1  christos     /* return stream */
    266  1.1  christos     return (gzFile)state;
    267  1.1  christos }
    268  1.1  christos 
    269  1.1  christos /* -- see zlib.h -- */
    270  1.1  christos gzFile ZEXPORT gzopen(path, mode)
    271  1.1  christos     const char *path;
    272  1.1  christos     const char *mode;
    273  1.1  christos {
    274  1.1  christos     return gz_open(path, -1, mode);
    275  1.1  christos }
    276  1.1  christos 
    277  1.1  christos /* -- see zlib.h -- */
    278  1.1  christos gzFile ZEXPORT gzopen64(path, mode)
    279  1.1  christos     const char *path;
    280  1.1  christos     const char *mode;
    281  1.1  christos {
    282  1.1  christos     return gz_open(path, -1, mode);
    283  1.1  christos }
    284  1.1  christos 
    285  1.1  christos /* -- see zlib.h -- */
    286  1.1  christos gzFile ZEXPORT gzdopen(fd, mode)
    287  1.1  christos     int fd;
    288  1.1  christos     const char *mode;
    289  1.1  christos {
    290  1.1  christos     char *path;         /* identifier for error messages */
    291  1.1  christos     gzFile gz;
    292  1.1  christos 
    293  1.1  christos     if (fd == -1 || (path = (char *)malloc(7 + 3 * sizeof(int))) == NULL)
    294  1.1  christos         return NULL;
    295  1.1  christos #if !defined(NO_snprintf) && !defined(NO_vsnprintf)
    296  1.1  christos     (void)snprintf(path, 7 + 3 * sizeof(int), "<fd:%d>", fd);
    297  1.1  christos #else
    298  1.1  christos     sprintf(path, "<fd:%d>", fd);   /* for debugging */
    299  1.1  christos #endif
    300  1.1  christos     gz = gz_open(path, fd, mode);
    301  1.1  christos     free(path);
    302  1.1  christos     return gz;
    303  1.1  christos }
    304  1.1  christos 
    305  1.1  christos /* -- see zlib.h -- */
    306  1.1  christos #ifdef WIDECHAR
    307  1.1  christos gzFile ZEXPORT gzopen_w(path, mode)
    308  1.1  christos     const wchar_t *path;
    309  1.1  christos     const char *mode;
    310  1.1  christos {
    311  1.1  christos     return gz_open(path, -2, mode);
    312  1.1  christos }
    313  1.1  christos #endif
    314  1.1  christos 
    315  1.1  christos /* -- see zlib.h -- */
    316  1.1  christos int ZEXPORT gzbuffer(file, size)
    317  1.1  christos     gzFile file;
    318  1.1  christos     unsigned size;
    319  1.1  christos {
    320  1.1  christos     gz_statep state;
    321  1.1  christos 
    322  1.1  christos     /* get internal structure and check integrity */
    323  1.1  christos     if (file == NULL)
    324  1.1  christos         return -1;
    325  1.1  christos     state = (gz_statep)file;
    326  1.1  christos     if (state->mode != GZ_READ && state->mode != GZ_WRITE)
    327  1.1  christos         return -1;
    328  1.1  christos 
    329  1.1  christos     /* make sure we haven't already allocated memory */
    330  1.1  christos     if (state->size != 0)
    331  1.1  christos         return -1;
    332  1.1  christos 
    333  1.1  christos     /* check and set requested size */
    334  1.1  christos     if ((size << 1) < size)
    335  1.1  christos         return -1;              /* need to be able to double it */
    336  1.1  christos     if (size < 2)
    337  1.1  christos         size = 2;               /* need two bytes to check magic header */
    338  1.1  christos     state->want = size;
    339  1.1  christos     return 0;
    340  1.1  christos }
    341  1.1  christos 
    342  1.1  christos /* -- see zlib.h -- */
    343  1.1  christos int ZEXPORT gzrewind(file)
    344  1.1  christos     gzFile file;
    345  1.1  christos {
    346  1.1  christos     gz_statep state;
    347  1.1  christos 
    348  1.1  christos     /* get internal structure */
    349  1.1  christos     if (file == NULL)
    350  1.1  christos         return -1;
    351  1.1  christos     state = (gz_statep)file;
    352  1.1  christos 
    353  1.1  christos     /* check that we're reading and that there's no error */
    354  1.1  christos     if (state->mode != GZ_READ ||
    355  1.1  christos             (state->err != Z_OK && state->err != Z_BUF_ERROR))
    356  1.1  christos         return -1;
    357  1.1  christos 
    358  1.1  christos     /* back up and start over */
    359  1.1  christos     if (LSEEK(state->fd, state->start, SEEK_SET) == -1)
    360  1.1  christos         return -1;
    361  1.1  christos     gz_reset(state);
    362  1.1  christos     return 0;
    363  1.1  christos }
    364  1.1  christos 
    365  1.1  christos /* -- see zlib.h -- */
    366  1.1  christos z_off64_t ZEXPORT gzseek64(file, offset, whence)
    367  1.1  christos     gzFile file;
    368  1.1  christos     z_off64_t offset;
    369  1.1  christos     int whence;
    370  1.1  christos {
    371  1.1  christos     unsigned n;
    372  1.1  christos     z_off64_t ret;
    373  1.1  christos     gz_statep state;
    374  1.1  christos 
    375  1.1  christos     /* get internal structure and check integrity */
    376  1.1  christos     if (file == NULL)
    377  1.1  christos         return -1;
    378  1.1  christos     state = (gz_statep)file;
    379  1.1  christos     if (state->mode != GZ_READ && state->mode != GZ_WRITE)
    380  1.1  christos         return -1;
    381  1.1  christos 
    382  1.1  christos     /* check that there's no error */
    383  1.1  christos     if (state->err != Z_OK && state->err != Z_BUF_ERROR)
    384  1.1  christos         return -1;
    385  1.1  christos 
    386  1.1  christos     /* can only seek from start or relative to current position */
    387  1.1  christos     if (whence != SEEK_SET && whence != SEEK_CUR)
    388  1.1  christos         return -1;
    389  1.1  christos 
    390  1.1  christos     /* normalize offset to a SEEK_CUR specification */
    391  1.1  christos     if (whence == SEEK_SET)
    392  1.1  christos         offset -= state->x.pos;
    393  1.1  christos     else if (state->seek)
    394  1.1  christos         offset += state->skip;
    395  1.1  christos     state->seek = 0;
    396  1.1  christos 
    397  1.1  christos     /* if within raw area while reading, just go there */
    398  1.1  christos     if (state->mode == GZ_READ && state->how == COPY &&
    399  1.1  christos             state->x.pos + offset >= 0) {
    400  1.1  christos         ret = LSEEK(state->fd, offset - state->x.have, SEEK_CUR);
    401  1.1  christos         if (ret == -1)
    402  1.1  christos             return -1;
    403  1.1  christos         state->x.have = 0;
    404  1.1  christos         state->eof = 0;
    405  1.1  christos         state->past = 0;
    406  1.1  christos         state->seek = 0;
    407  1.1  christos         gz_error(state, Z_OK, NULL);
    408  1.1  christos         state->strm.avail_in = 0;
    409  1.1  christos         state->x.pos += offset;
    410  1.1  christos         return state->x.pos;
    411  1.1  christos     }
    412  1.1  christos 
    413  1.1  christos     /* calculate skip amount, rewinding if needed for back seek when reading */
    414  1.1  christos     if (offset < 0) {
    415  1.1  christos         if (state->mode != GZ_READ)         /* writing -- can't go backwards */
    416  1.1  christos             return -1;
    417  1.1  christos         offset += state->x.pos;
    418  1.1  christos         if (offset < 0)                     /* before start of file! */
    419  1.1  christos             return -1;
    420  1.1  christos         if (gzrewind(file) == -1)           /* rewind, then skip to offset */
    421  1.1  christos             return -1;
    422  1.1  christos     }
    423  1.1  christos 
    424  1.1  christos     /* if reading, skip what's in output buffer (one less gzgetc() check) */
    425  1.1  christos     if (state->mode == GZ_READ) {
    426  1.1  christos         n = GT_OFF(state->x.have) || (z_off64_t)state->x.have > offset ?
    427  1.1  christos             (unsigned)offset : state->x.have;
    428  1.1  christos         state->x.have -= n;
    429  1.1  christos         state->x.next += n;
    430  1.1  christos         state->x.pos += n;
    431  1.1  christos         offset -= n;
    432  1.1  christos     }
    433  1.1  christos 
    434  1.1  christos     /* request skip (if not zero) */
    435  1.1  christos     if (offset) {
    436  1.1  christos         state->seek = 1;
    437  1.1  christos         state->skip = offset;
    438  1.1  christos     }
    439  1.1  christos     return state->x.pos + offset;
    440  1.1  christos }
    441  1.1  christos 
    442  1.1  christos /* -- see zlib.h -- */
    443  1.1  christos z_off_t ZEXPORT gzseek(file, offset, whence)
    444  1.1  christos     gzFile file;
    445  1.1  christos     z_off_t offset;
    446  1.1  christos     int whence;
    447  1.1  christos {
    448  1.1  christos     z_off64_t ret;
    449  1.1  christos 
    450  1.1  christos     ret = gzseek64(file, (z_off64_t)offset, whence);
    451  1.1  christos     return ret == (z_off_t)ret ? (z_off_t)ret : -1;
    452  1.1  christos }
    453  1.1  christos 
    454  1.1  christos /* -- see zlib.h -- */
    455  1.1  christos z_off64_t ZEXPORT gztell64(file)
    456  1.1  christos     gzFile file;
    457  1.1  christos {
    458  1.1  christos     gz_statep state;
    459  1.1  christos 
    460  1.1  christos     /* get internal structure and check integrity */
    461  1.1  christos     if (file == NULL)
    462  1.1  christos         return -1;
    463  1.1  christos     state = (gz_statep)file;
    464  1.1  christos     if (state->mode != GZ_READ && state->mode != GZ_WRITE)
    465  1.1  christos         return -1;
    466  1.1  christos 
    467  1.1  christos     /* return position */
    468  1.1  christos     return state->x.pos + (state->seek ? state->skip : 0);
    469  1.1  christos }
    470  1.1  christos 
    471  1.1  christos /* -- see zlib.h -- */
    472  1.1  christos z_off_t ZEXPORT gztell(file)
    473  1.1  christos     gzFile file;
    474  1.1  christos {
    475  1.1  christos     z_off64_t ret;
    476  1.1  christos 
    477  1.1  christos     ret = gztell64(file);
    478  1.1  christos     return ret == (z_off_t)ret ? (z_off_t)ret : -1;
    479  1.1  christos }
    480  1.1  christos 
    481  1.1  christos /* -- see zlib.h -- */
    482  1.1  christos z_off64_t ZEXPORT gzoffset64(file)
    483  1.1  christos     gzFile file;
    484  1.1  christos {
    485  1.1  christos     z_off64_t offset;
    486  1.1  christos     gz_statep state;
    487  1.1  christos 
    488  1.1  christos     /* get internal structure and check integrity */
    489  1.1  christos     if (file == NULL)
    490  1.1  christos         return -1;
    491  1.1  christos     state = (gz_statep)file;
    492  1.1  christos     if (state->mode != GZ_READ && state->mode != GZ_WRITE)
    493  1.1  christos         return -1;
    494  1.1  christos 
    495  1.1  christos     /* compute and return effective offset in file */
    496  1.1  christos     offset = LSEEK(state->fd, 0, SEEK_CUR);
    497  1.1  christos     if (offset == -1)
    498  1.1  christos         return -1;
    499  1.1  christos     if (state->mode == GZ_READ)             /* reading */
    500  1.1  christos         offset -= state->strm.avail_in;     /* don't count buffered input */
    501  1.1  christos     return offset;
    502  1.1  christos }
    503  1.1  christos 
    504  1.1  christos /* -- see zlib.h -- */
    505  1.1  christos z_off_t ZEXPORT gzoffset(file)
    506  1.1  christos     gzFile file;
    507  1.1  christos {
    508  1.1  christos     z_off64_t ret;
    509  1.1  christos 
    510  1.1  christos     ret = gzoffset64(file);
    511  1.1  christos     return ret == (z_off_t)ret ? (z_off_t)ret : -1;
    512  1.1  christos }
    513  1.1  christos 
    514  1.1  christos /* -- see zlib.h -- */
    515  1.1  christos int ZEXPORT gzeof(file)
    516  1.1  christos     gzFile file;
    517  1.1  christos {
    518  1.1  christos     gz_statep state;
    519  1.1  christos 
    520  1.1  christos     /* get internal structure and check integrity */
    521  1.1  christos     if (file == NULL)
    522  1.1  christos         return 0;
    523  1.1  christos     state = (gz_statep)file;
    524  1.1  christos     if (state->mode != GZ_READ && state->mode != GZ_WRITE)
    525  1.1  christos         return 0;
    526  1.1  christos 
    527  1.1  christos     /* return end-of-file state */
    528  1.1  christos     return state->mode == GZ_READ ? state->past : 0;
    529  1.1  christos }
    530  1.1  christos 
    531  1.1  christos /* -- see zlib.h -- */
    532  1.1  christos const char * ZEXPORT gzerror(file, errnum)
    533  1.1  christos     gzFile file;
    534  1.1  christos     int *errnum;
    535  1.1  christos {
    536  1.1  christos     gz_statep state;
    537  1.1  christos 
    538  1.1  christos     /* get internal structure and check integrity */
    539  1.1  christos     if (file == NULL)
    540  1.1  christos         return NULL;
    541  1.1  christos     state = (gz_statep)file;
    542  1.1  christos     if (state->mode != GZ_READ && state->mode != GZ_WRITE)
    543  1.1  christos         return NULL;
    544  1.1  christos 
    545  1.1  christos     /* return error information */
    546  1.1  christos     if (errnum != NULL)
    547  1.1  christos         *errnum = state->err;
    548  1.1  christos     return state->err == Z_MEM_ERROR ? "out of memory" :
    549  1.1  christos                                        (state->msg == NULL ? "" : state->msg);
    550  1.1  christos }
    551  1.1  christos 
    552  1.1  christos /* -- see zlib.h -- */
    553  1.1  christos void ZEXPORT gzclearerr(file)
    554  1.1  christos     gzFile file;
    555  1.1  christos {
    556  1.1  christos     gz_statep state;
    557  1.1  christos 
    558  1.1  christos     /* get internal structure and check integrity */
    559  1.1  christos     if (file == NULL)
    560  1.1  christos         return;
    561  1.1  christos     state = (gz_statep)file;
    562  1.1  christos     if (state->mode != GZ_READ && state->mode != GZ_WRITE)
    563  1.1  christos         return;
    564  1.1  christos 
    565  1.1  christos     /* clear error and end-of-file */
    566  1.1  christos     if (state->mode == GZ_READ) {
    567  1.1  christos         state->eof = 0;
    568  1.1  christos         state->past = 0;
    569  1.1  christos     }
    570  1.1  christos     gz_error(state, Z_OK, NULL);
    571  1.1  christos }
    572  1.1  christos 
    573  1.1  christos /* Create an error message in allocated memory and set state->err and
    574  1.1  christos    state->msg accordingly.  Free any previous error message already there.  Do
    575  1.1  christos    not try to free or allocate space if the error is Z_MEM_ERROR (out of
    576  1.1  christos    memory).  Simply save the error message as a static string.  If there is an
    577  1.1  christos    allocation failure constructing the error message, then convert the error to
    578  1.1  christos    out of memory. */
    579  1.1  christos void ZLIB_INTERNAL gz_error(state, err, msg)
    580  1.1  christos     gz_statep state;
    581  1.1  christos     int err;
    582  1.1  christos     const char *msg;
    583  1.1  christos {
    584  1.1  christos     /* free previously allocated message and clear */
    585  1.1  christos     if (state->msg != NULL) {
    586  1.1  christos         if (state->err != Z_MEM_ERROR)
    587  1.1  christos             free(state->msg);
    588  1.1  christos         state->msg = NULL;
    589  1.1  christos     }
    590  1.1  christos 
    591  1.1  christos     /* if fatal, set state->x.have to 0 so that the gzgetc() macro fails */
    592  1.1  christos     if (err != Z_OK && err != Z_BUF_ERROR)
    593  1.1  christos         state->x.have = 0;
    594  1.1  christos 
    595  1.1  christos     /* set error code, and if no message, then done */
    596  1.1  christos     state->err = err;
    597  1.1  christos     if (msg == NULL)
    598  1.1  christos         return;
    599  1.1  christos 
    600  1.1  christos     /* for an out of memory error, return literal string when requested */
    601  1.1  christos     if (err == Z_MEM_ERROR)
    602  1.1  christos         return;
    603  1.1  christos 
    604  1.1  christos     /* construct error message with path */
    605  1.1  christos     if ((state->msg = (char *)malloc(strlen(state->path) + strlen(msg) + 3)) ==
    606  1.1  christos             NULL) {
    607  1.1  christos         state->err = Z_MEM_ERROR;
    608  1.1  christos         return;
    609  1.1  christos     }
    610  1.1  christos #if !defined(NO_snprintf) && !defined(NO_vsnprintf)
    611  1.1  christos     (void)snprintf(state->msg, strlen(state->path) + strlen(msg) + 3,
    612  1.1  christos                    "%s%s%s", state->path, ": ", msg);
    613  1.1  christos #else
    614  1.1  christos     strcpy(state->msg, state->path);
    615  1.1  christos     strcat(state->msg, ": ");
    616  1.1  christos     strcat(state->msg, msg);
    617  1.1  christos #endif
    618  1.1  christos }
    619  1.1  christos 
    620  1.1  christos #ifndef INT_MAX
    621  1.1  christos /* portably return maximum value for an int (when limits.h presumed not
    622  1.1  christos    available) -- we need to do this to cover cases where 2's complement not
    623  1.1  christos    used, since C standard permits 1's complement and sign-bit representations,
    624  1.1  christos    otherwise we could just use ((unsigned)-1) >> 1 */
    625  1.1  christos unsigned ZLIB_INTERNAL gz_intmax()
    626  1.1  christos {
    627  1.1  christos     unsigned p, q;
    628  1.1  christos 
    629  1.1  christos     p = 1;
    630  1.1  christos     do {
    631  1.1  christos         q = p;
    632  1.1  christos         p <<= 1;
    633  1.1  christos         p++;
    634  1.1  christos     } while (p > q);
    635  1.1  christos     return q >> 1;
    636  1.1  christos }
    637  1.1  christos #endif
    638