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