blob: c726515113c328a7b3a85a8213f5998bc207067c [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
Danielle Rozenblit4dffc352022-12-14 06:58:35 -08006 * 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 */
orbea1e09cff2022-07-29 12:22:10 -070022local 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. */
Ed Maste2ce02902023-12-13 19:54:29 -050036char ZLIB_INTERNAL *gz_strwinerror(DWORD error) {
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +010037 static char buf[1024];
38
39 wchar_t *msgbuf;
40 DWORD lasterr = GetLastError();
41 DWORD chars = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM
42 | FORMAT_MESSAGE_ALLOCATE_BUFFER,
43 NULL,
44 error,
45 0, /* Default language */
46 (LPVOID)&msgbuf,
47 0,
48 NULL);
49 if (chars != 0) {
50 /* If there is an \r\n appended, zap it. */
51 if (chars >= 2
52 && msgbuf[chars - 2] == '\r' && msgbuf[chars - 1] == '\n') {
53 chars -= 2;
54 msgbuf[chars] = 0;
55 }
56
57 if (chars > sizeof (buf) - 1) {
58 chars = sizeof (buf) - 1;
59 msgbuf[chars] = 0;
60 }
61
62 wcstombs(buf, msgbuf, chars + 1);
63 LocalFree(msgbuf);
64 }
65 else {
66 sprintf(buf, "unknown win32 error (%ld)", error);
67 }
68
69 SetLastError(lasterr);
70 return buf;
71}
72
73#endif /* UNDER_CE */
74
75/* Reset gzip file state */
Ed Maste2ce02902023-12-13 19:54:29 -050076local void gz_reset(gz_statep state) {
Przemyslaw Skibinskia1f60632016-11-29 15:50:28 +010077 state.state->x.have = 0; /* no output data available */
78 if (state.state->mode == GZ_READ) { /* for reading ... */
79 state.state->eof = 0; /* not at end of file */
80 state.state->past = 0; /* have not read past end yet */
81 state.state->how = LOOK; /* look for gzip header */
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +010082 }
Przemyslaw Skibinskia1f60632016-11-29 15:50:28 +010083 state.state->seek = 0; /* no seek request pending */
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +010084 gz_error(state, Z_OK, NULL); /* clear error */
Przemyslaw Skibinskia1f60632016-11-29 15:50:28 +010085 state.state->x.pos = 0; /* no uncompressed data yet */
86 state.state->strm.avail_in = 0; /* no input data yet */
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +010087}
88
89/* Open a gzip file either by name or file descriptor. */
Ed Maste2ce02902023-12-13 19:54:29 -050090local gzFile gz_open(const void *path, int fd, const char *mode) {
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +010091 gz_statep state;
Przemyslaw Skibinski7f82aad2017-01-18 12:08:08 +010092 z_size_t len;
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +010093 int oflag;
94#ifdef O_CLOEXEC
95 int cloexec = 0;
96#endif
97#ifdef O_EXCL
98 int exclusive = 0;
99#endif
100
101 /* check input */
102 if (path == NULL)
103 return NULL;
104
105 /* allocate gzFile structure to return */
Yann Colletda558652018-08-15 16:43:13 -0700106 state.state = (gz_state*)malloc(sizeof(gz_state));
Przemyslaw Skibinskia1f60632016-11-29 15:50:28 +0100107 if (state.state == NULL)
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100108 return NULL;
Przemyslaw Skibinskia1f60632016-11-29 15:50:28 +0100109 state.state->size = 0; /* no buffers allocated yet */
110 state.state->want = GZBUFSIZE; /* requested buffer size */
111 state.state->msg = NULL; /* no error message yet */
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100112
113 /* interpret mode */
Przemyslaw Skibinskia1f60632016-11-29 15:50:28 +0100114 state.state->mode = GZ_NONE;
115 state.state->level = Z_DEFAULT_COMPRESSION;
116 state.state->strategy = Z_DEFAULT_STRATEGY;
117 state.state->direct = 0;
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100118 while (*mode) {
119 if (*mode >= '0' && *mode <= '9')
Przemyslaw Skibinskia1f60632016-11-29 15:50:28 +0100120 state.state->level = *mode - '0';
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100121 else
122 switch (*mode) {
123 case 'r':
Przemyslaw Skibinskia1f60632016-11-29 15:50:28 +0100124 state.state->mode = GZ_READ;
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100125 break;
126#ifndef NO_GZCOMPRESS
127 case 'w':
Przemyslaw Skibinskia1f60632016-11-29 15:50:28 +0100128 state.state->mode = GZ_WRITE;
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100129 break;
130 case 'a':
Przemyslaw Skibinskia1f60632016-11-29 15:50:28 +0100131 state.state->mode = GZ_APPEND;
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100132 break;
133#endif
134 case '+': /* can't read and write at the same time */
Przemyslaw Skibinskia1f60632016-11-29 15:50:28 +0100135 free(state.state);
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100136 return NULL;
137 case 'b': /* ignore -- will request binary anyway */
138 break;
139#ifdef O_CLOEXEC
140 case 'e':
141 cloexec = 1;
142 break;
143#endif
144#ifdef O_EXCL
145 case 'x':
146 exclusive = 1;
147 break;
148#endif
149 case 'f':
Przemyslaw Skibinskia1f60632016-11-29 15:50:28 +0100150 state.state->strategy = Z_FILTERED;
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100151 break;
152 case 'h':
Przemyslaw Skibinskia1f60632016-11-29 15:50:28 +0100153 state.state->strategy = Z_HUFFMAN_ONLY;
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100154 break;
155 case 'R':
Przemyslaw Skibinskia1f60632016-11-29 15:50:28 +0100156 state.state->strategy = Z_RLE;
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100157 break;
158 case 'F':
Przemyslaw Skibinskia1f60632016-11-29 15:50:28 +0100159 state.state->strategy = Z_FIXED;
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100160 break;
161 case 'T':
Przemyslaw Skibinskia1f60632016-11-29 15:50:28 +0100162 state.state->direct = 1;
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100163 break;
164 default: /* could consider as an error, but just ignore */
165 ;
166 }
167 mode++;
168 }
169
170 /* must provide an "r", "w", or "a" */
Przemyslaw Skibinskia1f60632016-11-29 15:50:28 +0100171 if (state.state->mode == GZ_NONE) {
172 free(state.state);
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100173 return NULL;
174 }
175
176 /* can't force transparent read */
Przemyslaw Skibinskia1f60632016-11-29 15:50:28 +0100177 if (state.state->mode == GZ_READ) {
178 if (state.state->direct) {
179 free(state.state);
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100180 return NULL;
181 }
Przemyslaw Skibinskia1f60632016-11-29 15:50:28 +0100182 state.state->direct = 1; /* for empty file */
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100183 }
184
185 /* save the path name for error messages */
Przemyslaw Skibinski7f82aad2017-01-18 12:08:08 +0100186#ifdef WIDECHAR
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100187 if (fd == -2) {
188 len = wcstombs(NULL, path, 0);
Przemyslaw Skibinski7f82aad2017-01-18 12:08:08 +0100189 if (len == (z_size_t)-1)
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100190 len = 0;
191 }
192 else
193#endif
194 len = strlen((const char *)path);
Przemyslaw Skibinskia1f60632016-11-29 15:50:28 +0100195 state.state->path = (char *)malloc(len + 1);
196 if (state.state->path == NULL) {
197 free(state.state);
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100198 return NULL;
199 }
Przemyslaw Skibinski7f82aad2017-01-18 12:08:08 +0100200#ifdef WIDECHAR
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100201 if (fd == -2)
202 if (len)
Przemyslaw Skibinskia1f60632016-11-29 15:50:28 +0100203 wcstombs(state.state->path, path, len + 1);
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100204 else
Przemyslaw Skibinskia1f60632016-11-29 15:50:28 +0100205 *(state.state->path) = 0;
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100206 else
207#endif
208#if !defined(NO_snprintf) && !defined(NO_vsnprintf)
Przemyslaw Skibinski7f82aad2017-01-18 12:08:08 +0100209 (void)snprintf(state.state->path, len + 1, "%s", (const char *)path);
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100210#else
Yann Colletc69ed0f2019-10-02 17:32:19 -0700211 strcpy(state.state->path, (const char*)path);
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100212#endif
213
214 /* compute the flags for open() */
215 oflag =
216#ifdef O_LARGEFILE
217 O_LARGEFILE |
218#endif
219#ifdef O_BINARY
220 O_BINARY |
221#endif
222#ifdef O_CLOEXEC
223 (cloexec ? O_CLOEXEC : 0) |
224#endif
Przemyslaw Skibinskia1f60632016-11-29 15:50:28 +0100225 (state.state->mode == GZ_READ ?
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100226 O_RDONLY :
227 (O_WRONLY | O_CREAT |
228#ifdef O_EXCL
229 (exclusive ? O_EXCL : 0) |
230#endif
Przemyslaw Skibinskia1f60632016-11-29 15:50:28 +0100231 (state.state->mode == GZ_WRITE ?
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100232 O_TRUNC :
233 O_APPEND)));
234
235 /* open the file with the appropriate flags (or just use fd) */
Przemyslaw Skibinskia1f60632016-11-29 15:50:28 +0100236 state.state->fd = fd > -1 ? fd : (
Przemyslaw Skibinski7f82aad2017-01-18 12:08:08 +0100237#ifdef WIDECHAR
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100238 fd == -2 ? _wopen(path, oflag, 0666) :
239#endif
240 open((const char *)path, oflag, 0666));
Przemyslaw Skibinskia1f60632016-11-29 15:50:28 +0100241 if (state.state->fd == -1) {
242 free(state.state->path);
243 free(state.state);
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100244 return NULL;
245 }
Przemyslaw Skibinski7f82aad2017-01-18 12:08:08 +0100246 if (state.state->mode == GZ_APPEND) {
247 LSEEK(state.state->fd, 0, SEEK_END); /* so gzoffset() is correct */
Przemyslaw Skibinskia1f60632016-11-29 15:50:28 +0100248 state.state->mode = GZ_WRITE; /* simplify later checks */
Przemyslaw Skibinski7f82aad2017-01-18 12:08:08 +0100249 }
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100250
251 /* save the current position for rewinding (only if reading) */
Przemyslaw Skibinskia1f60632016-11-29 15:50:28 +0100252 if (state.state->mode == GZ_READ) {
253 state.state->start = LSEEK(state.state->fd, 0, SEEK_CUR);
254 if (state.state->start == -1) state.state->start = 0;
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100255 }
256
257 /* initialize stream */
258 gz_reset(state);
259
260 /* return stream */
Yann Colletda558652018-08-15 16:43:13 -0700261 return state.file;
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100262}
263
264/* -- see zlib.h -- */
Ed Maste2ce02902023-12-13 19:54:29 -0500265gzFile ZEXPORT gzopen(const char *path, const char *mode) {
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100266 return gz_open(path, -1, mode);
267}
268
269/* -- see zlib.h -- */
Ed Maste2ce02902023-12-13 19:54:29 -0500270gzFile ZEXPORT gzopen64(const char *path, const char *mode) {
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100271 return gz_open(path, -1, mode);
272}
273
274/* -- see zlib.h -- */
Ed Maste2ce02902023-12-13 19:54:29 -0500275gzFile ZEXPORT gzdopen(int fd, const char *mode) {
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100276 char *path; /* identifier for error messages */
277 gzFile gz;
278
279 if (fd == -1 || (path = (char *)malloc(7 + 3 * sizeof(int))) == NULL)
280 return NULL;
281#if !defined(NO_snprintf) && !defined(NO_vsnprintf)
Przemyslaw Skibinski7f82aad2017-01-18 12:08:08 +0100282 (void)snprintf(path, 7 + 3 * sizeof(int), "<fd:%d>", fd);
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100283#else
284 sprintf(path, "<fd:%d>", fd); /* for debugging */
285#endif
286 gz = gz_open(path, fd, mode);
287 free(path);
288 return gz;
289}
290
291/* -- see zlib.h -- */
Przemyslaw Skibinski7f82aad2017-01-18 12:08:08 +0100292#ifdef WIDECHAR
Ed Maste2ce02902023-12-13 19:54:29 -0500293gzFile ZEXPORT gzopen_w(const wchar_t *path, const char *mode) {
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100294 return gz_open(path, -2, mode);
295}
296#endif
297
298/* -- see zlib.h -- */
Ed Maste2ce02902023-12-13 19:54:29 -0500299int ZEXPORT gzbuffer(gzFile file, unsigned size) {
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100300 gz_statep state;
301
302 /* get internal structure and check integrity */
303 if (file == NULL)
304 return -1;
Yann Colletcb18fff2019-09-24 17:50:58 -0700305 state.file = file;
Przemyslaw Skibinskia1f60632016-11-29 15:50:28 +0100306 if (state.state->mode != GZ_READ && state.state->mode != GZ_WRITE)
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100307 return -1;
308
309 /* make sure we haven't already allocated memory */
Przemyslaw Skibinskia1f60632016-11-29 15:50:28 +0100310 if (state.state->size != 0)
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100311 return -1;
312
313 /* check and set requested size */
Przemyslaw Skibinski7f82aad2017-01-18 12:08:08 +0100314 if ((size << 1) < size)
315 return -1; /* need to be able to double it */
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100316 if (size < 2)
317 size = 2; /* need two bytes to check magic header */
Przemyslaw Skibinskia1f60632016-11-29 15:50:28 +0100318 state.state->want = size;
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100319 return 0;
320}
321
322/* -- see zlib.h -- */
Ed Maste2ce02902023-12-13 19:54:29 -0500323int ZEXPORT gzrewind(gzFile file) {
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100324 gz_statep state;
325
326 /* get internal structure */
327 if (file == NULL)
328 return -1;
Yann Colletcb18fff2019-09-24 17:50:58 -0700329 state.file = file;
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100330
331 /* check that we're reading and that there's no error */
Przemyslaw Skibinskia1f60632016-11-29 15:50:28 +0100332 if (state.state->mode != GZ_READ ||
333 (state.state->err != Z_OK && state.state->err != Z_BUF_ERROR))
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100334 return -1;
335
336 /* back up and start over */
Przemyslaw Skibinskia1f60632016-11-29 15:50:28 +0100337 if (LSEEK(state.state->fd, state.state->start, SEEK_SET) == -1)
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100338 return -1;
339 gz_reset(state);
340 return 0;
341}
342
343/* -- see zlib.h -- */
Ed Maste2ce02902023-12-13 19:54:29 -0500344z_off64_t ZEXPORT gzseek64(gzFile file, z_off64_t offset, int whence) {
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100345 unsigned n;
346 z_off64_t ret;
347 gz_statep state;
348
349 /* get internal structure and check integrity */
350 if (file == NULL)
351 return -1;
Yann Colletcb18fff2019-09-24 17:50:58 -0700352 state.file = file;
Przemyslaw Skibinskia1f60632016-11-29 15:50:28 +0100353 if (state.state->mode != GZ_READ && state.state->mode != GZ_WRITE)
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100354 return -1;
355
356 /* check that there's no error */
Przemyslaw Skibinskia1f60632016-11-29 15:50:28 +0100357 if (state.state->err != Z_OK && state.state->err != Z_BUF_ERROR)
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100358 return -1;
359
360 /* can only seek from start or relative to current position */
361 if (whence != SEEK_SET && whence != SEEK_CUR)
362 return -1;
363
364 /* normalize offset to a SEEK_CUR specification */
365 if (whence == SEEK_SET)
Przemyslaw Skibinskia1f60632016-11-29 15:50:28 +0100366 offset -= state.state->x.pos;
367 else if (state.state->seek)
368 offset += state.state->skip;
369 state.state->seek = 0;
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100370
371 /* if within raw area while reading, just go there */
Przemyslaw Skibinskia1f60632016-11-29 15:50:28 +0100372 if (state.state->mode == GZ_READ && state.state->how == COPY &&
373 state.state->x.pos + offset >= 0) {
374 ret = LSEEK(state.state->fd, offset - state.state->x.have, SEEK_CUR);
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100375 if (ret == -1)
376 return -1;
Przemyslaw Skibinskia1f60632016-11-29 15:50:28 +0100377 state.state->x.have = 0;
378 state.state->eof = 0;
379 state.state->past = 0;
380 state.state->seek = 0;
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100381 gz_error(state, Z_OK, NULL);
Przemyslaw Skibinskia1f60632016-11-29 15:50:28 +0100382 state.state->strm.avail_in = 0;
383 state.state->x.pos += offset;
384 return state.state->x.pos;
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100385 }
386
387 /* calculate skip amount, rewinding if needed for back seek when reading */
388 if (offset < 0) {
Przemyslaw Skibinskia1f60632016-11-29 15:50:28 +0100389 if (state.state->mode != GZ_READ) /* writing -- can't go backwards */
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100390 return -1;
Przemyslaw Skibinskia1f60632016-11-29 15:50:28 +0100391 offset += state.state->x.pos;
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100392 if (offset < 0) /* before start of file! */
393 return -1;
394 if (gzrewind(file) == -1) /* rewind, then skip to offset */
395 return -1;
396 }
397
398 /* if reading, skip what's in output buffer (one less gzgetc() check) */
Przemyslaw Skibinskia1f60632016-11-29 15:50:28 +0100399 if (state.state->mode == GZ_READ) {
400 n = GT_OFF(state.state->x.have) || (z_off64_t)state.state->x.have > offset ?
401 (unsigned)offset : state.state->x.have;
402 state.state->x.have -= n;
403 state.state->x.next += n;
404 state.state->x.pos += n;
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100405 offset -= n;
406 }
407
408 /* request skip (if not zero) */
409 if (offset) {
Przemyslaw Skibinskia1f60632016-11-29 15:50:28 +0100410 state.state->seek = 1;
411 state.state->skip = offset;
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100412 }
Przemyslaw Skibinskia1f60632016-11-29 15:50:28 +0100413 return state.state->x.pos + offset;
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100414}
415
416/* -- see zlib.h -- */
Ed Maste2ce02902023-12-13 19:54:29 -0500417z_off_t ZEXPORT gzseek(gzFile file, z_off_t offset, int whence) {
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100418 z_off64_t ret;
419
420 ret = gzseek64(file, (z_off64_t)offset, whence);
421 return ret == (z_off_t)ret ? (z_off_t)ret : -1;
422}
423
424/* -- see zlib.h -- */
Ed Maste2ce02902023-12-13 19:54:29 -0500425z_off64_t ZEXPORT gztell64(gzFile file) {
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100426 gz_statep state;
427
428 /* get internal structure and check integrity */
429 if (file == NULL)
430 return -1;
Yann Colletcb18fff2019-09-24 17:50:58 -0700431 state.file = file;
Przemyslaw Skibinskia1f60632016-11-29 15:50:28 +0100432 if (state.state->mode != GZ_READ && state.state->mode != GZ_WRITE)
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100433 return -1;
434
435 /* return position */
Przemyslaw Skibinskia1f60632016-11-29 15:50:28 +0100436 return state.state->x.pos + (state.state->seek ? state.state->skip : 0);
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100437}
438
439/* -- see zlib.h -- */
Ed Maste2ce02902023-12-13 19:54:29 -0500440z_off_t ZEXPORT gztell(gzFile file) {
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100441 z_off64_t ret;
442
443 ret = gztell64(file);
444 return ret == (z_off_t)ret ? (z_off_t)ret : -1;
445}
446
447/* -- see zlib.h -- */
Ed Maste2ce02902023-12-13 19:54:29 -0500448z_off64_t ZEXPORT gzoffset64(gzFile file) {
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100449 z_off64_t offset;
450 gz_statep state;
451
452 /* get internal structure and check integrity */
453 if (file == NULL)
454 return -1;
Yann Colletcb18fff2019-09-24 17:50:58 -0700455 state.file = file;
Przemyslaw Skibinskia1f60632016-11-29 15:50:28 +0100456 if (state.state->mode != GZ_READ && state.state->mode != GZ_WRITE)
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100457 return -1;
458
459 /* compute and return effective offset in file */
Przemyslaw Skibinskia1f60632016-11-29 15:50:28 +0100460 offset = LSEEK(state.state->fd, 0, SEEK_CUR);
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100461 if (offset == -1)
462 return -1;
Przemyslaw Skibinskia1f60632016-11-29 15:50:28 +0100463 if (state.state->mode == GZ_READ) /* reading */
464 offset -= state.state->strm.avail_in; /* don't count buffered input */
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100465 return offset;
466}
467
468/* -- see zlib.h -- */
Ed Maste2ce02902023-12-13 19:54:29 -0500469z_off_t ZEXPORT gzoffset(gzFile file) {
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100470 z_off64_t ret;
471
472 ret = gzoffset64(file);
473 return ret == (z_off_t)ret ? (z_off_t)ret : -1;
474}
475
476/* -- see zlib.h -- */
Ed Maste2ce02902023-12-13 19:54:29 -0500477int ZEXPORT gzeof(gzFile file) {
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100478 gz_statep state;
479
480 /* get internal structure and check integrity */
481 if (file == NULL)
482 return 0;
Yann Colletcb18fff2019-09-24 17:50:58 -0700483 state.file = file;
Przemyslaw Skibinskia1f60632016-11-29 15:50:28 +0100484 if (state.state->mode != GZ_READ && state.state->mode != GZ_WRITE)
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100485 return 0;
486
487 /* return end-of-file state */
Przemyslaw Skibinskia1f60632016-11-29 15:50:28 +0100488 return state.state->mode == GZ_READ ? state.state->past : 0;
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100489}
490
491/* -- see zlib.h -- */
Ed Maste2ce02902023-12-13 19:54:29 -0500492const char * ZEXPORT gzerror(gzFile file, int *errnum) {
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100493 gz_statep state;
494
495 /* get internal structure and check integrity */
496 if (file == NULL)
497 return NULL;
Yann Colletcb18fff2019-09-24 17:50:58 -0700498 state.file = file;
Przemyslaw Skibinskia1f60632016-11-29 15:50:28 +0100499 if (state.state->mode != GZ_READ && state.state->mode != GZ_WRITE)
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100500 return NULL;
501
502 /* return error information */
503 if (errnum != NULL)
Przemyslaw Skibinskia1f60632016-11-29 15:50:28 +0100504 *errnum = state.state->err;
505 return state.state->err == Z_MEM_ERROR ? "out of memory" :
506 (state.state->msg == NULL ? "" : state.state->msg);
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100507}
508
509/* -- see zlib.h -- */
Ed Maste2ce02902023-12-13 19:54:29 -0500510void ZEXPORT gzclearerr(gzFile file) {
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100511 gz_statep state;
512
513 /* get internal structure and check integrity */
514 if (file == NULL)
515 return;
Yann Colletcb18fff2019-09-24 17:50:58 -0700516 state.file = file;
Przemyslaw Skibinskia1f60632016-11-29 15:50:28 +0100517 if (state.state->mode != GZ_READ && state.state->mode != GZ_WRITE)
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100518 return;
519
520 /* clear error and end-of-file */
Przemyslaw Skibinskia1f60632016-11-29 15:50:28 +0100521 if (state.state->mode == GZ_READ) {
522 state.state->eof = 0;
523 state.state->past = 0;
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100524 }
525 gz_error(state, Z_OK, NULL);
526}
527
Przemyslaw Skibinski7f82aad2017-01-18 12:08:08 +0100528/* Create an error message in allocated memory and set state.state->err and
529 state.state->msg accordingly. Free any previous error message already there. Do
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100530 not try to free or allocate space if the error is Z_MEM_ERROR (out of
531 memory). Simply save the error message as a static string. If there is an
532 allocation failure constructing the error message, then convert the error to
533 out of memory. */
Ed Maste2ce02902023-12-13 19:54:29 -0500534void ZLIB_INTERNAL gz_error(gz_statep state, int err, const char *msg) {
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100535 /* free previously allocated message and clear */
Przemyslaw Skibinskia1f60632016-11-29 15:50:28 +0100536 if (state.state->msg != NULL) {
537 if (state.state->err != Z_MEM_ERROR)
538 free(state.state->msg);
539 state.state->msg = NULL;
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100540 }
541
Przemyslaw Skibinski7f82aad2017-01-18 12:08:08 +0100542 /* if fatal, set state.state->x.have to 0 so that the gzgetc() macro fails */
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100543 if (err != Z_OK && err != Z_BUF_ERROR)
Przemyslaw Skibinskia1f60632016-11-29 15:50:28 +0100544 state.state->x.have = 0;
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100545
546 /* set error code, and if no message, then done */
Przemyslaw Skibinskia1f60632016-11-29 15:50:28 +0100547 state.state->err = err;
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100548 if (msg == NULL)
549 return;
550
551 /* for an out of memory error, return literal string when requested */
552 if (err == Z_MEM_ERROR)
553 return;
554
555 /* construct error message with path */
Przemyslaw Skibinskia1f60632016-11-29 15:50:28 +0100556 if ((state.state->msg = (char *)malloc(strlen(state.state->path) + strlen(msg) + 3)) ==
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100557 NULL) {
Przemyslaw Skibinskia1f60632016-11-29 15:50:28 +0100558 state.state->err = Z_MEM_ERROR;
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100559 return;
560 }
561#if !defined(NO_snprintf) && !defined(NO_vsnprintf)
Przemyslaw Skibinski7f82aad2017-01-18 12:08:08 +0100562 (void)snprintf(state.state->msg, strlen(state.state->path) + strlen(msg) + 3,
563 "%s%s%s", state.state->path, ": ", msg);
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100564#else
Przemyslaw Skibinskia1f60632016-11-29 15:50:28 +0100565 strcpy(state.state->msg, state.state->path);
566 strcat(state.state->msg, ": ");
567 strcat(state.state->msg, msg);
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100568#endif
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100569}
570
571#ifndef INT_MAX
572/* portably return maximum value for an int (when limits.h presumed not
573 available) -- we need to do this to cover cases where 2's complement not
574 used, since C standard permits 1's complement and sign-bit representations,
575 otherwise we could just use ((unsigned)-1) >> 1 */
Ed Maste2ce02902023-12-13 19:54:29 -0500576unsigned ZLIB_INTERNAL gz_intmax() {
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100577 unsigned p, q;
578
579 p = 1;
580 do {
581 q = p;
582 p <<= 1;
583 p++;
584 } while (p > q);
585 return q >> 1;
586}
587#endif