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