VirtualBox

source: vbox/trunk/src/libs/zlib-1.2.13/gzlib.c@ 98879

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