VirtualBox

source: vbox/trunk/src/libs/zlib-1.2.13/gzread.c@ 106945

Last change on this file since 106945 was 97832, checked in by vboxsync, 2 years ago

zlib-1.2.13: adding svn:sync-process property to all zlib files (except LICESNSE and zlib.3.pdf). bugref:10335

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

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette