1 /* gzread.c -- zlib functions for reading gzip files
2 * Copyright (C) 2004, 2005, 2010 Mark Adler
3 * For conditions of distribution and use, see copyright notice in zlib.h
9 #if TARGET_MSDOS == 16 && (defined(__SMALL__) || defined(__MEDIUM__))
15 local int gz_load OF((gz_statep, voidpf, unsigned, unsigned *));
16 local int gz_avail OF((gz_statep));
17 local int gz_next4 OF((gz_statep, unsigned long *));
18 local int gz_head OF((gz_statep));
19 local int gz_decomp OF((gz_statep));
20 local int gz_make OF((gz_statep));
21 local int gz_skip OF((gz_statep, z_off64_t));
23 /* Use read() to load a buffer -- return -1 on error, otherwise 0. Read from
24 state->fd, and update state->eof, state->err, and state->msg as appropriate.
25 This function needs to loop on read(), since read() is not guaranteed to
26 read the number of bytes requested, depending on the type of descriptor. */
27 local int gz_load(state, buf, len, have)
37 #if TARGET_MSDOS == 16 && (defined(__SMALL__) || defined(__MEDIUM__))
39 if (_dos_read(state->fd, (unsigned char FAR*)buf + *have, len - *have, (unsigned*)(&ret)) != 0 || ret == 0)
42 ret = read(state->fd, (unsigned char*)buf + *have, len - *have);
47 } while (*have < len);
49 gz_error(state, Z_ERRNO, zstrerror());
58 /* Load up input buffer and set eof flag if last data loaded -- return -1 on
59 error, 0 otherwise. Note that the eof flag is set when the end of the input
60 file is reached, even though there may be unused data in the buffer. Once
61 that data has been used, no more attempts will be made to read the file.
62 gz_avail() assumes that strm->avail_in == 0. */
63 local int gz_avail(state)
66 z_streamp strm = &(state->strm);
68 if (state->err != Z_OK)
70 if (state->eof == 0) {
71 if (gz_load(state, state->in, state->size,
72 (unsigned *)&(strm->avail_in)) == -1)
74 strm->next_in = state->in;
79 /* Get next byte from input, or -1 if end or error. */
80 #define NEXT() ((strm->avail_in == 0 && gz_avail(state) == -1) ? -1 : \
81 (strm->avail_in == 0 ? -1 : \
82 (strm->avail_in--, *(strm->next_in)++)))
84 /* Get a four-byte little-endian integer and return 0 on success and the value
85 in *ret. Otherwise -1 is returned and *ret is not modified. */
86 local int gz_next4(state, ret)
92 z_streamp strm = &(state->strm);
95 val += (unsigned)NEXT() << 8;
96 val += (unsigned long)NEXT() << 16;
100 val += (unsigned long)ch << 24;
105 /* Look for gzip header, set up for inflate or copy. state->have must be zero.
106 If this is the first time in, allocate required memory. state->how will be
107 left unchanged if there is no more input data available, will be set to COPY
108 if there is no gzip header and direct copying will be performed, or it will
109 be set to GZIP for decompression, and the gzip header will be skipped so
110 that the next available input data is the raw deflate stream. If direct
111 copying, then leftover input data from the input buffer will be copied to
112 the output buffer. In that case, all further file reads will be directly to
113 either the output buffer or a user buffer. If decompressing, the inflate
114 state and the check value will be initialized. gz_head() will return 0 on
115 success or -1 on failure. Failures may include read errors or gzip header
117 local int gz_head(state)
120 z_streamp strm = &(state->strm);
124 /* allocate read buffers and inflate memory */
125 if (state->size == 0) {
126 /* allocate buffers */
127 #if TARGET_MSDOS == 16 && (defined(__SMALL__) || defined(__MEDIUM__))
128 state->in = _fmalloc(state->want);
129 state->out = _fmalloc(state->want << 1);
131 state->in = malloc(state->want);
132 state->out = malloc(state->want << 1);
134 if (state->in == NULL || state->out == NULL) {
135 #if TARGET_MSDOS == 16 && (defined(__SMALL__) || defined(__MEDIUM__))
136 if (state->out != NULL)
138 if (state->in != NULL)
141 if (state->out != NULL)
143 if (state->in != NULL)
146 gz_error(state, Z_MEM_ERROR, "out of memory");
149 state->size = state->want;
151 /* allocate inflate memory */
152 state->strm.zalloc = Z_NULL;
153 state->strm.zfree = Z_NULL;
154 state->strm.opaque = Z_NULL;
155 state->strm.avail_in = 0;
156 state->strm.next_in = Z_NULL;
157 if (inflateInit2(&(state->strm), -15) != Z_OK) { /* raw inflate */
158 #if TARGET_MSDOS == 16 && (defined(__SMALL__) || defined(__MEDIUM__))
166 gz_error(state, Z_MEM_ERROR, "out of memory");
171 /* get some data in the input buffer */
172 if (strm->avail_in == 0) {
173 if (gz_avail(state) == -1)
175 if (strm->avail_in == 0)
179 /* look for the gzip magic header bytes 31 and 139 */
180 if (strm->next_in[0] == 31) {
183 if (strm->avail_in == 0 && gz_avail(state) == -1)
185 if (strm->avail_in && strm->next_in[0] == 139) {
186 /* we have a gzip header, woo hoo! */
190 /* skip rest of header */
191 if (NEXT() != 8) { /* compression method */
192 gz_error(state, Z_DATA_ERROR, "unknown compression method");
196 if (flags & 0xe0) { /* reserved flag bits */
197 gz_error(state, Z_DATA_ERROR, "unknown header flags set");
200 NEXT(); /* modification time */
204 NEXT(); /* extra flags */
205 NEXT(); /* operating system */
206 if (flags & 4) { /* extra field */
207 len = (unsigned)NEXT();
208 len += (unsigned)NEXT() << 8;
213 if (flags & 8) /* file name */
216 if (flags & 16) /* comment */
219 if (flags & 2) { /* header crc */
223 /* an unexpected end of file is not checked for here -- it will be
224 noticed on the first request for uncompressed data */
226 /* set up for decompression */
228 strm->adler = crc32(0L, Z_NULL, 0);
234 /* not a gzip file -- save first byte (31) and fall to raw i/o */
240 /* doing raw i/o, save start of raw data for seeking, copy any leftover
241 input to output -- this assumes that the output buffer is larger than
242 the input buffer, which also assures space for gzungetc() */
243 state->raw = state->pos;
244 state->next = state->out;
245 if (strm->avail_in) {
246 zmemcpy(state->next + state->have, strm->next_in, strm->avail_in);
247 state->have += strm->avail_in;
255 /* Decompress from input to the provided next_out and avail_out in the state.
256 If the end of the compressed data is reached, then verify the gzip trailer
257 check value and length (modulo 2^32). state->have and state->next are set
258 to point to the just decompressed data, and the crc is updated. If the
259 trailer is verified, state->how is reset to LOOK to look for the next gzip
260 stream or raw data, once state->have is depleted. Returns 0 on success, -1
261 on failure. Failures may include invalid compressed data or a failed gzip
262 trailer verification. */
263 local int gz_decomp(state)
268 unsigned long crc, len;
269 z_streamp strm = &(state->strm);
271 /* fill output buffer up to end of deflate stream */
272 had = strm->avail_out;
274 /* get more input for inflate() */
275 if (strm->avail_in == 0 && gz_avail(state) == -1)
277 if (strm->avail_in == 0) {
278 gz_error(state, Z_DATA_ERROR, "unexpected end of file");
282 /* decompress and handle errors */
283 ret = inflate(strm, Z_NO_FLUSH);
284 if (ret == Z_STREAM_ERROR || ret == Z_NEED_DICT) {
285 gz_error(state, Z_STREAM_ERROR,
286 "internal error: inflate stream corrupt");
289 if (ret == Z_MEM_ERROR) {
290 gz_error(state, Z_MEM_ERROR, "out of memory");
293 if (ret == Z_DATA_ERROR) { /* deflate stream invalid */
294 gz_error(state, Z_DATA_ERROR,
295 strm->msg == NULL ? "compressed data error" : strm->msg);
298 } while (strm->avail_out && ret != Z_STREAM_END);
300 /* update available output and crc check value */
301 state->have = had - strm->avail_out;
302 state->next = strm->next_out - state->have;
303 strm->adler = crc32(strm->adler, state->next, state->have);
305 /* check gzip trailer if at end of deflate stream */
306 if (ret == Z_STREAM_END) {
307 if (gz_next4(state, &crc) == -1 || gz_next4(state, &len) == -1) {
308 gz_error(state, Z_DATA_ERROR, "unexpected end of file");
311 if (crc != strm->adler) {
312 gz_error(state, Z_DATA_ERROR, "incorrect data check");
315 if (len != (strm->total_out & 0xffffffffL)) {
316 gz_error(state, Z_DATA_ERROR, "incorrect length check");
319 state->how = LOOK; /* ready for next stream, once have is 0 (leave
320 state->direct unchanged to remember how) */
323 /* good decompression */
327 /* Make data and put in the output buffer. Assumes that state->have == 0.
328 Data is either copied from the input file or decompressed from the input
329 file depending on state->how. If state->how is LOOK, then a gzip header is
330 looked for (and skipped if found) to determine wither to copy or decompress.
331 Returns -1 on error, otherwise 0. gz_make() will leave state->have as COPY
332 or GZIP unless the end of the input file has been reached and all data has
334 local int gz_make(state)
337 z_streamp strm = &(state->strm);
339 if (state->how == LOOK) { /* look for gzip header */
340 if (gz_head(state) == -1)
342 if (state->have) /* got some data from gz_head() */
345 if (state->how == COPY) { /* straight copy */
346 if (gz_load(state, state->out, state->size << 1, &(state->have)) == -1)
348 state->next = state->out;
350 else if (state->how == GZIP) { /* decompress */
351 strm->avail_out = state->size << 1;
352 strm->next_out = state->out;
353 if (gz_decomp(state) == -1)
359 /* Skip len uncompressed bytes of output. Return -1 on error, 0 on success. */
360 local int gz_skip(state, len)
366 /* skip over len bytes or reach end-of-file, whichever comes first */
368 /* skip over whatever is in output buffer */
370 n = GT_OFF(state->have) || (z_off64_t)state->have > len ?
371 (unsigned)len : state->have;
378 /* output buffer empty -- return if we're at the end of the input */
379 else if (state->eof && state->strm.avail_in == 0)
382 /* need more data to skip -- load up output buffer */
384 /* get more output, looking for header if required */
385 if (gz_make(state) == -1)
391 /* -- see zlib.h -- */
392 int ZEXPORT gzread(file, buf, len)
401 /* get internal structure */
404 state = (gz_statep)file;
405 strm = &(state->strm);
407 /* check that we're reading and that there's no error */
408 if (state->mode != GZ_READ || state->err != Z_OK)
411 /* since an int is returned, make sure len fits in one, otherwise return
412 with an error (this avoids the flaw in the interface) */
414 gz_error(state, Z_BUF_ERROR, "requested length does not fit in int");
418 /* if len is zero, avoid unnecessary operations */
422 /* process a skip request */
425 if (gz_skip(state, state->skip) == -1)
429 /* get len bytes to buf, or less than len if at the end */
432 /* first just try copying data from the output buffer */
434 n = state->have > len ? len : state->have;
435 zmemcpy(buf, state->next, n);
440 /* output buffer empty -- return if we're at the end of the input */
441 else if (state->eof && strm->avail_in == 0)
444 /* need output data -- for small len or new stream load up our output
446 else if (state->how == LOOK || len < (state->size << 1)) {
447 /* get more output, looking for header if required */
448 if (gz_make(state) == -1)
450 continue; /* no progress yet -- go back to memcpy() above */
451 /* the copy above assures that we will leave with space in the
452 output buffer, allowing at least one gzungetc() to succeed */
455 /* large len -- read directly into user buffer */
456 else if (state->how == COPY) { /* read directly */
457 if (gz_load(state, buf, len, &n) == -1)
461 /* large len -- decompress directly into user buffer */
462 else { /* state->how == GZIP */
463 strm->avail_out = len;
464 strm->next_out = buf;
465 if (gz_decomp(state) == -1)
471 /* update progress */
473 buf = (char FAR *)buf + n;
478 /* return number of bytes read into user buffer (will fit in int) */
482 /* -- see zlib.h -- */
483 int ZEXPORT gzgetc(file)
487 unsigned char buf[1];
490 /* get internal structure */
493 state = (gz_statep)file;
495 /* check that we're reading and that there's no error */
496 if (state->mode != GZ_READ || state->err != Z_OK)
499 /* try output buffer (no need to check for skip request) */
503 return *(state->next)++;
506 /* nothing there -- try gzread() */
507 ret = gzread(file, buf, 1);
508 return ret < 1 ? -1 : buf[0];
511 /* -- see zlib.h -- */
512 int ZEXPORT gzungetc(c, file)
518 /* get internal structure */
521 state = (gz_statep)file;
523 /* check that we're reading and that there's no error */
524 if (state->mode != GZ_READ || state->err != Z_OK)
527 /* process a skip request */
530 if (gz_skip(state, state->skip) == -1)
538 /* if output buffer empty, put byte at end (allows more pushing) */
539 if (state->have == 0) {
541 state->next = state->out + (state->size << 1) - 1;
547 /* if no room, give up (must have already done a gzungetc()) */
548 if (state->have == (state->size << 1)) {
549 gz_error(state, Z_BUF_ERROR, "out of room to push characters");
553 /* slide output data if needed and insert byte before existing data */
554 if (state->next == state->out) {
555 unsigned char FAR *src = state->out + state->have;
556 unsigned char FAR *dest = state->out + (state->size << 1);
557 while (src > state->out)
568 /* -- see zlib.h -- */
569 char * ZEXPORT gzgets(file, buf, len)
576 unsigned char FAR *eol;
579 /* check parameters and get internal structure */
580 if (file == NULL || buf == NULL || len < 1)
582 state = (gz_statep)file;
584 /* check that we're reading and that there's no error */
585 if (state->mode != GZ_READ || state->err != Z_OK)
588 /* process a skip request */
591 if (gz_skip(state, state->skip) == -1)
595 /* copy output bytes up to new line or len - 1, whichever comes first --
596 append a terminating zero to the string (we don't check for a zero in
597 the contents, let the user worry about that) */
599 left = (unsigned)len - 1;
601 /* assure that something is in the output buffer */
602 if (state->have == 0) {
603 if (gz_make(state) == -1)
604 return NULL; /* error */
605 if (state->have == 0) { /* end of file */
606 if (buf == str) /* got bupkus */
608 break; /* got something -- return it */
612 /* look for end-of-line in current output buffer */
613 n = state->have > left ? left : state->have;
614 eol = zmemchr(state->next, '\n', n);
616 n = (unsigned)(eol - state->next) + 1;
618 /* copy through end-of-line, or remainder if not found */
619 zmemcpy(buf, state->next, n);
625 } while (left && eol == NULL);
627 /* found end-of-line or out of space -- terminate string and return it */
632 /* -- see zlib.h -- */
633 int ZEXPORT gzdirect(file)
638 /* get internal structure */
641 state = (gz_statep)file;
643 /* check that we're reading */
644 if (state->mode != GZ_READ)
647 /* if the state is not known, but we can find out, then do so (this is
648 mainly for right after a gzopen() or gzdopen()) */
649 if (state->how == LOOK && state->have == 0)
650 (void)gz_head(state);
652 /* return 1 if reading direct, 0 if decompressing a gzip stream */
653 return state->direct;
656 /* -- see zlib.h -- */
657 int ZEXPORT gzclose_r(file)
663 /* get internal structure */
665 return Z_STREAM_ERROR;
666 state = (gz_statep)file;
668 /* check that we're reading */
669 if (state->mode != GZ_READ)
670 return Z_STREAM_ERROR;
672 /* free memory and close file */
674 inflateEnd(&(state->strm));
675 #if TARGET_MSDOS == 16 && (defined(__SMALL__) || defined(__MEDIUM__))
683 gz_error(state, Z_OK, NULL);
685 ret = close(state->fd);
687 return ret ? Z_ERRNO : Z_OK;