VirtualBox

source: vbox/trunk/src/libs/zlib-1.3.1/gzlib.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
檔案大小: 21.4 KB
 
1/* gzlib.c -- zlib functions common to reading and writing gzip files
2 * Copyright (C) 2004-2024 Mark Adler
3 * For conditions of distribution and use, see copyright notice in zlib.h
4 */
5
6#include "gzguts.h"
7
8#if defined(_WIN32) && !defined(__BORLANDC__)
9# define LSEEK _lseeki64
10#else
11#if defined(_LARGEFILE64_SOURCE) && _LFS64_LARGEFILE-0
12# define LSEEK lseek64
13#else
14# define LSEEK lseek
15#endif
16#endif
17
18#if defined UNDER_CE
19
20/* Map the Windows error number in ERROR to a locale-dependent error message
21 string and return a pointer to it. Typically, the values for ERROR come
22 from GetLastError.
23
24 The string pointed to shall not be modified by the application, but may be
25 overwritten by a subsequent call to gz_strwinerror
26
27 The gz_strwinerror function does not change the current setting of
28 GetLastError. */
29char ZLIB_INTERNAL *gz_strwinerror(DWORD error) {
30 static char buf[1024];
31
32 wchar_t *msgbuf;
33 DWORD lasterr = GetLastError();
34 DWORD chars = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM
35 | FORMAT_MESSAGE_ALLOCATE_BUFFER,
36 NULL,
37 error,
38 0, /* Default language */
39 (LPVOID)&msgbuf,
40 0,
41 NULL);
42 if (chars != 0) {
43 /* If there is an \r\n appended, zap it. */
44 if (chars >= 2
45 && msgbuf[chars - 2] == '\r' && msgbuf[chars - 1] == '\n') {
46 chars -= 2;
47 msgbuf[chars] = 0;
48 }
49
50 if (chars > sizeof (buf) - 1) {
51 chars = sizeof (buf) - 1;
52 msgbuf[chars] = 0;
53 }
54
55 wcstombs(buf, msgbuf, chars + 1);
56 LocalFree(msgbuf);
57 }
58 else {
59 sprintf(buf, "unknown win32 error (%ld)", error);
60 }
61
62 SetLastError(lasterr);
63 return buf;
64}
65
66#endif /* UNDER_CE */
67
68/* Reset gzip file state */
69local void gz_reset(gz_statep state) {
70 state->x.have = 0; /* no output data available */
71 if (state->mode == GZ_READ) { /* for reading ... */
72 state->eof = 0; /* not at end of file */
73 state->past = 0; /* have not read past end yet */
74 state->how = LOOK; /* look for gzip header */
75 }
76 else /* for writing ... */
77 state->reset = 0; /* no deflateReset pending */
78 state->seek = 0; /* no seek request pending */
79 gz_error(state, Z_OK, NULL); /* clear error */
80 state->x.pos = 0; /* no uncompressed data yet */
81 state->strm.avail_in = 0; /* no input data yet */
82}
83
84/* Open a gzip file either by name or file descriptor. */
85local gzFile gz_open(const void *path, int fd, const char *mode) {
86 gz_statep state;
87 z_size_t len;
88#ifndef IPRT_NO_CRT /* VBox */
89 int oflag;
90#else /* VBox */
91 uint64_t fOpen; /* VBox */
92 int rc; /* VBox */
93# define O_CLOEXEC /* VBox */
94# define O_EXCL /* VBox */
95#endif /* VBox */
96#ifdef O_CLOEXEC
97 int cloexec = 0;
98#endif
99#ifdef O_EXCL
100 int exclusive = 0;
101#endif
102
103 /* check input */
104 if (path == NULL)
105 return NULL;
106
107 /* allocate gzFile structure to return */
108 state = (gz_statep)malloc(sizeof(gz_state));
109 if (state == NULL)
110 return NULL;
111 state->size = 0; /* no buffers allocated yet */
112 state->want = GZBUFSIZE; /* requested buffer size */
113 state->msg = NULL; /* no error message yet */
114
115 /* interpret mode */
116 state->mode = GZ_NONE;
117 state->level = Z_DEFAULT_COMPRESSION;
118 state->strategy = Z_DEFAULT_STRATEGY;
119 state->direct = 0;
120 while (*mode) {
121 if (*mode >= '0' && *mode <= '9')
122 state->level = *mode - '0';
123 else
124 switch (*mode) {
125 case 'r':
126 state->mode = GZ_READ;
127 break;
128#ifndef NO_GZCOMPRESS
129 case 'w':
130 state->mode = GZ_WRITE;
131 break;
132 case 'a':
133 state->mode = GZ_APPEND;
134 break;
135#endif
136 case '+': /* can't read and write at the same time */
137 free(state);
138 return NULL;
139 case 'b': /* ignore -- will request binary anyway */
140 break;
141#ifdef O_CLOEXEC
142 case 'e':
143 cloexec = 1;
144 break;
145#endif
146#ifdef O_EXCL
147 case 'x':
148 exclusive = 1;
149 break;
150#endif
151 case 'f':
152 state->strategy = Z_FILTERED;
153 break;
154 case 'h':
155 state->strategy = Z_HUFFMAN_ONLY;
156 break;
157 case 'R':
158 state->strategy = Z_RLE;
159 break;
160 case 'F':
161 state->strategy = Z_FIXED;
162 break;
163 case 'T':
164 state->direct = 1;
165 break;
166 default: /* could consider as an error, but just ignore */
167 ;
168 }
169 mode++;
170 }
171
172 /* must provide an "r", "w", or "a" */
173 if (state->mode == GZ_NONE) {
174 free(state);
175 return NULL;
176 }
177
178 /* can't force transparent read */
179 if (state->mode == GZ_READ) {
180 if (state->direct) {
181 free(state);
182 return NULL;
183 }
184 state->direct = 1; /* for empty file */
185 }
186
187 /* save the path name for error messages */
188#ifdef WIDECHAR
189 if (fd == -2) {
190 len = wcstombs(NULL, path, 0);
191 if (len == (z_size_t)-1)
192 len = 0;
193 }
194 else
195#endif
196 len = strlen((const char *)path);
197 state->path = (char *)malloc(len + 1);
198 if (state->path == NULL) {
199 free(state);
200 return NULL;
201 }
202#ifdef WIDECHAR
203 if (fd == -2)
204 if (len)
205 wcstombs(state->path, path, len + 1);
206 else
207 *(state->path) = 0;
208 else
209#endif
210#if !defined(NO_snprintf) && !defined(NO_vsnprintf)
211 (void)snprintf(state->path, len + 1, "%s", (const char *)path);
212#else
213 strcpy(state->path, path);
214#endif
215
216 /* compute the flags for open() */
217#ifndef IPRT_NO_CRT /* VBox */
218 oflag =
219#ifdef O_LARGEFILE
220 O_LARGEFILE |
221#endif
222#ifdef O_BINARY
223 O_BINARY |
224#endif
225#ifdef O_CLOEXEC
226 (cloexec ? O_CLOEXEC : 0) |
227#endif
228 (state->mode == GZ_READ ?
229 O_RDONLY :
230 (O_WRONLY | O_CREAT |
231#ifdef O_EXCL
232 (exclusive ? O_EXCL : 0) |
233#endif
234 (state->mode == GZ_WRITE ?
235 O_TRUNC :
236 O_APPEND)));
237#else /* IPRT_NO_CRT */ /* VBox */
238 fOpen = RTFILE_O_DENY_NONE /* VBox */
239 | (0666 << RTFILE_O_CREATE_MODE_SHIFT) /* VBox */
240 | (cloexec ? 0 : RTFILE_O_INHERIT) /* VBox */
241 | (state->mode == GZ_READ /* VBox */
242 ? RTFILE_O_READ | RTFILE_O_OPEN /* VBox */
243 : RTFILE_O_WRITE /* VBox */
244 | (exclusive /* VBox */
245 ? RTFILE_O_CREATE /* VBox */
246 : state->mode == GZ_WRITE /* VBox */
247 ? RTFILE_O_CREATE_REPLACE /* VBox */
248 : RTFILE_O_OPEN_CREATE | RTFILE_O_APPEND) /* VBox */
249 ); /* VBox */
250#endif /* IPRT_NO_CRT */ /* VBox */
251
252 /* open the file with the appropriate flags (or just use fd) */
253#ifndef IPRT_NO_CRT /* VBox */
254 state->fd = fd > -1 ? fd : (
255#ifdef WIDECHAR
256 fd == -2 ? _wopen(path, oflag, 0666) :
257#endif
258 open((const char *)path, oflag, 0666));
259 if (state->fd == -1) {
260#else /* IPRT_NO_CRT */ /* VBox */
261 rc = RTFileOpen(&state->fd, path, fOpen); /* VBox */
262 if (RT_FAILURE(rc)) { /* VBox */
263#endif /* IPRT_NO_CRT */ /* VBox */
264
265 free(state->path);
266 free(state);
267 return NULL;
268 }
269 if (state->mode == GZ_APPEND) {
270#ifndef IPRT_NO_CRT /* VBox */
271 LSEEK(state->fd, 0, SEEK_END); /* so gzoffset() is correct */
272#else /* VBox */
273 RTFileSeek(state->fd, 0, RTFILE_SEEK_END, NULL); /* VBox */
274#endif /* VBox */
275 state->mode = GZ_WRITE; /* simplify later checks */
276 }
277
278 /* save the current position for rewinding (only if reading) */
279 if (state->mode == GZ_READ) {
280#ifndef IPRT_NO_CRT /* VBox */
281 state->start = LSEEK(state->fd, 0, SEEK_CUR);
282#else /* VBox */
283 state->start = RTFileTell(state->fd); /* VBox */
284#endif /* VBox */
285 if (state->start == -1) state->start = 0;
286 }
287
288 /* initialize stream */
289 gz_reset(state);
290
291 /* return stream */
292 return (gzFile)state;
293}
294
295/* -- see zlib.h -- */
296gzFile ZEXPORT gzopen(const char *path, const char *mode) {
297 return gz_open(path, -1, mode);
298}
299
300/* -- see zlib.h -- */
301gzFile ZEXPORT gzopen64(const char *path, const char *mode) {
302 return gz_open(path, -1, mode);
303}
304
305/* -- see zlib.h -- */
306gzFile ZEXPORT gzdopen(int fd, const char *mode) {
307 char *path; /* identifier for error messages */
308 gzFile gz;
309
310 if (fd == -1 || (path = (char *)malloc(7 + 3 * sizeof(int))) == NULL)
311 return NULL;
312#if !defined(NO_snprintf) && !defined(NO_vsnprintf)
313 (void)snprintf(path, 7 + 3 * sizeof(int), "<fd:%d>", fd);
314#else
315 sprintf(path, "<fd:%d>", fd); /* for debugging */
316#endif
317 gz = gz_open(path, fd, mode);
318 free(path);
319 return gz;
320}
321
322/* -- see zlib.h -- */
323#ifdef WIDECHAR
324gzFile ZEXPORT gzopen_w(const wchar_t *path, const char *mode) {
325 return gz_open(path, -2, mode);
326}
327#endif
328
329/* -- see zlib.h -- */
330int ZEXPORT gzbuffer(gzFile file, unsigned size) {
331 gz_statep state;
332
333 /* get internal structure and check integrity */
334 if (file == NULL)
335 return -1;
336 state = (gz_statep)file;
337 if (state->mode != GZ_READ && state->mode != GZ_WRITE)
338 return -1;
339
340 /* make sure we haven't already allocated memory */
341 if (state->size != 0)
342 return -1;
343
344 /* check and set requested size */
345 if ((size << 1) < size)
346 return -1; /* need to be able to double it */
347 if (size < 8)
348 size = 8; /* needed to behave well with flushing */
349 state->want = size;
350 return 0;
351}
352
353/* -- see zlib.h -- */
354int ZEXPORT gzrewind(gzFile file) {
355 gz_statep state;
356
357 /* get internal structure */
358 if (file == NULL)
359 return -1;
360 state = (gz_statep)file;
361
362 /* check that we're reading and that there's no error */
363 if (state->mode != GZ_READ ||
364 (state->err != Z_OK && state->err != Z_BUF_ERROR))
365 return -1;
366
367 /* back up and start over */
368#ifndef IPRT_NO_CRT /* VBox */
369 if (LSEEK(state->fd, state->start, SEEK_SET) == -1)
370#else /* VBox */
371 if (RT_FAILURE(RTFileSeek(state->fd, state->start, RTFILE_SEEK_CURRENT, NULL))) /* VBox */
372#endif /* VBox */
373 return -1;
374 gz_reset(state);
375 return 0;
376}
377
378/* -- see zlib.h -- */
379z_off64_t ZEXPORT gzseek64(gzFile file, z_off64_t offset, int whence) {
380 unsigned n;
381 z_off64_t ret;
382 gz_statep state;
383
384 /* get internal structure and check integrity */
385 if (file == NULL)
386 return -1;
387 state = (gz_statep)file;
388 if (state->mode != GZ_READ && state->mode != GZ_WRITE)
389 return -1;
390
391 /* check that there's no error */
392 if (state->err != Z_OK && state->err != Z_BUF_ERROR)
393 return -1;
394
395 /* can only seek from start or relative to current position */
396 if (whence != SEEK_SET && whence != SEEK_CUR)
397 return -1;
398
399 /* normalize offset to a SEEK_CUR specification */
400 if (whence == SEEK_SET)
401 offset -= state->x.pos;
402 else if (state->seek)
403 offset += state->skip;
404 state->seek = 0;
405
406 /* if within raw area while reading, just go there */
407 if (state->mode == GZ_READ && state->how == COPY &&
408 state->x.pos + offset >= 0) {
409#ifndef IPRT_NO_CRT /* VBox */
410 ret = LSEEK(state->fd, offset - (z_off64_t)state->x.have, SEEK_CUR);
411 if (ret == -1)
412#else /* VBox */
413 ret = RTFileSeek(state->fd, offset - (z_off64_t)state->x.have, SEEK_CUR, NULL); /* VBox */
414 if (RT_FAILURE(ret)) /* VBox */
415#endif /* VBox */
416 return -1;
417 state->x.have = 0;
418 state->eof = 0;
419 state->past = 0;
420 state->seek = 0;
421 gz_error(state, Z_OK, NULL);
422 state->strm.avail_in = 0;
423 state->x.pos += offset;
424 return state->x.pos;
425 }
426
427 /* calculate skip amount, rewinding if needed for back seek when reading */
428 if (offset < 0) {
429 if (state->mode != GZ_READ) /* writing -- can't go backwards */
430 return -1;
431 offset += state->x.pos;
432 if (offset < 0) /* before start of file! */
433 return -1;
434 if (gzrewind(file) == -1) /* rewind, then skip to offset */
435 return -1;
436 }
437
438 /* if reading, skip what's in output buffer (one less gzgetc() check) */
439 if (state->mode == GZ_READ) {
440 n = GT_OFF(state->x.have) || (z_off64_t)state->x.have > offset ?
441 (unsigned)offset : state->x.have;
442 state->x.have -= n;
443 state->x.next += n;
444 state->x.pos += n;
445 offset -= n;
446 }
447
448 /* request skip (if not zero) */
449 if (offset) {
450 state->seek = 1;
451 state->skip = offset;
452 }
453 return state->x.pos + offset;
454}
455
456/* -- see zlib.h -- */
457z_off_t ZEXPORT gzseek(gzFile file, z_off_t offset, int whence) {
458 z_off64_t ret;
459
460 ret = gzseek64(file, (z_off64_t)offset, whence);
461 return ret == (z_off_t)ret ? (z_off_t)ret : -1;
462}
463
464/* -- see zlib.h -- */
465z_off64_t ZEXPORT gztell64(gzFile file) {
466 gz_statep state;
467
468 /* get internal structure and check integrity */
469 if (file == NULL)
470 return -1;
471 state = (gz_statep)file;
472 if (state->mode != GZ_READ && state->mode != GZ_WRITE)
473 return -1;
474
475 /* return position */
476 return state->x.pos + (state->seek ? state->skip : 0);
477}
478
479/* -- see zlib.h -- */
480z_off_t ZEXPORT gztell(gzFile file) {
481 z_off64_t ret;
482
483 ret = gztell64(file);
484 return ret == (z_off_t)ret ? (z_off_t)ret : -1;
485}
486
487/* -- see zlib.h -- */
488z_off64_t ZEXPORT gzoffset64(gzFile file) {
489 z_off64_t offset;
490 gz_statep state;
491
492 /* get internal structure and check integrity */
493 if (file == NULL)
494 return -1;
495 state = (gz_statep)file;
496 if (state->mode != GZ_READ && state->mode != GZ_WRITE)
497 return -1;
498
499 /* compute and return effective offset in file */
500#ifndef IPRT_NO_CRT /* VBox */
501 offset = LSEEK(state->fd, 0, SEEK_CUR);
502 if (offset == -1)
503#else /* VBox */
504 offset = RTFileTell(state->fd); /* VBox */
505 if ((uint64_t)offset == UINT64_MAX) /* VBox */
506#endif /* VBox */
507 return -1;
508 if (state->mode == GZ_READ) /* reading */
509 offset -= state->strm.avail_in; /* don't count buffered input */
510 return offset;
511}
512
513/* -- see zlib.h -- */
514z_off_t ZEXPORT gzoffset(gzFile file) {
515 z_off64_t ret;
516
517 ret = gzoffset64(file);
518 return ret == (z_off_t)ret ? (z_off_t)ret : -1;
519}
520
521/* -- see zlib.h -- */
522int ZEXPORT gzeof(gzFile file) {
523 gz_statep state;
524
525 /* get internal structure and check integrity */
526 if (file == NULL)
527 return 0;
528 state = (gz_statep)file;
529 if (state->mode != GZ_READ && state->mode != GZ_WRITE)
530 return 0;
531
532 /* return end-of-file state */
533 return state->mode == GZ_READ ? state->past : 0;
534}
535
536/* -- see zlib.h -- */
537const char * ZEXPORT gzerror(gzFile file, int *errnum) {
538 gz_statep state;
539
540 /* get internal structure and check integrity */
541 if (file == NULL)
542 return NULL;
543 state = (gz_statep)file;
544 if (state->mode != GZ_READ && state->mode != GZ_WRITE)
545 return NULL;
546
547 /* return error information */
548 if (errnum != NULL)
549 *errnum = state->err;
550 return state->err == Z_MEM_ERROR ? "out of memory" :
551 (state->msg == NULL ? "" : state->msg);
552}
553
554/* -- see zlib.h -- */
555void ZEXPORT gzclearerr(gzFile file) {
556 gz_statep state;
557
558 /* get internal structure and check integrity */
559 if (file == NULL)
560 return;
561 state = (gz_statep)file;
562 if (state->mode != GZ_READ && state->mode != GZ_WRITE)
563 return;
564
565 /* clear error and end-of-file */
566 if (state->mode == GZ_READ) {
567 state->eof = 0;
568 state->past = 0;
569 }
570 gz_error(state, Z_OK, NULL);
571}
572
573/* Create an error message in allocated memory and set state->err and
574 state->msg accordingly. Free any previous error message already there. Do
575 not try to free or allocate space if the error is Z_MEM_ERROR (out of
576 memory). Simply save the error message as a static string. If there is an
577 allocation failure constructing the error message, then convert the error to
578 out of memory. */
579void ZLIB_INTERNAL gz_error(gz_statep state, int err, const char *msg) {
580 /* free previously allocated message and clear */
581 if (state->msg != NULL) {
582 if (state->err != Z_MEM_ERROR)
583 free(state->msg);
584 state->msg = NULL;
585 }
586
587 /* if fatal, set state->x.have to 0 so that the gzgetc() macro fails */
588 if (err != Z_OK && err != Z_BUF_ERROR)
589 state->x.have = 0;
590
591 /* set error code, and if no message, then done */
592 state->err = err;
593 if (msg == NULL)
594 return;
595
596 /* for an out of memory error, return literal string when requested */
597 if (err == Z_MEM_ERROR)
598 return;
599
600 /* construct error message with path */
601 if ((state->msg = (char *)malloc(strlen(state->path) + strlen(msg) + 3)) ==
602 NULL) {
603 state->err = Z_MEM_ERROR;
604 return;
605 }
606#if !defined(NO_snprintf) && !defined(NO_vsnprintf)
607 (void)snprintf(state->msg, strlen(state->path) + strlen(msg) + 3,
608 "%s%s%s", state->path, ": ", msg);
609#else
610 strcpy(state->msg, state->path);
611 strcat(state->msg, ": ");
612 strcat(state->msg, msg);
613#endif
614}
615
616/* portably return maximum value for an int (when limits.h presumed not
617 available) -- we need to do this to cover cases where 2's complement not
618 used, since C standard permits 1's complement and sign-bit representations,
619 otherwise we could just use ((unsigned)-1) >> 1 */
620unsigned ZLIB_INTERNAL gz_intmax(void) {
621#ifdef INT_MAX
622 return INT_MAX;
623#else
624 unsigned p = 1, q;
625 do {
626 q = p;
627 p <<= 1;
628 p++;
629 } while (p > q);
630 return q >> 1;
631#endif
632}
注意: 瀏覽 TracBrowser 來幫助您使用儲存庫瀏覽器

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