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