1381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes/* gzlib.c -- zlib functions common to reading and writing gzip files
204351a92ecc8429c999acbfc5dfe5aa8bee1d19dElliott Hughes * Copyright (C) 2004, 2010, 2011, 2012, 2013 Mark Adler
3381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes * For conditions of distribution and use, see copyright notice in zlib.h
4381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes */
5381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
6381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes#include "gzguts.h"
7381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
8ee9e11d0d4e3361533860bf04896abb86a291bfbElliott Hughes#if defined(_WIN32) && !defined(__BORLANDC__)
9ee9e11d0d4e3361533860bf04896abb86a291bfbElliott Hughes#  define LSEEK _lseeki64
10ee9e11d0d4e3361533860bf04896abb86a291bfbElliott Hughes#else
11381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes#if defined(_LARGEFILE64_SOURCE) && _LFS64_LARGEFILE-0
12381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes#  define LSEEK lseek64
13381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes#else
14381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes#  define LSEEK lseek
15381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes#endif
16ee9e11d0d4e3361533860bf04896abb86a291bfbElliott Hughes#endif
17381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
18381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes/* Local functions */
19381716e9396b55b1adb8235b020c37344f60ab07Elliott Hugheslocal void gz_reset OF((gz_statep));
2009eb358bbbb9aad3fe48dd3368c8a7a481cbda1cElliott Hugheslocal gzFile gz_open OF((const void *, int, const char *));
21381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
22381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes#if defined UNDER_CE
23381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
24381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes/* Map the Windows error number in ERROR to a locale-dependent error message
25381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes   string and return a pointer to it.  Typically, the values for ERROR come
26381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes   from GetLastError.
27381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
28381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes   The string pointed to shall not be modified by the application, but may be
29381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes   overwritten by a subsequent call to gz_strwinerror
30381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
31381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes   The gz_strwinerror function does not change the current setting of
32381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes   GetLastError. */
33381716e9396b55b1adb8235b020c37344f60ab07Elliott Hugheschar ZLIB_INTERNAL *gz_strwinerror (error)
34381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes     DWORD error;
35381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes{
36381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    static char buf[1024];
37381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
38381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    wchar_t *msgbuf;
39381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    DWORD lasterr = GetLastError();
40381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    DWORD chars = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM
41381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        | FORMAT_MESSAGE_ALLOCATE_BUFFER,
42381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        NULL,
43381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        error,
44381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        0, /* Default language */
45381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        (LPVOID)&msgbuf,
46381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        0,
47381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        NULL);
48381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    if (chars != 0) {
49381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        /* If there is an \r\n appended, zap it.  */
50381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        if (chars >= 2
51381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes            && msgbuf[chars - 2] == '\r' && msgbuf[chars - 1] == '\n') {
52381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes            chars -= 2;
53381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes            msgbuf[chars] = 0;
54381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        }
55381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
56381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        if (chars > sizeof (buf) - 1) {
57381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes            chars = sizeof (buf) - 1;
58381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes            msgbuf[chars] = 0;
59381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        }
60381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
61381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        wcstombs(buf, msgbuf, chars + 1);
62381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        LocalFree(msgbuf);
63381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    }
64381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    else {
65381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        sprintf(buf, "unknown win32 error (%ld)", error);
66381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    }
67381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
68381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    SetLastError(lasterr);
69381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    return buf;
70381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes}
71381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
72381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes#endif /* UNDER_CE */
73381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
74381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes/* Reset gzip file state */
75381716e9396b55b1adb8235b020c37344f60ab07Elliott Hugheslocal void gz_reset(state)
76381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    gz_statep state;
77381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes{
78ee9e11d0d4e3361533860bf04896abb86a291bfbElliott Hughes    state->x.have = 0;              /* no output data available */
79381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    if (state->mode == GZ_READ) {   /* for reading ... */
80381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        state->eof = 0;             /* not at end of file */
81ee9e11d0d4e3361533860bf04896abb86a291bfbElliott Hughes        state->past = 0;            /* have not read past end yet */
82381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        state->how = LOOK;          /* look for gzip header */
83381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    }
84381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    state->seek = 0;                /* no seek request pending */
85381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    gz_error(state, Z_OK, NULL);    /* clear error */
86ee9e11d0d4e3361533860bf04896abb86a291bfbElliott Hughes    state->x.pos = 0;               /* no uncompressed data yet */
87381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    state->strm.avail_in = 0;       /* no input data yet */
88381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes}
89381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
90381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes/* Open a gzip file either by name or file descriptor. */
91381716e9396b55b1adb8235b020c37344f60ab07Elliott Hugheslocal gzFile gz_open(path, fd, mode)
9209eb358bbbb9aad3fe48dd3368c8a7a481cbda1cElliott Hughes    const void *path;
93381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    int fd;
94381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    const char *mode;
95381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes{
96381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    gz_statep state;
9709eb358bbbb9aad3fe48dd3368c8a7a481cbda1cElliott Hughes    size_t len;
9809eb358bbbb9aad3fe48dd3368c8a7a481cbda1cElliott Hughes    int oflag;
9909eb358bbbb9aad3fe48dd3368c8a7a481cbda1cElliott Hughes#ifdef O_CLOEXEC
10009eb358bbbb9aad3fe48dd3368c8a7a481cbda1cElliott Hughes    int cloexec = 0;
10109eb358bbbb9aad3fe48dd3368c8a7a481cbda1cElliott Hughes#endif
10209eb358bbbb9aad3fe48dd3368c8a7a481cbda1cElliott Hughes#ifdef O_EXCL
10309eb358bbbb9aad3fe48dd3368c8a7a481cbda1cElliott Hughes    int exclusive = 0;
10409eb358bbbb9aad3fe48dd3368c8a7a481cbda1cElliott Hughes#endif
105381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
106ee9e11d0d4e3361533860bf04896abb86a291bfbElliott Hughes    /* check input */
107ee9e11d0d4e3361533860bf04896abb86a291bfbElliott Hughes    if (path == NULL)
108ee9e11d0d4e3361533860bf04896abb86a291bfbElliott Hughes        return NULL;
109ee9e11d0d4e3361533860bf04896abb86a291bfbElliott Hughes
110381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    /* allocate gzFile structure to return */
11104351a92ecc8429c999acbfc5dfe5aa8bee1d19dElliott Hughes    state = (gz_statep)malloc(sizeof(gz_state));
112381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    if (state == NULL)
113381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        return NULL;
114381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    state->size = 0;            /* no buffers allocated yet */
115381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    state->want = GZBUFSIZE;    /* requested buffer size */
116381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    state->msg = NULL;          /* no error message yet */
117381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
118381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    /* interpret mode */
119381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    state->mode = GZ_NONE;
120381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    state->level = Z_DEFAULT_COMPRESSION;
121381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    state->strategy = Z_DEFAULT_STRATEGY;
122ee9e11d0d4e3361533860bf04896abb86a291bfbElliott Hughes    state->direct = 0;
123381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    while (*mode) {
124381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        if (*mode >= '0' && *mode <= '9')
125381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes            state->level = *mode - '0';
126381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        else
127381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes            switch (*mode) {
128381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes            case 'r':
129381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes                state->mode = GZ_READ;
130381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes                break;
131381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes#ifndef NO_GZCOMPRESS
132381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes            case 'w':
133381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes                state->mode = GZ_WRITE;
134381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes                break;
135381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes            case 'a':
136381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes                state->mode = GZ_APPEND;
137381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes                break;
138381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes#endif
139381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes            case '+':       /* can't read and write at the same time */
140381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes                free(state);
141381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes                return NULL;
142381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes            case 'b':       /* ignore -- will request binary anyway */
143381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes                break;
14409eb358bbbb9aad3fe48dd3368c8a7a481cbda1cElliott Hughes#ifdef O_CLOEXEC
14509eb358bbbb9aad3fe48dd3368c8a7a481cbda1cElliott Hughes            case 'e':
14609eb358bbbb9aad3fe48dd3368c8a7a481cbda1cElliott Hughes                cloexec = 1;
14709eb358bbbb9aad3fe48dd3368c8a7a481cbda1cElliott Hughes                break;
14809eb358bbbb9aad3fe48dd3368c8a7a481cbda1cElliott Hughes#endif
14909eb358bbbb9aad3fe48dd3368c8a7a481cbda1cElliott Hughes#ifdef O_EXCL
15009eb358bbbb9aad3fe48dd3368c8a7a481cbda1cElliott Hughes            case 'x':
15109eb358bbbb9aad3fe48dd3368c8a7a481cbda1cElliott Hughes                exclusive = 1;
15209eb358bbbb9aad3fe48dd3368c8a7a481cbda1cElliott Hughes                break;
15309eb358bbbb9aad3fe48dd3368c8a7a481cbda1cElliott Hughes#endif
154381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes            case 'f':
155381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes                state->strategy = Z_FILTERED;
156381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes                break;
157381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes            case 'h':
158381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes                state->strategy = Z_HUFFMAN_ONLY;
159381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes                break;
160381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes            case 'R':
161381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes                state->strategy = Z_RLE;
162381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes                break;
163381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes            case 'F':
164381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes                state->strategy = Z_FIXED;
16504351a92ecc8429c999acbfc5dfe5aa8bee1d19dElliott Hughes                break;
166ee9e11d0d4e3361533860bf04896abb86a291bfbElliott Hughes            case 'T':
167ee9e11d0d4e3361533860bf04896abb86a291bfbElliott Hughes                state->direct = 1;
16804351a92ecc8429c999acbfc5dfe5aa8bee1d19dElliott Hughes                break;
169381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes            default:        /* could consider as an error, but just ignore */
170381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes                ;
171381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes            }
172381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        mode++;
173381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    }
174381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
175381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    /* must provide an "r", "w", or "a" */
176381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    if (state->mode == GZ_NONE) {
177381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        free(state);
178381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        return NULL;
179381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    }
180381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
181ee9e11d0d4e3361533860bf04896abb86a291bfbElliott Hughes    /* can't force transparent read */
182ee9e11d0d4e3361533860bf04896abb86a291bfbElliott Hughes    if (state->mode == GZ_READ) {
183ee9e11d0d4e3361533860bf04896abb86a291bfbElliott Hughes        if (state->direct) {
184ee9e11d0d4e3361533860bf04896abb86a291bfbElliott Hughes            free(state);
185ee9e11d0d4e3361533860bf04896abb86a291bfbElliott Hughes            return NULL;
186ee9e11d0d4e3361533860bf04896abb86a291bfbElliott Hughes        }
187ee9e11d0d4e3361533860bf04896abb86a291bfbElliott Hughes        state->direct = 1;      /* for empty file */
188ee9e11d0d4e3361533860bf04896abb86a291bfbElliott Hughes    }
189ee9e11d0d4e3361533860bf04896abb86a291bfbElliott Hughes
190381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    /* save the path name for error messages */
19109eb358bbbb9aad3fe48dd3368c8a7a481cbda1cElliott Hughes#ifdef _WIN32
19209eb358bbbb9aad3fe48dd3368c8a7a481cbda1cElliott Hughes    if (fd == -2) {
19309eb358bbbb9aad3fe48dd3368c8a7a481cbda1cElliott Hughes        len = wcstombs(NULL, path, 0);
19409eb358bbbb9aad3fe48dd3368c8a7a481cbda1cElliott Hughes        if (len == (size_t)-1)
19509eb358bbbb9aad3fe48dd3368c8a7a481cbda1cElliott Hughes            len = 0;
19609eb358bbbb9aad3fe48dd3368c8a7a481cbda1cElliott Hughes    }
19709eb358bbbb9aad3fe48dd3368c8a7a481cbda1cElliott Hughes    else
19809eb358bbbb9aad3fe48dd3368c8a7a481cbda1cElliott Hughes#endif
19904351a92ecc8429c999acbfc5dfe5aa8bee1d19dElliott Hughes        len = strlen((const char *)path);
20004351a92ecc8429c999acbfc5dfe5aa8bee1d19dElliott Hughes    state->path = (char *)malloc(len + 1);
201381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    if (state->path == NULL) {
202381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        free(state);
203381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        return NULL;
204381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    }
20509eb358bbbb9aad3fe48dd3368c8a7a481cbda1cElliott Hughes#ifdef _WIN32
20609eb358bbbb9aad3fe48dd3368c8a7a481cbda1cElliott Hughes    if (fd == -2)
20709eb358bbbb9aad3fe48dd3368c8a7a481cbda1cElliott Hughes        if (len)
20809eb358bbbb9aad3fe48dd3368c8a7a481cbda1cElliott Hughes            wcstombs(state->path, path, len + 1);
20909eb358bbbb9aad3fe48dd3368c8a7a481cbda1cElliott Hughes        else
21009eb358bbbb9aad3fe48dd3368c8a7a481cbda1cElliott Hughes            *(state->path) = 0;
21109eb358bbbb9aad3fe48dd3368c8a7a481cbda1cElliott Hughes    else
21209eb358bbbb9aad3fe48dd3368c8a7a481cbda1cElliott Hughes#endif
21304351a92ecc8429c999acbfc5dfe5aa8bee1d19dElliott Hughes#if !defined(NO_snprintf) && !defined(NO_vsnprintf)
21404351a92ecc8429c999acbfc5dfe5aa8bee1d19dElliott Hughes        snprintf(state->path, len + 1, "%s", (const char *)path);
21504351a92ecc8429c999acbfc5dfe5aa8bee1d19dElliott Hughes#else
21609eb358bbbb9aad3fe48dd3368c8a7a481cbda1cElliott Hughes        strcpy(state->path, path);
21704351a92ecc8429c999acbfc5dfe5aa8bee1d19dElliott Hughes#endif
218381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
21909eb358bbbb9aad3fe48dd3368c8a7a481cbda1cElliott Hughes    /* compute the flags for open() */
22009eb358bbbb9aad3fe48dd3368c8a7a481cbda1cElliott Hughes    oflag =
221381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes#ifdef O_LARGEFILE
22209eb358bbbb9aad3fe48dd3368c8a7a481cbda1cElliott Hughes        O_LARGEFILE |
223381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes#endif
224381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes#ifdef O_BINARY
22509eb358bbbb9aad3fe48dd3368c8a7a481cbda1cElliott Hughes        O_BINARY |
226381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes#endif
22709eb358bbbb9aad3fe48dd3368c8a7a481cbda1cElliott Hughes#ifdef O_CLOEXEC
22809eb358bbbb9aad3fe48dd3368c8a7a481cbda1cElliott Hughes        (cloexec ? O_CLOEXEC : 0) |
22909eb358bbbb9aad3fe48dd3368c8a7a481cbda1cElliott Hughes#endif
23009eb358bbbb9aad3fe48dd3368c8a7a481cbda1cElliott Hughes        (state->mode == GZ_READ ?
23109eb358bbbb9aad3fe48dd3368c8a7a481cbda1cElliott Hughes         O_RDONLY :
23209eb358bbbb9aad3fe48dd3368c8a7a481cbda1cElliott Hughes         (O_WRONLY | O_CREAT |
23309eb358bbbb9aad3fe48dd3368c8a7a481cbda1cElliott Hughes#ifdef O_EXCL
23409eb358bbbb9aad3fe48dd3368c8a7a481cbda1cElliott Hughes          (exclusive ? O_EXCL : 0) |
23509eb358bbbb9aad3fe48dd3368c8a7a481cbda1cElliott Hughes#endif
23609eb358bbbb9aad3fe48dd3368c8a7a481cbda1cElliott Hughes          (state->mode == GZ_WRITE ?
23709eb358bbbb9aad3fe48dd3368c8a7a481cbda1cElliott Hughes           O_TRUNC :
23809eb358bbbb9aad3fe48dd3368c8a7a481cbda1cElliott Hughes           O_APPEND)));
23909eb358bbbb9aad3fe48dd3368c8a7a481cbda1cElliott Hughes
24009eb358bbbb9aad3fe48dd3368c8a7a481cbda1cElliott Hughes    /* open the file with the appropriate flags (or just use fd) */
24109eb358bbbb9aad3fe48dd3368c8a7a481cbda1cElliott Hughes    state->fd = fd > -1 ? fd : (
24209eb358bbbb9aad3fe48dd3368c8a7a481cbda1cElliott Hughes#ifdef _WIN32
24309eb358bbbb9aad3fe48dd3368c8a7a481cbda1cElliott Hughes        fd == -2 ? _wopen(path, oflag, 0666) :
24409eb358bbbb9aad3fe48dd3368c8a7a481cbda1cElliott Hughes#endif
24504351a92ecc8429c999acbfc5dfe5aa8bee1d19dElliott Hughes        open((const char *)path, oflag, 0666));
246381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    if (state->fd == -1) {
247381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        free(state->path);
248381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        free(state);
249381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        return NULL;
250381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    }
251381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    if (state->mode == GZ_APPEND)
252381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        state->mode = GZ_WRITE;         /* simplify later checks */
253381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
254381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    /* save the current position for rewinding (only if reading) */
255381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    if (state->mode == GZ_READ) {
256381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        state->start = LSEEK(state->fd, 0, SEEK_CUR);
257381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        if (state->start == -1) state->start = 0;
258381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    }
259381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
260381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    /* initialize stream */
261381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    gz_reset(state);
262381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
263381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    /* return stream */
264381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    return (gzFile)state;
265381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes}
266381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
267381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes/* -- see zlib.h -- */
268381716e9396b55b1adb8235b020c37344f60ab07Elliott HughesgzFile ZEXPORT gzopen(path, mode)
269381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    const char *path;
270381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    const char *mode;
271381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes{
272381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    return gz_open(path, -1, mode);
273381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes}
274381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
275381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes/* -- see zlib.h -- */
276381716e9396b55b1adb8235b020c37344f60ab07Elliott HughesgzFile ZEXPORT gzopen64(path, mode)
277381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    const char *path;
278381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    const char *mode;
279381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes{
280381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    return gz_open(path, -1, mode);
281381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes}
282381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
283381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes/* -- see zlib.h -- */
284381716e9396b55b1adb8235b020c37344f60ab07Elliott HughesgzFile ZEXPORT gzdopen(fd, mode)
285381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    int fd;
286381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    const char *mode;
287381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes{
288381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    char *path;         /* identifier for error messages */
289381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    gzFile gz;
290381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
29104351a92ecc8429c999acbfc5dfe5aa8bee1d19dElliott Hughes    if (fd == -1 || (path = (char *)malloc(7 + 3 * sizeof(int))) == NULL)
292381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        return NULL;
29304351a92ecc8429c999acbfc5dfe5aa8bee1d19dElliott Hughes#if !defined(NO_snprintf) && !defined(NO_vsnprintf)
29404351a92ecc8429c999acbfc5dfe5aa8bee1d19dElliott Hughes    snprintf(path, 7 + 3 * sizeof(int), "<fd:%d>", fd); /* for debugging */
29504351a92ecc8429c999acbfc5dfe5aa8bee1d19dElliott Hughes#else
296381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    sprintf(path, "<fd:%d>", fd);   /* for debugging */
29704351a92ecc8429c999acbfc5dfe5aa8bee1d19dElliott Hughes#endif
298381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    gz = gz_open(path, fd, mode);
299381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    free(path);
300381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    return gz;
301381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes}
302381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
303381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes/* -- see zlib.h -- */
30409eb358bbbb9aad3fe48dd3368c8a7a481cbda1cElliott Hughes#ifdef _WIN32
30509eb358bbbb9aad3fe48dd3368c8a7a481cbda1cElliott HughesgzFile ZEXPORT gzopen_w(path, mode)
30609eb358bbbb9aad3fe48dd3368c8a7a481cbda1cElliott Hughes    const wchar_t *path;
30709eb358bbbb9aad3fe48dd3368c8a7a481cbda1cElliott Hughes    const char *mode;
30809eb358bbbb9aad3fe48dd3368c8a7a481cbda1cElliott Hughes{
30909eb358bbbb9aad3fe48dd3368c8a7a481cbda1cElliott Hughes    return gz_open(path, -2, mode);
31009eb358bbbb9aad3fe48dd3368c8a7a481cbda1cElliott Hughes}
31109eb358bbbb9aad3fe48dd3368c8a7a481cbda1cElliott Hughes#endif
31209eb358bbbb9aad3fe48dd3368c8a7a481cbda1cElliott Hughes
31309eb358bbbb9aad3fe48dd3368c8a7a481cbda1cElliott Hughes/* -- see zlib.h -- */
314381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughesint ZEXPORT gzbuffer(file, size)
315381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    gzFile file;
316381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    unsigned size;
317381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes{
318381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    gz_statep state;
319381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
320381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    /* get internal structure and check integrity */
321381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    if (file == NULL)
322381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        return -1;
323381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    state = (gz_statep)file;
324381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    if (state->mode != GZ_READ && state->mode != GZ_WRITE)
325381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        return -1;
326381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
327381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    /* make sure we haven't already allocated memory */
328381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    if (state->size != 0)
329381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        return -1;
330381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
331381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    /* check and set requested size */
332ee9e11d0d4e3361533860bf04896abb86a291bfbElliott Hughes    if (size < 2)
333ee9e11d0d4e3361533860bf04896abb86a291bfbElliott Hughes        size = 2;               /* need two bytes to check magic header */
334381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    state->want = size;
335381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    return 0;
336381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes}
337381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
338381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes/* -- see zlib.h -- */
339381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughesint ZEXPORT gzrewind(file)
340381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    gzFile file;
341381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes{
342381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    gz_statep state;
343381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
344381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    /* get internal structure */
345381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    if (file == NULL)
346381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        return -1;
347381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    state = (gz_statep)file;
348381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
349381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    /* check that we're reading and that there's no error */
350ee9e11d0d4e3361533860bf04896abb86a291bfbElliott Hughes    if (state->mode != GZ_READ ||
351ee9e11d0d4e3361533860bf04896abb86a291bfbElliott Hughes            (state->err != Z_OK && state->err != Z_BUF_ERROR))
352381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        return -1;
353381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
354381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    /* back up and start over */
355381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    if (LSEEK(state->fd, state->start, SEEK_SET) == -1)
356381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        return -1;
357381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    gz_reset(state);
358381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    return 0;
359381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes}
360381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
361381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes/* -- see zlib.h -- */
362381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughesz_off64_t ZEXPORT gzseek64(file, offset, whence)
363381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    gzFile file;
364381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    z_off64_t offset;
365381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    int whence;
366381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes{
367381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    unsigned n;
368381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    z_off64_t ret;
369381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    gz_statep state;
370381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
371381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    /* get internal structure and check integrity */
372381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    if (file == NULL)
373381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        return -1;
374381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    state = (gz_statep)file;
375381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    if (state->mode != GZ_READ && state->mode != GZ_WRITE)
376381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        return -1;
377381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
378381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    /* check that there's no error */
379ee9e11d0d4e3361533860bf04896abb86a291bfbElliott Hughes    if (state->err != Z_OK && state->err != Z_BUF_ERROR)
380381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        return -1;
381381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
382381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    /* can only seek from start or relative to current position */
383381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    if (whence != SEEK_SET && whence != SEEK_CUR)
384381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        return -1;
385381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
386381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    /* normalize offset to a SEEK_CUR specification */
387381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    if (whence == SEEK_SET)
388ee9e11d0d4e3361533860bf04896abb86a291bfbElliott Hughes        offset -= state->x.pos;
389381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    else if (state->seek)
390381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        offset += state->skip;
391381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    state->seek = 0;
392381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
393381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    /* if within raw area while reading, just go there */
394381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    if (state->mode == GZ_READ && state->how == COPY &&
395ee9e11d0d4e3361533860bf04896abb86a291bfbElliott Hughes            state->x.pos + offset >= 0) {
396ee9e11d0d4e3361533860bf04896abb86a291bfbElliott Hughes        ret = LSEEK(state->fd, offset - state->x.have, SEEK_CUR);
397381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        if (ret == -1)
398381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes            return -1;
399ee9e11d0d4e3361533860bf04896abb86a291bfbElliott Hughes        state->x.have = 0;
400381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        state->eof = 0;
401ee9e11d0d4e3361533860bf04896abb86a291bfbElliott Hughes        state->past = 0;
402381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        state->seek = 0;
403381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        gz_error(state, Z_OK, NULL);
404381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        state->strm.avail_in = 0;
405ee9e11d0d4e3361533860bf04896abb86a291bfbElliott Hughes        state->x.pos += offset;
406ee9e11d0d4e3361533860bf04896abb86a291bfbElliott Hughes        return state->x.pos;
407381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    }
408381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
409381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    /* calculate skip amount, rewinding if needed for back seek when reading */
410381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    if (offset < 0) {
411381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        if (state->mode != GZ_READ)         /* writing -- can't go backwards */
412381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes            return -1;
413ee9e11d0d4e3361533860bf04896abb86a291bfbElliott Hughes        offset += state->x.pos;
414381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        if (offset < 0)                     /* before start of file! */
415381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes            return -1;
416381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        if (gzrewind(file) == -1)           /* rewind, then skip to offset */
417381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes            return -1;
418381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    }
419381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
420381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    /* if reading, skip what's in output buffer (one less gzgetc() check) */
421381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    if (state->mode == GZ_READ) {
422ee9e11d0d4e3361533860bf04896abb86a291bfbElliott Hughes        n = GT_OFF(state->x.have) || (z_off64_t)state->x.have > offset ?
423ee9e11d0d4e3361533860bf04896abb86a291bfbElliott Hughes            (unsigned)offset : state->x.have;
424ee9e11d0d4e3361533860bf04896abb86a291bfbElliott Hughes        state->x.have -= n;
425ee9e11d0d4e3361533860bf04896abb86a291bfbElliott Hughes        state->x.next += n;
426ee9e11d0d4e3361533860bf04896abb86a291bfbElliott Hughes        state->x.pos += n;
427381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        offset -= n;
428381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    }
429381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
430381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    /* request skip (if not zero) */
431381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    if (offset) {
432381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        state->seek = 1;
433381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        state->skip = offset;
434381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    }
435ee9e11d0d4e3361533860bf04896abb86a291bfbElliott Hughes    return state->x.pos + offset;
436381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes}
437381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
438381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes/* -- see zlib.h -- */
439381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughesz_off_t ZEXPORT gzseek(file, offset, whence)
440381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    gzFile file;
441381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    z_off_t offset;
442381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    int whence;
443381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes{
444381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    z_off64_t ret;
445381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
446381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    ret = gzseek64(file, (z_off64_t)offset, whence);
447381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    return ret == (z_off_t)ret ? (z_off_t)ret : -1;
448381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes}
449381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
450381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes/* -- see zlib.h -- */
451381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughesz_off64_t ZEXPORT gztell64(file)
452381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    gzFile file;
453381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes{
454381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    gz_statep state;
455381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
456381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    /* get internal structure and check integrity */
457381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    if (file == NULL)
458381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        return -1;
459381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    state = (gz_statep)file;
460381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    if (state->mode != GZ_READ && state->mode != GZ_WRITE)
461381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        return -1;
462381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
463381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    /* return position */
464ee9e11d0d4e3361533860bf04896abb86a291bfbElliott Hughes    return state->x.pos + (state->seek ? state->skip : 0);
465381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes}
466381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
467381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes/* -- see zlib.h -- */
468381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughesz_off_t ZEXPORT gztell(file)
469381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    gzFile file;
470381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes{
471381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    z_off64_t ret;
472381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
473381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    ret = gztell64(file);
474381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    return ret == (z_off_t)ret ? (z_off_t)ret : -1;
475381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes}
476381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
477381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes/* -- see zlib.h -- */
478381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughesz_off64_t ZEXPORT gzoffset64(file)
479381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    gzFile file;
480381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes{
481381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    z_off64_t offset;
482381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    gz_statep state;
483381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
484381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    /* get internal structure and check integrity */
485381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    if (file == NULL)
486381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        return -1;
487381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    state = (gz_statep)file;
488381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    if (state->mode != GZ_READ && state->mode != GZ_WRITE)
489381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        return -1;
490381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
491381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    /* compute and return effective offset in file */
492381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    offset = LSEEK(state->fd, 0, SEEK_CUR);
493381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    if (offset == -1)
494381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        return -1;
495381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    if (state->mode == GZ_READ)             /* reading */
496381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        offset -= state->strm.avail_in;     /* don't count buffered input */
497381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    return offset;
498381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes}
499381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
500381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes/* -- see zlib.h -- */
501381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughesz_off_t ZEXPORT gzoffset(file)
502381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    gzFile file;
503381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes{
504381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    z_off64_t ret;
505381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
506381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    ret = gzoffset64(file);
507381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    return ret == (z_off_t)ret ? (z_off_t)ret : -1;
508381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes}
509381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
510381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes/* -- see zlib.h -- */
511381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughesint ZEXPORT gzeof(file)
512381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    gzFile file;
513381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes{
514381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    gz_statep state;
515381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
516381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    /* get internal structure and check integrity */
517381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    if (file == NULL)
518381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        return 0;
519381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    state = (gz_statep)file;
520381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    if (state->mode != GZ_READ && state->mode != GZ_WRITE)
521381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        return 0;
522381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
523381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    /* return end-of-file state */
524ee9e11d0d4e3361533860bf04896abb86a291bfbElliott Hughes    return state->mode == GZ_READ ? state->past : 0;
525381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes}
526381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
527381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes/* -- see zlib.h -- */
528381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughesconst char * ZEXPORT gzerror(file, errnum)
529381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    gzFile file;
530381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    int *errnum;
531381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes{
532381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    gz_statep state;
533381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
534381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    /* get internal structure and check integrity */
535381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    if (file == NULL)
536381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        return NULL;
537381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    state = (gz_statep)file;
538381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    if (state->mode != GZ_READ && state->mode != GZ_WRITE)
539381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        return NULL;
540381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
541381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    /* return error information */
542381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    if (errnum != NULL)
543381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        *errnum = state->err;
54404351a92ecc8429c999acbfc5dfe5aa8bee1d19dElliott Hughes    return state->err == Z_MEM_ERROR ? "out of memory" :
54504351a92ecc8429c999acbfc5dfe5aa8bee1d19dElliott Hughes                                       (state->msg == NULL ? "" : state->msg);
546381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes}
547381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
548381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes/* -- see zlib.h -- */
549381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughesvoid ZEXPORT gzclearerr(file)
550381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    gzFile file;
551381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes{
552381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    gz_statep state;
553381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
554381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    /* get internal structure and check integrity */
555381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    if (file == NULL)
556381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        return;
557381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    state = (gz_statep)file;
558381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    if (state->mode != GZ_READ && state->mode != GZ_WRITE)
559381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        return;
560381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
561381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    /* clear error and end-of-file */
562ee9e11d0d4e3361533860bf04896abb86a291bfbElliott Hughes    if (state->mode == GZ_READ) {
563381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        state->eof = 0;
564ee9e11d0d4e3361533860bf04896abb86a291bfbElliott Hughes        state->past = 0;
565ee9e11d0d4e3361533860bf04896abb86a291bfbElliott Hughes    }
566381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    gz_error(state, Z_OK, NULL);
567381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes}
568381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
569381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes/* Create an error message in allocated memory and set state->err and
570381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes   state->msg accordingly.  Free any previous error message already there.  Do
571381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes   not try to free or allocate space if the error is Z_MEM_ERROR (out of
572381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes   memory).  Simply save the error message as a static string.  If there is an
573381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes   allocation failure constructing the error message, then convert the error to
574381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes   out of memory. */
575381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughesvoid ZLIB_INTERNAL gz_error(state, err, msg)
576381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    gz_statep state;
577381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    int err;
578381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    const char *msg;
579381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes{
580381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    /* free previously allocated message and clear */
581381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    if (state->msg != NULL) {
582381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        if (state->err != Z_MEM_ERROR)
583381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes            free(state->msg);
584381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        state->msg = NULL;
585381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    }
586381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
587ee9e11d0d4e3361533860bf04896abb86a291bfbElliott Hughes    /* if fatal, set state->x.have to 0 so that the gzgetc() macro fails */
588ee9e11d0d4e3361533860bf04896abb86a291bfbElliott Hughes    if (err != Z_OK && err != Z_BUF_ERROR)
589ee9e11d0d4e3361533860bf04896abb86a291bfbElliott Hughes        state->x.have = 0;
590ee9e11d0d4e3361533860bf04896abb86a291bfbElliott Hughes
591381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    /* set error code, and if no message, then done */
592381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    state->err = err;
593381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    if (msg == NULL)
594381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        return;
595381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
59604351a92ecc8429c999acbfc5dfe5aa8bee1d19dElliott Hughes    /* for an out of memory error, return literal string when requested */
59704351a92ecc8429c999acbfc5dfe5aa8bee1d19dElliott Hughes    if (err == Z_MEM_ERROR)
598381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        return;
599381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
600381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    /* construct error message with path */
60104351a92ecc8429c999acbfc5dfe5aa8bee1d19dElliott Hughes    if ((state->msg = (char *)malloc(strlen(state->path) + strlen(msg) + 3)) ==
60204351a92ecc8429c999acbfc5dfe5aa8bee1d19dElliott Hughes            NULL) {
603381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        state->err = Z_MEM_ERROR;
604381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        return;
605381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    }
60604351a92ecc8429c999acbfc5dfe5aa8bee1d19dElliott Hughes#if !defined(NO_snprintf) && !defined(NO_vsnprintf)
60704351a92ecc8429c999acbfc5dfe5aa8bee1d19dElliott Hughes    snprintf(state->msg, strlen(state->path) + strlen(msg) + 3,
60804351a92ecc8429c999acbfc5dfe5aa8bee1d19dElliott Hughes             "%s%s%s", state->path, ": ", msg);
60904351a92ecc8429c999acbfc5dfe5aa8bee1d19dElliott Hughes#else
610381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    strcpy(state->msg, state->path);
611381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    strcat(state->msg, ": ");
612381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    strcat(state->msg, msg);
61304351a92ecc8429c999acbfc5dfe5aa8bee1d19dElliott Hughes#endif
614381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    return;
615381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes}
616381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
617381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes#ifndef INT_MAX
618381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes/* portably return maximum value for an int (when limits.h presumed not
619381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes   available) -- we need to do this to cover cases where 2's complement not
620381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes   used, since C standard permits 1's complement and sign-bit representations,
621381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes   otherwise we could just use ((unsigned)-1) >> 1 */
622381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughesunsigned ZLIB_INTERNAL gz_intmax()
623381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes{
624381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    unsigned p, q;
625381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
626381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    p = 1;
627381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    do {
628381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        q = p;
629381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        p <<= 1;
630381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        p++;
631381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    } while (p > q);
632381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    return q >> 1;
633381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes}
634381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes#endif
635