]> git.lizzy.rs Git - zlib.git/blob - gzread.c
zlib 1.2.3.7
[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 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_off_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 = state->have > len ? (unsigned)len : state->have;
342             state->have -= n;
343             state->next += n;
344             state->pos += n;
345             len -= n;
346         }
347
348         /* output buffer empty -- return if we're at the end of the input */
349         else if (state->eof && state->strm.avail_in == 0)
350             break;
351
352         /* need more data to skip -- load up output buffer */
353         else {
354             /* get more output, looking for header if required */
355             if (gz_make(state) == -1)
356                 return -1;
357         }
358     return 0;
359 }
360
361 /* -- see zlib.h -- */
362 int ZEXPORT gzread(file, buf, len)
363     gzFile file;
364     voidp buf;
365     unsigned len;
366 {
367     unsigned got, n;
368     gz_statep state;
369     z_streamp strm;
370
371     /* get internal structure */
372     if (file == NULL)
373         return -1;
374     state = (gz_statep)file;
375     strm = &(state->strm);
376
377     /* check that we're reading and that there's no error */
378     if (state->mode != GZ_READ || state->err != Z_OK)
379         return -1;
380
381     /* since an int is returned, make sure len fits in one, otherwise return
382        with an error (this avoids the flaw in the interface) */
383     if ((int)len < 0) {
384         gz_error(state, Z_BUF_ERROR, "requested length does not fit in int");
385         return -1;
386     }
387
388     /* if len is zero, avoid unnecessary operations */
389     if (len == 0)
390         return 0;
391
392     /* process a skip request */
393     if (state->seek) {
394         state->seek = 0;
395         if (gz_skip(state, state->skip) == -1)
396             return -1;
397     }
398
399     /* get len bytes to buf, or less than len if at the end */
400     got = 0;
401     do {
402         /* first just try copying data from the output buffer */
403         if (state->have) {
404             n = state->have > len ? len : state->have;
405             memcpy(buf, state->next, n);
406             state->next += n;
407             state->have -= n;
408         }
409
410         /* output buffer empty -- return if we're at the end of the input */
411         else if (state->eof && strm->avail_in == 0)
412             break;
413
414         /* need output data -- for small len or new stream load up our output
415            buffer */
416         else if (state->how == LOOK || len < (state->size << 1)) {
417             /* get more output, looking for header if required */
418             if (gz_make(state) == -1)
419                 return -1;
420             continue;       /* no progress yet -- go back to memcpy() above */
421             /* the copy above assures that we will leave with space in the
422                output buffer, allowing at least one gzungetc() to succeed */
423         }
424
425         /* large len -- read directly into user buffer */
426         else if (state->how == COPY) {      /* read directly */
427             if (gz_load(state, buf, len, &n) == -1)
428                 return -1;
429         }
430
431         /* large len -- decompress directly into user buffer */
432         else {  /* state->how == GZIP */
433             strm->avail_out = len;
434             strm->next_out = buf;
435             if (gz_decomp(state) == -1)
436                 return -1;
437             n = state->have;
438             state->have = 0;
439         }
440
441         /* update progress */
442         len -= n;
443         buf = (char *)buf + n;
444         got += n;
445         state->pos += n;
446     } while (len);
447
448     /* return number of bytes read into user buffer (will fit in int) */
449     return (int)got;
450 }
451
452 /* -- see zlib.h -- */
453 int ZEXPORT gzgetc(file)
454     gzFile file;
455 {
456     int ret;
457     unsigned char buf[1];
458     gz_statep state;
459
460     /* get internal structure */
461     if (file == NULL)
462         return -1;
463     state = (gz_statep)file;
464
465     /* check that we're reading and that there's no error */
466     if (state->mode != GZ_READ || state->err != Z_OK)
467         return -1;
468
469     /* try output buffer (no need to check for skip request) */
470     if (state->have) {
471         state->have--;
472         state->pos++;
473         return *(state->next)++;
474     }
475
476     /* nothing there -- try gzread() */
477     ret = gzread(file, buf, 1);
478     return ret < 1 ? -1 : buf[0];
479 }
480
481 /* -- see zlib.h -- */
482 int ZEXPORT gzungetc(c, file)
483     int c;
484     gzFile file;
485 {
486     gz_statep state;
487
488     /* get internal structure */
489     if (file == NULL)
490         return -1;
491     state = (gz_statep)file;
492
493     /* check that we're reading and that there's no error */
494     if (state->mode != GZ_READ || state->err != Z_OK)
495         return -1;
496
497     /* process a skip request */
498     if (state->seek) {
499         state->seek = 0;
500         if (gz_skip(state, state->skip) == -1)
501             return -1;
502     }
503
504     /* can't push EOF */
505     if (c < 0)
506         return -1;
507
508     /* if output buffer empty, put byte at end (allows more pushing) */
509     if (state->have == 0) {
510         state->have = 1;
511         state->next = state->out + (state->size << 1) - 1;
512         state->next[0] = c;
513         state->pos--;
514         return c;
515     }
516
517     /* if no room, give up (must have already done a gzungetc()) */
518     if (state->have == (state->size << 1)) {
519         gz_error(state, Z_BUF_ERROR, "out of room to push characters");
520         return -1;
521     }
522
523     /* slide output data if needed and insert byte before existing data */
524     if (state->next == state->out) {
525         unsigned char *src = state->out + state->have;
526         unsigned char *dest = state->out + (state->size << 1);
527         while (src > state->out)
528             *--dest = *--src;
529         state->next = dest;
530     }
531     state->have++;
532     state->next--;
533     state->next[0] = c;
534     state->pos--;
535     return c;
536 }
537
538 /* -- see zlib.h -- */
539 char * ZEXPORT gzgets(file, buf, len)
540     gzFile file;
541     char *buf;
542     int len;
543 {
544     unsigned left, n;
545     char *str;
546     unsigned char *eol;
547     gz_statep state;
548
549     /* get internal structure */
550     if (file == NULL)
551         return NULL;
552     state = (gz_statep)file;
553
554     /* check that we're reading and that there's no error */
555     if (state->mode != GZ_READ || state->err != Z_OK)
556         return NULL;
557
558     /* process a skip request */
559     if (state->seek) {
560         state->seek = 0;
561         if (gz_skip(state, state->skip) == -1)
562             return NULL;
563     }
564
565     /* check for a dumb length */
566     if (len < 2)
567         return NULL;
568
569     /* copy output bytes up to new line or len - 1, whichever comes first --
570        append a terminating zero to the string (we don't check for a zero in
571        the contents, let the user worry about that) */
572     str = buf;
573     left = (unsigned)len - 1;
574     do {
575         /* assure that something is in the output buffer */
576         if (state->have == 0) {
577             if (gz_make(state) == -1)
578                 return NULL;            /* error */
579             if (state->have == 0) {     /* end of file */
580                 if (buf == str)         /* got bupkus */
581                     return NULL;
582                 break;                  /* got something -- return it */
583             }
584         }
585
586         /* look for end-of-line in current output buffer */
587         n = state->have > left ? left : state->have;
588         eol = memchr(state->next, '\n', n);
589         if (eol != NULL)
590             n = (eol - state->next) + 1;
591
592         /* copy through end-of-line, or remainder if not found */
593         memcpy(buf, state->next, n);
594         state->have -= n;
595         state->next += n;
596         state->pos += n;
597         left -= n;
598         buf += n;
599     } while (left && eol == NULL);
600
601     /* found end-of-line or out of space -- terminate string and return it */
602     buf[0] = 0;
603     return str;
604 }
605
606 /* -- see zlib.h -- */
607 int ZEXPORT gzdirect(file)
608     gzFile file;
609 {
610     gz_statep state;
611
612     /* get internal structure */
613     if (file == NULL)
614         return 0;
615     state = (gz_statep)file;
616
617     /* check that we're reading */
618     if (state->mode != GZ_READ)
619         return 0;
620
621     /* if the state is not known, but we can find out, then do so (this is
622        mainly for right after a gzopen() or gzdopen()) */
623     if (state->how == LOOK && state->have == 0)
624         (void)gz_head(state);
625
626     /* return 1 if reading direct, 0 if decompressing a gzip stream */
627     return state->direct;
628 }
629
630 /* -- see zlib.h -- */
631 int ZEXPORT gzclose_r(file)
632     gzFile file;
633 {
634     int ret;
635     gz_statep state;
636
637     /* get internal structure */
638     if (file == NULL)
639         return Z_STREAM_ERROR;
640     state = (gz_statep)file;
641
642     /* check that we're reading */
643     if (state->mode != GZ_READ)
644         return Z_STREAM_ERROR;
645
646     /* free memory and close file */
647     if (state->size) {
648         inflateEnd(&(state->strm));
649         free(state->out);
650         free(state->in);
651     }
652     gz_error(state, Z_OK, NULL);
653     ret = close(state->fd);
654     free(state);
655     return ret ? Z_ERRNO : Z_OK;
656 }
657
658 #endif /* !OLD_GZIO */