1 /* gzread.c contains minimal changes required to be compiled with zlibWrapper:
2 * - gz_statep was converted to union to work with -Wstrict-aliasing=1 */
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 http://www.zlib.net/zlib_license.html
12 local int gz_load OF((gz_statep, unsigned char *, unsigned, unsigned *));
13 local int gz_avail OF((gz_statep));
14 local int gz_look OF((gz_statep));
15 local int gz_decomp OF((gz_statep));
16 local int gz_fetch OF((gz_statep));
17 local int gz_skip OF((gz_statep, z_off64_t));
18 local z_size_t gz_read OF((gz_statep, voidp, z_size_t));
20 /* Use read() to load a buffer -- return -1 on error, otherwise 0. Read from
21 state.state->fd, and update state.state->eof, state.state->err, and state.state->msg as appropriate.
22 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. */
24 local int gz_load(state, buf, len, have)
31 unsigned get, max = ((unsigned)-1 >> 2) + 1;
38 ret = read(state.state->fd, buf + *have, get);
41 *have += (unsigned)ret;
42 } while (*have < len);
44 gz_error(state, Z_ERRNO, zstrerror());
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. */
59 local int gz_avail(state)
63 z_streamp strm = &(state.state->strm);
65 if (state.state->err != Z_OK && state.state->err != Z_BUF_ERROR)
67 if (state.state->eof == 0) {
68 if (strm->avail_in) { /* copy what's there to the start */
69 unsigned char *p = state.state->in;
70 unsigned const char *q = strm->next_in;
71 unsigned n = strm->avail_in;
76 if (gz_load(state, state.state->in + strm->avail_in,
77 state.state->size - strm->avail_in, &got) == -1)
79 strm->avail_in += got;
80 strm->next_in = state.state->in;
85 /* 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
87 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. */
94 local int gz_look(state)
97 z_streamp strm = &(state.state->strm);
99 /* allocate read buffers and inflate memory */
100 if (state.state->size == 0) {
101 /* allocate buffers */
102 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) {
105 free(state.state->out);
106 free(state.state->in);
107 gz_error(state, Z_MEM_ERROR, "out of memory");
110 state.state->size = state.state->want;
112 /* allocate inflate memory */
113 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;
122 gz_error(state, Z_MEM_ERROR, "out of memory");
127 /* get at least the magic bytes in the input buffer */
128 if (strm->avail_in < 2) {
129 if (gz_avail(state) == -1)
131 if (strm->avail_in == 0)
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) */
142 if (strm->avail_in > 1 &&
143 ((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 */
146 state.state->how = GZIP;
147 state.state->direct = 0;
151 /* no gzip header -- if we were decoding gzip before, then this is trailing
152 garbage. Ignore the trailing garbage and finish. */
153 if (state.state->direct == 0) {
155 state.state->eof = 1;
156 state.state->x.have = 0;
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() */
163 state.state->x.next = state.state->out;
164 if (strm->avail_in) {
165 memcpy(state.state->x.next, strm->next_in, strm->avail_in);
166 state.state->x.have = strm->avail_in;
169 state.state->how = COPY;
170 state.state->direct = 1;
174 /* Decompress from input to the provided next_out and avail_out in the state.
175 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
178 on success, -1 on failure. */
179 local int gz_decomp(state)
184 z_streamp strm = &(state.state->strm);
186 /* fill output buffer up to end of deflate stream */
187 had = strm->avail_out;
189 /* get more input for inflate() */
190 if (strm->avail_in == 0 && gz_avail(state) == -1)
192 if (strm->avail_in == 0) {
193 gz_error(state, Z_BUF_ERROR, "unexpected end of file");
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");
204 if (ret == Z_MEM_ERROR) {
205 gz_error(state, Z_MEM_ERROR, "out of memory");
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);
213 } while (strm->avail_out && ret != Z_STREAM_END);
215 /* update available output */
216 state.state->x.have = had - strm->avail_out;
217 state.state->x.next = strm->next_out - state.state->x.have;
219 /* if the gzip stream completed successfully, look for another */
220 if (ret == Z_STREAM_END)
221 state.state->how = LOOK;
223 /* good decompression */
227 /* Fetch data and put it in the output buffer. Assumes state.state->x.have is 0.
228 Data is either copied from the input file or decompressed from the input
229 file depending on state.state->how. If state.state->how is LOOK, then a gzip header is
230 looked for to determine whether to copy or decompress. Returns -1 on error,
231 otherwise 0. gz_fetch() will leave state.state->how as COPY or GZIP unless the
232 end of the input file has been reached and all data has been processed. */
233 local int gz_fetch(state)
236 z_streamp strm = &(state.state->strm);
239 switch(state.state->how) {
240 case LOOK: /* -> LOOK, COPY (only if never GZIP), or GZIP */
241 if (gz_look(state) == -1)
243 if (state.state->how == LOOK)
246 case COPY: /* -> COPY */
247 if (gz_load(state, state.state->out, state.state->size << 1, &(state.state->x.have))
250 state.state->x.next = state.state->out;
252 case GZIP: /* -> GZIP or LOOK (if end of gzip stream) */
253 strm->avail_out = state.state->size << 1;
254 strm->next_out = state.state->out;
255 if (gz_decomp(state) == -1)
258 } while (state.state->x.have == 0 && (!state.state->eof || strm->avail_in));
262 /* Skip len uncompressed bytes of output. Return -1 on error, 0 on success. */
263 local int gz_skip(state, len)
269 /* skip over len bytes or reach end-of-file, whichever comes first */
271 /* skip over whatever is in output buffer */
272 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;
281 /* output buffer empty -- return if we're at the end of the input */
282 else if (state.state->eof && state.state->strm.avail_in == 0)
285 /* need more data to skip -- load up output buffer */
287 /* get more output, looking for header if required */
288 if (gz_fetch(state) == -1)
294 /* 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. */
298 local z_size_t gz_read(state, buf, len)
306 /* if len is zero, avoid unnecessary operations */
310 /* process a skip request */
311 if (state.state->seek) {
312 state.state->seek = 0;
313 if (gz_skip(state, state.state->skip) == -1)
317 /* get len bytes to buf, or less than len if at the end */
320 /* set n to the maximum amount of len that fits in an unsigned int */
325 /* first just try copying data from the output buffer */
326 if (state.state->x.have) {
327 if (state.state->x.have < n)
328 n = state.state->x.have;
329 memcpy(buf, state.state->x.next, n);
330 state.state->x.next += n;
331 state.state->x.have -= n;
334 /* output buffer empty -- return if we're at the end of the input */
335 else if (state.state->eof && state.state->strm.avail_in == 0) {
336 state.state->past = 1; /* tried to read past end */
340 /* need output data -- for small len or new stream load up our output
342 else if (state.state->how == LOOK || n < (state.state->size << 1)) {
343 /* get more output, looking for header if required */
344 if (gz_fetch(state) == -1)
346 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 */
351 /* large len -- read directly into user buffer */
352 else if (state.state->how == COPY) { /* read directly */
353 if (gz_load(state, (unsigned char *)buf, n, &n) == -1)
357 /* large len -- decompress directly into user buffer */
358 else { /* state.state->how == GZIP */
359 state.state->strm.avail_out = n;
360 state.state->strm.next_out = (unsigned char *)buf;
361 if (gz_decomp(state) == -1)
363 n = state.state->x.have;
364 state.state->x.have = 0;
367 /* update progress */
369 buf = (char *)buf + n;
371 state.state->x.pos += n;
374 /* return number of bytes read into user buffer */
378 /* -- see zlib.h -- */
379 int ZEXPORT gzread(file, buf, len)
386 /* get internal structure */
389 state = (gz_statep)file;
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))
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) */
399 gz_error(state, Z_STREAM_ERROR, "request does not fit in an int");
403 /* read len or fewer bytes to buf */
404 len = (unsigned)gz_read(state, buf, len);
406 /* check for an error */
407 if (len == 0 && state.state->err != Z_OK && state.state->err != Z_BUF_ERROR)
410 /* return the number of bytes read (this is assured to fit in an int) */
414 /* -- see zlib.h -- */
415 z_size_t ZEXPORT gzfread(buf, size, nitems, file)
424 /* get internal structure */
427 state = (gz_statep)file;
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))
434 /* compute bytes to read -- error on overflow */
436 if (size && len / size != nitems) {
437 gz_error(state, Z_STREAM_ERROR, "request does not fit in a size_t");
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;
445 /* -- see zlib.h -- */
446 #if ZLIB_VERNUM >= 0x1261
454 #if ZLIB_VERNUM == 0x1260
458 #if ZLIB_VERNUM <= 0x1250
459 ZEXTERN int ZEXPORT gzgetc OF((gzFile file));
460 ZEXTERN int ZEXPORT gzgetc_ OF((gzFile file));
463 int ZEXPORT gzgetc(file)
467 unsigned char buf[1];
470 /* get internal structure */
473 state = (gz_statep)file;
475 /* check that we're reading and that there's no (serious) error */
476 if (state.state->mode != GZ_READ ||
477 (state.state->err != Z_OK && state.state->err != Z_BUF_ERROR))
480 /* try output buffer (no need to check for skip request) */
481 if (state.state->x.have) {
482 state.state->x.have--;
483 state.state->x.pos++;
484 return *(state.state->x.next)++;
487 /* nothing there -- try gz_read() */
488 ret = (unsigned)gz_read(state, buf, 1);
489 return ret < 1 ? -1 : buf[0];
492 int ZEXPORT gzgetc_(file)
498 /* -- see zlib.h -- */
499 int ZEXPORT gzungetc(c, file)
505 /* get internal structure */
508 state = (gz_statep)file;
510 /* check that we're reading and that there's no (serious) error */
511 if (state.state->mode != GZ_READ ||
512 (state.state->err != Z_OK && state.state->err != Z_BUF_ERROR))
515 /* process a skip request */
516 if (state.state->seek) {
517 state.state->seek = 0;
518 if (gz_skip(state, state.state->skip) == -1)
526 /* if output buffer empty, put byte at end (allows more pushing) */
527 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;
530 state.state->x.next[0] = (unsigned char)c;
531 state.state->x.pos--;
532 state.state->past = 0;
536 /* if no room, give up (must have already done a gzungetc()) */
537 if (state.state->x.have == (state.state->size << 1)) {
538 gz_error(state, Z_DATA_ERROR, "out of room to push characters");
542 /* slide output data if needed and insert byte before existing data */
543 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)
548 state.state->x.next = dest;
550 state.state->x.have++;
551 state.state->x.next--;
552 state.state->x.next[0] = (unsigned char)c;
553 state.state->x.pos--;
554 state.state->past = 0;
558 /* -- see zlib.h -- */
559 char * ZEXPORT gzgets(file, buf, len)
569 /* check parameters and get internal structure */
570 if (file == NULL || buf == NULL || len < 1)
572 state = (gz_statep)file;
574 /* check that we're reading and that there's no (serious) error */
575 if (state.state->mode != GZ_READ ||
576 (state.state->err != Z_OK && state.state->err != Z_BUF_ERROR))
579 /* process a skip request */
580 if (state.state->seek) {
581 state.state->seek = 0;
582 if (gz_skip(state, state.state->skip) == -1)
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) */
590 left = (unsigned)len - 1;
592 /* assure that something is in the output buffer */
593 if (state.state->x.have == 0 && gz_fetch(state) == -1)
594 return NULL; /* error */
595 if (state.state->x.have == 0) { /* end of file */
596 state.state->past = 1; /* read past end */
597 break; /* return what we have */
600 /* look for end-of-line in current output buffer */
601 n = state.state->x.have > left ? left : state.state->x.have;
602 eol = (unsigned char *)memchr(state.state->x.next, '\n', n);
604 n = (unsigned)(eol - state.state->x.next) + 1;
606 /* copy through end-of-line, or remainder if not found */
607 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;
613 } while (left && eol == NULL);
615 /* return terminated string, or if nothing, end of file */
622 /* -- see zlib.h -- */
623 int ZEXPORT gzdirect(file)
628 /* get internal structure */
631 state = (gz_statep)file;
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()) */
635 if (state.state->mode == GZ_READ && state.state->how == LOOK && state.state->x.have == 0)
636 (void)gz_look(state);
638 /* return 1 if transparent, 0 if processing a gzip stream */
639 return state.state->direct;
642 /* -- see zlib.h -- */
643 int ZEXPORT gzclose_r(file)
649 /* get internal structure */
651 return Z_STREAM_ERROR;
652 state = (gz_statep)file;
654 /* check that we're reading */
655 if (state.state->mode != GZ_READ)
656 return Z_STREAM_ERROR;
658 /* free memory and close file */
659 if (state.state->size) {
660 inflateEnd(&(state.state->strm));
661 free(state.state->out);
662 free(state.state->in);
664 err = state.state->err == Z_BUF_ERROR ? Z_BUF_ERROR : Z_OK;
665 gz_error(state, Z_OK, NULL);
666 free(state.state->path);
667 ret = close(state.state->fd);
669 return ret ? Z_ERRNO : err;