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