VirtualBox

source: vbox/trunk/src/libs/zlib-1.2.12/gzread.c@ 96686

Last change on this file since 96686 was 95819, checked in by vboxsync, 2 years ago

libs/zlib: In IPRT_NO_CRT mode don't try use CRT for reading & writing files, use IPRT. bugref:10261

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