1*86ee64e7SAndroid Build Coastguard Worker /* gzread.c -- zlib functions for reading gzip files
2*86ee64e7SAndroid Build Coastguard Worker * Copyright (C) 2004-2017 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 /* Use read() to load a buffer -- return -1 on error, otherwise 0. Read from
9*86ee64e7SAndroid Build Coastguard Worker state->fd, and update state->eof, state->err, and state->msg as appropriate.
10*86ee64e7SAndroid Build Coastguard Worker This function needs to loop on read(), since read() is not guaranteed to
11*86ee64e7SAndroid Build Coastguard Worker read the number of bytes requested, depending on the type of descriptor. */
gz_load(gz_statep state,unsigned char * buf,unsigned len,unsigned * have)12*86ee64e7SAndroid Build Coastguard Worker local int gz_load(gz_statep state, unsigned char *buf, unsigned len,
13*86ee64e7SAndroid Build Coastguard Worker unsigned *have) {
14*86ee64e7SAndroid Build Coastguard Worker int ret;
15*86ee64e7SAndroid Build Coastguard Worker unsigned get, max = ((unsigned)-1 >> 2) + 1;
16*86ee64e7SAndroid Build Coastguard Worker
17*86ee64e7SAndroid Build Coastguard Worker *have = 0;
18*86ee64e7SAndroid Build Coastguard Worker do {
19*86ee64e7SAndroid Build Coastguard Worker get = len - *have;
20*86ee64e7SAndroid Build Coastguard Worker if (get > max)
21*86ee64e7SAndroid Build Coastguard Worker get = max;
22*86ee64e7SAndroid Build Coastguard Worker ret = read(state->fd, buf + *have, get);
23*86ee64e7SAndroid Build Coastguard Worker if (ret <= 0)
24*86ee64e7SAndroid Build Coastguard Worker break;
25*86ee64e7SAndroid Build Coastguard Worker *have += (unsigned)ret;
26*86ee64e7SAndroid Build Coastguard Worker } while (*have < len);
27*86ee64e7SAndroid Build Coastguard Worker if (ret < 0) {
28*86ee64e7SAndroid Build Coastguard Worker gz_error(state, Z_ERRNO, zstrerror());
29*86ee64e7SAndroid Build Coastguard Worker return -1;
30*86ee64e7SAndroid Build Coastguard Worker }
31*86ee64e7SAndroid Build Coastguard Worker if (ret == 0)
32*86ee64e7SAndroid Build Coastguard Worker state->eof = 1;
33*86ee64e7SAndroid Build Coastguard Worker return 0;
34*86ee64e7SAndroid Build Coastguard Worker }
35*86ee64e7SAndroid Build Coastguard Worker
36*86ee64e7SAndroid Build Coastguard Worker /* Load up input buffer and set eof flag if last data loaded -- return -1 on
37*86ee64e7SAndroid Build Coastguard Worker error, 0 otherwise. Note that the eof flag is set when the end of the input
38*86ee64e7SAndroid Build Coastguard Worker file is reached, even though there may be unused data in the buffer. Once
39*86ee64e7SAndroid Build Coastguard Worker that data has been used, no more attempts will be made to read the file.
40*86ee64e7SAndroid Build Coastguard Worker If strm->avail_in != 0, then the current data is moved to the beginning of
41*86ee64e7SAndroid Build Coastguard Worker the input buffer, and then the remainder of the buffer is loaded with the
42*86ee64e7SAndroid Build Coastguard Worker available data from the input file. */
gz_avail(gz_statep state)43*86ee64e7SAndroid Build Coastguard Worker local int gz_avail(gz_statep state) {
44*86ee64e7SAndroid Build Coastguard Worker unsigned got;
45*86ee64e7SAndroid Build Coastguard Worker z_streamp strm = &(state->strm);
46*86ee64e7SAndroid Build Coastguard Worker
47*86ee64e7SAndroid Build Coastguard Worker if (state->err != Z_OK && state->err != Z_BUF_ERROR)
48*86ee64e7SAndroid Build Coastguard Worker return -1;
49*86ee64e7SAndroid Build Coastguard Worker if (state->eof == 0) {
50*86ee64e7SAndroid Build Coastguard Worker if (strm->avail_in) { /* copy what's there to the start */
51*86ee64e7SAndroid Build Coastguard Worker unsigned char *p = state->in;
52*86ee64e7SAndroid Build Coastguard Worker unsigned const char *q = strm->next_in;
53*86ee64e7SAndroid Build Coastguard Worker unsigned n = strm->avail_in;
54*86ee64e7SAndroid Build Coastguard Worker do {
55*86ee64e7SAndroid Build Coastguard Worker *p++ = *q++;
56*86ee64e7SAndroid Build Coastguard Worker } while (--n);
57*86ee64e7SAndroid Build Coastguard Worker }
58*86ee64e7SAndroid Build Coastguard Worker if (gz_load(state, state->in + strm->avail_in,
59*86ee64e7SAndroid Build Coastguard Worker state->size - strm->avail_in, &got) == -1)
60*86ee64e7SAndroid Build Coastguard Worker return -1;
61*86ee64e7SAndroid Build Coastguard Worker strm->avail_in += got;
62*86ee64e7SAndroid Build Coastguard Worker strm->next_in = state->in;
63*86ee64e7SAndroid Build Coastguard Worker }
64*86ee64e7SAndroid Build Coastguard Worker return 0;
65*86ee64e7SAndroid Build Coastguard Worker }
66*86ee64e7SAndroid Build Coastguard Worker
67*86ee64e7SAndroid Build Coastguard Worker /* Look for gzip header, set up for inflate or copy. state->x.have must be 0.
68*86ee64e7SAndroid Build Coastguard Worker If this is the first time in, allocate required memory. state->how will be
69*86ee64e7SAndroid Build Coastguard Worker left unchanged if there is no more input data available, will be set to COPY
70*86ee64e7SAndroid Build Coastguard Worker if there is no gzip header and direct copying will be performed, or it will
71*86ee64e7SAndroid Build Coastguard Worker be set to GZIP for decompression. If direct copying, then leftover input
72*86ee64e7SAndroid Build Coastguard Worker data from the input buffer will be copied to the output buffer. In that
73*86ee64e7SAndroid Build Coastguard Worker case, all further file reads will be directly to either the output buffer or
74*86ee64e7SAndroid Build Coastguard Worker a user buffer. If decompressing, the inflate state will be initialized.
75*86ee64e7SAndroid Build Coastguard Worker gz_look() will return 0 on success or -1 on failure. */
gz_look(gz_statep state)76*86ee64e7SAndroid Build Coastguard Worker local int gz_look(gz_statep state) {
77*86ee64e7SAndroid Build Coastguard Worker z_streamp strm = &(state->strm);
78*86ee64e7SAndroid Build Coastguard Worker
79*86ee64e7SAndroid Build Coastguard Worker /* allocate read buffers and inflate memory */
80*86ee64e7SAndroid Build Coastguard Worker if (state->size == 0) {
81*86ee64e7SAndroid Build Coastguard Worker /* allocate buffers */
82*86ee64e7SAndroid Build Coastguard Worker state->in = (unsigned char *)malloc(state->want);
83*86ee64e7SAndroid Build Coastguard Worker state->out = (unsigned char *)malloc(state->want << 1);
84*86ee64e7SAndroid Build Coastguard Worker if (state->in == NULL || state->out == NULL) {
85*86ee64e7SAndroid Build Coastguard Worker free(state->out);
86*86ee64e7SAndroid Build Coastguard Worker free(state->in);
87*86ee64e7SAndroid Build Coastguard Worker gz_error(state, Z_MEM_ERROR, "out of memory");
88*86ee64e7SAndroid Build Coastguard Worker return -1;
89*86ee64e7SAndroid Build Coastguard Worker }
90*86ee64e7SAndroid Build Coastguard Worker state->size = state->want;
91*86ee64e7SAndroid Build Coastguard Worker
92*86ee64e7SAndroid Build Coastguard Worker /* allocate inflate memory */
93*86ee64e7SAndroid Build Coastguard Worker state->strm.zalloc = Z_NULL;
94*86ee64e7SAndroid Build Coastguard Worker state->strm.zfree = Z_NULL;
95*86ee64e7SAndroid Build Coastguard Worker state->strm.opaque = Z_NULL;
96*86ee64e7SAndroid Build Coastguard Worker state->strm.avail_in = 0;
97*86ee64e7SAndroid Build Coastguard Worker state->strm.next_in = Z_NULL;
98*86ee64e7SAndroid Build Coastguard Worker if (inflateInit2(&(state->strm), 15 + 16) != Z_OK) { /* gunzip */
99*86ee64e7SAndroid Build Coastguard Worker free(state->out);
100*86ee64e7SAndroid Build Coastguard Worker free(state->in);
101*86ee64e7SAndroid Build Coastguard Worker state->size = 0;
102*86ee64e7SAndroid Build Coastguard Worker gz_error(state, Z_MEM_ERROR, "out of memory");
103*86ee64e7SAndroid Build Coastguard Worker return -1;
104*86ee64e7SAndroid Build Coastguard Worker }
105*86ee64e7SAndroid Build Coastguard Worker }
106*86ee64e7SAndroid Build Coastguard Worker
107*86ee64e7SAndroid Build Coastguard Worker /* get at least the magic bytes in the input buffer */
108*86ee64e7SAndroid Build Coastguard Worker if (strm->avail_in < 2) {
109*86ee64e7SAndroid Build Coastguard Worker if (gz_avail(state) == -1)
110*86ee64e7SAndroid Build Coastguard Worker return -1;
111*86ee64e7SAndroid Build Coastguard Worker if (strm->avail_in == 0)
112*86ee64e7SAndroid Build Coastguard Worker return 0;
113*86ee64e7SAndroid Build Coastguard Worker }
114*86ee64e7SAndroid Build Coastguard Worker
115*86ee64e7SAndroid Build Coastguard Worker /* look for gzip magic bytes -- if there, do gzip decoding (note: there is
116*86ee64e7SAndroid Build Coastguard Worker a logical dilemma here when considering the case of a partially written
117*86ee64e7SAndroid Build Coastguard Worker gzip file, to wit, if a single 31 byte is written, then we cannot tell
118*86ee64e7SAndroid Build Coastguard Worker whether this is a single-byte file, or just a partially written gzip
119*86ee64e7SAndroid Build Coastguard Worker file -- for here we assume that if a gzip file is being written, then
120*86ee64e7SAndroid Build Coastguard Worker the header will be written in a single operation, so that reading a
121*86ee64e7SAndroid Build Coastguard Worker single byte is sufficient indication that it is not a gzip file) */
122*86ee64e7SAndroid Build Coastguard Worker if (strm->avail_in > 1 &&
123*86ee64e7SAndroid Build Coastguard Worker strm->next_in[0] == 31 && strm->next_in[1] == 139) {
124*86ee64e7SAndroid Build Coastguard Worker inflateReset(strm);
125*86ee64e7SAndroid Build Coastguard Worker state->how = GZIP;
126*86ee64e7SAndroid Build Coastguard Worker state->direct = 0;
127*86ee64e7SAndroid Build Coastguard Worker return 0;
128*86ee64e7SAndroid Build Coastguard Worker }
129*86ee64e7SAndroid Build Coastguard Worker
130*86ee64e7SAndroid Build Coastguard Worker /* no gzip header -- if we were decoding gzip before, then this is trailing
131*86ee64e7SAndroid Build Coastguard Worker garbage. Ignore the trailing garbage and finish. */
132*86ee64e7SAndroid Build Coastguard Worker if (state->direct == 0) {
133*86ee64e7SAndroid Build Coastguard Worker strm->avail_in = 0;
134*86ee64e7SAndroid Build Coastguard Worker state->eof = 1;
135*86ee64e7SAndroid Build Coastguard Worker state->x.have = 0;
136*86ee64e7SAndroid Build Coastguard Worker return 0;
137*86ee64e7SAndroid Build Coastguard Worker }
138*86ee64e7SAndroid Build Coastguard Worker
139*86ee64e7SAndroid Build Coastguard Worker /* doing raw i/o, copy any leftover input to output -- this assumes that
140*86ee64e7SAndroid Build Coastguard Worker the output buffer is larger than the input buffer, which also assures
141*86ee64e7SAndroid Build Coastguard Worker space for gzungetc() */
142*86ee64e7SAndroid Build Coastguard Worker state->x.next = state->out;
143*86ee64e7SAndroid Build Coastguard Worker memcpy(state->x.next, strm->next_in, strm->avail_in);
144*86ee64e7SAndroid Build Coastguard Worker state->x.have = strm->avail_in;
145*86ee64e7SAndroid Build Coastguard Worker strm->avail_in = 0;
146*86ee64e7SAndroid Build Coastguard Worker state->how = COPY;
147*86ee64e7SAndroid Build Coastguard Worker state->direct = 1;
148*86ee64e7SAndroid Build Coastguard Worker return 0;
149*86ee64e7SAndroid Build Coastguard Worker }
150*86ee64e7SAndroid Build Coastguard Worker
151*86ee64e7SAndroid Build Coastguard Worker /* Decompress from input to the provided next_out and avail_out in the state.
152*86ee64e7SAndroid Build Coastguard Worker On return, state->x.have and state->x.next point to the just decompressed
153*86ee64e7SAndroid Build Coastguard Worker data. If the gzip stream completes, state->how is reset to LOOK to look for
154*86ee64e7SAndroid Build Coastguard Worker the next gzip stream or raw data, once state->x.have is depleted. Returns 0
155*86ee64e7SAndroid Build Coastguard Worker on success, -1 on failure. */
gz_decomp(gz_statep state)156*86ee64e7SAndroid Build Coastguard Worker local int gz_decomp(gz_statep state) {
157*86ee64e7SAndroid Build Coastguard Worker int ret = Z_OK;
158*86ee64e7SAndroid Build Coastguard Worker unsigned had;
159*86ee64e7SAndroid Build Coastguard Worker z_streamp strm = &(state->strm);
160*86ee64e7SAndroid Build Coastguard Worker
161*86ee64e7SAndroid Build Coastguard Worker /* fill output buffer up to end of deflate stream */
162*86ee64e7SAndroid Build Coastguard Worker had = strm->avail_out;
163*86ee64e7SAndroid Build Coastguard Worker do {
164*86ee64e7SAndroid Build Coastguard Worker /* get more input for inflate() */
165*86ee64e7SAndroid Build Coastguard Worker if (strm->avail_in == 0 && gz_avail(state) == -1)
166*86ee64e7SAndroid Build Coastguard Worker return -1;
167*86ee64e7SAndroid Build Coastguard Worker if (strm->avail_in == 0) {
168*86ee64e7SAndroid Build Coastguard Worker gz_error(state, Z_BUF_ERROR, "unexpected end of file");
169*86ee64e7SAndroid Build Coastguard Worker break;
170*86ee64e7SAndroid Build Coastguard Worker }
171*86ee64e7SAndroid Build Coastguard Worker
172*86ee64e7SAndroid Build Coastguard Worker /* decompress and handle errors */
173*86ee64e7SAndroid Build Coastguard Worker ret = inflate(strm, Z_NO_FLUSH);
174*86ee64e7SAndroid Build Coastguard Worker if (ret == Z_STREAM_ERROR || ret == Z_NEED_DICT) {
175*86ee64e7SAndroid Build Coastguard Worker gz_error(state, Z_STREAM_ERROR,
176*86ee64e7SAndroid Build Coastguard Worker "internal error: inflate stream corrupt");
177*86ee64e7SAndroid Build Coastguard Worker return -1;
178*86ee64e7SAndroid Build Coastguard Worker }
179*86ee64e7SAndroid Build Coastguard Worker if (ret == Z_MEM_ERROR) {
180*86ee64e7SAndroid Build Coastguard Worker gz_error(state, Z_MEM_ERROR, "out of memory");
181*86ee64e7SAndroid Build Coastguard Worker return -1;
182*86ee64e7SAndroid Build Coastguard Worker }
183*86ee64e7SAndroid Build Coastguard Worker if (ret == Z_DATA_ERROR) { /* deflate stream invalid */
184*86ee64e7SAndroid Build Coastguard Worker gz_error(state, Z_DATA_ERROR,
185*86ee64e7SAndroid Build Coastguard Worker strm->msg == NULL ? "compressed data error" : strm->msg);
186*86ee64e7SAndroid Build Coastguard Worker return -1;
187*86ee64e7SAndroid Build Coastguard Worker }
188*86ee64e7SAndroid Build Coastguard Worker } while (strm->avail_out && ret != Z_STREAM_END);
189*86ee64e7SAndroid Build Coastguard Worker
190*86ee64e7SAndroid Build Coastguard Worker /* update available output */
191*86ee64e7SAndroid Build Coastguard Worker state->x.have = had - strm->avail_out;
192*86ee64e7SAndroid Build Coastguard Worker state->x.next = strm->next_out - state->x.have;
193*86ee64e7SAndroid Build Coastguard Worker
194*86ee64e7SAndroid Build Coastguard Worker /* if the gzip stream completed successfully, look for another */
195*86ee64e7SAndroid Build Coastguard Worker if (ret == Z_STREAM_END)
196*86ee64e7SAndroid Build Coastguard Worker state->how = LOOK;
197*86ee64e7SAndroid Build Coastguard Worker
198*86ee64e7SAndroid Build Coastguard Worker /* good decompression */
199*86ee64e7SAndroid Build Coastguard Worker return 0;
200*86ee64e7SAndroid Build Coastguard Worker }
201*86ee64e7SAndroid Build Coastguard Worker
202*86ee64e7SAndroid Build Coastguard Worker /* Fetch data and put it in the output buffer. Assumes state->x.have is 0.
203*86ee64e7SAndroid Build Coastguard Worker Data is either copied from the input file or decompressed from the input
204*86ee64e7SAndroid Build Coastguard Worker file depending on state->how. If state->how is LOOK, then a gzip header is
205*86ee64e7SAndroid Build Coastguard Worker looked for to determine whether to copy or decompress. Returns -1 on error,
206*86ee64e7SAndroid Build Coastguard Worker otherwise 0. gz_fetch() will leave state->how as COPY or GZIP unless the
207*86ee64e7SAndroid Build Coastguard Worker end of the input file has been reached and all data has been processed. */
gz_fetch(gz_statep state)208*86ee64e7SAndroid Build Coastguard Worker local int gz_fetch(gz_statep state) {
209*86ee64e7SAndroid Build Coastguard Worker z_streamp strm = &(state->strm);
210*86ee64e7SAndroid Build Coastguard Worker
211*86ee64e7SAndroid Build Coastguard Worker do {
212*86ee64e7SAndroid Build Coastguard Worker switch(state->how) {
213*86ee64e7SAndroid Build Coastguard Worker case LOOK: /* -> LOOK, COPY (only if never GZIP), or GZIP */
214*86ee64e7SAndroid Build Coastguard Worker if (gz_look(state) == -1)
215*86ee64e7SAndroid Build Coastguard Worker return -1;
216*86ee64e7SAndroid Build Coastguard Worker if (state->how == LOOK)
217*86ee64e7SAndroid Build Coastguard Worker return 0;
218*86ee64e7SAndroid Build Coastguard Worker break;
219*86ee64e7SAndroid Build Coastguard Worker case COPY: /* -> COPY */
220*86ee64e7SAndroid Build Coastguard Worker if (gz_load(state, state->out, state->size << 1, &(state->x.have))
221*86ee64e7SAndroid Build Coastguard Worker == -1)
222*86ee64e7SAndroid Build Coastguard Worker return -1;
223*86ee64e7SAndroid Build Coastguard Worker state->x.next = state->out;
224*86ee64e7SAndroid Build Coastguard Worker return 0;
225*86ee64e7SAndroid Build Coastguard Worker case GZIP: /* -> GZIP or LOOK (if end of gzip stream) */
226*86ee64e7SAndroid Build Coastguard Worker strm->avail_out = state->size << 1;
227*86ee64e7SAndroid Build Coastguard Worker strm->next_out = state->out;
228*86ee64e7SAndroid Build Coastguard Worker if (gz_decomp(state) == -1)
229*86ee64e7SAndroid Build Coastguard Worker return -1;
230*86ee64e7SAndroid Build Coastguard Worker }
231*86ee64e7SAndroid Build Coastguard Worker } while (state->x.have == 0 && (!state->eof || strm->avail_in));
232*86ee64e7SAndroid Build Coastguard Worker return 0;
233*86ee64e7SAndroid Build Coastguard Worker }
234*86ee64e7SAndroid Build Coastguard Worker
235*86ee64e7SAndroid Build Coastguard Worker /* Skip len uncompressed bytes of output. Return -1 on error, 0 on success. */
gz_skip(gz_statep state,z_off64_t len)236*86ee64e7SAndroid Build Coastguard Worker local int gz_skip(gz_statep state, z_off64_t len) {
237*86ee64e7SAndroid Build Coastguard Worker unsigned n;
238*86ee64e7SAndroid Build Coastguard Worker
239*86ee64e7SAndroid Build Coastguard Worker /* skip over len bytes or reach end-of-file, whichever comes first */
240*86ee64e7SAndroid Build Coastguard Worker while (len)
241*86ee64e7SAndroid Build Coastguard Worker /* skip over whatever is in output buffer */
242*86ee64e7SAndroid Build Coastguard Worker if (state->x.have) {
243*86ee64e7SAndroid Build Coastguard Worker n = GT_OFF(state->x.have) || (z_off64_t)state->x.have > len ?
244*86ee64e7SAndroid Build Coastguard Worker (unsigned)len : state->x.have;
245*86ee64e7SAndroid Build Coastguard Worker state->x.have -= n;
246*86ee64e7SAndroid Build Coastguard Worker state->x.next += n;
247*86ee64e7SAndroid Build Coastguard Worker state->x.pos += n;
248*86ee64e7SAndroid Build Coastguard Worker len -= n;
249*86ee64e7SAndroid Build Coastguard Worker }
250*86ee64e7SAndroid Build Coastguard Worker
251*86ee64e7SAndroid Build Coastguard Worker /* output buffer empty -- return if we're at the end of the input */
252*86ee64e7SAndroid Build Coastguard Worker else if (state->eof && state->strm.avail_in == 0)
253*86ee64e7SAndroid Build Coastguard Worker break;
254*86ee64e7SAndroid Build Coastguard Worker
255*86ee64e7SAndroid Build Coastguard Worker /* need more data to skip -- load up output buffer */
256*86ee64e7SAndroid Build Coastguard Worker else {
257*86ee64e7SAndroid Build Coastguard Worker /* get more output, looking for header if required */
258*86ee64e7SAndroid Build Coastguard Worker if (gz_fetch(state) == -1)
259*86ee64e7SAndroid Build Coastguard Worker return -1;
260*86ee64e7SAndroid Build Coastguard Worker }
261*86ee64e7SAndroid Build Coastguard Worker return 0;
262*86ee64e7SAndroid Build Coastguard Worker }
263*86ee64e7SAndroid Build Coastguard Worker
264*86ee64e7SAndroid Build Coastguard Worker /* Read len bytes into buf from file, or less than len up to the end of the
265*86ee64e7SAndroid Build Coastguard Worker input. Return the number of bytes read. If zero is returned, either the
266*86ee64e7SAndroid Build Coastguard Worker end of file was reached, or there was an error. state->err must be
267*86ee64e7SAndroid Build Coastguard Worker consulted in that case to determine which. */
gz_read(gz_statep state,voidp buf,z_size_t len)268*86ee64e7SAndroid Build Coastguard Worker local z_size_t gz_read(gz_statep state, voidp buf, z_size_t len) {
269*86ee64e7SAndroid Build Coastguard Worker z_size_t got;
270*86ee64e7SAndroid Build Coastguard Worker unsigned n;
271*86ee64e7SAndroid Build Coastguard Worker
272*86ee64e7SAndroid Build Coastguard Worker /* if len is zero, avoid unnecessary operations */
273*86ee64e7SAndroid Build Coastguard Worker if (len == 0)
274*86ee64e7SAndroid Build Coastguard Worker return 0;
275*86ee64e7SAndroid Build Coastguard Worker
276*86ee64e7SAndroid Build Coastguard Worker /* process a skip request */
277*86ee64e7SAndroid Build Coastguard Worker if (state->seek) {
278*86ee64e7SAndroid Build Coastguard Worker state->seek = 0;
279*86ee64e7SAndroid Build Coastguard Worker if (gz_skip(state, state->skip) == -1)
280*86ee64e7SAndroid Build Coastguard Worker return 0;
281*86ee64e7SAndroid Build Coastguard Worker }
282*86ee64e7SAndroid Build Coastguard Worker
283*86ee64e7SAndroid Build Coastguard Worker /* get len bytes to buf, or less than len if at the end */
284*86ee64e7SAndroid Build Coastguard Worker got = 0;
285*86ee64e7SAndroid Build Coastguard Worker do {
286*86ee64e7SAndroid Build Coastguard Worker /* set n to the maximum amount of len that fits in an unsigned int */
287*86ee64e7SAndroid Build Coastguard Worker n = (unsigned)-1;
288*86ee64e7SAndroid Build Coastguard Worker if (n > len)
289*86ee64e7SAndroid Build Coastguard Worker n = (unsigned)len;
290*86ee64e7SAndroid Build Coastguard Worker
291*86ee64e7SAndroid Build Coastguard Worker /* first just try copying data from the output buffer */
292*86ee64e7SAndroid Build Coastguard Worker if (state->x.have) {
293*86ee64e7SAndroid Build Coastguard Worker if (state->x.have < n)
294*86ee64e7SAndroid Build Coastguard Worker n = state->x.have;
295*86ee64e7SAndroid Build Coastguard Worker memcpy(buf, state->x.next, n);
296*86ee64e7SAndroid Build Coastguard Worker state->x.next += n;
297*86ee64e7SAndroid Build Coastguard Worker state->x.have -= n;
298*86ee64e7SAndroid Build Coastguard Worker }
299*86ee64e7SAndroid Build Coastguard Worker
300*86ee64e7SAndroid Build Coastguard Worker /* output buffer empty -- return if we're at the end of the input */
301*86ee64e7SAndroid Build Coastguard Worker else if (state->eof && state->strm.avail_in == 0) {
302*86ee64e7SAndroid Build Coastguard Worker state->past = 1; /* tried to read past end */
303*86ee64e7SAndroid Build Coastguard Worker break;
304*86ee64e7SAndroid Build Coastguard Worker }
305*86ee64e7SAndroid Build Coastguard Worker
306*86ee64e7SAndroid Build Coastguard Worker /* need output data -- for small len or new stream load up our output
307*86ee64e7SAndroid Build Coastguard Worker buffer */
308*86ee64e7SAndroid Build Coastguard Worker else if (state->how == LOOK || n < (state->size << 1)) {
309*86ee64e7SAndroid Build Coastguard Worker /* get more output, looking for header if required */
310*86ee64e7SAndroid Build Coastguard Worker if (gz_fetch(state) == -1)
311*86ee64e7SAndroid Build Coastguard Worker return 0;
312*86ee64e7SAndroid Build Coastguard Worker continue; /* no progress yet -- go back to copy above */
313*86ee64e7SAndroid Build Coastguard Worker /* the copy above assures that we will leave with space in the
314*86ee64e7SAndroid Build Coastguard Worker output buffer, allowing at least one gzungetc() to succeed */
315*86ee64e7SAndroid Build Coastguard Worker }
316*86ee64e7SAndroid Build Coastguard Worker
317*86ee64e7SAndroid Build Coastguard Worker /* large len -- read directly into user buffer */
318*86ee64e7SAndroid Build Coastguard Worker else if (state->how == COPY) { /* read directly */
319*86ee64e7SAndroid Build Coastguard Worker if (gz_load(state, (unsigned char *)buf, n, &n) == -1)
320*86ee64e7SAndroid Build Coastguard Worker return 0;
321*86ee64e7SAndroid Build Coastguard Worker }
322*86ee64e7SAndroid Build Coastguard Worker
323*86ee64e7SAndroid Build Coastguard Worker /* large len -- decompress directly into user buffer */
324*86ee64e7SAndroid Build Coastguard Worker else { /* state->how == GZIP */
325*86ee64e7SAndroid Build Coastguard Worker state->strm.avail_out = n;
326*86ee64e7SAndroid Build Coastguard Worker state->strm.next_out = (unsigned char *)buf;
327*86ee64e7SAndroid Build Coastguard Worker if (gz_decomp(state) == -1)
328*86ee64e7SAndroid Build Coastguard Worker return 0;
329*86ee64e7SAndroid Build Coastguard Worker n = state->x.have;
330*86ee64e7SAndroid Build Coastguard Worker state->x.have = 0;
331*86ee64e7SAndroid Build Coastguard Worker }
332*86ee64e7SAndroid Build Coastguard Worker
333*86ee64e7SAndroid Build Coastguard Worker /* update progress */
334*86ee64e7SAndroid Build Coastguard Worker len -= n;
335*86ee64e7SAndroid Build Coastguard Worker buf = (char *)buf + n;
336*86ee64e7SAndroid Build Coastguard Worker got += n;
337*86ee64e7SAndroid Build Coastguard Worker state->x.pos += n;
338*86ee64e7SAndroid Build Coastguard Worker } while (len);
339*86ee64e7SAndroid Build Coastguard Worker
340*86ee64e7SAndroid Build Coastguard Worker /* return number of bytes read into user buffer */
341*86ee64e7SAndroid Build Coastguard Worker return got;
342*86ee64e7SAndroid Build Coastguard Worker }
343*86ee64e7SAndroid Build Coastguard Worker
344*86ee64e7SAndroid Build Coastguard Worker /* -- see zlib.h -- */
gzread(gzFile file,voidp buf,unsigned len)345*86ee64e7SAndroid Build Coastguard Worker int ZEXPORT gzread(gzFile file, voidp buf, unsigned len) {
346*86ee64e7SAndroid Build Coastguard Worker gz_statep state;
347*86ee64e7SAndroid Build Coastguard Worker
348*86ee64e7SAndroid Build Coastguard Worker /* get internal structure */
349*86ee64e7SAndroid Build Coastguard Worker if (file == NULL)
350*86ee64e7SAndroid Build Coastguard Worker return -1;
351*86ee64e7SAndroid Build Coastguard Worker state = (gz_statep)file;
352*86ee64e7SAndroid Build Coastguard Worker
353*86ee64e7SAndroid Build Coastguard Worker /* check that we're reading and that there's no (serious) error */
354*86ee64e7SAndroid Build Coastguard Worker if (state->mode != GZ_READ ||
355*86ee64e7SAndroid Build Coastguard Worker (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 /* since an int is returned, make sure len fits in one, otherwise return
359*86ee64e7SAndroid Build Coastguard Worker with an error (this avoids a flaw in the interface) */
360*86ee64e7SAndroid Build Coastguard Worker if ((int)len < 0) {
361*86ee64e7SAndroid Build Coastguard Worker gz_error(state, Z_STREAM_ERROR, "request does not fit in an int");
362*86ee64e7SAndroid Build Coastguard Worker return -1;
363*86ee64e7SAndroid Build Coastguard Worker }
364*86ee64e7SAndroid Build Coastguard Worker
365*86ee64e7SAndroid Build Coastguard Worker /* read len or fewer bytes to buf */
366*86ee64e7SAndroid Build Coastguard Worker len = (unsigned)gz_read(state, buf, len);
367*86ee64e7SAndroid Build Coastguard Worker
368*86ee64e7SAndroid Build Coastguard Worker /* check for an error */
369*86ee64e7SAndroid Build Coastguard Worker if (len == 0 && state->err != Z_OK && state->err != Z_BUF_ERROR)
370*86ee64e7SAndroid Build Coastguard Worker return -1;
371*86ee64e7SAndroid Build Coastguard Worker
372*86ee64e7SAndroid Build Coastguard Worker /* return the number of bytes read (this is assured to fit in an int) */
373*86ee64e7SAndroid Build Coastguard Worker return (int)len;
374*86ee64e7SAndroid Build Coastguard Worker }
375*86ee64e7SAndroid Build Coastguard Worker
376*86ee64e7SAndroid Build Coastguard Worker /* -- see zlib.h -- */
gzfread(voidp buf,z_size_t size,z_size_t nitems,gzFile file)377*86ee64e7SAndroid Build Coastguard Worker z_size_t ZEXPORT gzfread(voidp buf, z_size_t size, z_size_t nitems, gzFile file) {
378*86ee64e7SAndroid Build Coastguard Worker z_size_t len;
379*86ee64e7SAndroid Build Coastguard Worker gz_statep state;
380*86ee64e7SAndroid Build Coastguard Worker
381*86ee64e7SAndroid Build Coastguard Worker /* get internal structure */
382*86ee64e7SAndroid Build Coastguard Worker if (file == NULL)
383*86ee64e7SAndroid Build Coastguard Worker return 0;
384*86ee64e7SAndroid Build Coastguard Worker state = (gz_statep)file;
385*86ee64e7SAndroid Build Coastguard Worker
386*86ee64e7SAndroid Build Coastguard Worker /* check that we're reading and that there's no (serious) error */
387*86ee64e7SAndroid Build Coastguard Worker if (state->mode != GZ_READ ||
388*86ee64e7SAndroid Build Coastguard Worker (state->err != Z_OK && state->err != Z_BUF_ERROR))
389*86ee64e7SAndroid Build Coastguard Worker return 0;
390*86ee64e7SAndroid Build Coastguard Worker
391*86ee64e7SAndroid Build Coastguard Worker /* compute bytes to read -- error on overflow */
392*86ee64e7SAndroid Build Coastguard Worker len = nitems * size;
393*86ee64e7SAndroid Build Coastguard Worker if (size && len / size != nitems) {
394*86ee64e7SAndroid Build Coastguard Worker gz_error(state, Z_STREAM_ERROR, "request does not fit in a size_t");
395*86ee64e7SAndroid Build Coastguard Worker return 0;
396*86ee64e7SAndroid Build Coastguard Worker }
397*86ee64e7SAndroid Build Coastguard Worker
398*86ee64e7SAndroid Build Coastguard Worker /* read len or fewer bytes to buf, return the number of full items read */
399*86ee64e7SAndroid Build Coastguard Worker return len ? gz_read(state, buf, len) / size : 0;
400*86ee64e7SAndroid Build Coastguard Worker }
401*86ee64e7SAndroid Build Coastguard Worker
402*86ee64e7SAndroid Build Coastguard Worker /* -- see zlib.h -- */
403*86ee64e7SAndroid Build Coastguard Worker #ifdef Z_PREFIX_SET
404*86ee64e7SAndroid Build Coastguard Worker # undef z_gzgetc
405*86ee64e7SAndroid Build Coastguard Worker #else
406*86ee64e7SAndroid Build Coastguard Worker # undef gzgetc
407*86ee64e7SAndroid Build Coastguard Worker # ifdef Z_CR_PREFIX_SET
408*86ee64e7SAndroid Build Coastguard Worker # define gzgetc Cr_z_gzgetc
409*86ee64e7SAndroid Build Coastguard Worker # endif
410*86ee64e7SAndroid Build Coastguard Worker #endif
411*86ee64e7SAndroid Build Coastguard Worker
gzgetc(gzFile file)412*86ee64e7SAndroid Build Coastguard Worker int ZEXPORT gzgetc(gzFile file) {
413*86ee64e7SAndroid Build Coastguard Worker unsigned char buf[1];
414*86ee64e7SAndroid Build Coastguard Worker gz_statep state;
415*86ee64e7SAndroid Build Coastguard Worker
416*86ee64e7SAndroid Build Coastguard Worker /* get internal structure */
417*86ee64e7SAndroid Build Coastguard Worker if (file == NULL)
418*86ee64e7SAndroid Build Coastguard Worker return -1;
419*86ee64e7SAndroid Build Coastguard Worker state = (gz_statep)file;
420*86ee64e7SAndroid Build Coastguard Worker
421*86ee64e7SAndroid Build Coastguard Worker /* check that we're reading and that there's no (serious) error */
422*86ee64e7SAndroid Build Coastguard Worker if (state->mode != GZ_READ ||
423*86ee64e7SAndroid Build Coastguard Worker (state->err != Z_OK && state->err != Z_BUF_ERROR))
424*86ee64e7SAndroid Build Coastguard Worker return -1;
425*86ee64e7SAndroid Build Coastguard Worker
426*86ee64e7SAndroid Build Coastguard Worker /* try output buffer (no need to check for skip request) */
427*86ee64e7SAndroid Build Coastguard Worker if (state->x.have) {
428*86ee64e7SAndroid Build Coastguard Worker state->x.have--;
429*86ee64e7SAndroid Build Coastguard Worker state->x.pos++;
430*86ee64e7SAndroid Build Coastguard Worker return *(state->x.next)++;
431*86ee64e7SAndroid Build Coastguard Worker }
432*86ee64e7SAndroid Build Coastguard Worker
433*86ee64e7SAndroid Build Coastguard Worker /* nothing there -- try gz_read() */
434*86ee64e7SAndroid Build Coastguard Worker return gz_read(state, buf, 1) < 1 ? -1 : buf[0];
435*86ee64e7SAndroid Build Coastguard Worker }
436*86ee64e7SAndroid Build Coastguard Worker
gzgetc_(gzFile file)437*86ee64e7SAndroid Build Coastguard Worker int ZEXPORT gzgetc_(gzFile file) {
438*86ee64e7SAndroid Build Coastguard Worker return gzgetc(file);
439*86ee64e7SAndroid Build Coastguard Worker }
440*86ee64e7SAndroid Build Coastguard Worker
441*86ee64e7SAndroid Build Coastguard Worker /* -- see zlib.h -- */
gzungetc(int c,gzFile file)442*86ee64e7SAndroid Build Coastguard Worker int ZEXPORT gzungetc(int c, gzFile file) {
443*86ee64e7SAndroid Build Coastguard Worker gz_statep state;
444*86ee64e7SAndroid Build Coastguard Worker
445*86ee64e7SAndroid Build Coastguard Worker /* get internal structure */
446*86ee64e7SAndroid Build Coastguard Worker if (file == NULL)
447*86ee64e7SAndroid Build Coastguard Worker return -1;
448*86ee64e7SAndroid Build Coastguard Worker state = (gz_statep)file;
449*86ee64e7SAndroid Build Coastguard Worker
450*86ee64e7SAndroid Build Coastguard Worker /* check that we're reading and that there's no (serious) error */
451*86ee64e7SAndroid Build Coastguard Worker if (state->mode != GZ_READ ||
452*86ee64e7SAndroid Build Coastguard Worker (state->err != Z_OK && state->err != Z_BUF_ERROR))
453*86ee64e7SAndroid Build Coastguard Worker return -1;
454*86ee64e7SAndroid Build Coastguard Worker
455*86ee64e7SAndroid Build Coastguard Worker /* process a skip request */
456*86ee64e7SAndroid Build Coastguard Worker if (state->seek) {
457*86ee64e7SAndroid Build Coastguard Worker state->seek = 0;
458*86ee64e7SAndroid Build Coastguard Worker if (gz_skip(state, state->skip) == -1)
459*86ee64e7SAndroid Build Coastguard Worker return -1;
460*86ee64e7SAndroid Build Coastguard Worker }
461*86ee64e7SAndroid Build Coastguard Worker
462*86ee64e7SAndroid Build Coastguard Worker /* can't push EOF */
463*86ee64e7SAndroid Build Coastguard Worker if (c < 0)
464*86ee64e7SAndroid Build Coastguard Worker return -1;
465*86ee64e7SAndroid Build Coastguard Worker
466*86ee64e7SAndroid Build Coastguard Worker /* if output buffer empty, put byte at end (allows more pushing) */
467*86ee64e7SAndroid Build Coastguard Worker if (state->x.have == 0) {
468*86ee64e7SAndroid Build Coastguard Worker state->x.have = 1;
469*86ee64e7SAndroid Build Coastguard Worker state->x.next = state->out + (state->size << 1) - 1;
470*86ee64e7SAndroid Build Coastguard Worker state->x.next[0] = (unsigned char)c;
471*86ee64e7SAndroid Build Coastguard Worker state->x.pos--;
472*86ee64e7SAndroid Build Coastguard Worker state->past = 0;
473*86ee64e7SAndroid Build Coastguard Worker return c;
474*86ee64e7SAndroid Build Coastguard Worker }
475*86ee64e7SAndroid Build Coastguard Worker
476*86ee64e7SAndroid Build Coastguard Worker /* if no room, give up (must have already done a gzungetc()) */
477*86ee64e7SAndroid Build Coastguard Worker if (state->x.have == (state->size << 1)) {
478*86ee64e7SAndroid Build Coastguard Worker gz_error(state, Z_DATA_ERROR, "out of room to push characters");
479*86ee64e7SAndroid Build Coastguard Worker return -1;
480*86ee64e7SAndroid Build Coastguard Worker }
481*86ee64e7SAndroid Build Coastguard Worker
482*86ee64e7SAndroid Build Coastguard Worker /* slide output data if needed and insert byte before existing data */
483*86ee64e7SAndroid Build Coastguard Worker if (state->x.next == state->out) {
484*86ee64e7SAndroid Build Coastguard Worker unsigned char *src = state->out + state->x.have;
485*86ee64e7SAndroid Build Coastguard Worker unsigned char *dest = state->out + (state->size << 1);
486*86ee64e7SAndroid Build Coastguard Worker while (src > state->out)
487*86ee64e7SAndroid Build Coastguard Worker *--dest = *--src;
488*86ee64e7SAndroid Build Coastguard Worker state->x.next = dest;
489*86ee64e7SAndroid Build Coastguard Worker }
490*86ee64e7SAndroid Build Coastguard Worker state->x.have++;
491*86ee64e7SAndroid Build Coastguard Worker state->x.next--;
492*86ee64e7SAndroid Build Coastguard Worker state->x.next[0] = (unsigned char)c;
493*86ee64e7SAndroid Build Coastguard Worker state->x.pos--;
494*86ee64e7SAndroid Build Coastguard Worker state->past = 0;
495*86ee64e7SAndroid Build Coastguard Worker return c;
496*86ee64e7SAndroid Build Coastguard Worker }
497*86ee64e7SAndroid Build Coastguard Worker
498*86ee64e7SAndroid Build Coastguard Worker /* -- see zlib.h -- */
gzgets(gzFile file,char * buf,int len)499*86ee64e7SAndroid Build Coastguard Worker char * ZEXPORT gzgets(gzFile file, char *buf, int len) {
500*86ee64e7SAndroid Build Coastguard Worker unsigned left, n;
501*86ee64e7SAndroid Build Coastguard Worker char *str;
502*86ee64e7SAndroid Build Coastguard Worker unsigned char *eol;
503*86ee64e7SAndroid Build Coastguard Worker gz_statep state;
504*86ee64e7SAndroid Build Coastguard Worker
505*86ee64e7SAndroid Build Coastguard Worker /* check parameters and get internal structure */
506*86ee64e7SAndroid Build Coastguard Worker if (file == NULL || buf == NULL || len < 1)
507*86ee64e7SAndroid Build Coastguard Worker return NULL;
508*86ee64e7SAndroid Build Coastguard Worker state = (gz_statep)file;
509*86ee64e7SAndroid Build Coastguard Worker
510*86ee64e7SAndroid Build Coastguard Worker /* check that we're reading and that there's no (serious) error */
511*86ee64e7SAndroid Build Coastguard Worker if (state->mode != GZ_READ ||
512*86ee64e7SAndroid Build Coastguard Worker (state->err != Z_OK && state->err != Z_BUF_ERROR))
513*86ee64e7SAndroid Build Coastguard Worker return NULL;
514*86ee64e7SAndroid Build Coastguard Worker
515*86ee64e7SAndroid Build Coastguard Worker /* process a skip request */
516*86ee64e7SAndroid Build Coastguard Worker if (state->seek) {
517*86ee64e7SAndroid Build Coastguard Worker state->seek = 0;
518*86ee64e7SAndroid Build Coastguard Worker if (gz_skip(state, state->skip) == -1)
519*86ee64e7SAndroid Build Coastguard Worker return NULL;
520*86ee64e7SAndroid Build Coastguard Worker }
521*86ee64e7SAndroid Build Coastguard Worker
522*86ee64e7SAndroid Build Coastguard Worker /* copy output bytes up to new line or len - 1, whichever comes first --
523*86ee64e7SAndroid Build Coastguard Worker append a terminating zero to the string (we don't check for a zero in
524*86ee64e7SAndroid Build Coastguard Worker the contents, let the user worry about that) */
525*86ee64e7SAndroid Build Coastguard Worker str = buf;
526*86ee64e7SAndroid Build Coastguard Worker left = (unsigned)len - 1;
527*86ee64e7SAndroid Build Coastguard Worker if (left) do {
528*86ee64e7SAndroid Build Coastguard Worker /* assure that something is in the output buffer */
529*86ee64e7SAndroid Build Coastguard Worker if (state->x.have == 0 && gz_fetch(state) == -1)
530*86ee64e7SAndroid Build Coastguard Worker return NULL; /* error */
531*86ee64e7SAndroid Build Coastguard Worker if (state->x.have == 0) { /* end of file */
532*86ee64e7SAndroid Build Coastguard Worker state->past = 1; /* read past end */
533*86ee64e7SAndroid Build Coastguard Worker break; /* return what we have */
534*86ee64e7SAndroid Build Coastguard Worker }
535*86ee64e7SAndroid Build Coastguard Worker
536*86ee64e7SAndroid Build Coastguard Worker /* look for end-of-line in current output buffer */
537*86ee64e7SAndroid Build Coastguard Worker n = state->x.have > left ? left : state->x.have;
538*86ee64e7SAndroid Build Coastguard Worker eol = (unsigned char *)memchr(state->x.next, '\n', n);
539*86ee64e7SAndroid Build Coastguard Worker if (eol != NULL)
540*86ee64e7SAndroid Build Coastguard Worker n = (unsigned)(eol - state->x.next) + 1;
541*86ee64e7SAndroid Build Coastguard Worker
542*86ee64e7SAndroid Build Coastguard Worker /* copy through end-of-line, or remainder if not found */
543*86ee64e7SAndroid Build Coastguard Worker memcpy(buf, state->x.next, n);
544*86ee64e7SAndroid Build Coastguard Worker state->x.have -= n;
545*86ee64e7SAndroid Build Coastguard Worker state->x.next += n;
546*86ee64e7SAndroid Build Coastguard Worker state->x.pos += n;
547*86ee64e7SAndroid Build Coastguard Worker left -= n;
548*86ee64e7SAndroid Build Coastguard Worker buf += n;
549*86ee64e7SAndroid Build Coastguard Worker } while (left && eol == NULL);
550*86ee64e7SAndroid Build Coastguard Worker
551*86ee64e7SAndroid Build Coastguard Worker /* return terminated string, or if nothing, end of file */
552*86ee64e7SAndroid Build Coastguard Worker if (buf == str)
553*86ee64e7SAndroid Build Coastguard Worker return NULL;
554*86ee64e7SAndroid Build Coastguard Worker buf[0] = 0;
555*86ee64e7SAndroid Build Coastguard Worker return str;
556*86ee64e7SAndroid Build Coastguard Worker }
557*86ee64e7SAndroid Build Coastguard Worker
558*86ee64e7SAndroid Build Coastguard Worker /* -- see zlib.h -- */
gzdirect(gzFile file)559*86ee64e7SAndroid Build Coastguard Worker int ZEXPORT gzdirect(gzFile file) {
560*86ee64e7SAndroid Build Coastguard Worker gz_statep state;
561*86ee64e7SAndroid Build Coastguard Worker
562*86ee64e7SAndroid Build Coastguard Worker /* get internal structure */
563*86ee64e7SAndroid Build Coastguard Worker if (file == NULL)
564*86ee64e7SAndroid Build Coastguard Worker return 0;
565*86ee64e7SAndroid Build Coastguard Worker state = (gz_statep)file;
566*86ee64e7SAndroid Build Coastguard Worker
567*86ee64e7SAndroid Build Coastguard Worker /* if the state is not known, but we can find out, then do so (this is
568*86ee64e7SAndroid Build Coastguard Worker mainly for right after a gzopen() or gzdopen()) */
569*86ee64e7SAndroid Build Coastguard Worker if (state->mode == GZ_READ && state->how == LOOK && state->x.have == 0)
570*86ee64e7SAndroid Build Coastguard Worker (void)gz_look(state);
571*86ee64e7SAndroid Build Coastguard Worker
572*86ee64e7SAndroid Build Coastguard Worker /* return 1 if transparent, 0 if processing a gzip stream */
573*86ee64e7SAndroid Build Coastguard Worker return state->direct;
574*86ee64e7SAndroid Build Coastguard Worker }
575*86ee64e7SAndroid Build Coastguard Worker
576*86ee64e7SAndroid Build Coastguard Worker /* -- see zlib.h -- */
gzclose_r(gzFile file)577*86ee64e7SAndroid Build Coastguard Worker int ZEXPORT gzclose_r(gzFile file) {
578*86ee64e7SAndroid Build Coastguard Worker int ret, err;
579*86ee64e7SAndroid Build Coastguard Worker gz_statep state;
580*86ee64e7SAndroid Build Coastguard Worker
581*86ee64e7SAndroid Build Coastguard Worker /* get internal structure */
582*86ee64e7SAndroid Build Coastguard Worker if (file == NULL)
583*86ee64e7SAndroid Build Coastguard Worker return Z_STREAM_ERROR;
584*86ee64e7SAndroid Build Coastguard Worker state = (gz_statep)file;
585*86ee64e7SAndroid Build Coastguard Worker
586*86ee64e7SAndroid Build Coastguard Worker /* check that we're reading */
587*86ee64e7SAndroid Build Coastguard Worker if (state->mode != GZ_READ)
588*86ee64e7SAndroid Build Coastguard Worker return Z_STREAM_ERROR;
589*86ee64e7SAndroid Build Coastguard Worker
590*86ee64e7SAndroid Build Coastguard Worker /* free memory and close file */
591*86ee64e7SAndroid Build Coastguard Worker if (state->size) {
592*86ee64e7SAndroid Build Coastguard Worker inflateEnd(&(state->strm));
593*86ee64e7SAndroid Build Coastguard Worker free(state->out);
594*86ee64e7SAndroid Build Coastguard Worker free(state->in);
595*86ee64e7SAndroid Build Coastguard Worker }
596*86ee64e7SAndroid Build Coastguard Worker err = state->err == Z_BUF_ERROR ? Z_BUF_ERROR : Z_OK;
597*86ee64e7SAndroid Build Coastguard Worker gz_error(state, Z_OK, NULL);
598*86ee64e7SAndroid Build Coastguard Worker free(state->path);
599*86ee64e7SAndroid Build Coastguard Worker ret = close(state->fd);
600*86ee64e7SAndroid Build Coastguard Worker free(state);
601*86ee64e7SAndroid Build Coastguard Worker return ret ? Z_ERRNO : err;
602*86ee64e7SAndroid Build Coastguard Worker }
603