]> git.lizzy.rs Git - zlib.git/blob - gzread.c
zlib 1.2.3.6
[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_off_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 1 if
96    there is no gzip header and direct copying will be performed, or it will be
97    set to 2 for decompression, and the gzip header will be skipped so that the
98    next available input data is the raw deflate stream.  If direct copying,
99    then leftover input data from the input buffer will be copied to the output
100    buffer.  In that case, all further file reads will be directly to either the
101    output buffer or a user buffer.  If decompressing, the inflate state and the
102    check value will be initialized.  gz_head() will return 0 on success or -1
103    on failure.  Failures may include read errors or gzip header 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 = 2;
200             return 0;
201         }
202         else {
203             /* not a gzip file -- save first byte (31) and fall to raw i/o */
204             state->out[0] = 31;
205             state->have = 1;
206         }
207     }
208
209     /* doing raw i/o, save start of raw data for seeking, copy any leftover
210        input to output -- this assumes that the output buffer is larger than
211        the input buffer, which also assures space for gzungetc() */
212     state->raw = state->pos;
213     state->next = state->out;
214     if (strm->avail_in) {
215         memcpy(state->next + state->have, strm->next_in, strm->avail_in);
216         state->have += strm->avail_in;
217         strm->avail_in = 0;
218     }
219     state->how = 1;
220     return 0;
221 }
222
223 /* Decompress from input to the provided next_out and avail_out in the state.
224    If the end of the compressed data is reached, then verify the gzip trailer
225    check value and length (modulo 2^32).  state->have and state->next are set
226    to point to the just decompressed data, and the crc is updated.  If the
227    trailer is verified, state->how is reset to zero to look for the next gzip
228    stream or raw data, once state->have is depleted.  Returns 0 on success, -1
229    on failure.  Failures may include invalid compressed data or a failed gzip
230    trailer verification. */
231 local int gz_decomp(state)
232     gz_statep state;
233 {
234     int ret;
235     unsigned had;
236     unsigned long crc, len;
237     z_streamp strm = &(state->strm);
238
239     /* fill output buffer up to end of deflate stream */
240     had = strm->avail_out;
241     do {
242         /* get more input for inflate() */
243         if (strm->avail_in == 0 && gz_avail(state) == -1)
244             return -1;
245         if (strm->avail_in == 0) {
246             gz_error(state, Z_DATA_ERROR, "unexpected end of file");
247             return -1;
248         }
249
250         /* decompress and handle errors */
251         ret = inflate(strm, Z_NO_FLUSH);
252         if (ret == Z_STREAM_ERROR || ret == Z_NEED_DICT) {
253             gz_error(state, Z_STREAM_ERROR,
254                       "internal error: inflate stream corrupt");
255             return -1;
256         }
257         if (ret == Z_MEM_ERROR) {
258             gz_error(state, Z_MEM_ERROR, "out of memory");
259             return -1;
260         }
261         if (ret == Z_DATA_ERROR) {              /* deflate stream invalid */
262             gz_error(state, Z_DATA_ERROR,
263                       strm->msg == NULL ? "compressed data error" : strm->msg);
264             return -1;
265         }
266     } while (strm->avail_out && ret != Z_STREAM_END);
267
268     /* update available output and crc check value */
269     state->have = had - strm->avail_out;
270     state->next = strm->next_out - state->have;
271     strm->adler = crc32(strm->adler, state->next, state->have);
272
273     /* check gzip trailer if at end of deflate stream */
274     if (ret == Z_STREAM_END) {
275         if (gz_next4(state, &crc) == -1 || gz_next4(state, &len) == -1) {
276             gz_error(state, Z_DATA_ERROR, "unexpected end of file");
277             return -1;
278         }
279         if (crc != strm->adler) {
280             gz_error(state, Z_DATA_ERROR, "incorrect data check");
281             return -1;
282         }
283         if (len != (strm->total_out & 0xffffffffL)) {
284             gz_error(state, Z_DATA_ERROR, "incorrect length check");
285             return -1;
286         }
287         state->how = 0;         /* ready for next stream, once have is 0 */
288     }
289
290     /* good decompression */
291     return 0;
292 }
293
294 /* Make data and put in the output buffer.  Assumes that state->have == 0.
295    Data is either copied from the input file or decompressed from the input
296    file depending on state->how.  If state->how is zero, then a gzip header is
297    looked for (and skipped if found) to determine wither to copy or decompress.
298    Returns -1 on error, otherwise 0.  gz_make() will leave state->have non-zero
299    unless the end of the input file has been reached and all data has been
300    processed. */
301 local int gz_make(state)
302     gz_statep state;
303 {
304     z_streamp strm = &(state->strm);
305
306     if (state->how == 0) {              /* look for gzip header */
307         if (gz_head(state) == -1)
308             return -1;
309         if (state->have)                /* got some data from gz_head() */
310             return 0;
311     }
312     if (state->how == 1) {              /* straight copy */
313         if (gz_load(state, state->out, state->size << 1, &(state->have)) == -1)
314             return -1;
315         state->next = state->out;
316     }
317     else if (state->how == 2) {         /* decompress */
318         strm->avail_out = state->size << 1;
319         strm->next_out = state->out;
320         if (gz_decomp(state) == -1)
321             return -1;
322     }
323     return 0;
324 }
325
326 /* Skip len uncompressed bytes of output.  Return -1 on error, 0 on success. */
327 local int gz_skip(state, len)
328     gz_statep state;
329     z_off_t len;
330 {
331     unsigned n;
332
333     /* skip over len bytes or reach end-of-file, whichever comes first */
334     while (len)
335         /* skip over whatever is in output buffer */
336         if (state->have) {
337             n = state->have > len ? (unsigned)len : state->have;
338             state->have -= n;
339             state->next += n;
340             state->pos += n;
341             len -= n;
342         }
343
344         /* output buffer empty -- return if we're at the end of the input */
345         else if (state->eof && state->strm.avail_in == 0)
346             break;
347
348         /* need more data to skip -- load up output buffer */
349         else {
350             /* get more output, looking for header if required */
351             if (gz_make(state) == -1)
352                 return -1;
353         }
354     return 0;
355 }
356
357 /* -- see zlib.h -- */
358 int ZEXPORT gzread(file, buf, len)
359     gzFile file;
360     voidp buf;
361     unsigned len;
362 {
363     unsigned got, n;
364     gz_statep state;
365     z_streamp strm;
366
367     /* get internal structure */
368     if (file == NULL)
369         return -1;
370     state = (gz_statep)file;
371     strm = &(state->strm);
372
373     /* check that we're reading and that there's no error */
374     if (state->mode != GZ_READ || state->err != Z_OK)
375         return -1;
376
377     /* since an int is returned, make sure len fits in one, otherwise return
378        with an error (this avoids the flaw in the interface) */
379     if ((int)len < 0) {
380         gz_error(state, Z_BUF_ERROR, "requested length does not fit in int");
381         return -1;
382     }
383
384     /* if len is zero, avoid unnecessary operations */
385     if (len == 0)
386         return 0;
387
388     /* process a skip request */
389     if (state->seek) {
390         state->seek = 0;
391         if (gz_skip(state, state->skip) == -1)
392             return -1;
393     }
394
395     /* get len bytes to buf, or less than len if at the end */
396     got = 0;
397     do {
398         /* first just try copying data from the output buffer */
399         if (state->have) {
400             n = state->have > len ? len : state->have;
401             memcpy(buf, state->next, n);
402             state->next += n;
403             state->have -= n;
404         }
405
406         /* output buffer empty -- return if we're at the end of the input */
407         else if (state->eof && strm->avail_in == 0)
408             break;
409
410         /* need output data -- for small len or new stream load up our output
411            buffer */
412         else if (state->how == 0 || len < (state->size << 1)) {
413             /* get more output, looking for header if required */
414             if (gz_make(state) == -1)
415                 return -1;
416             continue;       /* no progress yet -- go back to memcpy() above */
417             /* the copy above assures that we will leave with space in the
418                output buffer, allowing at least one gzungetc() to succeed */
419         }
420
421         /* large len -- read directly into user buffer */
422         else if (state->how == 1) {          /* read directly */
423             if (gz_load(state, buf, len, &n) == -1)
424                 return -1;
425         }
426
427         /* large len -- decompress directly into user buffer */
428         else {  /* state->how == 2 */
429             strm->avail_out = len;
430             strm->next_out = buf;
431             if (gz_decomp(state) == -1)
432                 return -1;
433             n = state->have;
434             state->have = 0;
435         }
436
437         /* update progress */
438         len -= n;
439         buf = (char *)buf + n;
440         got += n;
441         state->pos += n;
442     } while (len);
443
444     /* return number of bytes read into user buffer (will fit in int) */
445     return (int)got;
446 }
447
448 /* -- see zlib.h -- */
449 int ZEXPORT gzgetc(file)
450     gzFile file;
451 {
452     int ret;
453     unsigned char buf[1];
454     gz_statep state;
455
456     /* get internal structure */
457     if (file == NULL)
458         return -1;
459     state = (gz_statep)file;
460
461     /* check that we're reading and that there's no error */
462     if (state->mode != GZ_READ || state->err != Z_OK)
463         return -1;
464
465     /* try output buffer (no need to check for skip request) */
466     if (state->have) {
467         state->have--;
468         state->pos++;
469         return *(state->next)++;
470     }
471
472     /* nothing there -- try gzread() */
473     ret = gzread(file, buf, 1);
474     return ret < 1 ? -1 : buf[0];
475 }
476
477 /* -- see zlib.h -- */
478 int ZEXPORT gzungetc(c, file)
479     int c;
480     gzFile file;
481 {
482     gz_statep state;
483
484     /* get internal structure */
485     if (file == NULL)
486         return -1;
487     state = (gz_statep)file;
488
489     /* check that we're reading and that there's no error */
490     if (state->mode != GZ_READ || state->err != Z_OK)
491         return -1;
492
493     /* process a skip request */
494     if (state->seek) {
495         state->seek = 0;
496         if (gz_skip(state, state->skip) == -1)
497             return -1;
498     }
499
500     /* can't push EOF */
501     if (c < 0)
502         return -1;
503
504     /* if output buffer empty, put byte at end (allows more pushing) */
505     if (state->have == 0) {
506         state->have = 1;
507         state->next = state->out + (state->size << 1) - 1;
508         state->next[0] = c;
509         state->pos--;
510         return c;
511     }
512
513     /* if no room, give up (must have already done a gzungetc()) */
514     if (state->have == (state->size << 1)) {
515         gz_error(state, Z_BUF_ERROR, "out of room to push characters");
516         return -1;
517     }
518
519     /* slide output data if needed and insert byte before existing data */
520     if (state->next == state->out) {
521         unsigned char *src = state->out + state->have;
522         unsigned char *dest = state->out + (state->size << 1);
523         while (src > state->out)
524             *--dest = *--src;
525         state->next = dest;
526     }
527     state->have++;
528     state->next--;
529     state->next[0] = c;
530     state->pos--;
531     return c;
532 }
533
534 /* -- see zlib.h -- */
535 char * ZEXPORT gzgets(file, buf, len)
536     gzFile file;
537     char *buf;
538     int len;
539 {
540     unsigned left, n;
541     char *str;
542     unsigned char *eol;
543     gz_statep state;
544
545     /* get internal structure */
546     if (file == NULL)
547         return NULL;
548     state = (gz_statep)file;
549
550     /* check that we're reading and that there's no error */
551     if (state->mode != GZ_READ || state->err != Z_OK)
552         return NULL;
553
554     /* process a skip request */
555     if (state->seek) {
556         state->seek = 0;
557         if (gz_skip(state, state->skip) == -1)
558             return NULL;
559     }
560
561     /* check for a dumb length */
562     if (len < 2)
563         return NULL;
564
565     /* copy output bytes up to new line or len - 1, whichever comes first --
566        append a terminating zero to the string (we don't check for a zero in
567        the contents, let the user worry about that) */
568     str = buf;
569     left = (unsigned)len - 1;
570     do {
571         /* assure that something is in the output buffer */
572         if (state->have == 0) {
573             if (gz_make(state) == -1)
574                 return NULL;            /* error */
575             if (state->have == 0) {     /* end of file */
576                 if (buf == str)         /* got bupkus */
577                     return NULL;
578                 break;                  /* got something -- return it */
579             }
580         }
581
582         /* look for end-of-line in current output buffer */
583         n = state->have > left ? left : state->have;
584         eol = memchr(state->next, '\n', n);
585         if (eol != NULL)
586             n = (eol - state->next) + 1;
587
588         /* copy through end-of-line, or remainder if not found */
589         memcpy(buf, state->next, n);
590         state->have -= n;
591         state->next += n;
592         state->pos += n;
593         left -= n;
594         buf += n;
595     } while (left && eol == NULL);
596
597     /* found end-of-line or out of space -- terminate string and return it */
598     buf[0] = 0;
599     return str;
600 }
601
602 /* -- see zlib.h -- */
603 int ZEXPORT gzdirect(file)
604     gzFile file;
605 {
606     gz_statep state;
607
608     /* get internal structure */
609     if (file == NULL)
610         return 0;
611     state = (gz_statep)file;
612
613     /* check that we're reading */
614     if (state->mode != GZ_READ)
615         return 0;
616
617     /* return true if reading without decompression */
618     return state->how == 1;
619 }
620
621 /* -- see zlib.h -- */
622 int ZEXPORT gzclose_r(file)
623     gzFile file;
624 {
625     gz_statep state;
626
627     /* get internal structure */
628     if (file == NULL)
629         return Z_STREAM_ERROR;
630     state = (gz_statep)file;
631
632     /* check that we're reading */
633     if (state->mode != GZ_READ)
634         return Z_STREAM_ERROR;
635
636     /* free memory and close file */
637     if (state->size) {
638         inflateEnd(&(state->strm));
639         free(state->out);
640         free(state->in);
641     }
642     gz_error(state, Z_OK, NULL);
643     close(state->fd);
644     free(state);
645     return Z_OK;
646 }
647
648 #endif /* !OLD_GZIO */