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