xref: /aosp_15_r20/external/libwebsockets/win32port/zlib/gzlib.c (revision 1c60b9aca93fdbc9b5f19b2d2194c91294b22281)
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