blob: 004fe6af9c2a4e3a0e2c76a82c42e7d23a0f9cc4 [file] [log] [blame]
Przemyslaw Skibinskif0d7da72016-11-29 18:02:34 +01001/* gzread.c contains minimal changes required to be compiled with zlibWrapper:
Przemyslaw Skibinski5735fd72017-01-18 12:14:01 +01002 * - gz_statep was converted to union to work with -Wstrict-aliasing=1 */
3
4 /* gzread.c -- zlib functions for reading gzip files
5 * Copyright (C) 2004, 2005, 2010, 2011, 2012, 2013, 2016 Mark Adler
6 * For conditions of distribution and use, see copyright notice in zlib.h
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +01007 */
8
9#include "gzguts.h"
10
11/* Local functions */
12local int gz_load OF((gz_statep, unsigned char *, unsigned, unsigned *));
13local int gz_avail OF((gz_statep));
14local int gz_look OF((gz_statep));
15local int gz_decomp OF((gz_statep));
16local int gz_fetch OF((gz_statep));
17local int gz_skip OF((gz_statep, z_off64_t));
Przemyslaw Skibinski5735fd72017-01-18 12:14:01 +010018local z_size_t gz_read OF((gz_statep, voidp, z_size_t));
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +010019
20/* Use read() to load a buffer -- return -1 on error, otherwise 0. Read from
Przemyslaw Skibinski5735fd72017-01-18 12:14:01 +010021 state.state->fd, and update state.state->eof, state.state->err, and state.state->msg as appropriate.
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +010022 This function needs to loop on read(), since read() is not guaranteed to
23 read the number of bytes requested, depending on the type of descriptor. */
24local int gz_load(state, buf, len, have)
25 gz_statep state;
26 unsigned char *buf;
27 unsigned len;
28 unsigned *have;
29{
30 int ret;
Przemyslaw Skibinski5735fd72017-01-18 12:14:01 +010031 unsigned get, max = ((unsigned)-1 >> 2) + 1;
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +010032
33 *have = 0;
34 do {
Przemyslaw Skibinski5735fd72017-01-18 12:14:01 +010035 get = len - *have;
36 if (get > max)
37 get = max;
38 ret = read(state.state->fd, buf + *have, get);
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +010039 if (ret <= 0)
40 break;
Przemyslaw Skibinski5735fd72017-01-18 12:14:01 +010041 *have += (unsigned)ret;
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +010042 } while (*have < len);
43 if (ret < 0) {
44 gz_error(state, Z_ERRNO, zstrerror());
45 return -1;
46 }
47 if (ret == 0)
Przemyslaw Skibinski0feb24a2016-11-29 16:05:52 +010048 state.state->eof = 1;
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +010049 return 0;
50}
51
52/* Load up input buffer and set eof flag if last data loaded -- return -1 on
53 error, 0 otherwise. Note that the eof flag is set when the end of the input
54 file is reached, even though there may be unused data in the buffer. Once
55 that data has been used, no more attempts will be made to read the file.
56 If strm->avail_in != 0, then the current data is moved to the beginning of
57 the input buffer, and then the remainder of the buffer is loaded with the
58 available data from the input file. */
59local int gz_avail(state)
60 gz_statep state;
61{
62 unsigned got;
Przemyslaw Skibinski0feb24a2016-11-29 16:05:52 +010063 z_streamp strm = &(state.state->strm);
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +010064
Przemyslaw Skibinski0feb24a2016-11-29 16:05:52 +010065 if (state.state->err != Z_OK && state.state->err != Z_BUF_ERROR)
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +010066 return -1;
Przemyslaw Skibinski0feb24a2016-11-29 16:05:52 +010067 if (state.state->eof == 0) {
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +010068 if (strm->avail_in) { /* copy what's there to the start */
Przemyslaw Skibinski0feb24a2016-11-29 16:05:52 +010069 unsigned char *p = state.state->in;
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +010070 unsigned const char *q = strm->next_in;
71 unsigned n = strm->avail_in;
72 do {
73 *p++ = *q++;
74 } while (--n);
75 }
Przemyslaw Skibinski0feb24a2016-11-29 16:05:52 +010076 if (gz_load(state, state.state->in + strm->avail_in,
77 state.state->size - strm->avail_in, &got) == -1)
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +010078 return -1;
79 strm->avail_in += got;
Przemyslaw Skibinski0feb24a2016-11-29 16:05:52 +010080 strm->next_in = state.state->in;
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +010081 }
82 return 0;
83}
84
Przemyslaw Skibinski5735fd72017-01-18 12:14:01 +010085/* Look for gzip header, set up for inflate or copy. state.state->x.have must be 0.
86 If this is the first time in, allocate required memory. state.state->how will be
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +010087 left unchanged if there is no more input data available, will be set to COPY
88 if there is no gzip header and direct copying will be performed, or it will
89 be set to GZIP for decompression. If direct copying, then leftover input
90 data from the input buffer will be copied to the output buffer. In that
91 case, all further file reads will be directly to either the output buffer or
92 a user buffer. If decompressing, the inflate state will be initialized.
93 gz_look() will return 0 on success or -1 on failure. */
94local int gz_look(state)
95 gz_statep state;
96{
Przemyslaw Skibinski0feb24a2016-11-29 16:05:52 +010097 z_streamp strm = &(state.state->strm);
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +010098
99 /* allocate read buffers and inflate memory */
Przemyslaw Skibinski0feb24a2016-11-29 16:05:52 +0100100 if (state.state->size == 0) {
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100101 /* allocate buffers */
Przemyslaw Skibinski0feb24a2016-11-29 16:05:52 +0100102 state.state->in = (unsigned char *)malloc(state.state->want);
103 state.state->out = (unsigned char *)malloc(state.state->want << 1);
104 if (state.state->in == NULL || state.state->out == NULL) {
Przemyslaw Skibinski5735fd72017-01-18 12:14:01 +0100105 free(state.state->out);
106 free(state.state->in);
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100107 gz_error(state, Z_MEM_ERROR, "out of memory");
108 return -1;
109 }
Przemyslaw Skibinski0feb24a2016-11-29 16:05:52 +0100110 state.state->size = state.state->want;
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100111
112 /* allocate inflate memory */
Przemyslaw Skibinski0feb24a2016-11-29 16:05:52 +0100113 state.state->strm.zalloc = Z_NULL;
114 state.state->strm.zfree = Z_NULL;
115 state.state->strm.opaque = Z_NULL;
116 state.state->strm.avail_in = 0;
117 state.state->strm.next_in = Z_NULL;
118 if (inflateInit2(&(state.state->strm), 15 + 16) != Z_OK) { /* gunzip */
119 free(state.state->out);
120 free(state.state->in);
121 state.state->size = 0;
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100122 gz_error(state, Z_MEM_ERROR, "out of memory");
123 return -1;
124 }
125 }
126
127 /* get at least the magic bytes in the input buffer */
128 if (strm->avail_in < 2) {
129 if (gz_avail(state) == -1)
130 return -1;
131 if (strm->avail_in == 0)
132 return 0;
133 }
134
135 /* look for gzip magic bytes -- if there, do gzip decoding (note: there is
136 a logical dilemma here when considering the case of a partially written
137 gzip file, to wit, if a single 31 byte is written, then we cannot tell
138 whether this is a single-byte file, or just a partially written gzip
139 file -- for here we assume that if a gzip file is being written, then
140 the header will be written in a single operation, so that reading a
141 single byte is sufficient indication that it is not a gzip file) */
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100142 if (strm->avail_in > 1 &&
Przemyslaw Skibinskidc2fe752016-12-01 11:56:20 +0100143 ((strm->next_in[0] == 31 && strm->next_in[1] == 139) /* gz header */
144 || (strm->next_in[0] == 40 && strm->next_in[1] == 181))) { /* zstd header */
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100145 inflateReset(strm);
Przemyslaw Skibinski0feb24a2016-11-29 16:05:52 +0100146 state.state->how = GZIP;
147 state.state->direct = 0;
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100148 return 0;
149 }
150
151 /* no gzip header -- if we were decoding gzip before, then this is trailing
152 garbage. Ignore the trailing garbage and finish. */
Przemyslaw Skibinski0feb24a2016-11-29 16:05:52 +0100153 if (state.state->direct == 0) {
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100154 strm->avail_in = 0;
Przemyslaw Skibinski0feb24a2016-11-29 16:05:52 +0100155 state.state->eof = 1;
156 state.state->x.have = 0;
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100157 return 0;
158 }
159
160 /* doing raw i/o, copy any leftover input to output -- this assumes that
161 the output buffer is larger than the input buffer, which also assures
162 space for gzungetc() */
Przemyslaw Skibinski0feb24a2016-11-29 16:05:52 +0100163 state.state->x.next = state.state->out;
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100164 if (strm->avail_in) {
Przemyslaw Skibinski0feb24a2016-11-29 16:05:52 +0100165 memcpy(state.state->x.next, strm->next_in, strm->avail_in);
166 state.state->x.have = strm->avail_in;
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100167 strm->avail_in = 0;
168 }
Przemyslaw Skibinski0feb24a2016-11-29 16:05:52 +0100169 state.state->how = COPY;
170 state.state->direct = 1;
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100171 return 0;
172}
173
174/* Decompress from input to the provided next_out and avail_out in the state.
Przemyslaw Skibinski5735fd72017-01-18 12:14:01 +0100175 On return, state.state->x.have and state.state->x.next point to the just decompressed
176 data. If the gzip stream completes, state.state->how is reset to LOOK to look for
177 the next gzip stream or raw data, once state.state->x.have is depleted. Returns 0
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100178 on success, -1 on failure. */
179local int gz_decomp(state)
180 gz_statep state;
181{
182 int ret = Z_OK;
183 unsigned had;
Przemyslaw Skibinski0feb24a2016-11-29 16:05:52 +0100184 z_streamp strm = &(state.state->strm);
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100185
186 /* fill output buffer up to end of deflate stream */
187 had = strm->avail_out;
188 do {
189 /* get more input for inflate() */
190 if (strm->avail_in == 0 && gz_avail(state) == -1)
191 return -1;
192 if (strm->avail_in == 0) {
193 gz_error(state, Z_BUF_ERROR, "unexpected end of file");
194 break;
195 }
196
197 /* decompress and handle errors */
198 ret = inflate(strm, Z_NO_FLUSH);
199 if (ret == Z_STREAM_ERROR || ret == Z_NEED_DICT) {
200 gz_error(state, Z_STREAM_ERROR,
201 "internal error: inflate stream corrupt");
202 return -1;
203 }
204 if (ret == Z_MEM_ERROR) {
205 gz_error(state, Z_MEM_ERROR, "out of memory");
206 return -1;
207 }
208 if (ret == Z_DATA_ERROR) { /* deflate stream invalid */
209 gz_error(state, Z_DATA_ERROR,
210 strm->msg == NULL ? "compressed data error" : strm->msg);
211 return -1;
212 }
213 } while (strm->avail_out && ret != Z_STREAM_END);
214
215 /* update available output */
Przemyslaw Skibinski0feb24a2016-11-29 16:05:52 +0100216 state.state->x.have = had - strm->avail_out;
217 state.state->x.next = strm->next_out - state.state->x.have;
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100218
219 /* if the gzip stream completed successfully, look for another */
220 if (ret == Z_STREAM_END)
Przemyslaw Skibinski0feb24a2016-11-29 16:05:52 +0100221 state.state->how = LOOK;
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100222
223 /* good decompression */
224 return 0;
225}
226
Przemyslaw Skibinski5735fd72017-01-18 12:14:01 +0100227/* Fetch data and put it in the output buffer. Assumes state.state->x.have is 0.
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100228 Data is either copied from the input file or decompressed from the input
Przemyslaw Skibinski5735fd72017-01-18 12:14:01 +0100229 file depending on state.state->how. If state.state->how is LOOK, then a gzip header is
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100230 looked for to determine whether to copy or decompress. Returns -1 on error,
Przemyslaw Skibinski5735fd72017-01-18 12:14:01 +0100231 otherwise 0. gz_fetch() will leave state.state->how as COPY or GZIP unless the
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100232 end of the input file has been reached and all data has been processed. */
233local int gz_fetch(state)
234 gz_statep state;
235{
Przemyslaw Skibinski0feb24a2016-11-29 16:05:52 +0100236 z_streamp strm = &(state.state->strm);
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100237
238 do {
Przemyslaw Skibinski0feb24a2016-11-29 16:05:52 +0100239 switch(state.state->how) {
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100240 case LOOK: /* -> LOOK, COPY (only if never GZIP), or GZIP */
241 if (gz_look(state) == -1)
242 return -1;
Przemyslaw Skibinski0feb24a2016-11-29 16:05:52 +0100243 if (state.state->how == LOOK)
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100244 return 0;
245 break;
246 case COPY: /* -> COPY */
Przemyslaw Skibinski0feb24a2016-11-29 16:05:52 +0100247 if (gz_load(state, state.state->out, state.state->size << 1, &(state.state->x.have))
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100248 == -1)
249 return -1;
Przemyslaw Skibinski0feb24a2016-11-29 16:05:52 +0100250 state.state->x.next = state.state->out;
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100251 return 0;
252 case GZIP: /* -> GZIP or LOOK (if end of gzip stream) */
Przemyslaw Skibinski0feb24a2016-11-29 16:05:52 +0100253 strm->avail_out = state.state->size << 1;
254 strm->next_out = state.state->out;
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100255 if (gz_decomp(state) == -1)
256 return -1;
257 }
Przemyslaw Skibinski0feb24a2016-11-29 16:05:52 +0100258 } while (state.state->x.have == 0 && (!state.state->eof || strm->avail_in));
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100259 return 0;
260}
261
262/* Skip len uncompressed bytes of output. Return -1 on error, 0 on success. */
263local int gz_skip(state, len)
264 gz_statep state;
265 z_off64_t len;
266{
267 unsigned n;
268
269 /* skip over len bytes or reach end-of-file, whichever comes first */
270 while (len)
271 /* skip over whatever is in output buffer */
Przemyslaw Skibinski0feb24a2016-11-29 16:05:52 +0100272 if (state.state->x.have) {
273 n = GT_OFF(state.state->x.have) || (z_off64_t)state.state->x.have > len ?
274 (unsigned)len : state.state->x.have;
275 state.state->x.have -= n;
276 state.state->x.next += n;
277 state.state->x.pos += n;
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100278 len -= n;
279 }
280
281 /* output buffer empty -- return if we're at the end of the input */
Przemyslaw Skibinski0feb24a2016-11-29 16:05:52 +0100282 else if (state.state->eof && state.state->strm.avail_in == 0)
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100283 break;
284
285 /* need more data to skip -- load up output buffer */
286 else {
287 /* get more output, looking for header if required */
288 if (gz_fetch(state) == -1)
289 return -1;
290 }
291 return 0;
292}
293
Przemyslaw Skibinski5735fd72017-01-18 12:14:01 +0100294/* Read len bytes into buf from file, or less than len up to the end of the
295 input. Return the number of bytes read. If zero is returned, either the
296 end of file was reached, or there was an error. state.state->err must be
297 consulted in that case to determine which. */
298local z_size_t gz_read(state, buf, len)
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100299 gz_statep state;
Przemyslaw Skibinski5735fd72017-01-18 12:14:01 +0100300 voidp buf;
301 z_size_t len;
302{
303 z_size_t got;
304 unsigned n;
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100305
306 /* if len is zero, avoid unnecessary operations */
307 if (len == 0)
308 return 0;
309
310 /* process a skip request */
Przemyslaw Skibinski0feb24a2016-11-29 16:05:52 +0100311 if (state.state->seek) {
312 state.state->seek = 0;
313 if (gz_skip(state, state.state->skip) == -1)
Przemyslaw Skibinski5735fd72017-01-18 12:14:01 +0100314 return 0;
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100315 }
316
317 /* get len bytes to buf, or less than len if at the end */
318 got = 0;
319 do {
Przemyslaw Skibinski5735fd72017-01-18 12:14:01 +0100320 /* set n to the maximum amount of len that fits in an unsigned int */
321 n = -1;
322 if (n > len)
323 n = len;
324
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100325 /* first just try copying data from the output buffer */
Przemyslaw Skibinski0feb24a2016-11-29 16:05:52 +0100326 if (state.state->x.have) {
Przemyslaw Skibinski5735fd72017-01-18 12:14:01 +0100327 if (state.state->x.have < n)
328 n = state.state->x.have;
Przemyslaw Skibinski0feb24a2016-11-29 16:05:52 +0100329 memcpy(buf, state.state->x.next, n);
330 state.state->x.next += n;
331 state.state->x.have -= n;
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100332 }
333
334 /* output buffer empty -- return if we're at the end of the input */
Przemyslaw Skibinski5735fd72017-01-18 12:14:01 +0100335 else if (state.state->eof && state.state->strm.avail_in == 0) {
Przemyslaw Skibinski0feb24a2016-11-29 16:05:52 +0100336 state.state->past = 1; /* tried to read past end */
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100337 break;
338 }
339
340 /* need output data -- for small len or new stream load up our output
341 buffer */
Przemyslaw Skibinski5735fd72017-01-18 12:14:01 +0100342 else if (state.state->how == LOOK || n < (state.state->size << 1)) {
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100343 /* get more output, looking for header if required */
344 if (gz_fetch(state) == -1)
Przemyslaw Skibinski5735fd72017-01-18 12:14:01 +0100345 return 0;
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100346 continue; /* no progress yet -- go back to copy above */
347 /* the copy above assures that we will leave with space in the
348 output buffer, allowing at least one gzungetc() to succeed */
349 }
350
351 /* large len -- read directly into user buffer */
Przemyslaw Skibinski0feb24a2016-11-29 16:05:52 +0100352 else if (state.state->how == COPY) { /* read directly */
Przemyslaw Skibinski5735fd72017-01-18 12:14:01 +0100353 if (gz_load(state, (unsigned char *)buf, n, &n) == -1)
354 return 0;
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100355 }
356
357 /* large len -- decompress directly into user buffer */
Przemyslaw Skibinski5735fd72017-01-18 12:14:01 +0100358 else { /* state.state->how == GZIP */
359 state.state->strm.avail_out = n;
360 state.state->strm.next_out = (unsigned char *)buf;
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100361 if (gz_decomp(state) == -1)
Przemyslaw Skibinski5735fd72017-01-18 12:14:01 +0100362 return 0;
Przemyslaw Skibinski0feb24a2016-11-29 16:05:52 +0100363 n = state.state->x.have;
364 state.state->x.have = 0;
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100365 }
366
367 /* update progress */
368 len -= n;
369 buf = (char *)buf + n;
370 got += n;
Przemyslaw Skibinski0feb24a2016-11-29 16:05:52 +0100371 state.state->x.pos += n;
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100372 } while (len);
373
Przemyslaw Skibinski5735fd72017-01-18 12:14:01 +0100374 /* return number of bytes read into user buffer */
375 return got;
376}
377
378/* -- see zlib.h -- */
379int ZEXPORT gzread(file, buf, len)
380 gzFile file;
381 voidp buf;
382 unsigned len;
383{
384 gz_statep state;
385
386 /* get internal structure */
387 if (file == NULL)
388 return -1;
389 state = (gz_statep)file;
390
391 /* check that we're reading and that there's no (serious) error */
392 if (state.state->mode != GZ_READ ||
393 (state.state->err != Z_OK && state.state->err != Z_BUF_ERROR))
394 return -1;
395
396 /* since an int is returned, make sure len fits in one, otherwise return
397 with an error (this avoids a flaw in the interface) */
398 if ((int)len < 0) {
399 gz_error(state, Z_STREAM_ERROR, "request does not fit in an int");
400 return -1;
401 }
402
403 /* read len or fewer bytes to buf */
404 len = gz_read(state, buf, len);
405
406 /* check for an error */
407 if (len == 0 && state.state->err != Z_OK && state.state->err != Z_BUF_ERROR)
408 return -1;
409
410 /* return the number of bytes read (this is assured to fit in an int) */
411 return (int)len;
412}
413
414/* -- see zlib.h -- */
415z_size_t ZEXPORT gzfread(buf, size, nitems, file)
416 voidp buf;
417 z_size_t size;
418 z_size_t nitems;
419 gzFile file;
420{
421 z_size_t len;
422 gz_statep state;
423
424 /* get internal structure */
425 if (file == NULL)
426 return 0;
427 state = (gz_statep)file;
428
429 /* check that we're reading and that there's no (serious) error */
430 if (state.state->mode != GZ_READ ||
431 (state.state->err != Z_OK && state.state->err != Z_BUF_ERROR))
432 return 0;
433
434 /* compute bytes to read -- error on overflow */
435 len = nitems * size;
436 if (size && len / size != nitems) {
437 gz_error(state, Z_STREAM_ERROR, "request does not fit in a size_t");
438 return 0;
439 }
440
441 /* read len or fewer bytes to buf, return the number of full items read */
442 return len ? gz_read(state, buf, len) / size : 0;
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100443}
444
445/* -- see zlib.h -- */
Przemyslaw Skibinskic77befe2016-11-28 14:09:26 +0100446#if ZLIB_VERNUM >= 0x1261
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100447#ifdef Z_PREFIX_SET
448# undef z_gzgetc
449#else
450# undef gzgetc
451#endif
Przemyslaw Skibinskic77befe2016-11-28 14:09:26 +0100452#endif
453
454#if ZLIB_VERNUM == 0x1260
455# undef gzgetc
456#endif
457
458#if ZLIB_VERNUM <= 0x1250
459ZEXTERN int ZEXPORT gzgetc OF((gzFile file));
460ZEXTERN int ZEXPORT gzgetc_ OF((gzFile file));
461#endif
462
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100463int ZEXPORT gzgetc(file)
464 gzFile file;
465{
466 int ret;
467 unsigned char buf[1];
468 gz_statep state;
469
470 /* get internal structure */
471 if (file == NULL)
472 return -1;
473 state = (gz_statep)file;
474
475 /* check that we're reading and that there's no (serious) error */
Przemyslaw Skibinski0feb24a2016-11-29 16:05:52 +0100476 if (state.state->mode != GZ_READ ||
477 (state.state->err != Z_OK && state.state->err != Z_BUF_ERROR))
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100478 return -1;
479
480 /* try output buffer (no need to check for skip request) */
Przemyslaw Skibinski0feb24a2016-11-29 16:05:52 +0100481 if (state.state->x.have) {
482 state.state->x.have--;
483 state.state->x.pos++;
484 return *(state.state->x.next)++;
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100485 }
486
Przemyslaw Skibinski5735fd72017-01-18 12:14:01 +0100487 /* nothing there -- try gz_read() */
488 ret = gz_read(state, buf, 1);
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100489 return ret < 1 ? -1 : buf[0];
490}
491
492int ZEXPORT gzgetc_(file)
493gzFile file;
494{
495 return gzgetc(file);
496}
497
498/* -- see zlib.h -- */
499int ZEXPORT gzungetc(c, file)
500 int c;
501 gzFile file;
502{
503 gz_statep state;
504
505 /* get internal structure */
506 if (file == NULL)
507 return -1;
508 state = (gz_statep)file;
509
510 /* check that we're reading and that there's no (serious) error */
Przemyslaw Skibinski0feb24a2016-11-29 16:05:52 +0100511 if (state.state->mode != GZ_READ ||
512 (state.state->err != Z_OK && state.state->err != Z_BUF_ERROR))
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100513 return -1;
514
515 /* process a skip request */
Przemyslaw Skibinski0feb24a2016-11-29 16:05:52 +0100516 if (state.state->seek) {
517 state.state->seek = 0;
518 if (gz_skip(state, state.state->skip) == -1)
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100519 return -1;
520 }
521
522 /* can't push EOF */
523 if (c < 0)
524 return -1;
525
526 /* if output buffer empty, put byte at end (allows more pushing) */
Przemyslaw Skibinski0feb24a2016-11-29 16:05:52 +0100527 if (state.state->x.have == 0) {
528 state.state->x.have = 1;
529 state.state->x.next = state.state->out + (state.state->size << 1) - 1;
Yann Collet9ceb49e2016-12-22 15:26:33 +0100530 state.state->x.next[0] = (unsigned char)c;
Przemyslaw Skibinski0feb24a2016-11-29 16:05:52 +0100531 state.state->x.pos--;
532 state.state->past = 0;
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100533 return c;
534 }
535
536 /* if no room, give up (must have already done a gzungetc()) */
Przemyslaw Skibinski0feb24a2016-11-29 16:05:52 +0100537 if (state.state->x.have == (state.state->size << 1)) {
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100538 gz_error(state, Z_DATA_ERROR, "out of room to push characters");
539 return -1;
540 }
541
542 /* slide output data if needed and insert byte before existing data */
Przemyslaw Skibinski0feb24a2016-11-29 16:05:52 +0100543 if (state.state->x.next == state.state->out) {
544 unsigned char *src = state.state->out + state.state->x.have;
545 unsigned char *dest = state.state->out + (state.state->size << 1);
546 while (src > state.state->out)
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100547 *--dest = *--src;
Przemyslaw Skibinski0feb24a2016-11-29 16:05:52 +0100548 state.state->x.next = dest;
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100549 }
Przemyslaw Skibinski0feb24a2016-11-29 16:05:52 +0100550 state.state->x.have++;
551 state.state->x.next--;
Yann Collet9ceb49e2016-12-22 15:26:33 +0100552 state.state->x.next[0] = (unsigned char)c;
Przemyslaw Skibinski0feb24a2016-11-29 16:05:52 +0100553 state.state->x.pos--;
554 state.state->past = 0;
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100555 return c;
556}
557
558/* -- see zlib.h -- */
559char * ZEXPORT gzgets(file, buf, len)
560 gzFile file;
561 char *buf;
562 int len;
563{
564 unsigned left, n;
565 char *str;
566 unsigned char *eol;
567 gz_statep state;
568
569 /* check parameters and get internal structure */
570 if (file == NULL || buf == NULL || len < 1)
571 return NULL;
572 state = (gz_statep)file;
573
574 /* check that we're reading and that there's no (serious) error */
Przemyslaw Skibinski0feb24a2016-11-29 16:05:52 +0100575 if (state.state->mode != GZ_READ ||
576 (state.state->err != Z_OK && state.state->err != Z_BUF_ERROR))
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100577 return NULL;
578
579 /* process a skip request */
Przemyslaw Skibinski0feb24a2016-11-29 16:05:52 +0100580 if (state.state->seek) {
581 state.state->seek = 0;
582 if (gz_skip(state, state.state->skip) == -1)
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100583 return NULL;
584 }
585
586 /* copy output bytes up to new line or len - 1, whichever comes first --
587 append a terminating zero to the string (we don't check for a zero in
588 the contents, let the user worry about that) */
589 str = buf;
590 left = (unsigned)len - 1;
591 if (left) do {
592 /* assure that something is in the output buffer */
Przemyslaw Skibinski0feb24a2016-11-29 16:05:52 +0100593 if (state.state->x.have == 0 && gz_fetch(state) == -1)
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100594 return NULL; /* error */
Przemyslaw Skibinski0feb24a2016-11-29 16:05:52 +0100595 if (state.state->x.have == 0) { /* end of file */
596 state.state->past = 1; /* read past end */
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100597 break; /* return what we have */
598 }
599
600 /* look for end-of-line in current output buffer */
Przemyslaw Skibinski0feb24a2016-11-29 16:05:52 +0100601 n = state.state->x.have > left ? left : state.state->x.have;
602 eol = (unsigned char *)memchr(state.state->x.next, '\n', n);
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100603 if (eol != NULL)
Przemyslaw Skibinski0feb24a2016-11-29 16:05:52 +0100604 n = (unsigned)(eol - state.state->x.next) + 1;
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100605
606 /* copy through end-of-line, or remainder if not found */
Przemyslaw Skibinski0feb24a2016-11-29 16:05:52 +0100607 memcpy(buf, state.state->x.next, n);
608 state.state->x.have -= n;
609 state.state->x.next += n;
610 state.state->x.pos += n;
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100611 left -= n;
612 buf += n;
613 } while (left && eol == NULL);
614
615 /* return terminated string, or if nothing, end of file */
616 if (buf == str)
617 return NULL;
618 buf[0] = 0;
619 return str;
620}
621
622/* -- see zlib.h -- */
623int ZEXPORT gzdirect(file)
624 gzFile file;
625{
626 gz_statep state;
627
628 /* get internal structure */
629 if (file == NULL)
630 return 0;
631 state = (gz_statep)file;
632
633 /* if the state is not known, but we can find out, then do so (this is
634 mainly for right after a gzopen() or gzdopen()) */
Przemyslaw Skibinski0feb24a2016-11-29 16:05:52 +0100635 if (state.state->mode == GZ_READ && state.state->how == LOOK && state.state->x.have == 0)
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100636 (void)gz_look(state);
637
638 /* return 1 if transparent, 0 if processing a gzip stream */
Przemyslaw Skibinski0feb24a2016-11-29 16:05:52 +0100639 return state.state->direct;
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100640}
641
642/* -- see zlib.h -- */
643int ZEXPORT gzclose_r(file)
644 gzFile file;
645{
646 int ret, err;
647 gz_statep state;
648
649 /* get internal structure */
650 if (file == NULL)
651 return Z_STREAM_ERROR;
652 state = (gz_statep)file;
653
654 /* check that we're reading */
Przemyslaw Skibinski0feb24a2016-11-29 16:05:52 +0100655 if (state.state->mode != GZ_READ)
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100656 return Z_STREAM_ERROR;
657
658 /* free memory and close file */
Przemyslaw Skibinski0feb24a2016-11-29 16:05:52 +0100659 if (state.state->size) {
660 inflateEnd(&(state.state->strm));
661 free(state.state->out);
662 free(state.state->in);
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100663 }
Przemyslaw Skibinski0feb24a2016-11-29 16:05:52 +0100664 err = state.state->err == Z_BUF_ERROR ? Z_BUF_ERROR : Z_OK;
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100665 gz_error(state, Z_OK, NULL);
Przemyslaw Skibinski0feb24a2016-11-29 16:05:52 +0100666 free(state.state->path);
667 ret = close(state.state->fd);
668 free(state.state);
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100669 return ret ? Z_ERRNO : err;
670}