VirtualBox

source: vbox/trunk/src/libs/zlib-1.3.1/gzread.c

最後變更 在這個檔案是 108382,由 vboxsync 提交於 3 週 前

zlib-1.3.1: Applied and adjusted our zlib changes to 1.3.1. jiraref:VBP-1328

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

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