aboutsummaryrefslogtreecommitdiff
path: root/gzread.c
diff options
context:
space:
mode:
authorMark Adler <madler@alumni.caltech.edu>2011-09-09 23:26:49 -0700
committerMark Adler <madler@alumni.caltech.edu>2011-09-09 23:26:49 -0700
commitd004b047838a7e803818b4973a2e39e0ff8c1fa2 (patch)
tree9e8c804f78d73152c70d4ff24c6a7531a0d46782 /gzread.c
parentf6194ef39af5864f792412460c354cc339dde7d1 (diff)
downloadzlib-d004b047838a7e803818b4973a2e39e0ff8c1fa2.tar.gz
zlib-d004b047838a7e803818b4973a2e39e0ff8c1fa2.tar.bz2
zlib-d004b047838a7e803818b4973a2e39e0ff8c1fa2.zip
zlib 1.2.3.5v1.2.3.5
Diffstat (limited to 'gzread.c')
-rw-r--r--gzread.c632
1 files changed, 632 insertions, 0 deletions
diff --git a/gzread.c b/gzread.c
new file mode 100644
index 0000000..836c57c
--- /dev/null
+++ b/gzread.c
@@ -0,0 +1,632 @@
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 */
11local int gz_load OF((gz_statep, unsigned char *, unsigned, unsigned *));
12local int gz_avail OF((gz_statep));
13local int gz_next4 OF((gz_statep, unsigned long *));
14local int gz_head OF((gz_statep));
15local int gz_decomp OF((gz_statep));
16local int gz_make OF((gz_statep));
17local 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. */
23local 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. */
52local 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. */
74local 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. */
104local 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. */
229local 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. */
299local 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. */
325local 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 -- */
356int 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 -- */
435int 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 -- */
464int 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 -- */
519char * 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 -- */
587int 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 -- */
606int 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 */