Annotation of embedaddon/sudo/zlib/gzread.c, revision 1.1.1.1
1.1 misho 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: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>