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