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