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