1*01826a49SYabin Cui /* gzlib.c contains minimal changes required to be compiled with zlibWrapper:
2*01826a49SYabin Cui * - gz_statep was converted to union to work with -Wstrict-aliasing=1 */
3*01826a49SYabin Cui
4*01826a49SYabin Cui /* gzlib.c -- zlib functions common to reading and writing gzip files
5*01826a49SYabin Cui * Copyright (C) 2004-2017 Mark Adler
6*01826a49SYabin Cui * For conditions of distribution and use, see https://www.zlib.net/zlib_license.html
7*01826a49SYabin Cui */
8*01826a49SYabin Cui
9*01826a49SYabin Cui #include "gzguts.h"
10*01826a49SYabin Cui
11*01826a49SYabin Cui #if defined(_WIN32) && !defined(__BORLANDC__) && !defined(__MINGW32__)
12*01826a49SYabin Cui # define LSEEK _lseeki64
13*01826a49SYabin Cui #else
14*01826a49SYabin Cui #if defined(_LARGEFILE64_SOURCE) && _LFS64_LARGEFILE-0
15*01826a49SYabin Cui # define LSEEK lseek64
16*01826a49SYabin Cui #else
17*01826a49SYabin Cui # define LSEEK lseek
18*01826a49SYabin Cui #endif
19*01826a49SYabin Cui #endif
20*01826a49SYabin Cui
21*01826a49SYabin Cui /* Local functions */
22*01826a49SYabin Cui local void gz_reset _Z_OF((gz_statep));
23*01826a49SYabin Cui local gzFile gz_open _Z_OF((const void *, int, const char *));
24*01826a49SYabin Cui
25*01826a49SYabin Cui #if defined UNDER_CE
26*01826a49SYabin Cui
27*01826a49SYabin Cui /* Map the Windows error number in ERROR to a locale-dependent error message
28*01826a49SYabin Cui string and return a pointer to it. Typically, the values for ERROR come
29*01826a49SYabin Cui from GetLastError.
30*01826a49SYabin Cui
31*01826a49SYabin Cui The string pointed to shall not be modified by the application, but may be
32*01826a49SYabin Cui overwritten by a subsequent call to gz_strwinerror
33*01826a49SYabin Cui
34*01826a49SYabin Cui The gz_strwinerror function does not change the current setting of
35*01826a49SYabin Cui GetLastError. */
gz_strwinerror(DWORD error)36*01826a49SYabin Cui char ZLIB_INTERNAL *gz_strwinerror(DWORD error) {
37*01826a49SYabin Cui static char buf[1024];
38*01826a49SYabin Cui
39*01826a49SYabin Cui wchar_t *msgbuf;
40*01826a49SYabin Cui DWORD lasterr = GetLastError();
41*01826a49SYabin Cui DWORD chars = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM
42*01826a49SYabin Cui | FORMAT_MESSAGE_ALLOCATE_BUFFER,
43*01826a49SYabin Cui NULL,
44*01826a49SYabin Cui error,
45*01826a49SYabin Cui 0, /* Default language */
46*01826a49SYabin Cui (LPVOID)&msgbuf,
47*01826a49SYabin Cui 0,
48*01826a49SYabin Cui NULL);
49*01826a49SYabin Cui if (chars != 0) {
50*01826a49SYabin Cui /* If there is an \r\n appended, zap it. */
51*01826a49SYabin Cui if (chars >= 2
52*01826a49SYabin Cui && msgbuf[chars - 2] == '\r' && msgbuf[chars - 1] == '\n') {
53*01826a49SYabin Cui chars -= 2;
54*01826a49SYabin Cui msgbuf[chars] = 0;
55*01826a49SYabin Cui }
56*01826a49SYabin Cui
57*01826a49SYabin Cui if (chars > sizeof (buf) - 1) {
58*01826a49SYabin Cui chars = sizeof (buf) - 1;
59*01826a49SYabin Cui msgbuf[chars] = 0;
60*01826a49SYabin Cui }
61*01826a49SYabin Cui
62*01826a49SYabin Cui wcstombs(buf, msgbuf, chars + 1);
63*01826a49SYabin Cui LocalFree(msgbuf);
64*01826a49SYabin Cui }
65*01826a49SYabin Cui else {
66*01826a49SYabin Cui sprintf(buf, "unknown win32 error (%ld)", error);
67*01826a49SYabin Cui }
68*01826a49SYabin Cui
69*01826a49SYabin Cui SetLastError(lasterr);
70*01826a49SYabin Cui return buf;
71*01826a49SYabin Cui }
72*01826a49SYabin Cui
73*01826a49SYabin Cui #endif /* UNDER_CE */
74*01826a49SYabin Cui
75*01826a49SYabin Cui /* Reset gzip file state */
gz_reset(gz_statep state)76*01826a49SYabin Cui local void gz_reset(gz_statep state) {
77*01826a49SYabin Cui state.state->x.have = 0; /* no output data available */
78*01826a49SYabin Cui if (state.state->mode == GZ_READ) { /* for reading ... */
79*01826a49SYabin Cui state.state->eof = 0; /* not at end of file */
80*01826a49SYabin Cui state.state->past = 0; /* have not read past end yet */
81*01826a49SYabin Cui state.state->how = LOOK; /* look for gzip header */
82*01826a49SYabin Cui }
83*01826a49SYabin Cui state.state->seek = 0; /* no seek request pending */
84*01826a49SYabin Cui gz_error(state, Z_OK, NULL); /* clear error */
85*01826a49SYabin Cui state.state->x.pos = 0; /* no uncompressed data yet */
86*01826a49SYabin Cui state.state->strm.avail_in = 0; /* no input data yet */
87*01826a49SYabin Cui }
88*01826a49SYabin Cui
89*01826a49SYabin Cui /* Open a gzip file either by name or file descriptor. */
gz_open(const void * path,int fd,const char * mode)90*01826a49SYabin Cui local gzFile gz_open(const void *path, int fd, const char *mode) {
91*01826a49SYabin Cui gz_statep state;
92*01826a49SYabin Cui z_size_t len;
93*01826a49SYabin Cui int oflag;
94*01826a49SYabin Cui #ifdef O_CLOEXEC
95*01826a49SYabin Cui int cloexec = 0;
96*01826a49SYabin Cui #endif
97*01826a49SYabin Cui #ifdef O_EXCL
98*01826a49SYabin Cui int exclusive = 0;
99*01826a49SYabin Cui #endif
100*01826a49SYabin Cui
101*01826a49SYabin Cui /* check input */
102*01826a49SYabin Cui if (path == NULL)
103*01826a49SYabin Cui return NULL;
104*01826a49SYabin Cui
105*01826a49SYabin Cui /* allocate gzFile structure to return */
106*01826a49SYabin Cui state.state = (gz_state*)malloc(sizeof(gz_state));
107*01826a49SYabin Cui if (state.state == NULL)
108*01826a49SYabin Cui return NULL;
109*01826a49SYabin Cui state.state->size = 0; /* no buffers allocated yet */
110*01826a49SYabin Cui state.state->want = GZBUFSIZE; /* requested buffer size */
111*01826a49SYabin Cui state.state->msg = NULL; /* no error message yet */
112*01826a49SYabin Cui
113*01826a49SYabin Cui /* interpret mode */
114*01826a49SYabin Cui state.state->mode = GZ_NONE;
115*01826a49SYabin Cui state.state->level = Z_DEFAULT_COMPRESSION;
116*01826a49SYabin Cui state.state->strategy = Z_DEFAULT_STRATEGY;
117*01826a49SYabin Cui state.state->direct = 0;
118*01826a49SYabin Cui while (*mode) {
119*01826a49SYabin Cui if (*mode >= '0' && *mode <= '9')
120*01826a49SYabin Cui state.state->level = *mode - '0';
121*01826a49SYabin Cui else
122*01826a49SYabin Cui switch (*mode) {
123*01826a49SYabin Cui case 'r':
124*01826a49SYabin Cui state.state->mode = GZ_READ;
125*01826a49SYabin Cui break;
126*01826a49SYabin Cui #ifndef NO_GZCOMPRESS
127*01826a49SYabin Cui case 'w':
128*01826a49SYabin Cui state.state->mode = GZ_WRITE;
129*01826a49SYabin Cui break;
130*01826a49SYabin Cui case 'a':
131*01826a49SYabin Cui state.state->mode = GZ_APPEND;
132*01826a49SYabin Cui break;
133*01826a49SYabin Cui #endif
134*01826a49SYabin Cui case '+': /* can't read and write at the same time */
135*01826a49SYabin Cui free(state.state);
136*01826a49SYabin Cui return NULL;
137*01826a49SYabin Cui case 'b': /* ignore -- will request binary anyway */
138*01826a49SYabin Cui break;
139*01826a49SYabin Cui #ifdef O_CLOEXEC
140*01826a49SYabin Cui case 'e':
141*01826a49SYabin Cui cloexec = 1;
142*01826a49SYabin Cui break;
143*01826a49SYabin Cui #endif
144*01826a49SYabin Cui #ifdef O_EXCL
145*01826a49SYabin Cui case 'x':
146*01826a49SYabin Cui exclusive = 1;
147*01826a49SYabin Cui break;
148*01826a49SYabin Cui #endif
149*01826a49SYabin Cui case 'f':
150*01826a49SYabin Cui state.state->strategy = Z_FILTERED;
151*01826a49SYabin Cui break;
152*01826a49SYabin Cui case 'h':
153*01826a49SYabin Cui state.state->strategy = Z_HUFFMAN_ONLY;
154*01826a49SYabin Cui break;
155*01826a49SYabin Cui case 'R':
156*01826a49SYabin Cui state.state->strategy = Z_RLE;
157*01826a49SYabin Cui break;
158*01826a49SYabin Cui case 'F':
159*01826a49SYabin Cui state.state->strategy = Z_FIXED;
160*01826a49SYabin Cui break;
161*01826a49SYabin Cui case 'T':
162*01826a49SYabin Cui state.state->direct = 1;
163*01826a49SYabin Cui break;
164*01826a49SYabin Cui default: /* could consider as an error, but just ignore */
165*01826a49SYabin Cui ;
166*01826a49SYabin Cui }
167*01826a49SYabin Cui mode++;
168*01826a49SYabin Cui }
169*01826a49SYabin Cui
170*01826a49SYabin Cui /* must provide an "r", "w", or "a" */
171*01826a49SYabin Cui if (state.state->mode == GZ_NONE) {
172*01826a49SYabin Cui free(state.state);
173*01826a49SYabin Cui return NULL;
174*01826a49SYabin Cui }
175*01826a49SYabin Cui
176*01826a49SYabin Cui /* can't force transparent read */
177*01826a49SYabin Cui if (state.state->mode == GZ_READ) {
178*01826a49SYabin Cui if (state.state->direct) {
179*01826a49SYabin Cui free(state.state);
180*01826a49SYabin Cui return NULL;
181*01826a49SYabin Cui }
182*01826a49SYabin Cui state.state->direct = 1; /* for empty file */
183*01826a49SYabin Cui }
184*01826a49SYabin Cui
185*01826a49SYabin Cui /* save the path name for error messages */
186*01826a49SYabin Cui #ifdef WIDECHAR
187*01826a49SYabin Cui if (fd == -2) {
188*01826a49SYabin Cui len = wcstombs(NULL, path, 0);
189*01826a49SYabin Cui if (len == (z_size_t)-1)
190*01826a49SYabin Cui len = 0;
191*01826a49SYabin Cui }
192*01826a49SYabin Cui else
193*01826a49SYabin Cui #endif
194*01826a49SYabin Cui len = strlen((const char *)path);
195*01826a49SYabin Cui state.state->path = (char *)malloc(len + 1);
196*01826a49SYabin Cui if (state.state->path == NULL) {
197*01826a49SYabin Cui free(state.state);
198*01826a49SYabin Cui return NULL;
199*01826a49SYabin Cui }
200*01826a49SYabin Cui #ifdef WIDECHAR
201*01826a49SYabin Cui if (fd == -2)
202*01826a49SYabin Cui if (len)
203*01826a49SYabin Cui wcstombs(state.state->path, path, len + 1);
204*01826a49SYabin Cui else
205*01826a49SYabin Cui *(state.state->path) = 0;
206*01826a49SYabin Cui else
207*01826a49SYabin Cui #endif
208*01826a49SYabin Cui #if !defined(NO_snprintf) && !defined(NO_vsnprintf)
209*01826a49SYabin Cui (void)snprintf(state.state->path, len + 1, "%s", (const char *)path);
210*01826a49SYabin Cui #else
211*01826a49SYabin Cui strcpy(state.state->path, (const char*)path);
212*01826a49SYabin Cui #endif
213*01826a49SYabin Cui
214*01826a49SYabin Cui /* compute the flags for open() */
215*01826a49SYabin Cui oflag =
216*01826a49SYabin Cui #ifdef O_LARGEFILE
217*01826a49SYabin Cui O_LARGEFILE |
218*01826a49SYabin Cui #endif
219*01826a49SYabin Cui #ifdef O_BINARY
220*01826a49SYabin Cui O_BINARY |
221*01826a49SYabin Cui #endif
222*01826a49SYabin Cui #ifdef O_CLOEXEC
223*01826a49SYabin Cui (cloexec ? O_CLOEXEC : 0) |
224*01826a49SYabin Cui #endif
225*01826a49SYabin Cui (state.state->mode == GZ_READ ?
226*01826a49SYabin Cui O_RDONLY :
227*01826a49SYabin Cui (O_WRONLY | O_CREAT |
228*01826a49SYabin Cui #ifdef O_EXCL
229*01826a49SYabin Cui (exclusive ? O_EXCL : 0) |
230*01826a49SYabin Cui #endif
231*01826a49SYabin Cui (state.state->mode == GZ_WRITE ?
232*01826a49SYabin Cui O_TRUNC :
233*01826a49SYabin Cui O_APPEND)));
234*01826a49SYabin Cui
235*01826a49SYabin Cui /* open the file with the appropriate flags (or just use fd) */
236*01826a49SYabin Cui state.state->fd = fd > -1 ? fd : (
237*01826a49SYabin Cui #ifdef WIDECHAR
238*01826a49SYabin Cui fd == -2 ? _wopen(path, oflag, 0666) :
239*01826a49SYabin Cui #endif
240*01826a49SYabin Cui open((const char *)path, oflag, 0666));
241*01826a49SYabin Cui if (state.state->fd == -1) {
242*01826a49SYabin Cui free(state.state->path);
243*01826a49SYabin Cui free(state.state);
244*01826a49SYabin Cui return NULL;
245*01826a49SYabin Cui }
246*01826a49SYabin Cui if (state.state->mode == GZ_APPEND) {
247*01826a49SYabin Cui LSEEK(state.state->fd, 0, SEEK_END); /* so gzoffset() is correct */
248*01826a49SYabin Cui state.state->mode = GZ_WRITE; /* simplify later checks */
249*01826a49SYabin Cui }
250*01826a49SYabin Cui
251*01826a49SYabin Cui /* save the current position for rewinding (only if reading) */
252*01826a49SYabin Cui if (state.state->mode == GZ_READ) {
253*01826a49SYabin Cui state.state->start = LSEEK(state.state->fd, 0, SEEK_CUR);
254*01826a49SYabin Cui if (state.state->start == -1) state.state->start = 0;
255*01826a49SYabin Cui }
256*01826a49SYabin Cui
257*01826a49SYabin Cui /* initialize stream */
258*01826a49SYabin Cui gz_reset(state);
259*01826a49SYabin Cui
260*01826a49SYabin Cui /* return stream */
261*01826a49SYabin Cui return state.file;
262*01826a49SYabin Cui }
263*01826a49SYabin Cui
264*01826a49SYabin Cui /* -- see zlib.h -- */
gzopen(const char * path,const char * mode)265*01826a49SYabin Cui gzFile ZEXPORT gzopen(const char *path, const char *mode) {
266*01826a49SYabin Cui return gz_open(path, -1, mode);
267*01826a49SYabin Cui }
268*01826a49SYabin Cui
269*01826a49SYabin Cui /* -- see zlib.h -- */
gzopen64(const char * path,const char * mode)270*01826a49SYabin Cui gzFile ZEXPORT gzopen64(const char *path, const char *mode) {
271*01826a49SYabin Cui return gz_open(path, -1, mode);
272*01826a49SYabin Cui }
273*01826a49SYabin Cui
274*01826a49SYabin Cui /* -- see zlib.h -- */
gzdopen(int fd,const char * mode)275*01826a49SYabin Cui gzFile ZEXPORT gzdopen(int fd, const char *mode) {
276*01826a49SYabin Cui char *path; /* identifier for error messages */
277*01826a49SYabin Cui gzFile gz;
278*01826a49SYabin Cui
279*01826a49SYabin Cui if (fd == -1 || (path = (char *)malloc(7 + 3 * sizeof(int))) == NULL)
280*01826a49SYabin Cui return NULL;
281*01826a49SYabin Cui #if !defined(NO_snprintf) && !defined(NO_vsnprintf)
282*01826a49SYabin Cui (void)snprintf(path, 7 + 3 * sizeof(int), "<fd:%d>", fd);
283*01826a49SYabin Cui #else
284*01826a49SYabin Cui sprintf(path, "<fd:%d>", fd); /* for debugging */
285*01826a49SYabin Cui #endif
286*01826a49SYabin Cui gz = gz_open(path, fd, mode);
287*01826a49SYabin Cui free(path);
288*01826a49SYabin Cui return gz;
289*01826a49SYabin Cui }
290*01826a49SYabin Cui
291*01826a49SYabin Cui /* -- see zlib.h -- */
292*01826a49SYabin Cui #ifdef WIDECHAR
gzopen_w(const wchar_t * path,const char * mode)293*01826a49SYabin Cui gzFile ZEXPORT gzopen_w(const wchar_t *path, const char *mode) {
294*01826a49SYabin Cui return gz_open(path, -2, mode);
295*01826a49SYabin Cui }
296*01826a49SYabin Cui #endif
297*01826a49SYabin Cui
298*01826a49SYabin Cui /* -- see zlib.h -- */
gzbuffer(gzFile file,unsigned size)299*01826a49SYabin Cui int ZEXPORT gzbuffer(gzFile file, unsigned size) {
300*01826a49SYabin Cui gz_statep state;
301*01826a49SYabin Cui
302*01826a49SYabin Cui /* get internal structure and check integrity */
303*01826a49SYabin Cui if (file == NULL)
304*01826a49SYabin Cui return -1;
305*01826a49SYabin Cui state.file = file;
306*01826a49SYabin Cui if (state.state->mode != GZ_READ && state.state->mode != GZ_WRITE)
307*01826a49SYabin Cui return -1;
308*01826a49SYabin Cui
309*01826a49SYabin Cui /* make sure we haven't already allocated memory */
310*01826a49SYabin Cui if (state.state->size != 0)
311*01826a49SYabin Cui return -1;
312*01826a49SYabin Cui
313*01826a49SYabin Cui /* check and set requested size */
314*01826a49SYabin Cui if ((size << 1) < size)
315*01826a49SYabin Cui return -1; /* need to be able to double it */
316*01826a49SYabin Cui if (size < 2)
317*01826a49SYabin Cui size = 2; /* need two bytes to check magic header */
318*01826a49SYabin Cui state.state->want = size;
319*01826a49SYabin Cui return 0;
320*01826a49SYabin Cui }
321*01826a49SYabin Cui
322*01826a49SYabin Cui /* -- see zlib.h -- */
gzrewind(gzFile file)323*01826a49SYabin Cui int ZEXPORT gzrewind(gzFile file) {
324*01826a49SYabin Cui gz_statep state;
325*01826a49SYabin Cui
326*01826a49SYabin Cui /* get internal structure */
327*01826a49SYabin Cui if (file == NULL)
328*01826a49SYabin Cui return -1;
329*01826a49SYabin Cui state.file = file;
330*01826a49SYabin Cui
331*01826a49SYabin Cui /* check that we're reading and that there's no error */
332*01826a49SYabin Cui if (state.state->mode != GZ_READ ||
333*01826a49SYabin Cui (state.state->err != Z_OK && state.state->err != Z_BUF_ERROR))
334*01826a49SYabin Cui return -1;
335*01826a49SYabin Cui
336*01826a49SYabin Cui /* back up and start over */
337*01826a49SYabin Cui if (LSEEK(state.state->fd, state.state->start, SEEK_SET) == -1)
338*01826a49SYabin Cui return -1;
339*01826a49SYabin Cui gz_reset(state);
340*01826a49SYabin Cui return 0;
341*01826a49SYabin Cui }
342*01826a49SYabin Cui
343*01826a49SYabin Cui /* -- see zlib.h -- */
gzseek64(gzFile file,z_off64_t offset,int whence)344*01826a49SYabin Cui z_off64_t ZEXPORT gzseek64(gzFile file, z_off64_t offset, int whence) {
345*01826a49SYabin Cui unsigned n;
346*01826a49SYabin Cui z_off64_t ret;
347*01826a49SYabin Cui gz_statep state;
348*01826a49SYabin Cui
349*01826a49SYabin Cui /* get internal structure and check integrity */
350*01826a49SYabin Cui if (file == NULL)
351*01826a49SYabin Cui return -1;
352*01826a49SYabin Cui state.file = file;
353*01826a49SYabin Cui if (state.state->mode != GZ_READ && state.state->mode != GZ_WRITE)
354*01826a49SYabin Cui return -1;
355*01826a49SYabin Cui
356*01826a49SYabin Cui /* check that there's no error */
357*01826a49SYabin Cui if (state.state->err != Z_OK && state.state->err != Z_BUF_ERROR)
358*01826a49SYabin Cui return -1;
359*01826a49SYabin Cui
360*01826a49SYabin Cui /* can only seek from start or relative to current position */
361*01826a49SYabin Cui if (whence != SEEK_SET && whence != SEEK_CUR)
362*01826a49SYabin Cui return -1;
363*01826a49SYabin Cui
364*01826a49SYabin Cui /* normalize offset to a SEEK_CUR specification */
365*01826a49SYabin Cui if (whence == SEEK_SET)
366*01826a49SYabin Cui offset -= state.state->x.pos;
367*01826a49SYabin Cui else if (state.state->seek)
368*01826a49SYabin Cui offset += state.state->skip;
369*01826a49SYabin Cui state.state->seek = 0;
370*01826a49SYabin Cui
371*01826a49SYabin Cui /* if within raw area while reading, just go there */
372*01826a49SYabin Cui if (state.state->mode == GZ_READ && state.state->how == COPY &&
373*01826a49SYabin Cui state.state->x.pos + offset >= 0) {
374*01826a49SYabin Cui ret = LSEEK(state.state->fd, offset - state.state->x.have, SEEK_CUR);
375*01826a49SYabin Cui if (ret == -1)
376*01826a49SYabin Cui return -1;
377*01826a49SYabin Cui state.state->x.have = 0;
378*01826a49SYabin Cui state.state->eof = 0;
379*01826a49SYabin Cui state.state->past = 0;
380*01826a49SYabin Cui state.state->seek = 0;
381*01826a49SYabin Cui gz_error(state, Z_OK, NULL);
382*01826a49SYabin Cui state.state->strm.avail_in = 0;
383*01826a49SYabin Cui state.state->x.pos += offset;
384*01826a49SYabin Cui return state.state->x.pos;
385*01826a49SYabin Cui }
386*01826a49SYabin Cui
387*01826a49SYabin Cui /* calculate skip amount, rewinding if needed for back seek when reading */
388*01826a49SYabin Cui if (offset < 0) {
389*01826a49SYabin Cui if (state.state->mode != GZ_READ) /* writing -- can't go backwards */
390*01826a49SYabin Cui return -1;
391*01826a49SYabin Cui offset += state.state->x.pos;
392*01826a49SYabin Cui if (offset < 0) /* before start of file! */
393*01826a49SYabin Cui return -1;
394*01826a49SYabin Cui if (gzrewind(file) == -1) /* rewind, then skip to offset */
395*01826a49SYabin Cui return -1;
396*01826a49SYabin Cui }
397*01826a49SYabin Cui
398*01826a49SYabin Cui /* if reading, skip what's in output buffer (one less gzgetc() check) */
399*01826a49SYabin Cui if (state.state->mode == GZ_READ) {
400*01826a49SYabin Cui n = GT_OFF(state.state->x.have) || (z_off64_t)state.state->x.have > offset ?
401*01826a49SYabin Cui (unsigned)offset : state.state->x.have;
402*01826a49SYabin Cui state.state->x.have -= n;
403*01826a49SYabin Cui state.state->x.next += n;
404*01826a49SYabin Cui state.state->x.pos += n;
405*01826a49SYabin Cui offset -= n;
406*01826a49SYabin Cui }
407*01826a49SYabin Cui
408*01826a49SYabin Cui /* request skip (if not zero) */
409*01826a49SYabin Cui if (offset) {
410*01826a49SYabin Cui state.state->seek = 1;
411*01826a49SYabin Cui state.state->skip = offset;
412*01826a49SYabin Cui }
413*01826a49SYabin Cui return state.state->x.pos + offset;
414*01826a49SYabin Cui }
415*01826a49SYabin Cui
416*01826a49SYabin Cui /* -- see zlib.h -- */
gzseek(gzFile file,z_off_t offset,int whence)417*01826a49SYabin Cui z_off_t ZEXPORT gzseek(gzFile file, z_off_t offset, int whence) {
418*01826a49SYabin Cui z_off64_t ret;
419*01826a49SYabin Cui
420*01826a49SYabin Cui ret = gzseek64(file, (z_off64_t)offset, whence);
421*01826a49SYabin Cui return ret == (z_off_t)ret ? (z_off_t)ret : -1;
422*01826a49SYabin Cui }
423*01826a49SYabin Cui
424*01826a49SYabin Cui /* -- see zlib.h -- */
gztell64(gzFile file)425*01826a49SYabin Cui z_off64_t ZEXPORT gztell64(gzFile file) {
426*01826a49SYabin Cui gz_statep state;
427*01826a49SYabin Cui
428*01826a49SYabin Cui /* get internal structure and check integrity */
429*01826a49SYabin Cui if (file == NULL)
430*01826a49SYabin Cui return -1;
431*01826a49SYabin Cui state.file = file;
432*01826a49SYabin Cui if (state.state->mode != GZ_READ && state.state->mode != GZ_WRITE)
433*01826a49SYabin Cui return -1;
434*01826a49SYabin Cui
435*01826a49SYabin Cui /* return position */
436*01826a49SYabin Cui return state.state->x.pos + (state.state->seek ? state.state->skip : 0);
437*01826a49SYabin Cui }
438*01826a49SYabin Cui
439*01826a49SYabin Cui /* -- see zlib.h -- */
gztell(gzFile file)440*01826a49SYabin Cui z_off_t ZEXPORT gztell(gzFile file) {
441*01826a49SYabin Cui z_off64_t ret;
442*01826a49SYabin Cui
443*01826a49SYabin Cui ret = gztell64(file);
444*01826a49SYabin Cui return ret == (z_off_t)ret ? (z_off_t)ret : -1;
445*01826a49SYabin Cui }
446*01826a49SYabin Cui
447*01826a49SYabin Cui /* -- see zlib.h -- */
gzoffset64(gzFile file)448*01826a49SYabin Cui z_off64_t ZEXPORT gzoffset64(gzFile file) {
449*01826a49SYabin Cui z_off64_t offset;
450*01826a49SYabin Cui gz_statep state;
451*01826a49SYabin Cui
452*01826a49SYabin Cui /* get internal structure and check integrity */
453*01826a49SYabin Cui if (file == NULL)
454*01826a49SYabin Cui return -1;
455*01826a49SYabin Cui state.file = file;
456*01826a49SYabin Cui if (state.state->mode != GZ_READ && state.state->mode != GZ_WRITE)
457*01826a49SYabin Cui return -1;
458*01826a49SYabin Cui
459*01826a49SYabin Cui /* compute and return effective offset in file */
460*01826a49SYabin Cui offset = LSEEK(state.state->fd, 0, SEEK_CUR);
461*01826a49SYabin Cui if (offset == -1)
462*01826a49SYabin Cui return -1;
463*01826a49SYabin Cui if (state.state->mode == GZ_READ) /* reading */
464*01826a49SYabin Cui offset -= state.state->strm.avail_in; /* don't count buffered input */
465*01826a49SYabin Cui return offset;
466*01826a49SYabin Cui }
467*01826a49SYabin Cui
468*01826a49SYabin Cui /* -- see zlib.h -- */
gzoffset(gzFile file)469*01826a49SYabin Cui z_off_t ZEXPORT gzoffset(gzFile file) {
470*01826a49SYabin Cui z_off64_t ret;
471*01826a49SYabin Cui
472*01826a49SYabin Cui ret = gzoffset64(file);
473*01826a49SYabin Cui return ret == (z_off_t)ret ? (z_off_t)ret : -1;
474*01826a49SYabin Cui }
475*01826a49SYabin Cui
476*01826a49SYabin Cui /* -- see zlib.h -- */
gzeof(gzFile file)477*01826a49SYabin Cui int ZEXPORT gzeof(gzFile file) {
478*01826a49SYabin Cui gz_statep state;
479*01826a49SYabin Cui
480*01826a49SYabin Cui /* get internal structure and check integrity */
481*01826a49SYabin Cui if (file == NULL)
482*01826a49SYabin Cui return 0;
483*01826a49SYabin Cui state.file = file;
484*01826a49SYabin Cui if (state.state->mode != GZ_READ && state.state->mode != GZ_WRITE)
485*01826a49SYabin Cui return 0;
486*01826a49SYabin Cui
487*01826a49SYabin Cui /* return end-of-file state */
488*01826a49SYabin Cui return state.state->mode == GZ_READ ? state.state->past : 0;
489*01826a49SYabin Cui }
490*01826a49SYabin Cui
491*01826a49SYabin Cui /* -- see zlib.h -- */
gzerror(gzFile file,int * errnum)492*01826a49SYabin Cui const char * ZEXPORT gzerror(gzFile file, int *errnum) {
493*01826a49SYabin Cui gz_statep state;
494*01826a49SYabin Cui
495*01826a49SYabin Cui /* get internal structure and check integrity */
496*01826a49SYabin Cui if (file == NULL)
497*01826a49SYabin Cui return NULL;
498*01826a49SYabin Cui state.file = file;
499*01826a49SYabin Cui if (state.state->mode != GZ_READ && state.state->mode != GZ_WRITE)
500*01826a49SYabin Cui return NULL;
501*01826a49SYabin Cui
502*01826a49SYabin Cui /* return error information */
503*01826a49SYabin Cui if (errnum != NULL)
504*01826a49SYabin Cui *errnum = state.state->err;
505*01826a49SYabin Cui return state.state->err == Z_MEM_ERROR ? "out of memory" :
506*01826a49SYabin Cui (state.state->msg == NULL ? "" : state.state->msg);
507*01826a49SYabin Cui }
508*01826a49SYabin Cui
509*01826a49SYabin Cui /* -- see zlib.h -- */
gzclearerr(gzFile file)510*01826a49SYabin Cui void ZEXPORT gzclearerr(gzFile file) {
511*01826a49SYabin Cui gz_statep state;
512*01826a49SYabin Cui
513*01826a49SYabin Cui /* get internal structure and check integrity */
514*01826a49SYabin Cui if (file == NULL)
515*01826a49SYabin Cui return;
516*01826a49SYabin Cui state.file = file;
517*01826a49SYabin Cui if (state.state->mode != GZ_READ && state.state->mode != GZ_WRITE)
518*01826a49SYabin Cui return;
519*01826a49SYabin Cui
520*01826a49SYabin Cui /* clear error and end-of-file */
521*01826a49SYabin Cui if (state.state->mode == GZ_READ) {
522*01826a49SYabin Cui state.state->eof = 0;
523*01826a49SYabin Cui state.state->past = 0;
524*01826a49SYabin Cui }
525*01826a49SYabin Cui gz_error(state, Z_OK, NULL);
526*01826a49SYabin Cui }
527*01826a49SYabin Cui
528*01826a49SYabin Cui /* Create an error message in allocated memory and set state.state->err and
529*01826a49SYabin Cui state.state->msg accordingly. Free any previous error message already there. Do
530*01826a49SYabin Cui not try to free or allocate space if the error is Z_MEM_ERROR (out of
531*01826a49SYabin Cui memory). Simply save the error message as a static string. If there is an
532*01826a49SYabin Cui allocation failure constructing the error message, then convert the error to
533*01826a49SYabin Cui out of memory. */
gz_error(gz_statep state,int err,const char * msg)534*01826a49SYabin Cui void ZLIB_INTERNAL gz_error(gz_statep state, int err, const char *msg) {
535*01826a49SYabin Cui /* free previously allocated message and clear */
536*01826a49SYabin Cui if (state.state->msg != NULL) {
537*01826a49SYabin Cui if (state.state->err != Z_MEM_ERROR)
538*01826a49SYabin Cui free(state.state->msg);
539*01826a49SYabin Cui state.state->msg = NULL;
540*01826a49SYabin Cui }
541*01826a49SYabin Cui
542*01826a49SYabin Cui /* if fatal, set state.state->x.have to 0 so that the gzgetc() macro fails */
543*01826a49SYabin Cui if (err != Z_OK && err != Z_BUF_ERROR)
544*01826a49SYabin Cui state.state->x.have = 0;
545*01826a49SYabin Cui
546*01826a49SYabin Cui /* set error code, and if no message, then done */
547*01826a49SYabin Cui state.state->err = err;
548*01826a49SYabin Cui if (msg == NULL)
549*01826a49SYabin Cui return;
550*01826a49SYabin Cui
551*01826a49SYabin Cui /* for an out of memory error, return literal string when requested */
552*01826a49SYabin Cui if (err == Z_MEM_ERROR)
553*01826a49SYabin Cui return;
554*01826a49SYabin Cui
555*01826a49SYabin Cui /* construct error message with path */
556*01826a49SYabin Cui if ((state.state->msg = (char *)malloc(strlen(state.state->path) + strlen(msg) + 3)) ==
557*01826a49SYabin Cui NULL) {
558*01826a49SYabin Cui state.state->err = Z_MEM_ERROR;
559*01826a49SYabin Cui return;
560*01826a49SYabin Cui }
561*01826a49SYabin Cui #if !defined(NO_snprintf) && !defined(NO_vsnprintf)
562*01826a49SYabin Cui (void)snprintf(state.state->msg, strlen(state.state->path) + strlen(msg) + 3,
563*01826a49SYabin Cui "%s%s%s", state.state->path, ": ", msg);
564*01826a49SYabin Cui #else
565*01826a49SYabin Cui strcpy(state.state->msg, state.state->path);
566*01826a49SYabin Cui strcat(state.state->msg, ": ");
567*01826a49SYabin Cui strcat(state.state->msg, msg);
568*01826a49SYabin Cui #endif
569*01826a49SYabin Cui }
570*01826a49SYabin Cui
571*01826a49SYabin Cui #ifndef INT_MAX
572*01826a49SYabin Cui /* portably return maximum value for an int (when limits.h presumed not
573*01826a49SYabin Cui available) -- we need to do this to cover cases where 2's complement not
574*01826a49SYabin Cui used, since C standard permits 1's complement and sign-bit representations,
575*01826a49SYabin Cui otherwise we could just use ((unsigned)-1) >> 1 */
gz_intmax()576*01826a49SYabin Cui unsigned ZLIB_INTERNAL gz_intmax() {
577*01826a49SYabin Cui unsigned p, q;
578*01826a49SYabin Cui
579*01826a49SYabin Cui p = 1;
580*01826a49SYabin Cui do {
581*01826a49SYabin Cui q = p;
582*01826a49SYabin Cui p <<= 1;
583*01826a49SYabin Cui p++;
584*01826a49SYabin Cui } while (p > q);
585*01826a49SYabin Cui return q >> 1;
586*01826a49SYabin Cui }
587*01826a49SYabin Cui #endif
588