xref: /freebsd/sys/contrib/zlib/gzlib.c (revision 6255c67c3d1a268535c50de74d3300fd86d8f15d)
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