blob: eea480a74c9f23cc15f857ec75bd98ce09fe9680 [file] [log] [blame]
Przemyslaw Skibinskif0d7da72016-11-29 18:02:34 +01001/* gzlib.c contains minimal changes required to be compiled with zlibWrapper:
Yann Collet32fb4072017-08-18 16:52:05 -07002 * - gz_statep was converted to union to work with -Wstrict-aliasing=1 */
Przemyslaw Skibinskif0d7da72016-11-29 18:02:34 +01003
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +01004/* gzlib.c -- zlib functions common to reading and writing gzip files
Przemyslaw Skibinski7f82aad2017-01-18 12:08:08 +01005 * Copyright (C) 2004-2017 Mark Adler
Elliott Hughes44aba642023-09-12 20:18:59 +00006 * For conditions of distribution and use, see https://www.zlib.net/zlib_license.html
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +01007 */
8
9#include "gzguts.h"
10
Przemyslaw Skibinski7f82aad2017-01-18 12:08:08 +010011#if defined(_WIN32) && !defined(__BORLANDC__) && !defined(__MINGW32__)
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +010012# define LSEEK _lseeki64
13#else
14#if defined(_LARGEFILE64_SOURCE) && _LFS64_LARGEFILE-0
15# define LSEEK lseek64
16#else
17# define LSEEK lseek
18#endif
19#endif
20
21/* Local functions */
Elliott Hughes44aba642023-09-12 20:18:59 +000022local void gz_reset _Z_OF((gz_statep));
23local gzFile gz_open _Z_OF((const void *, int, const char *));
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +010024
25#if defined UNDER_CE
26
27/* Map the Windows error number in ERROR to a locale-dependent error message
28 string and return a pointer to it. Typically, the values for ERROR come
29 from GetLastError.
30
31 The string pointed to shall not be modified by the application, but may be
32 overwritten by a subsequent call to gz_strwinerror
33
34 The gz_strwinerror function does not change the current setting of
35 GetLastError. */
36char ZLIB_INTERNAL *gz_strwinerror (error)
37 DWORD error;
38{
39 static char buf[1024];
40
41 wchar_t *msgbuf;
42 DWORD lasterr = GetLastError();
43 DWORD chars = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM
44 | FORMAT_MESSAGE_ALLOCATE_BUFFER,
45 NULL,
46 error,
47 0, /* Default language */
48 (LPVOID)&msgbuf,
49 0,
50 NULL);
51 if (chars != 0) {
52 /* If there is an \r\n appended, zap it. */
53 if (chars >= 2
54 && msgbuf[chars - 2] == '\r' && msgbuf[chars - 1] == '\n') {
55 chars -= 2;
56 msgbuf[chars] = 0;
57 }
58
59 if (chars > sizeof (buf) - 1) {
60 chars = sizeof (buf) - 1;
61 msgbuf[chars] = 0;
62 }
63
64 wcstombs(buf, msgbuf, chars + 1);
65 LocalFree(msgbuf);
66 }
67 else {
68 sprintf(buf, "unknown win32 error (%ld)", error);
69 }
70
71 SetLastError(lasterr);
72 return buf;
73}
74
75#endif /* UNDER_CE */
76
77/* Reset gzip file state */
78local void gz_reset(state)
79 gz_statep state;
80{
Przemyslaw Skibinskia1f60632016-11-29 15:50:28 +010081 state.state->x.have = 0; /* no output data available */
82 if (state.state->mode == GZ_READ) { /* for reading ... */
83 state.state->eof = 0; /* not at end of file */
84 state.state->past = 0; /* have not read past end yet */
85 state.state->how = LOOK; /* look for gzip header */
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +010086 }
Przemyslaw Skibinskia1f60632016-11-29 15:50:28 +010087 state.state->seek = 0; /* no seek request pending */
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +010088 gz_error(state, Z_OK, NULL); /* clear error */
Przemyslaw Skibinskia1f60632016-11-29 15:50:28 +010089 state.state->x.pos = 0; /* no uncompressed data yet */
90 state.state->strm.avail_in = 0; /* no input data yet */
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +010091}
92
93/* Open a gzip file either by name or file descriptor. */
94local gzFile gz_open(path, fd, mode)
95 const void *path;
96 int fd;
97 const char *mode;
98{
99 gz_statep state;
Przemyslaw Skibinski7f82aad2017-01-18 12:08:08 +0100100 z_size_t len;
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100101 int oflag;
102#ifdef O_CLOEXEC
103 int cloexec = 0;
104#endif
105#ifdef O_EXCL
106 int exclusive = 0;
107#endif
108
109 /* check input */
110 if (path == NULL)
111 return NULL;
112
113 /* allocate gzFile structure to return */
Yann Colletda558652018-08-15 16:43:13 -0700114 state.state = (gz_state*)malloc(sizeof(gz_state));
Przemyslaw Skibinskia1f60632016-11-29 15:50:28 +0100115 if (state.state == NULL)
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100116 return NULL;
Przemyslaw Skibinskia1f60632016-11-29 15:50:28 +0100117 state.state->size = 0; /* no buffers allocated yet */
118 state.state->want = GZBUFSIZE; /* requested buffer size */
119 state.state->msg = NULL; /* no error message yet */
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100120
121 /* interpret mode */
Przemyslaw Skibinskia1f60632016-11-29 15:50:28 +0100122 state.state->mode = GZ_NONE;
123 state.state->level = Z_DEFAULT_COMPRESSION;
124 state.state->strategy = Z_DEFAULT_STRATEGY;
125 state.state->direct = 0;
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100126 while (*mode) {
127 if (*mode >= '0' && *mode <= '9')
Przemyslaw Skibinskia1f60632016-11-29 15:50:28 +0100128 state.state->level = *mode - '0';
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100129 else
130 switch (*mode) {
131 case 'r':
Przemyslaw Skibinskia1f60632016-11-29 15:50:28 +0100132 state.state->mode = GZ_READ;
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100133 break;
134#ifndef NO_GZCOMPRESS
135 case 'w':
Przemyslaw Skibinskia1f60632016-11-29 15:50:28 +0100136 state.state->mode = GZ_WRITE;
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100137 break;
138 case 'a':
Przemyslaw Skibinskia1f60632016-11-29 15:50:28 +0100139 state.state->mode = GZ_APPEND;
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100140 break;
141#endif
142 case '+': /* can't read and write at the same time */
Przemyslaw Skibinskia1f60632016-11-29 15:50:28 +0100143 free(state.state);
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100144 return NULL;
145 case 'b': /* ignore -- will request binary anyway */
146 break;
147#ifdef O_CLOEXEC
148 case 'e':
149 cloexec = 1;
150 break;
151#endif
152#ifdef O_EXCL
153 case 'x':
154 exclusive = 1;
155 break;
156#endif
157 case 'f':
Przemyslaw Skibinskia1f60632016-11-29 15:50:28 +0100158 state.state->strategy = Z_FILTERED;
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100159 break;
160 case 'h':
Przemyslaw Skibinskia1f60632016-11-29 15:50:28 +0100161 state.state->strategy = Z_HUFFMAN_ONLY;
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100162 break;
163 case 'R':
Przemyslaw Skibinskia1f60632016-11-29 15:50:28 +0100164 state.state->strategy = Z_RLE;
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100165 break;
166 case 'F':
Przemyslaw Skibinskia1f60632016-11-29 15:50:28 +0100167 state.state->strategy = Z_FIXED;
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100168 break;
169 case 'T':
Przemyslaw Skibinskia1f60632016-11-29 15:50:28 +0100170 state.state->direct = 1;
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100171 break;
172 default: /* could consider as an error, but just ignore */
173 ;
174 }
175 mode++;
176 }
177
178 /* must provide an "r", "w", or "a" */
Przemyslaw Skibinskia1f60632016-11-29 15:50:28 +0100179 if (state.state->mode == GZ_NONE) {
180 free(state.state);
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100181 return NULL;
182 }
183
184 /* can't force transparent read */
Przemyslaw Skibinskia1f60632016-11-29 15:50:28 +0100185 if (state.state->mode == GZ_READ) {
186 if (state.state->direct) {
187 free(state.state);
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100188 return NULL;
189 }
Przemyslaw Skibinskia1f60632016-11-29 15:50:28 +0100190 state.state->direct = 1; /* for empty file */
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100191 }
192
193 /* save the path name for error messages */
Przemyslaw Skibinski7f82aad2017-01-18 12:08:08 +0100194#ifdef WIDECHAR
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100195 if (fd == -2) {
196 len = wcstombs(NULL, path, 0);
Przemyslaw Skibinski7f82aad2017-01-18 12:08:08 +0100197 if (len == (z_size_t)-1)
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100198 len = 0;
199 }
200 else
201#endif
202 len = strlen((const char *)path);
Przemyslaw Skibinskia1f60632016-11-29 15:50:28 +0100203 state.state->path = (char *)malloc(len + 1);
204 if (state.state->path == NULL) {
205 free(state.state);
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100206 return NULL;
207 }
Przemyslaw Skibinski7f82aad2017-01-18 12:08:08 +0100208#ifdef WIDECHAR
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100209 if (fd == -2)
210 if (len)
Przemyslaw Skibinskia1f60632016-11-29 15:50:28 +0100211 wcstombs(state.state->path, path, len + 1);
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100212 else
Przemyslaw Skibinskia1f60632016-11-29 15:50:28 +0100213 *(state.state->path) = 0;
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100214 else
215#endif
216#if !defined(NO_snprintf) && !defined(NO_vsnprintf)
Przemyslaw Skibinski7f82aad2017-01-18 12:08:08 +0100217 (void)snprintf(state.state->path, len + 1, "%s", (const char *)path);
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100218#else
Yann Colletc69ed0f2019-10-02 17:32:19 -0700219 strcpy(state.state->path, (const char*)path);
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100220#endif
221
222 /* compute the flags for open() */
223 oflag =
224#ifdef O_LARGEFILE
225 O_LARGEFILE |
226#endif
227#ifdef O_BINARY
228 O_BINARY |
229#endif
230#ifdef O_CLOEXEC
231 (cloexec ? O_CLOEXEC : 0) |
232#endif
Przemyslaw Skibinskia1f60632016-11-29 15:50:28 +0100233 (state.state->mode == GZ_READ ?
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100234 O_RDONLY :
235 (O_WRONLY | O_CREAT |
236#ifdef O_EXCL
237 (exclusive ? O_EXCL : 0) |
238#endif
Przemyslaw Skibinskia1f60632016-11-29 15:50:28 +0100239 (state.state->mode == GZ_WRITE ?
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100240 O_TRUNC :
241 O_APPEND)));
242
243 /* open the file with the appropriate flags (or just use fd) */
Przemyslaw Skibinskia1f60632016-11-29 15:50:28 +0100244 state.state->fd = fd > -1 ? fd : (
Przemyslaw Skibinski7f82aad2017-01-18 12:08:08 +0100245#ifdef WIDECHAR
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100246 fd == -2 ? _wopen(path, oflag, 0666) :
247#endif
248 open((const char *)path, oflag, 0666));
Przemyslaw Skibinskia1f60632016-11-29 15:50:28 +0100249 if (state.state->fd == -1) {
250 free(state.state->path);
251 free(state.state);
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100252 return NULL;
253 }
Przemyslaw Skibinski7f82aad2017-01-18 12:08:08 +0100254 if (state.state->mode == GZ_APPEND) {
255 LSEEK(state.state->fd, 0, SEEK_END); /* so gzoffset() is correct */
Przemyslaw Skibinskia1f60632016-11-29 15:50:28 +0100256 state.state->mode = GZ_WRITE; /* simplify later checks */
Przemyslaw Skibinski7f82aad2017-01-18 12:08:08 +0100257 }
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100258
259 /* save the current position for rewinding (only if reading) */
Przemyslaw Skibinskia1f60632016-11-29 15:50:28 +0100260 if (state.state->mode == GZ_READ) {
261 state.state->start = LSEEK(state.state->fd, 0, SEEK_CUR);
262 if (state.state->start == -1) state.state->start = 0;
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100263 }
264
265 /* initialize stream */
266 gz_reset(state);
267
268 /* return stream */
Yann Colletda558652018-08-15 16:43:13 -0700269 return state.file;
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100270}
271
272/* -- see zlib.h -- */
273gzFile ZEXPORT gzopen(path, mode)
274 const char *path;
275 const char *mode;
276{
277 return gz_open(path, -1, mode);
278}
279
280/* -- see zlib.h -- */
281gzFile ZEXPORT gzopen64(path, mode)
282 const char *path;
283 const char *mode;
284{
285 return gz_open(path, -1, mode);
286}
287
288/* -- see zlib.h -- */
289gzFile ZEXPORT gzdopen(fd, mode)
290 int fd;
291 const char *mode;
292{
293 char *path; /* identifier for error messages */
294 gzFile gz;
295
296 if (fd == -1 || (path = (char *)malloc(7 + 3 * sizeof(int))) == NULL)
297 return NULL;
298#if !defined(NO_snprintf) && !defined(NO_vsnprintf)
Przemyslaw Skibinski7f82aad2017-01-18 12:08:08 +0100299 (void)snprintf(path, 7 + 3 * sizeof(int), "<fd:%d>", fd);
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100300#else
301 sprintf(path, "<fd:%d>", fd); /* for debugging */
302#endif
303 gz = gz_open(path, fd, mode);
304 free(path);
305 return gz;
306}
307
308/* -- see zlib.h -- */
Przemyslaw Skibinski7f82aad2017-01-18 12:08:08 +0100309#ifdef WIDECHAR
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100310gzFile ZEXPORT gzopen_w(path, mode)
311 const wchar_t *path;
312 const char *mode;
313{
314 return gz_open(path, -2, mode);
315}
316#endif
317
318/* -- see zlib.h -- */
319int ZEXPORT gzbuffer(file, size)
320 gzFile file;
321 unsigned size;
322{
323 gz_statep state;
324
325 /* get internal structure and check integrity */
326 if (file == NULL)
327 return -1;
Yann Colletcb18fff2019-09-24 17:50:58 -0700328 state.file = file;
Przemyslaw Skibinskia1f60632016-11-29 15:50:28 +0100329 if (state.state->mode != GZ_READ && state.state->mode != GZ_WRITE)
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100330 return -1;
331
332 /* make sure we haven't already allocated memory */
Przemyslaw Skibinskia1f60632016-11-29 15:50:28 +0100333 if (state.state->size != 0)
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100334 return -1;
335
336 /* check and set requested size */
Przemyslaw Skibinski7f82aad2017-01-18 12:08:08 +0100337 if ((size << 1) < size)
338 return -1; /* need to be able to double it */
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100339 if (size < 2)
340 size = 2; /* need two bytes to check magic header */
Przemyslaw Skibinskia1f60632016-11-29 15:50:28 +0100341 state.state->want = size;
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100342 return 0;
343}
344
345/* -- see zlib.h -- */
346int ZEXPORT gzrewind(file)
347 gzFile file;
348{
349 gz_statep state;
350
351 /* get internal structure */
352 if (file == NULL)
353 return -1;
Yann Colletcb18fff2019-09-24 17:50:58 -0700354 state.file = file;
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100355
356 /* check that we're reading and that there's no error */
Przemyslaw Skibinskia1f60632016-11-29 15:50:28 +0100357 if (state.state->mode != GZ_READ ||
358 (state.state->err != Z_OK && state.state->err != Z_BUF_ERROR))
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100359 return -1;
360
361 /* back up and start over */
Przemyslaw Skibinskia1f60632016-11-29 15:50:28 +0100362 if (LSEEK(state.state->fd, state.state->start, SEEK_SET) == -1)
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100363 return -1;
364 gz_reset(state);
365 return 0;
366}
367
368/* -- see zlib.h -- */
369z_off64_t ZEXPORT gzseek64(file, offset, whence)
370 gzFile file;
371 z_off64_t offset;
372 int whence;
373{
374 unsigned n;
375 z_off64_t ret;
376 gz_statep state;
377
378 /* get internal structure and check integrity */
379 if (file == NULL)
380 return -1;
Yann Colletcb18fff2019-09-24 17:50:58 -0700381 state.file = file;
Przemyslaw Skibinskia1f60632016-11-29 15:50:28 +0100382 if (state.state->mode != GZ_READ && state.state->mode != GZ_WRITE)
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100383 return -1;
384
385 /* check that there's no error */
Przemyslaw Skibinskia1f60632016-11-29 15:50:28 +0100386 if (state.state->err != Z_OK && state.state->err != Z_BUF_ERROR)
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100387 return -1;
388
389 /* can only seek from start or relative to current position */
390 if (whence != SEEK_SET && whence != SEEK_CUR)
391 return -1;
392
393 /* normalize offset to a SEEK_CUR specification */
394 if (whence == SEEK_SET)
Przemyslaw Skibinskia1f60632016-11-29 15:50:28 +0100395 offset -= state.state->x.pos;
396 else if (state.state->seek)
397 offset += state.state->skip;
398 state.state->seek = 0;
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100399
400 /* if within raw area while reading, just go there */
Przemyslaw Skibinskia1f60632016-11-29 15:50:28 +0100401 if (state.state->mode == GZ_READ && state.state->how == COPY &&
402 state.state->x.pos + offset >= 0) {
403 ret = LSEEK(state.state->fd, offset - state.state->x.have, SEEK_CUR);
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100404 if (ret == -1)
405 return -1;
Przemyslaw Skibinskia1f60632016-11-29 15:50:28 +0100406 state.state->x.have = 0;
407 state.state->eof = 0;
408 state.state->past = 0;
409 state.state->seek = 0;
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100410 gz_error(state, Z_OK, NULL);
Przemyslaw Skibinskia1f60632016-11-29 15:50:28 +0100411 state.state->strm.avail_in = 0;
412 state.state->x.pos += offset;
413 return state.state->x.pos;
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100414 }
415
416 /* calculate skip amount, rewinding if needed for back seek when reading */
417 if (offset < 0) {
Przemyslaw Skibinskia1f60632016-11-29 15:50:28 +0100418 if (state.state->mode != GZ_READ) /* writing -- can't go backwards */
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100419 return -1;
Przemyslaw Skibinskia1f60632016-11-29 15:50:28 +0100420 offset += state.state->x.pos;
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100421 if (offset < 0) /* before start of file! */
422 return -1;
423 if (gzrewind(file) == -1) /* rewind, then skip to offset */
424 return -1;
425 }
426
427 /* if reading, skip what's in output buffer (one less gzgetc() check) */
Przemyslaw Skibinskia1f60632016-11-29 15:50:28 +0100428 if (state.state->mode == GZ_READ) {
429 n = GT_OFF(state.state->x.have) || (z_off64_t)state.state->x.have > offset ?
430 (unsigned)offset : state.state->x.have;
431 state.state->x.have -= n;
432 state.state->x.next += n;
433 state.state->x.pos += n;
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100434 offset -= n;
435 }
436
437 /* request skip (if not zero) */
438 if (offset) {
Przemyslaw Skibinskia1f60632016-11-29 15:50:28 +0100439 state.state->seek = 1;
440 state.state->skip = offset;
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100441 }
Przemyslaw Skibinskia1f60632016-11-29 15:50:28 +0100442 return state.state->x.pos + offset;
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100443}
444
445/* -- see zlib.h -- */
446z_off_t ZEXPORT gzseek(file, offset, whence)
447 gzFile file;
448 z_off_t offset;
449 int whence;
450{
451 z_off64_t ret;
452
453 ret = gzseek64(file, (z_off64_t)offset, whence);
454 return ret == (z_off_t)ret ? (z_off_t)ret : -1;
455}
456
457/* -- see zlib.h -- */
458z_off64_t ZEXPORT gztell64(file)
459 gzFile file;
460{
461 gz_statep state;
462
463 /* get internal structure and check integrity */
464 if (file == NULL)
465 return -1;
Yann Colletcb18fff2019-09-24 17:50:58 -0700466 state.file = file;
Przemyslaw Skibinskia1f60632016-11-29 15:50:28 +0100467 if (state.state->mode != GZ_READ && state.state->mode != GZ_WRITE)
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100468 return -1;
469
470 /* return position */
Przemyslaw Skibinskia1f60632016-11-29 15:50:28 +0100471 return state.state->x.pos + (state.state->seek ? state.state->skip : 0);
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100472}
473
474/* -- see zlib.h -- */
475z_off_t ZEXPORT gztell(file)
476 gzFile file;
477{
478 z_off64_t ret;
479
480 ret = gztell64(file);
481 return ret == (z_off_t)ret ? (z_off_t)ret : -1;
482}
483
484/* -- see zlib.h -- */
485z_off64_t ZEXPORT gzoffset64(file)
486 gzFile file;
487{
488 z_off64_t offset;
489 gz_statep state;
490
491 /* get internal structure and check integrity */
492 if (file == NULL)
493 return -1;
Yann Colletcb18fff2019-09-24 17:50:58 -0700494 state.file = file;
Przemyslaw Skibinskia1f60632016-11-29 15:50:28 +0100495 if (state.state->mode != GZ_READ && state.state->mode != GZ_WRITE)
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100496 return -1;
497
498 /* compute and return effective offset in file */
Przemyslaw Skibinskia1f60632016-11-29 15:50:28 +0100499 offset = LSEEK(state.state->fd, 0, SEEK_CUR);
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100500 if (offset == -1)
501 return -1;
Przemyslaw Skibinskia1f60632016-11-29 15:50:28 +0100502 if (state.state->mode == GZ_READ) /* reading */
503 offset -= state.state->strm.avail_in; /* don't count buffered input */
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100504 return offset;
505}
506
507/* -- see zlib.h -- */
508z_off_t ZEXPORT gzoffset(file)
509 gzFile file;
510{
511 z_off64_t ret;
512
513 ret = gzoffset64(file);
514 return ret == (z_off_t)ret ? (z_off_t)ret : -1;
515}
516
517/* -- see zlib.h -- */
518int ZEXPORT gzeof(file)
519 gzFile file;
520{
521 gz_statep state;
522
523 /* get internal structure and check integrity */
524 if (file == NULL)
525 return 0;
Yann Colletcb18fff2019-09-24 17:50:58 -0700526 state.file = file;
Przemyslaw Skibinskia1f60632016-11-29 15:50:28 +0100527 if (state.state->mode != GZ_READ && state.state->mode != GZ_WRITE)
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100528 return 0;
529
530 /* return end-of-file state */
Przemyslaw Skibinskia1f60632016-11-29 15:50:28 +0100531 return state.state->mode == GZ_READ ? state.state->past : 0;
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100532}
533
534/* -- see zlib.h -- */
535const char * ZEXPORT gzerror(file, errnum)
536 gzFile file;
537 int *errnum;
538{
539 gz_statep state;
540
541 /* get internal structure and check integrity */
542 if (file == NULL)
543 return NULL;
Yann Colletcb18fff2019-09-24 17:50:58 -0700544 state.file = file;
Przemyslaw Skibinskia1f60632016-11-29 15:50:28 +0100545 if (state.state->mode != GZ_READ && state.state->mode != GZ_WRITE)
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100546 return NULL;
547
548 /* return error information */
549 if (errnum != NULL)
Przemyslaw Skibinskia1f60632016-11-29 15:50:28 +0100550 *errnum = state.state->err;
551 return state.state->err == Z_MEM_ERROR ? "out of memory" :
552 (state.state->msg == NULL ? "" : state.state->msg);
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100553}
554
555/* -- see zlib.h -- */
556void ZEXPORT gzclearerr(file)
557 gzFile file;
558{
559 gz_statep state;
560
561 /* get internal structure and check integrity */
562 if (file == NULL)
563 return;
Yann Colletcb18fff2019-09-24 17:50:58 -0700564 state.file = file;
Przemyslaw Skibinskia1f60632016-11-29 15:50:28 +0100565 if (state.state->mode != GZ_READ && state.state->mode != GZ_WRITE)
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100566 return;
567
568 /* clear error and end-of-file */
Przemyslaw Skibinskia1f60632016-11-29 15:50:28 +0100569 if (state.state->mode == GZ_READ) {
570 state.state->eof = 0;
571 state.state->past = 0;
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100572 }
573 gz_error(state, Z_OK, NULL);
574}
575
Przemyslaw Skibinski7f82aad2017-01-18 12:08:08 +0100576/* Create an error message in allocated memory and set state.state->err and
577 state.state->msg accordingly. Free any previous error message already there. Do
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100578 not try to free or allocate space if the error is Z_MEM_ERROR (out of
579 memory). Simply save the error message as a static string. If there is an
580 allocation failure constructing the error message, then convert the error to
581 out of memory. */
582void ZLIB_INTERNAL gz_error(state, err, msg)
583 gz_statep state;
584 int err;
585 const char *msg;
586{
587 /* free previously allocated message and clear */
Przemyslaw Skibinskia1f60632016-11-29 15:50:28 +0100588 if (state.state->msg != NULL) {
589 if (state.state->err != Z_MEM_ERROR)
590 free(state.state->msg);
591 state.state->msg = NULL;
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100592 }
593
Przemyslaw Skibinski7f82aad2017-01-18 12:08:08 +0100594 /* if fatal, set state.state->x.have to 0 so that the gzgetc() macro fails */
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100595 if (err != Z_OK && err != Z_BUF_ERROR)
Przemyslaw Skibinskia1f60632016-11-29 15:50:28 +0100596 state.state->x.have = 0;
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100597
598 /* set error code, and if no message, then done */
Przemyslaw Skibinskia1f60632016-11-29 15:50:28 +0100599 state.state->err = err;
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100600 if (msg == NULL)
601 return;
602
603 /* for an out of memory error, return literal string when requested */
604 if (err == Z_MEM_ERROR)
605 return;
606
607 /* construct error message with path */
Przemyslaw Skibinskia1f60632016-11-29 15:50:28 +0100608 if ((state.state->msg = (char *)malloc(strlen(state.state->path) + strlen(msg) + 3)) ==
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100609 NULL) {
Przemyslaw Skibinskia1f60632016-11-29 15:50:28 +0100610 state.state->err = Z_MEM_ERROR;
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100611 return;
612 }
613#if !defined(NO_snprintf) && !defined(NO_vsnprintf)
Przemyslaw Skibinski7f82aad2017-01-18 12:08:08 +0100614 (void)snprintf(state.state->msg, strlen(state.state->path) + strlen(msg) + 3,
615 "%s%s%s", state.state->path, ": ", msg);
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100616#else
Przemyslaw Skibinskia1f60632016-11-29 15:50:28 +0100617 strcpy(state.state->msg, state.state->path);
618 strcat(state.state->msg, ": ");
619 strcat(state.state->msg, msg);
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100620#endif
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100621}
622
623#ifndef INT_MAX
624/* portably return maximum value for an int (when limits.h presumed not
625 available) -- we need to do this to cover cases where 2's complement not
626 used, since C standard permits 1's complement and sign-bit representations,
627 otherwise we could just use ((unsigned)-1) >> 1 */
628unsigned ZLIB_INTERNAL gz_intmax()
629{
630 unsigned p, q;
631
632 p = 1;
633 do {
634 q = p;
635 p <<= 1;
636 p++;
637 } while (p > q);
638 return q >> 1;
639}
640#endif