1381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes/* gzlib.c -- zlib functions common to reading and writing gzip files
2381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes * Copyright (C) 2004, 2010 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
8381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes#if defined(_LARGEFILE64_SOURCE) && _LFS64_LARGEFILE-0
9381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes#  define LSEEK lseek64
10381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes#else
11381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes#  define LSEEK lseek
12381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes#endif
13381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
14381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes/* Local functions */
15381716e9396b55b1adb8235b020c37344f60ab07Elliott Hugheslocal void gz_reset OF((gz_statep));
16381716e9396b55b1adb8235b020c37344f60ab07Elliott Hugheslocal gzFile gz_open OF((const char *, int, const char *));
17381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
18381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes#if defined UNDER_CE
19381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
20381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes/* Map the Windows error number in ERROR to a locale-dependent error message
21381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes   string and return a pointer to it.  Typically, the values for ERROR come
22381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes   from GetLastError.
23381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
24381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes   The string pointed to shall not be modified by the application, but may be
25381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes   overwritten by a subsequent call to gz_strwinerror
26381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
27381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes   The gz_strwinerror function does not change the current setting of
28381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes   GetLastError. */
29381716e9396b55b1adb8235b020c37344f60ab07Elliott Hugheschar ZLIB_INTERNAL *gz_strwinerror (error)
30381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes     DWORD error;
31381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes{
32381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    static char buf[1024];
33381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
34381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    wchar_t *msgbuf;
35381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    DWORD lasterr = GetLastError();
36381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    DWORD chars = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM
37381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        | FORMAT_MESSAGE_ALLOCATE_BUFFER,
38381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        NULL,
39381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        error,
40381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        0, /* Default language */
41381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        (LPVOID)&msgbuf,
42381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        0,
43381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        NULL);
44381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    if (chars != 0) {
45381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        /* If there is an \r\n appended, zap it.  */
46381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        if (chars >= 2
47381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes            && msgbuf[chars - 2] == '\r' && msgbuf[chars - 1] == '\n') {
48381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes            chars -= 2;
49381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes            msgbuf[chars] = 0;
50381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        }
51381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
52381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        if (chars > sizeof (buf) - 1) {
53381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes            chars = sizeof (buf) - 1;
54381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes            msgbuf[chars] = 0;
55381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        }
56381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
57381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        wcstombs(buf, msgbuf, chars + 1);
58381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        LocalFree(msgbuf);
59381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    }
60381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    else {
61381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        sprintf(buf, "unknown win32 error (%ld)", error);
62381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    }
63381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
64381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    SetLastError(lasterr);
65381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    return buf;
66381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes}
67381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
68381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes#endif /* UNDER_CE */
69381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
70381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes/* Reset gzip file state */
71381716e9396b55b1adb8235b020c37344f60ab07Elliott Hugheslocal void gz_reset(state)
72381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    gz_statep state;
73381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes{
74381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    if (state->mode == GZ_READ) {   /* for reading ... */
75381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        state->have = 0;            /* no output data available */
76381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        state->eof = 0;             /* not at end of file */
77381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        state->how = LOOK;          /* look for gzip header */
78381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        state->direct = 1;          /* default for empty file */
79381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    }
80381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    state->seek = 0;                /* no seek request pending */
81381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    gz_error(state, Z_OK, NULL);    /* clear error */
82381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    state->pos = 0;                 /* no uncompressed data yet */
83381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    state->strm.avail_in = 0;       /* no input data yet */
84381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes}
85381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
86381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes/* Open a gzip file either by name or file descriptor. */
87381716e9396b55b1adb8235b020c37344f60ab07Elliott Hugheslocal gzFile gz_open(path, fd, mode)
88381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    const char *path;
89381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    int fd;
90381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    const char *mode;
91381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes{
92381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    gz_statep state;
93381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
94381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    /* allocate gzFile structure to return */
95381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    state = malloc(sizeof(gz_state));
96381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    if (state == NULL)
97381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        return NULL;
98381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    state->size = 0;            /* no buffers allocated yet */
99381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    state->want = GZBUFSIZE;    /* requested buffer size */
100381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    state->msg = NULL;          /* no error message yet */
101381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
102381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    /* interpret mode */
103381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    state->mode = GZ_NONE;
104381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    state->level = Z_DEFAULT_COMPRESSION;
105381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    state->strategy = Z_DEFAULT_STRATEGY;
106381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    while (*mode) {
107381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        if (*mode >= '0' && *mode <= '9')
108381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes            state->level = *mode - '0';
109381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        else
110381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes            switch (*mode) {
111381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes            case 'r':
112381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes                state->mode = GZ_READ;
113381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes                break;
114381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes#ifndef NO_GZCOMPRESS
115381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes            case 'w':
116381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes                state->mode = GZ_WRITE;
117381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes                break;
118381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes            case 'a':
119381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes                state->mode = GZ_APPEND;
120381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes                break;
121381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes#endif
122381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes            case '+':       /* can't read and write at the same time */
123381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes                free(state);
124381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes                return NULL;
125381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes            case 'b':       /* ignore -- will request binary anyway */
126381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes                break;
127381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes            case 'f':
128381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes                state->strategy = Z_FILTERED;
129381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes                break;
130381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes            case 'h':
131381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes                state->strategy = Z_HUFFMAN_ONLY;
132381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes                break;
133381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes            case 'R':
134381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes                state->strategy = Z_RLE;
135381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes                break;
136381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes            case 'F':
137381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes                state->strategy = Z_FIXED;
138381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes            default:        /* could consider as an error, but just ignore */
139381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes                ;
140381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes            }
141381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        mode++;
142381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    }
143381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
144381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    /* must provide an "r", "w", or "a" */
145381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    if (state->mode == GZ_NONE) {
146381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        free(state);
147381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        return NULL;
148381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    }
149381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
150381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    /* save the path name for error messages */
151381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    state->path = malloc(strlen(path) + 1);
152381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    if (state->path == NULL) {
153381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        free(state);
154381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        return NULL;
155381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    }
156381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    strcpy(state->path, path);
157381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
158381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    /* open the file with the appropriate mode (or just use fd) */
159381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    state->fd = fd != -1 ? fd :
160381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        open(path,
161381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes#ifdef O_LARGEFILE
162381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes            O_LARGEFILE |
163381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes#endif
164381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes#ifdef O_BINARY
165381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes            O_BINARY |
166381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes#endif
167381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes            (state->mode == GZ_READ ?
168381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes                O_RDONLY :
169381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes                (O_WRONLY | O_CREAT | (
170381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes                    state->mode == GZ_WRITE ?
171381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes                        O_TRUNC :
172381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes                        O_APPEND))),
173381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes            0666);
174381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    if (state->fd == -1) {
175381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        free(state->path);
176381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        free(state);
177381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        return NULL;
178381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    }
179381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    if (state->mode == GZ_APPEND)
180381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        state->mode = GZ_WRITE;         /* simplify later checks */
181381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
182381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    /* save the current position for rewinding (only if reading) */
183381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    if (state->mode == GZ_READ) {
184381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        state->start = LSEEK(state->fd, 0, SEEK_CUR);
185381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        if (state->start == -1) state->start = 0;
186381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    }
187381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
188381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    /* initialize stream */
189381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    gz_reset(state);
190381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
191381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    /* return stream */
192381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    return (gzFile)state;
193381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes}
194381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
195381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes/* -- see zlib.h -- */
196381716e9396b55b1adb8235b020c37344f60ab07Elliott HughesgzFile ZEXPORT gzopen(path, mode)
197381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    const char *path;
198381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    const char *mode;
199381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes{
200381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    return gz_open(path, -1, mode);
201381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes}
202381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
203381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes/* -- see zlib.h -- */
204381716e9396b55b1adb8235b020c37344f60ab07Elliott HughesgzFile ZEXPORT gzopen64(path, mode)
205381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    const char *path;
206381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    const char *mode;
207381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes{
208381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    return gz_open(path, -1, mode);
209381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes}
210381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
211381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes/* -- see zlib.h -- */
212381716e9396b55b1adb8235b020c37344f60ab07Elliott HughesgzFile ZEXPORT gzdopen(fd, mode)
213381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    int fd;
214381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    const char *mode;
215381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes{
216381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    char *path;         /* identifier for error messages */
217381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    gzFile gz;
218381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
219381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    if (fd == -1 || (path = malloc(7 + 3 * sizeof(int))) == NULL)
220381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        return NULL;
221381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    sprintf(path, "<fd:%d>", fd);   /* for debugging */
222381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    gz = gz_open(path, fd, mode);
223381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    free(path);
224381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    return gz;
225381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes}
226381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
227381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes/* -- see zlib.h -- */
228381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughesint ZEXPORT gzbuffer(file, size)
229381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    gzFile file;
230381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    unsigned size;
231381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes{
232381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    gz_statep state;
233381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
234381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    /* get internal structure and check integrity */
235381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    if (file == NULL)
236381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        return -1;
237381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    state = (gz_statep)file;
238381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    if (state->mode != GZ_READ && state->mode != GZ_WRITE)
239381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        return -1;
240381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
241381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    /* make sure we haven't already allocated memory */
242381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    if (state->size != 0)
243381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        return -1;
244381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
245381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    /* check and set requested size */
246381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    if (size == 0)
247381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        return -1;
248381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    state->want = size;
249381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    return 0;
250381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes}
251381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
252381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes/* -- see zlib.h -- */
253381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughesint ZEXPORT gzrewind(file)
254381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    gzFile file;
255381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes{
256381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    gz_statep state;
257381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
258381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    /* get internal structure */
259381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    if (file == NULL)
260381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        return -1;
261381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    state = (gz_statep)file;
262381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
263381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    /* check that we're reading and that there's no error */
264381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    if (state->mode != GZ_READ || state->err != Z_OK)
265381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        return -1;
266381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
267381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    /* back up and start over */
268381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    if (LSEEK(state->fd, state->start, SEEK_SET) == -1)
269381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        return -1;
270381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    gz_reset(state);
271381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    return 0;
272381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes}
273381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
274381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes/* -- see zlib.h -- */
275381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughesz_off64_t ZEXPORT gzseek64(file, offset, whence)
276381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    gzFile file;
277381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    z_off64_t offset;
278381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    int whence;
279381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes{
280381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    unsigned n;
281381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    z_off64_t ret;
282381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    gz_statep state;
283381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
284381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    /* get internal structure and check integrity */
285381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    if (file == NULL)
286381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        return -1;
287381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    state = (gz_statep)file;
288381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    if (state->mode != GZ_READ && state->mode != GZ_WRITE)
289381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        return -1;
290381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
291381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    /* check that there's no error */
292381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    if (state->err != Z_OK)
293381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        return -1;
294381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
295381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    /* can only seek from start or relative to current position */
296381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    if (whence != SEEK_SET && whence != SEEK_CUR)
297381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        return -1;
298381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
299381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    /* normalize offset to a SEEK_CUR specification */
300381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    if (whence == SEEK_SET)
301381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        offset -= state->pos;
302381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    else if (state->seek)
303381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        offset += state->skip;
304381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    state->seek = 0;
305381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
306381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    /* if within raw area while reading, just go there */
307381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    if (state->mode == GZ_READ && state->how == COPY &&
308381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        state->pos + offset >= state->raw) {
309381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        ret = LSEEK(state->fd, offset - state->have, SEEK_CUR);
310381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        if (ret == -1)
311381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes            return -1;
312381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        state->have = 0;
313381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        state->eof = 0;
314381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        state->seek = 0;
315381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        gz_error(state, Z_OK, NULL);
316381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        state->strm.avail_in = 0;
317381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        state->pos += offset;
318381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        return state->pos;
319381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    }
320381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
321381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    /* calculate skip amount, rewinding if needed for back seek when reading */
322381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    if (offset < 0) {
323381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        if (state->mode != GZ_READ)         /* writing -- can't go backwards */
324381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes            return -1;
325381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        offset += state->pos;
326381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        if (offset < 0)                     /* before start of file! */
327381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes            return -1;
328381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        if (gzrewind(file) == -1)           /* rewind, then skip to offset */
329381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes            return -1;
330381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    }
331381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
332381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    /* if reading, skip what's in output buffer (one less gzgetc() check) */
333381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    if (state->mode == GZ_READ) {
334381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        n = GT_OFF(state->have) || (z_off64_t)state->have > offset ?
335381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes            (unsigned)offset : state->have;
336381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        state->have -= n;
337381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        state->next += n;
338381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        state->pos += n;
339381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        offset -= n;
340381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    }
341381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
342381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    /* request skip (if not zero) */
343381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    if (offset) {
344381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        state->seek = 1;
345381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        state->skip = offset;
346381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    }
347381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    return state->pos + offset;
348381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes}
349381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
350381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes/* -- see zlib.h -- */
351381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughesz_off_t ZEXPORT gzseek(file, offset, whence)
352381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    gzFile file;
353381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    z_off_t offset;
354381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    int whence;
355381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes{
356381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    z_off64_t ret;
357381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
358381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    ret = gzseek64(file, (z_off64_t)offset, whence);
359381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    return ret == (z_off_t)ret ? (z_off_t)ret : -1;
360381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes}
361381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
362381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes/* -- see zlib.h -- */
363381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughesz_off64_t ZEXPORT gztell64(file)
364381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    gzFile file;
365381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes{
366381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    gz_statep state;
367381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
368381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    /* get internal structure and check integrity */
369381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    if (file == NULL)
370381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        return -1;
371381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    state = (gz_statep)file;
372381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    if (state->mode != GZ_READ && state->mode != GZ_WRITE)
373381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        return -1;
374381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
375381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    /* return position */
376381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    return state->pos + (state->seek ? state->skip : 0);
377381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes}
378381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
379381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes/* -- see zlib.h -- */
380381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughesz_off_t ZEXPORT gztell(file)
381381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    gzFile file;
382381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes{
383381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    z_off64_t ret;
384381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
385381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    ret = gztell64(file);
386381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    return ret == (z_off_t)ret ? (z_off_t)ret : -1;
387381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes}
388381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
389381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes/* -- see zlib.h -- */
390381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughesz_off64_t ZEXPORT gzoffset64(file)
391381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    gzFile file;
392381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes{
393381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    z_off64_t offset;
394381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    gz_statep state;
395381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
396381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    /* get internal structure and check integrity */
397381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    if (file == NULL)
398381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        return -1;
399381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    state = (gz_statep)file;
400381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    if (state->mode != GZ_READ && state->mode != GZ_WRITE)
401381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        return -1;
402381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
403381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    /* compute and return effective offset in file */
404381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    offset = LSEEK(state->fd, 0, SEEK_CUR);
405381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    if (offset == -1)
406381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        return -1;
407381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    if (state->mode == GZ_READ)             /* reading */
408381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        offset -= state->strm.avail_in;     /* don't count buffered input */
409381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    return offset;
410381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes}
411381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
412381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes/* -- see zlib.h -- */
413381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughesz_off_t ZEXPORT gzoffset(file)
414381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    gzFile file;
415381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes{
416381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    z_off64_t ret;
417381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
418381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    ret = gzoffset64(file);
419381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    return ret == (z_off_t)ret ? (z_off_t)ret : -1;
420381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes}
421381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
422381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes/* -- see zlib.h -- */
423381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughesint ZEXPORT gzeof(file)
424381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    gzFile file;
425381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes{
426381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    gz_statep state;
427381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
428381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    /* get internal structure and check integrity */
429381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    if (file == NULL)
430381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        return 0;
431381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    state = (gz_statep)file;
432381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    if (state->mode != GZ_READ && state->mode != GZ_WRITE)
433381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        return 0;
434381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
435381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    /* return end-of-file state */
436381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    return state->mode == GZ_READ ?
437381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        (state->eof && state->strm.avail_in == 0 && state->have == 0) : 0;
438381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes}
439381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
440381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes/* -- see zlib.h -- */
441381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughesconst char * ZEXPORT gzerror(file, errnum)
442381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    gzFile file;
443381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    int *errnum;
444381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes{
445381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    gz_statep state;
446381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
447381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    /* get internal structure and check integrity */
448381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    if (file == NULL)
449381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        return NULL;
450381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    state = (gz_statep)file;
451381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    if (state->mode != GZ_READ && state->mode != GZ_WRITE)
452381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        return NULL;
453381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
454381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    /* return error information */
455381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    if (errnum != NULL)
456381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        *errnum = state->err;
457381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    return state->msg == NULL ? "" : state->msg;
458381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes}
459381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
460381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes/* -- see zlib.h -- */
461381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughesvoid ZEXPORT gzclearerr(file)
462381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    gzFile file;
463381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes{
464381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    gz_statep state;
465381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
466381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    /* get internal structure and check integrity */
467381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    if (file == NULL)
468381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        return;
469381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    state = (gz_statep)file;
470381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    if (state->mode != GZ_READ && state->mode != GZ_WRITE)
471381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        return;
472381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
473381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    /* clear error and end-of-file */
474381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    if (state->mode == GZ_READ)
475381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        state->eof = 0;
476381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    gz_error(state, Z_OK, NULL);
477381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes}
478381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
479381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes/* Create an error message in allocated memory and set state->err and
480381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes   state->msg accordingly.  Free any previous error message already there.  Do
481381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes   not try to free or allocate space if the error is Z_MEM_ERROR (out of
482381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes   memory).  Simply save the error message as a static string.  If there is an
483381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes   allocation failure constructing the error message, then convert the error to
484381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes   out of memory. */
485381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughesvoid ZLIB_INTERNAL gz_error(state, err, msg)
486381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    gz_statep state;
487381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    int err;
488381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    const char *msg;
489381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes{
490381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    /* free previously allocated message and clear */
491381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    if (state->msg != NULL) {
492381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        if (state->err != Z_MEM_ERROR)
493381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes            free(state->msg);
494381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        state->msg = NULL;
495381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    }
496381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
497381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    /* set error code, and if no message, then done */
498381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    state->err = err;
499381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    if (msg == NULL)
500381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        return;
501381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
502381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    /* for an out of memory error, save as static string */
503381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    if (err == Z_MEM_ERROR) {
504381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        state->msg = (char *)msg;
505381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        return;
506381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    }
507381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
508381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    /* construct error message with path */
509381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    if ((state->msg = malloc(strlen(state->path) + strlen(msg) + 3)) == NULL) {
510381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        state->err = Z_MEM_ERROR;
511381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        state->msg = (char *)"out of memory";
512381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        return;
513381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    }
514381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    strcpy(state->msg, state->path);
515381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    strcat(state->msg, ": ");
516381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    strcat(state->msg, msg);
517381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    return;
518381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes}
519381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
520381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes#ifndef INT_MAX
521381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes/* portably return maximum value for an int (when limits.h presumed not
522381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes   available) -- we need to do this to cover cases where 2's complement not
523381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes   used, since C standard permits 1's complement and sign-bit representations,
524381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes   otherwise we could just use ((unsigned)-1) >> 1 */
525381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughesunsigned ZLIB_INTERNAL gz_intmax()
526381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes{
527381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    unsigned p, q;
528381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
529381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    p = 1;
530381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    do {
531381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        q = p;
532381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        p <<= 1;
533381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        p++;
534381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    } while (p > q);
535381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    return q >> 1;
536381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes}
537381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes#endif
538