]> git.jsancho.org Git - lugaru.git/blob - Dependencies/zlib/gzread.c
Removed an unused function
[lugaru.git] / Dependencies / zlib / 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 #include "gzguts.h"
7
8 /* Local functions */
9 local int gz_load OF((gz_statep, unsigned char *, unsigned, unsigned *));
10 local int gz_avail OF((gz_statep));
11 local int gz_next4 OF((gz_statep, unsigned long *));
12 local int gz_head OF((gz_statep));
13 local int gz_decomp OF((gz_statep));
14 local int gz_make OF((gz_statep));
15 local int gz_skip OF((gz_statep, z_off64_t));
16
17 /* Use read() to load a buffer -- return -1 on error, otherwise 0.  Read from
18    state->fd, and update state->eof, state->err, and state->msg as appropriate.
19    This function needs to loop on read(), since read() is not guaranteed to
20    read the number of bytes requested, depending on the type of descriptor. */
21 local int gz_load(state, buf, len, have)
22     gz_statep state;
23     unsigned char *buf;
24     unsigned len;
25     unsigned *have;
26 {
27     int ret;
28
29     *have = 0;
30     do {
31         ret = read(state->fd, buf + *have, len - *have);
32         if (ret <= 0)
33             break;
34         *have += ret;
35     } while (*have < len);
36     if (ret < 0) {
37         gz_error(state, Z_ERRNO, zstrerror());
38         return -1;
39     }
40     if (ret == 0)
41         state->eof = 1;
42     return 0;
43 }
44
45 /* Load up input buffer and set eof flag if last data loaded -- return -1 on
46    error, 0 otherwise.  Note that the eof flag is set when the end of the input
47    file is reached, even though there may be unused data in the buffer.  Once
48    that data has been used, no more attempts will be made to read the file.
49    gz_avail() assumes that strm->avail_in == 0. */
50 local int gz_avail(state)
51     gz_statep state;
52 {
53     z_streamp strm = &(state->strm);
54
55     if (state->err != Z_OK)
56         return -1;
57     if (state->eof == 0) {
58         if (gz_load(state, state->in, state->size,
59                 (unsigned *)&(strm->avail_in)) == -1)
60             return -1;
61         strm->next_in = state->in;
62     }
63     return 0;
64 }
65
66 /* Get next byte from input, or -1 if end or error. */
67 #define NEXT() ((strm->avail_in == 0 && gz_avail(state) == -1) ? -1 : \
68                 (strm->avail_in == 0 ? -1 : \
69                  (strm->avail_in--, *(strm->next_in)++)))
70
71 /* Get a four-byte little-endian integer and return 0 on success and the value
72    in *ret.  Otherwise -1 is returned and *ret is not modified. */
73 local int gz_next4(state, ret)
74     gz_statep state;
75     unsigned long *ret;
76 {
77     int ch;
78     unsigned long val;
79     z_streamp strm = &(state->strm);
80
81     val = NEXT();
82     val += (unsigned)NEXT() << 8;
83     val += (unsigned long)NEXT() << 16;
84     ch = NEXT();
85     if (ch == -1)
86         return -1;
87     val += (unsigned long)ch << 24;
88     *ret = val;
89     return 0;
90 }
91
92 /* Look for gzip header, set up for inflate or copy.  state->have must be zero.
93    If this is the first time in, allocate required memory.  state->how will be
94    left unchanged if there is no more input data available, will be set to COPY
95    if there is no gzip header and direct copying will be performed, or it will
96    be set to GZIP for decompression, and the gzip header will be skipped so
97    that the next available input data is the raw deflate stream.  If direct
98    copying, then leftover input data from the input buffer will be copied to
99    the output buffer.  In that case, all further file reads will be directly to
100    either the output buffer or a user buffer.  If decompressing, the inflate
101    state and the check value will be initialized.  gz_head() will return 0 on
102    success or -1 on failure.  Failures may include read errors or gzip header
103    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 = GZIP;
200             state->direct = 0;
201             return 0;
202         }
203         else {
204             /* not a gzip file -- save first byte (31) and fall to raw i/o */
205             state->out[0] = 31;
206             state->have = 1;
207         }
208     }
209
210     /* doing raw i/o, save start of raw data for seeking, copy any leftover
211        input to output -- this assumes that the output buffer is larger than
212        the input buffer, which also assures space for gzungetc() */
213     state->raw = state->pos;
214     state->next = state->out;
215     if (strm->avail_in) {
216         memcpy(state->next + state->have, strm->next_in, strm->avail_in);
217         state->have += strm->avail_in;
218         strm->avail_in = 0;
219     }
220     state->how = COPY;
221     state->direct = 1;
222     return 0;
223 }
224
225 /* Decompress from input to the provided next_out and avail_out in the state.
226    If the end of the compressed data is reached, then verify the gzip trailer
227    check value and length (modulo 2^32).  state->have and state->next are set
228    to point to the just decompressed data, and the crc is updated.  If the
229    trailer is verified, state->how is reset to LOOK to look for the next gzip
230    stream or raw data, once state->have is depleted.  Returns 0 on success, -1
231    on failure.  Failures may include invalid compressed data or a failed gzip
232    trailer verification. */
233 local int gz_decomp(state)
234     gz_statep state;
235 {
236     int ret;
237     unsigned had;
238     unsigned long crc, len;
239     z_streamp strm = &(state->strm);
240
241     /* fill output buffer up to end of deflate stream */
242     had = strm->avail_out;
243     do {
244         /* get more input for inflate() */
245         if (strm->avail_in == 0 && gz_avail(state) == -1)
246             return -1;
247         if (strm->avail_in == 0) {
248             gz_error(state, Z_DATA_ERROR, "unexpected end of file");
249             return -1;
250         }
251
252         /* decompress and handle errors */
253         ret = inflate(strm, Z_NO_FLUSH);
254         if (ret == Z_STREAM_ERROR || ret == Z_NEED_DICT) {
255             gz_error(state, Z_STREAM_ERROR,
256                       "internal error: inflate stream corrupt");
257             return -1;
258         }
259         if (ret == Z_MEM_ERROR) {
260             gz_error(state, Z_MEM_ERROR, "out of memory");
261             return -1;
262         }
263         if (ret == Z_DATA_ERROR) {              /* deflate stream invalid */
264             gz_error(state, Z_DATA_ERROR,
265                       strm->msg == NULL ? "compressed data error" : strm->msg);
266             return -1;
267         }
268     } while (strm->avail_out && ret != Z_STREAM_END);
269
270     /* update available output and crc check value */
271     state->have = had - strm->avail_out;
272     state->next = strm->next_out - state->have;
273     strm->adler = crc32(strm->adler, state->next, state->have);
274
275     /* check gzip trailer if at end of deflate stream */
276     if (ret == Z_STREAM_END) {
277         if (gz_next4(state, &crc) == -1 || gz_next4(state, &len) == -1) {
278             gz_error(state, Z_DATA_ERROR, "unexpected end of file");
279             return -1;
280         }
281         if (crc != strm->adler) {
282             gz_error(state, Z_DATA_ERROR, "incorrect data check");
283             return -1;
284         }
285         if (len != (strm->total_out & 0xffffffffL)) {
286             gz_error(state, Z_DATA_ERROR, "incorrect length check");
287             return -1;
288         }
289         state->how = LOOK;      /* ready for next stream, once have is 0 (leave
290                                    state->direct unchanged to remember how) */
291     }
292
293     /* good decompression */
294     return 0;
295 }
296
297 /* Make data and put in the output buffer.  Assumes that state->have == 0.
298    Data is either copied from the input file or decompressed from the input
299    file depending on state->how.  If state->how is LOOK, then a gzip header is
300    looked for (and skipped if found) to determine wither to copy or decompress.
301    Returns -1 on error, otherwise 0.  gz_make() will leave state->have as COPY
302    or GZIP unless the end of the input file has been reached and all data has
303    been processed.  */
304 local int gz_make(state)
305     gz_statep state;
306 {
307     z_streamp strm = &(state->strm);
308
309     if (state->how == LOOK) {           /* look for gzip header */
310         if (gz_head(state) == -1)
311             return -1;
312         if (state->have)                /* got some data from gz_head() */
313             return 0;
314     }
315     if (state->how == COPY) {           /* straight copy */
316         if (gz_load(state, state->out, state->size << 1, &(state->have)) == -1)
317             return -1;
318         state->next = state->out;
319     }
320     else if (state->how == GZIP) {      /* decompress */
321         strm->avail_out = state->size << 1;
322         strm->next_out = state->out;
323         if (gz_decomp(state) == -1)
324             return -1;
325     }
326     return 0;
327 }
328
329 /* Skip len uncompressed bytes of output.  Return -1 on error, 0 on success. */
330 local int gz_skip(state, len)
331     gz_statep state;
332     z_off64_t len;
333 {
334     unsigned n;
335
336     /* skip over len bytes or reach end-of-file, whichever comes first */
337     while (len)
338         /* skip over whatever is in output buffer */
339         if (state->have) {
340             n = GT_OFF(state->have) || (z_off64_t)state->have > len ?
341                 (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     /* check parameters and get internal structure */
550     if (file == NULL || buf == NULL || len < 1)
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     /* 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     if (left) 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 = (unsigned)(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     /* if the state is not known, but we can find out, then do so (this is
618        mainly for right after a gzopen() or gzdopen()) */
619     if (state->how == LOOK && state->have == 0)
620         (void)gz_head(state);
621
622     /* return 1 if reading direct, 0 if decompressing a gzip stream */
623     return state->direct;
624 }
625
626 /* -- see zlib.h -- */
627 int ZEXPORT gzclose_r(file)
628     gzFile file;
629 {
630     int ret;
631     gz_statep state;
632
633     /* get internal structure */
634     if (file == NULL)
635         return Z_STREAM_ERROR;
636     state = (gz_statep)file;
637
638     /* check that we're reading */
639     if (state->mode != GZ_READ)
640         return Z_STREAM_ERROR;
641
642     /* free memory and close file */
643     if (state->size) {
644         inflateEnd(&(state->strm));
645         free(state->out);
646         free(state->in);
647     }
648     gz_error(state, Z_OK, NULL);
649     free(state->path);
650     ret = close(state->fd);
651     free(state);
652     return ret ? Z_ERRNO : Z_OK;
653 }