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