| Bsoft 1.9 Bernard's software package

- Main Page
- Namespaces
- Classes
- Files

- File List
- File Members

gzread.c
Go to the documentation of this file.
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 }
gzdirect
int ZEXPORT gzdirect(gzFile file)
Definition: gzread.c:603
COPY
Definition: inflate.h:36
inflateReset
int ZEXPORT inflateReset(z_streamp strm)
Definition: inflate.c:103
read
int read(int fd, char *buf, int nbytes)
Definition: tif_acorn.c:331
Z_NO_FLUSH
#define Z_NO_FLUSH
Definition: zlib.h:164
gz_skip
local int gz_skip(gz_statep state, z_off64_t len)
Definition: gzread.c:330
gz_load
local int gz_load(gz_statep state, unsigned char *buf, unsigned len, unsigned *have)
Definition: gzread.c:21
GT_OFF
#define GT_OFF(x)
Definition: gzguts.h:131
Z_ERRNO
#define Z_ERRNO
Definition: zlib.h:176
GZ_READ
#define GZ_READ
Definition: gzguts.h:76
Z_NEED_DICT
#define Z_NEED_DICT
Definition: zlib.h:175
z_off64_t
#define z_off64_t
Definition: zconf.h:400
gz_head
local int gz_head(gz_statep state)
Definition: gzread.c:104
Z_STREAM_ERROR
#define Z_STREAM_ERROR
Definition: zlib.h:177
gzFile
voidp gzFile
Definition: zlib.h:1165
gzungetc
int ZEXPORT gzungetc(int c, gzFile file)
Definition: gzread.c:482
inflateInit2
#define inflateInit2(strm, windowBits)
Definition: zlib.h:1553
gz_error
void ZLIB_INTERNAL gz_error(gz_statep state, int err, const char *msg)
Definition: gzlib.c:485
zstrerror
#define zstrerror()
Definition: gzguts.h:59
Z_DATA_ERROR
#define Z_DATA_ERROR
Definition: zlib.h:178
close
int close(int fd)
Definition: tif_acorn.c:320
gzclose_r
int ZEXPORT gzclose_r(gzFile file)
Definition: gzread.c:627
Z_STREAM_END
#define Z_STREAM_END
Definition: zlib.h:174
local
#define local
Definition: adler32.c:10
gzguts.h
crc32
unsigned long ZEXPORT crc32(unsigned long crc, const unsigned char FAR *buf, uInt len)
Definition: crc32.c:221
val
int val
Definition: jpeglib.h:956
gz_decomp
local int gz_decomp(gz_statep state)
Definition: gzread.c:233
Z_MEM_ERROR
#define Z_MEM_ERROR
Definition: zlib.h:179
voidp
Byte * voidp
Definition: zconf.h:356
gzgets
char *ZEXPORT gzgets(gzFile file, char *buf, int len)
Definition: gzread.c:539
gz_make
local int gz_make(gz_statep state)
Definition: gzread.c:304
gzgetc
int ZEXPORT gzgetc(gzFile file)
Definition: gzread.c:453
gz_avail
local int gz_avail(gz_statep state)
Definition: gzread.c:50
LOOK
#define LOOK
Definition: gzguts.h:81
Z_BUF_ERROR
#define Z_BUF_ERROR
Definition: zlib.h:180
Z_OK
#define Z_OK
Definition: zlib.h:173
gz_statep
gz_state FAR * gz_statep
Definition: gzguts.h:116
inflate
int ZEXPORT inflate(z_streamp strm, int flush)
Definition: inflate.c:589
gz_next4
local int gz_next4(gz_statep state, unsigned long *ret)
Definition: gzread.c:73
Z_NULL
#define Z_NULL
Definition: zlib.h:208
NEXT
#define NEXT()
Definition: gzread.c:67
z_streamp
z_stream FAR * z_streamp
Definition: zlib.h:106
gzread
int ZEXPORT gzread(gzFile file, voidp buf, unsigned len)
Definition: gzread.c:362
ZEXPORT
#define ZEXPORT
Definition: zconf.h:322
inflateEnd
int ZEXPORT inflateEnd(z_streamp strm)
Definition: inflate.c:1238
OF
local int gz_load OF((gz_statep, unsigned char *, unsigned, unsigned *))
GZIP
#define GZIP
Definition: deflate.h:23