]> CyberLeo.Net >> Repos - FreeBSD/releng/9.2.git/blob - lib/libz/gzread.c
- Copy stable/9 to releng/9.2 as part of the 9.2-RELEASE cycle.
[FreeBSD/releng/9.2.git] / lib / libz / gzread.c
1 /* gzread.c -- zlib functions for reading gzip files
2  * Copyright (C) 2004, 2005, 2010, 2011, 2012 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_look OF((gz_statep));
15 local int gz_decomp OF((gz_statep));
16 local int gz_fetch 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    If strm->avail_in != 0, then the current data is moved to the beginning of
52    the input buffer, and then the remainder of the buffer is loaded with the
53    available data from the input file. */
54 local int gz_avail(state)
55     gz_statep state;
56 {
57     unsigned got;
58     z_streamp strm = &(state->strm);
59
60     if (state->err != Z_OK && state->err != Z_BUF_ERROR)
61         return -1;
62     if (state->eof == 0) {
63         if (strm->avail_in) {       /* copy what's there to the start */
64             unsigned char *p = state->in, *q = strm->next_in;
65             unsigned n = strm->avail_in;
66             do {
67                 *p++ = *q++;
68             } while (--n);
69         }
70         if (gz_load(state, state->in + strm->avail_in,
71                     state->size - strm->avail_in, &got) == -1)
72             return -1;
73         strm->avail_in += got;
74         strm->next_in = state->in;
75     }
76     return 0;
77 }
78
79 /* Look for gzip header, set up for inflate or copy.  state->x.have must be 0.
80    If this is the first time in, allocate required memory.  state->how will be
81    left unchanged if there is no more input data available, will be set to COPY
82    if there is no gzip header and direct copying will be performed, or it will
83    be set to GZIP for decompression.  If direct copying, then leftover input
84    data from the input buffer will be copied to the output buffer.  In that
85    case, all further file reads will be directly to either the output buffer or
86    a user buffer.  If decompressing, the inflate state will be initialized.
87    gz_look() will return 0 on success or -1 on failure. */
88 local int gz_look(state)
89     gz_statep state;
90 {
91     z_streamp strm = &(state->strm);
92
93     /* allocate read buffers and inflate memory */
94     if (state->size == 0) {
95         /* allocate buffers */
96         state->in = malloc(state->want);
97         state->out = malloc(state->want << 1);
98         if (state->in == NULL || state->out == NULL) {
99             if (state->out != NULL)
100                 free(state->out);
101             if (state->in != NULL)
102                 free(state->in);
103             gz_error(state, Z_MEM_ERROR, "out of memory");
104             return -1;
105         }
106         state->size = state->want;
107
108         /* allocate inflate memory */
109         state->strm.zalloc = Z_NULL;
110         state->strm.zfree = Z_NULL;
111         state->strm.opaque = Z_NULL;
112         state->strm.avail_in = 0;
113         state->strm.next_in = Z_NULL;
114         if (inflateInit2(&(state->strm), 15 + 16) != Z_OK) {    /* gunzip */
115             free(state->out);
116             free(state->in);
117             state->size = 0;
118             gz_error(state, Z_MEM_ERROR, "out of memory");
119             return -1;
120         }
121     }
122
123     /* get at least the magic bytes in the input buffer */
124     if (strm->avail_in < 2) {
125         if (gz_avail(state) == -1)
126             return -1;
127         if (strm->avail_in == 0)
128             return 0;
129     }
130
131     /* look for gzip magic bytes -- if there, do gzip decoding (note: there is
132        a logical dilemma here when considering the case of a partially written
133        gzip file, to wit, if a single 31 byte is written, then we cannot tell
134        whether this is a single-byte file, or just a partially written gzip
135        file -- for here we assume that if a gzip file is being written, then
136        the header will be written in a single operation, so that reading a
137        single byte is sufficient indication that it is not a gzip file) */
138     if (strm->avail_in > 1 &&
139             strm->next_in[0] == 31 && strm->next_in[1] == 139) {
140         inflateReset(strm);
141         state->how = GZIP;
142         state->direct = 0;
143         return 0;
144     }
145
146     /* no gzip header -- if we were decoding gzip before, then this is trailing
147        garbage.  Ignore the trailing garbage and finish. */
148     if (state->direct == 0) {
149         strm->avail_in = 0;
150         state->eof = 1;
151         state->x.have = 0;
152         return 0;
153     }
154
155     /* doing raw i/o, copy any leftover input to output -- this assumes that
156        the output buffer is larger than the input buffer, which also assures
157        space for gzungetc() */
158     state->x.next = state->out;
159     if (strm->avail_in) {
160         memcpy(state->x.next, strm->next_in, strm->avail_in);
161         state->x.have = strm->avail_in;
162         strm->avail_in = 0;
163     }
164     state->how = COPY;
165     state->direct = 1;
166     return 0;
167 }
168
169 /* Decompress from input to the provided next_out and avail_out in the state.
170    On return, state->x.have and state->x.next point to the just decompressed
171    data.  If the gzip stream completes, state->how is reset to LOOK to look for
172    the next gzip stream or raw data, once state->x.have is depleted.  Returns 0
173    on success, -1 on failure. */
174 local int gz_decomp(state)
175     gz_statep state;
176 {
177     int ret = Z_OK;
178     unsigned had;
179     z_streamp strm = &(state->strm);
180
181     /* fill output buffer up to end of deflate stream */
182     had = strm->avail_out;
183     do {
184         /* get more input for inflate() */
185         if (strm->avail_in == 0 && gz_avail(state) == -1)
186             return -1;
187         if (strm->avail_in == 0) {
188             gz_error(state, Z_BUF_ERROR, "unexpected end of file");
189             break;
190         }
191
192         /* decompress and handle errors */
193         ret = inflate(strm, Z_NO_FLUSH);
194         if (ret == Z_STREAM_ERROR || ret == Z_NEED_DICT) {
195             gz_error(state, Z_STREAM_ERROR,
196                      "internal error: inflate stream corrupt");
197             return -1;
198         }
199         if (ret == Z_MEM_ERROR) {
200             gz_error(state, Z_MEM_ERROR, "out of memory");
201             return -1;
202         }
203         if (ret == Z_DATA_ERROR) {              /* deflate stream invalid */
204             gz_error(state, Z_DATA_ERROR,
205                      strm->msg == NULL ? "compressed data error" : strm->msg);
206             return -1;
207         }
208     } while (strm->avail_out && ret != Z_STREAM_END);
209
210     /* update available output */
211     state->x.have = had - strm->avail_out;
212     state->x.next = strm->next_out - state->x.have;
213
214     /* if the gzip stream completed successfully, look for another */
215     if (ret == Z_STREAM_END)
216         state->how = LOOK;
217
218     /* good decompression */
219     return 0;
220 }
221
222 /* Fetch data and put it in the output buffer.  Assumes state->x.have is 0.
223    Data is either copied from the input file or decompressed from the input
224    file depending on state->how.  If state->how is LOOK, then a gzip header is
225    looked for to determine whether to copy or decompress.  Returns -1 on error,
226    otherwise 0.  gz_fetch() will leave state->how as COPY or GZIP unless the
227    end of the input file has been reached and all data has been processed.  */
228 local int gz_fetch(state)
229     gz_statep state;
230 {
231     z_streamp strm = &(state->strm);
232
233     do {
234         switch(state->how) {
235         case LOOK:      /* -> LOOK, COPY (only if never GZIP), or GZIP */
236             if (gz_look(state) == -1)
237                 return -1;
238             if (state->how == LOOK)
239                 return 0;
240             break;
241         case COPY:      /* -> COPY */
242             if (gz_load(state, state->out, state->size << 1, &(state->x.have))
243                     == -1)
244                 return -1;
245             state->x.next = state->out;
246             return 0;
247         case GZIP:      /* -> GZIP or LOOK (if end of gzip stream) */
248             strm->avail_out = state->size << 1;
249             strm->next_out = state->out;
250             if (gz_decomp(state) == -1)
251                 return -1;
252         }
253     } while (state->x.have == 0 && (!state->eof || strm->avail_in));
254     return 0;
255 }
256
257 /* Skip len uncompressed bytes of output.  Return -1 on error, 0 on success. */
258 local int gz_skip(state, len)
259     gz_statep state;
260     z_off64_t len;
261 {
262     unsigned n;
263
264     /* skip over len bytes or reach end-of-file, whichever comes first */
265     while (len)
266         /* skip over whatever is in output buffer */
267         if (state->x.have) {
268             n = GT_OFF(state->x.have) || (z_off64_t)state->x.have > len ?
269                 (unsigned)len : state->x.have;
270             state->x.have -= n;
271             state->x.next += n;
272             state->x.pos += n;
273             len -= n;
274         }
275
276         /* output buffer empty -- return if we're at the end of the input */
277         else if (state->eof && state->strm.avail_in == 0)
278             break;
279
280         /* need more data to skip -- load up output buffer */
281         else {
282             /* get more output, looking for header if required */
283             if (gz_fetch(state) == -1)
284                 return -1;
285         }
286     return 0;
287 }
288
289 /* -- see zlib.h -- */
290 int ZEXPORT gzread(file, buf, len)
291     gzFile file;
292     voidp buf;
293     unsigned len;
294 {
295     unsigned got, n;
296     gz_statep state;
297     z_streamp strm;
298
299     /* get internal structure */
300     if (file == NULL)
301         return -1;
302     state = (gz_statep)file;
303     strm = &(state->strm);
304
305     /* check that we're reading and that there's no (serious) error */
306     if (state->mode != GZ_READ ||
307             (state->err != Z_OK && state->err != Z_BUF_ERROR))
308         return -1;
309
310     /* since an int is returned, make sure len fits in one, otherwise return
311        with an error (this avoids the flaw in the interface) */
312     if ((int)len < 0) {
313         gz_error(state, Z_DATA_ERROR, "requested length does not fit in int");
314         return -1;
315     }
316
317     /* if len is zero, avoid unnecessary operations */
318     if (len == 0)
319         return 0;
320
321     /* process a skip request */
322     if (state->seek) {
323         state->seek = 0;
324         if (gz_skip(state, state->skip) == -1)
325             return -1;
326     }
327
328     /* get len bytes to buf, or less than len if at the end */
329     got = 0;
330     do {
331         /* first just try copying data from the output buffer */
332         if (state->x.have) {
333             n = state->x.have > len ? len : state->x.have;
334             memcpy(buf, state->x.next, n);
335             state->x.next += n;
336             state->x.have -= n;
337         }
338
339         /* output buffer empty -- return if we're at the end of the input */
340         else if (state->eof && strm->avail_in == 0) {
341             state->past = 1;        /* tried to read past end */
342             break;
343         }
344
345         /* need output data -- for small len or new stream load up our output
346            buffer */
347         else if (state->how == LOOK || len < (state->size << 1)) {
348             /* get more output, looking for header if required */
349             if (gz_fetch(state) == -1)
350                 return -1;
351             continue;       /* no progress yet -- go back to copy above */
352             /* the copy above assures that we will leave with space in the
353                output buffer, allowing at least one gzungetc() to succeed */
354         }
355
356         /* large len -- read directly into user buffer */
357         else if (state->how == COPY) {      /* read directly */
358             if (gz_load(state, buf, len, &n) == -1)
359                 return -1;
360         }
361
362         /* large len -- decompress directly into user buffer */
363         else {  /* state->how == GZIP */
364             strm->avail_out = len;
365             strm->next_out = buf;
366             if (gz_decomp(state) == -1)
367                 return -1;
368             n = state->x.have;
369             state->x.have = 0;
370         }
371
372         /* update progress */
373         len -= n;
374         buf = (char *)buf + n;
375         got += n;
376         state->x.pos += n;
377     } while (len);
378
379     /* return number of bytes read into user buffer (will fit in int) */
380     return (int)got;
381 }
382
383 /* -- see zlib.h -- */
384 #undef gzgetc
385 int ZEXPORT gzgetc(file)
386     gzFile file;
387 {
388     int ret;
389     unsigned char buf[1];
390     gz_statep state;
391
392     /* get internal structure */
393     if (file == NULL)
394         return -1;
395     state = (gz_statep)file;
396
397     /* check that we're reading and that there's no (serious) error */
398     if (state->mode != GZ_READ ||
399         (state->err != Z_OK && state->err != Z_BUF_ERROR))
400         return -1;
401
402     /* try output buffer (no need to check for skip request) */
403     if (state->x.have) {
404         state->x.have--;
405         state->x.pos++;
406         return *(state->x.next)++;
407     }
408
409     /* nothing there -- try gzread() */
410     ret = gzread(file, buf, 1);
411     return ret < 1 ? -1 : buf[0];
412 }
413
414 int ZEXPORT gzgetc_(file)
415 gzFile file;
416 {
417     return gzgetc(file);
418 }
419
420 /* -- see zlib.h -- */
421 int ZEXPORT gzungetc(c, file)
422     int c;
423     gzFile file;
424 {
425     gz_statep state;
426
427     /* get internal structure */
428     if (file == NULL)
429         return -1;
430     state = (gz_statep)file;
431
432     /* check that we're reading and that there's no (serious) error */
433     if (state->mode != GZ_READ ||
434         (state->err != Z_OK && state->err != Z_BUF_ERROR))
435         return -1;
436
437     /* process a skip request */
438     if (state->seek) {
439         state->seek = 0;
440         if (gz_skip(state, state->skip) == -1)
441             return -1;
442     }
443
444     /* can't push EOF */
445     if (c < 0)
446         return -1;
447
448     /* if output buffer empty, put byte at end (allows more pushing) */
449     if (state->x.have == 0) {
450         state->x.have = 1;
451         state->x.next = state->out + (state->size << 1) - 1;
452         state->x.next[0] = c;
453         state->x.pos--;
454         state->past = 0;
455         return c;
456     }
457
458     /* if no room, give up (must have already done a gzungetc()) */
459     if (state->x.have == (state->size << 1)) {
460         gz_error(state, Z_DATA_ERROR, "out of room to push characters");
461         return -1;
462     }
463
464     /* slide output data if needed and insert byte before existing data */
465     if (state->x.next == state->out) {
466         unsigned char *src = state->out + state->x.have;
467         unsigned char *dest = state->out + (state->size << 1);
468         while (src > state->out)
469             *--dest = *--src;
470         state->x.next = dest;
471     }
472     state->x.have++;
473     state->x.next--;
474     state->x.next[0] = c;
475     state->x.pos--;
476     state->past = 0;
477     return c;
478 }
479
480 /* -- see zlib.h -- */
481 char * ZEXPORT gzgets(file, buf, len)
482     gzFile file;
483     char *buf;
484     int len;
485 {
486     unsigned left, n;
487     char *str;
488     unsigned char *eol;
489     gz_statep state;
490
491     /* check parameters and get internal structure */
492     if (file == NULL || buf == NULL || len < 1)
493         return NULL;
494     state = (gz_statep)file;
495
496     /* check that we're reading and that there's no (serious) error */
497     if (state->mode != GZ_READ ||
498         (state->err != Z_OK && state->err != Z_BUF_ERROR))
499         return NULL;
500
501     /* process a skip request */
502     if (state->seek) {
503         state->seek = 0;
504         if (gz_skip(state, state->skip) == -1)
505             return NULL;
506     }
507
508     /* copy output bytes up to new line or len - 1, whichever comes first --
509        append a terminating zero to the string (we don't check for a zero in
510        the contents, let the user worry about that) */
511     str = buf;
512     left = (unsigned)len - 1;
513     if (left) do {
514         /* assure that something is in the output buffer */
515         if (state->x.have == 0 && gz_fetch(state) == -1)
516             return NULL;                /* error */
517         if (state->x.have == 0) {       /* end of file */
518             state->past = 1;            /* read past end */
519             break;                      /* return what we have */
520         }
521
522         /* look for end-of-line in current output buffer */
523         n = state->x.have > left ? left : state->x.have;
524         eol = memchr(state->x.next, '\n', n);
525         if (eol != NULL)
526             n = (unsigned)(eol - state->x.next) + 1;
527
528         /* copy through end-of-line, or remainder if not found */
529         memcpy(buf, state->x.next, n);
530         state->x.have -= n;
531         state->x.next += n;
532         state->x.pos += n;
533         left -= n;
534         buf += n;
535     } while (left && eol == NULL);
536
537     /* return terminated string, or if nothing, end of file */
538     if (buf == str)
539         return NULL;
540     buf[0] = 0;
541     return str;
542 }
543
544 /* -- see zlib.h -- */
545 int ZEXPORT gzdirect(file)
546     gzFile file;
547 {
548     gz_statep state;
549
550     /* get internal structure */
551     if (file == NULL)
552         return 0;
553     state = (gz_statep)file;
554
555     /* if the state is not known, but we can find out, then do so (this is
556        mainly for right after a gzopen() or gzdopen()) */
557     if (state->mode == GZ_READ && state->how == LOOK && state->x.have == 0)
558         (void)gz_look(state);
559
560     /* return 1 if transparent, 0 if processing a gzip stream */
561     return state->direct;
562 }
563
564 /* -- see zlib.h -- */
565 int ZEXPORT gzclose_r(file)
566     gzFile file;
567 {
568     int ret, err;
569     gz_statep state;
570
571     /* get internal structure */
572     if (file == NULL)
573         return Z_STREAM_ERROR;
574     state = (gz_statep)file;
575
576     /* check that we're reading */
577     if (state->mode != GZ_READ)
578         return Z_STREAM_ERROR;
579
580     /* free memory and close file */
581     if (state->size) {
582         inflateEnd(&(state->strm));
583         free(state->out);
584         free(state->in);
585     }
586     err = state->err == Z_BUF_ERROR ? Z_BUF_ERROR : Z_OK;
587     gz_error(state, Z_OK, NULL);
588     free(state->path);
589     ret = close(state->fd);
590     free(state);
591     return ret ? Z_ERRNO : err;
592 }