1381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes/* gzlib.c -- zlib functions common to reading and writing gzip files
2ee9e11d0d4e3361533860bf04896abb86a291bfbElliott Hughes * Copyright (C) 2004, 2010, 2011 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));
20381716e9396b55b1adb8235b020c37344f60ab07Elliott Hugheslocal gzFile gz_open OF((const char *, 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)
92381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    const char *path;
93381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    int fd;
94381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    const char *mode;
95381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes{
96381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    gz_statep state;
97381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
98ee9e11d0d4e3361533860bf04896abb86a291bfbElliott Hughes    /* check input */
99ee9e11d0d4e3361533860bf04896abb86a291bfbElliott Hughes    if (path == NULL)
100ee9e11d0d4e3361533860bf04896abb86a291bfbElliott Hughes        return NULL;
101ee9e11d0d4e3361533860bf04896abb86a291bfbElliott Hughes
102381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    /* allocate gzFile structure to return */
103381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    state = malloc(sizeof(gz_state));
104381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    if (state == NULL)
105381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        return NULL;
106381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    state->size = 0;            /* no buffers allocated yet */
107381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    state->want = GZBUFSIZE;    /* requested buffer size */
108381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    state->msg = NULL;          /* no error message yet */
109381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
110381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    /* interpret mode */
111381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    state->mode = GZ_NONE;
112381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    state->level = Z_DEFAULT_COMPRESSION;
113381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    state->strategy = Z_DEFAULT_STRATEGY;
114ee9e11d0d4e3361533860bf04896abb86a291bfbElliott Hughes    state->direct = 0;
115381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    while (*mode) {
116381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        if (*mode >= '0' && *mode <= '9')
117381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes            state->level = *mode - '0';
118381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        else
119381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes            switch (*mode) {
120381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes            case 'r':
121381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes                state->mode = GZ_READ;
122381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes                break;
123381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes#ifndef NO_GZCOMPRESS
124381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes            case 'w':
125381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes                state->mode = GZ_WRITE;
126381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes                break;
127381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes            case 'a':
128381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes                state->mode = GZ_APPEND;
129381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes                break;
130381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes#endif
131381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes            case '+':       /* can't read and write at the same time */
132381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes                free(state);
133381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes                return NULL;
134381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes            case 'b':       /* ignore -- will request binary anyway */
135381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes                break;
136381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes            case 'f':
137381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes                state->strategy = Z_FILTERED;
138381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes                break;
139381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes            case 'h':
140381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes                state->strategy = Z_HUFFMAN_ONLY;
141381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes                break;
142381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes            case 'R':
143381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes                state->strategy = Z_RLE;
144381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes                break;
145381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes            case 'F':
146381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes                state->strategy = Z_FIXED;
147ee9e11d0d4e3361533860bf04896abb86a291bfbElliott Hughes            case 'T':
148ee9e11d0d4e3361533860bf04896abb86a291bfbElliott Hughes                state->direct = 1;
149381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes            default:        /* could consider as an error, but just ignore */
150381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes                ;
151381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes            }
152381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        mode++;
153381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    }
154381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
155381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    /* must provide an "r", "w", or "a" */
156381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    if (state->mode == GZ_NONE) {
157381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        free(state);
158381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        return NULL;
159381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    }
160381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
161ee9e11d0d4e3361533860bf04896abb86a291bfbElliott Hughes    /* can't force transparent read */
162ee9e11d0d4e3361533860bf04896abb86a291bfbElliott Hughes    if (state->mode == GZ_READ) {
163ee9e11d0d4e3361533860bf04896abb86a291bfbElliott Hughes        if (state->direct) {
164ee9e11d0d4e3361533860bf04896abb86a291bfbElliott Hughes            free(state);
165ee9e11d0d4e3361533860bf04896abb86a291bfbElliott Hughes            return NULL;
166ee9e11d0d4e3361533860bf04896abb86a291bfbElliott Hughes        }
167ee9e11d0d4e3361533860bf04896abb86a291bfbElliott Hughes        state->direct = 1;      /* for empty file */
168ee9e11d0d4e3361533860bf04896abb86a291bfbElliott Hughes    }
169ee9e11d0d4e3361533860bf04896abb86a291bfbElliott Hughes
170381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    /* save the path name for error messages */
171381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    state->path = malloc(strlen(path) + 1);
172381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    if (state->path == NULL) {
173381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        free(state);
174381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        return NULL;
175381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    }
176381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    strcpy(state->path, path);
177381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
178381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    /* open the file with the appropriate mode (or just use fd) */
179381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    state->fd = fd != -1 ? fd :
180381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        open(path,
181381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes#ifdef O_LARGEFILE
182381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes            O_LARGEFILE |
183381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes#endif
184381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes#ifdef O_BINARY
185381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes            O_BINARY |
186381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes#endif
187381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes            (state->mode == GZ_READ ?
188381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes                O_RDONLY :
189381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes                (O_WRONLY | O_CREAT | (
190381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes                    state->mode == GZ_WRITE ?
191381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes                        O_TRUNC :
192381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes                        O_APPEND))),
193381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes            0666);
194381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    if (state->fd == -1) {
195381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        free(state->path);
196381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        free(state);
197381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        return NULL;
198381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    }
199381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    if (state->mode == GZ_APPEND)
200381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        state->mode = GZ_WRITE;         /* simplify later checks */
201381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
202381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    /* save the current position for rewinding (only if reading) */
203381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    if (state->mode == GZ_READ) {
204381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        state->start = LSEEK(state->fd, 0, SEEK_CUR);
205381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        if (state->start == -1) state->start = 0;
206381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    }
207381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
208381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    /* initialize stream */
209381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    gz_reset(state);
210381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
211381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    /* return stream */
212381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    return (gzFile)state;
213381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes}
214381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
215381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes/* -- see zlib.h -- */
216381716e9396b55b1adb8235b020c37344f60ab07Elliott HughesgzFile ZEXPORT gzopen(path, mode)
217381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    const char *path;
218381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    const char *mode;
219381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes{
220381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    return gz_open(path, -1, mode);
221381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes}
222381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
223381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes/* -- see zlib.h -- */
224381716e9396b55b1adb8235b020c37344f60ab07Elliott HughesgzFile ZEXPORT gzopen64(path, mode)
225381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    const char *path;
226381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    const char *mode;
227381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes{
228381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    return gz_open(path, -1, mode);
229381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes}
230381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
231381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes/* -- see zlib.h -- */
232381716e9396b55b1adb8235b020c37344f60ab07Elliott HughesgzFile ZEXPORT gzdopen(fd, mode)
233381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    int fd;
234381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    const char *mode;
235381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes{
236381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    char *path;         /* identifier for error messages */
237381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    gzFile gz;
238381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
239381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    if (fd == -1 || (path = malloc(7 + 3 * sizeof(int))) == NULL)
240381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        return NULL;
241381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    sprintf(path, "<fd:%d>", fd);   /* for debugging */
242381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    gz = gz_open(path, fd, mode);
243381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    free(path);
244381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    return gz;
245381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes}
246381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
247381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes/* -- see zlib.h -- */
248381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughesint ZEXPORT gzbuffer(file, size)
249381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    gzFile file;
250381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    unsigned size;
251381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes{
252381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    gz_statep state;
253381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
254381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    /* get internal structure and check integrity */
255381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    if (file == NULL)
256381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        return -1;
257381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    state = (gz_statep)file;
258381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    if (state->mode != GZ_READ && state->mode != GZ_WRITE)
259381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        return -1;
260381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
261381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    /* make sure we haven't already allocated memory */
262381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    if (state->size != 0)
263381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        return -1;
264381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
265381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    /* check and set requested size */
266ee9e11d0d4e3361533860bf04896abb86a291bfbElliott Hughes    if (size < 2)
267ee9e11d0d4e3361533860bf04896abb86a291bfbElliott Hughes        size = 2;               /* need two bytes to check magic header */
268381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    state->want = size;
269381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    return 0;
270381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes}
271381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
272381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes/* -- see zlib.h -- */
273381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughesint ZEXPORT gzrewind(file)
274381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    gzFile file;
275381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes{
276381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    gz_statep state;
277381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
278381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    /* get internal structure */
279381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    if (file == NULL)
280381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        return -1;
281381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    state = (gz_statep)file;
282381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
283381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    /* check that we're reading and that there's no error */
284ee9e11d0d4e3361533860bf04896abb86a291bfbElliott Hughes    if (state->mode != GZ_READ ||
285ee9e11d0d4e3361533860bf04896abb86a291bfbElliott Hughes            (state->err != Z_OK && state->err != Z_BUF_ERROR))
286381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        return -1;
287381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
288381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    /* back up and start over */
289381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    if (LSEEK(state->fd, state->start, SEEK_SET) == -1)
290381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        return -1;
291381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    gz_reset(state);
292381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    return 0;
293381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes}
294381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
295381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes/* -- see zlib.h -- */
296381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughesz_off64_t ZEXPORT gzseek64(file, offset, whence)
297381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    gzFile file;
298381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    z_off64_t offset;
299381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    int whence;
300381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes{
301381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    unsigned n;
302381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    z_off64_t ret;
303381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    gz_statep state;
304381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
305381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    /* get internal structure and check integrity */
306381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    if (file == NULL)
307381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        return -1;
308381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    state = (gz_statep)file;
309381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    if (state->mode != GZ_READ && state->mode != GZ_WRITE)
310381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        return -1;
311381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
312381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    /* check that there's no error */
313ee9e11d0d4e3361533860bf04896abb86a291bfbElliott Hughes    if (state->err != Z_OK && state->err != Z_BUF_ERROR)
314381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        return -1;
315381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
316381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    /* can only seek from start or relative to current position */
317381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    if (whence != SEEK_SET && whence != SEEK_CUR)
318381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        return -1;
319381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
320381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    /* normalize offset to a SEEK_CUR specification */
321381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    if (whence == SEEK_SET)
322ee9e11d0d4e3361533860bf04896abb86a291bfbElliott Hughes        offset -= state->x.pos;
323381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    else if (state->seek)
324381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        offset += state->skip;
325381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    state->seek = 0;
326381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
327381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    /* if within raw area while reading, just go there */
328381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    if (state->mode == GZ_READ && state->how == COPY &&
329ee9e11d0d4e3361533860bf04896abb86a291bfbElliott Hughes            state->x.pos + offset >= 0) {
330ee9e11d0d4e3361533860bf04896abb86a291bfbElliott Hughes        ret = LSEEK(state->fd, offset - state->x.have, SEEK_CUR);
331381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        if (ret == -1)
332381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes            return -1;
333ee9e11d0d4e3361533860bf04896abb86a291bfbElliott Hughes        state->x.have = 0;
334381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        state->eof = 0;
335ee9e11d0d4e3361533860bf04896abb86a291bfbElliott Hughes        state->past = 0;
336381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        state->seek = 0;
337381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        gz_error(state, Z_OK, NULL);
338381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        state->strm.avail_in = 0;
339ee9e11d0d4e3361533860bf04896abb86a291bfbElliott Hughes        state->x.pos += offset;
340ee9e11d0d4e3361533860bf04896abb86a291bfbElliott Hughes        return state->x.pos;
341381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    }
342381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
343381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    /* calculate skip amount, rewinding if needed for back seek when reading */
344381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    if (offset < 0) {
345381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        if (state->mode != GZ_READ)         /* writing -- can't go backwards */
346381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes            return -1;
347ee9e11d0d4e3361533860bf04896abb86a291bfbElliott Hughes        offset += state->x.pos;
348381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        if (offset < 0)                     /* before start of file! */
349381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes            return -1;
350381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        if (gzrewind(file) == -1)           /* rewind, then skip to offset */
351381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes            return -1;
352381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    }
353381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
354381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    /* if reading, skip what's in output buffer (one less gzgetc() check) */
355381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    if (state->mode == GZ_READ) {
356ee9e11d0d4e3361533860bf04896abb86a291bfbElliott Hughes        n = GT_OFF(state->x.have) || (z_off64_t)state->x.have > offset ?
357ee9e11d0d4e3361533860bf04896abb86a291bfbElliott Hughes            (unsigned)offset : state->x.have;
358ee9e11d0d4e3361533860bf04896abb86a291bfbElliott Hughes        state->x.have -= n;
359ee9e11d0d4e3361533860bf04896abb86a291bfbElliott Hughes        state->x.next += n;
360ee9e11d0d4e3361533860bf04896abb86a291bfbElliott Hughes        state->x.pos += n;
361381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        offset -= n;
362381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    }
363381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
364381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    /* request skip (if not zero) */
365381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    if (offset) {
366381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        state->seek = 1;
367381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        state->skip = offset;
368381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    }
369ee9e11d0d4e3361533860bf04896abb86a291bfbElliott Hughes    return state->x.pos + offset;
370381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes}
371381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
372381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes/* -- see zlib.h -- */
373381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughesz_off_t ZEXPORT gzseek(file, offset, whence)
374381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    gzFile file;
375381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    z_off_t offset;
376381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    int whence;
377381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes{
378381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    z_off64_t ret;
379381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
380381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    ret = gzseek64(file, (z_off64_t)offset, whence);
381381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    return ret == (z_off_t)ret ? (z_off_t)ret : -1;
382381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes}
383381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
384381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes/* -- see zlib.h -- */
385381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughesz_off64_t ZEXPORT gztell64(file)
386381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    gzFile file;
387381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes{
388381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    gz_statep state;
389381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
390381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    /* get internal structure and check integrity */
391381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    if (file == NULL)
392381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        return -1;
393381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    state = (gz_statep)file;
394381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    if (state->mode != GZ_READ && state->mode != GZ_WRITE)
395381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        return -1;
396381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
397381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    /* return position */
398ee9e11d0d4e3361533860bf04896abb86a291bfbElliott Hughes    return state->x.pos + (state->seek ? state->skip : 0);
399381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes}
400381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
401381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes/* -- see zlib.h -- */
402381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughesz_off_t ZEXPORT gztell(file)
403381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    gzFile file;
404381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes{
405381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    z_off64_t ret;
406381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
407381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    ret = gztell64(file);
408381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    return ret == (z_off_t)ret ? (z_off_t)ret : -1;
409381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes}
410381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
411381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes/* -- see zlib.h -- */
412381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughesz_off64_t ZEXPORT gzoffset64(file)
413381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    gzFile file;
414381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes{
415381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    z_off64_t offset;
416381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    gz_statep state;
417381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
418381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    /* get internal structure and check integrity */
419381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    if (file == NULL)
420381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        return -1;
421381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    state = (gz_statep)file;
422381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    if (state->mode != GZ_READ && state->mode != GZ_WRITE)
423381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        return -1;
424381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
425381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    /* compute and return effective offset in file */
426381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    offset = LSEEK(state->fd, 0, SEEK_CUR);
427381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    if (offset == -1)
428381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        return -1;
429381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    if (state->mode == GZ_READ)             /* reading */
430381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        offset -= state->strm.avail_in;     /* don't count buffered input */
431381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    return offset;
432381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes}
433381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
434381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes/* -- see zlib.h -- */
435381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughesz_off_t ZEXPORT gzoffset(file)
436381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    gzFile file;
437381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes{
438381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    z_off64_t ret;
439381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
440381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    ret = gzoffset64(file);
441381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    return ret == (z_off_t)ret ? (z_off_t)ret : -1;
442381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes}
443381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
444381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes/* -- see zlib.h -- */
445381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughesint ZEXPORT gzeof(file)
446381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    gzFile file;
447381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes{
448381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    gz_statep state;
449381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
450381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    /* get internal structure and check integrity */
451381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    if (file == NULL)
452381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        return 0;
453381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    state = (gz_statep)file;
454381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    if (state->mode != GZ_READ && state->mode != GZ_WRITE)
455381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        return 0;
456381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
457381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    /* return end-of-file state */
458ee9e11d0d4e3361533860bf04896abb86a291bfbElliott Hughes    return state->mode == GZ_READ ? state->past : 0;
459381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes}
460381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
461381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes/* -- see zlib.h -- */
462381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughesconst char * ZEXPORT gzerror(file, errnum)
463381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    gzFile file;
464381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    int *errnum;
465381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes{
466381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    gz_statep state;
467381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
468381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    /* get internal structure and check integrity */
469381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    if (file == NULL)
470381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        return NULL;
471381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    state = (gz_statep)file;
472381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    if (state->mode != GZ_READ && state->mode != GZ_WRITE)
473381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        return NULL;
474381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
475381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    /* return error information */
476381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    if (errnum != NULL)
477381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        *errnum = state->err;
478381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    return state->msg == NULL ? "" : state->msg;
479381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes}
480381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
481381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes/* -- see zlib.h -- */
482381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughesvoid ZEXPORT gzclearerr(file)
483381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    gzFile file;
484381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes{
485381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    gz_statep state;
486381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
487381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    /* get internal structure and check integrity */
488381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    if (file == NULL)
489381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        return;
490381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    state = (gz_statep)file;
491381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    if (state->mode != GZ_READ && state->mode != GZ_WRITE)
492381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        return;
493381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
494381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    /* clear error and end-of-file */
495ee9e11d0d4e3361533860bf04896abb86a291bfbElliott Hughes    if (state->mode == GZ_READ) {
496381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        state->eof = 0;
497ee9e11d0d4e3361533860bf04896abb86a291bfbElliott Hughes        state->past = 0;
498ee9e11d0d4e3361533860bf04896abb86a291bfbElliott Hughes    }
499381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    gz_error(state, Z_OK, NULL);
500381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes}
501381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
502381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes/* Create an error message in allocated memory and set state->err and
503381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes   state->msg accordingly.  Free any previous error message already there.  Do
504381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes   not try to free or allocate space if the error is Z_MEM_ERROR (out of
505381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes   memory).  Simply save the error message as a static string.  If there is an
506381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes   allocation failure constructing the error message, then convert the error to
507381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes   out of memory. */
508381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughesvoid ZLIB_INTERNAL gz_error(state, err, msg)
509381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    gz_statep state;
510381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    int err;
511381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    const char *msg;
512381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes{
513381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    /* free previously allocated message and clear */
514381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    if (state->msg != NULL) {
515381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        if (state->err != Z_MEM_ERROR)
516381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes            free(state->msg);
517381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        state->msg = NULL;
518381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    }
519381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
520ee9e11d0d4e3361533860bf04896abb86a291bfbElliott Hughes    /* if fatal, set state->x.have to 0 so that the gzgetc() macro fails */
521ee9e11d0d4e3361533860bf04896abb86a291bfbElliott Hughes    if (err != Z_OK && err != Z_BUF_ERROR)
522ee9e11d0d4e3361533860bf04896abb86a291bfbElliott Hughes        state->x.have = 0;
523ee9e11d0d4e3361533860bf04896abb86a291bfbElliott Hughes
524381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    /* set error code, and if no message, then done */
525381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    state->err = err;
526381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    if (msg == NULL)
527381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        return;
528381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
529381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    /* for an out of memory error, save as static string */
530381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    if (err == Z_MEM_ERROR) {
531381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        state->msg = (char *)msg;
532381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        return;
533381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    }
534381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
535381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    /* construct error message with path */
536381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    if ((state->msg = malloc(strlen(state->path) + strlen(msg) + 3)) == NULL) {
537381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        state->err = Z_MEM_ERROR;
538381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        state->msg = (char *)"out of memory";
539381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        return;
540381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    }
541381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    strcpy(state->msg, state->path);
542381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    strcat(state->msg, ": ");
543381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    strcat(state->msg, msg);
544381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    return;
545381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes}
546381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
547381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes#ifndef INT_MAX
548381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes/* portably return maximum value for an int (when limits.h presumed not
549381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes   available) -- we need to do this to cover cases where 2's complement not
550381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes   used, since C standard permits 1's complement and sign-bit representations,
551381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes   otherwise we could just use ((unsigned)-1) >> 1 */
552381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughesunsigned ZLIB_INTERNAL gz_intmax()
553381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes{
554381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    unsigned p, q;
555381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
556381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    p = 1;
557381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    do {
558381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        q = p;
559381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        p <<= 1;
560381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        p++;
561381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    } while (p > q);
562381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    return q >> 1;
563381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes}
564381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes#endif
565