VirtualBox

source: vbox/trunk/src/libs/zlib-1.2.12/gzlib.c@ 95970

Last change on this file since 95970 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: 20.0 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 */
273 rc = RTFileOpen(&state->fd, path, fOpen);
274 if (RT_FAILURE(rc)) {
275#endif /* IPRT_NO_CRT */
276 free(state->path);
277 free(state);
278 return NULL;
279 }
280 if (state->mode == GZ_APPEND) {
281#ifndef IPRT_NO_CRT /* VBox */
282 LSEEK(state->fd, 0, SEEK_END); /* so gzoffset() is correct */
283#else
284 RTFileSeek(state->fd, 0, RTFILE_SEEK_END, NULL);
285#endif
286 state->mode = GZ_WRITE; /* simplify later checks */
287 }
288
289 /* save the current position for rewinding (only if reading) */
290 if (state->mode == GZ_READ) {
291#ifndef IPRT_NO_CRT /* VBox */
292 state->start = LSEEK(state->fd, 0, SEEK_CUR);
293#else
294 state->start = RTFileTell(state->fd);
295#endif
296 if (state->start == -1) state->start = 0;
297 }
298
299 /* initialize stream */
300 gz_reset(state);
301
302 /* return stream */
303 return (gzFile)state;
304}
305
306/* -- see zlib.h -- */
307gzFile ZEXPORT gzopen(path, mode)
308 const char *path;
309 const char *mode;
310{
311 return gz_open(path, -1, mode);
312}
313
314/* -- see zlib.h -- */
315gzFile ZEXPORT gzopen64(path, mode)
316 const char *path;
317 const char *mode;
318{
319 return gz_open(path, -1, mode);
320}
321
322/* -- see zlib.h -- */
323gzFile ZEXPORT gzdopen(fd, mode)
324 int fd;
325 const char *mode;
326{
327 char *path; /* identifier for error messages */
328 gzFile gz;
329
330 if (fd == -1 || (path = (char *)malloc(7 + 3 * sizeof(int))) == NULL)
331 return NULL;
332#if !defined(NO_snprintf) && !defined(NO_vsnprintf)
333 (void)snprintf(path, 7 + 3 * sizeof(int), "<fd:%d>", fd);
334#else
335 sprintf(path, "<fd:%d>", fd); /* for debugging */
336#endif
337 gz = gz_open(path, fd, mode);
338 free(path);
339 return gz;
340}
341
342/* -- see zlib.h -- */
343#ifdef WIDECHAR
344gzFile ZEXPORT gzopen_w(path, mode)
345 const wchar_t *path;
346 const char *mode;
347{
348 return gz_open(path, -2, mode);
349}
350#endif
351
352/* -- see zlib.h -- */
353int ZEXPORT gzbuffer(file, size)
354 gzFile file;
355 unsigned size;
356{
357 gz_statep state;
358
359 /* get internal structure and check integrity */
360 if (file == NULL)
361 return -1;
362 state = (gz_statep)file;
363 if (state->mode != GZ_READ && state->mode != GZ_WRITE)
364 return -1;
365
366 /* make sure we haven't already allocated memory */
367 if (state->size != 0)
368 return -1;
369
370 /* check and set requested size */
371 if ((size << 1) < size)
372 return -1; /* need to be able to double it */
373 if (size < 2)
374 size = 2; /* need two bytes to check magic header */
375 state->want = size;
376 return 0;
377}
378
379/* -- see zlib.h -- */
380int ZEXPORT gzrewind(file)
381 gzFile file;
382{
383 gz_statep state;
384
385 /* get internal structure */
386 if (file == NULL)
387 return -1;
388 state = (gz_statep)file;
389
390 /* check that we're reading and that there's no error */
391 if (state->mode != GZ_READ ||
392 (state->err != Z_OK && state->err != Z_BUF_ERROR))
393 return -1;
394
395 /* back up and start over */
396#ifndef IPRT_NO_CRT /* VBox */
397 if (LSEEK(state->fd, state->start, SEEK_SET) == -1)
398#else
399 if (RT_FAILURE(RTFileSeek(state->fd, state->start, RTFILE_SEEK_CURRENT, NULL)))
400#endif
401 return -1;
402 gz_reset(state);
403 return 0;
404}
405
406/* -- see zlib.h -- */
407z_off64_t ZEXPORT gzseek64(file, offset, whence)
408 gzFile file;
409 z_off64_t offset;
410 int whence;
411{
412 unsigned n;
413 z_off64_t ret;
414 gz_statep state;
415
416 /* get internal structure and check integrity */
417 if (file == NULL)
418 return -1;
419 state = (gz_statep)file;
420 if (state->mode != GZ_READ && state->mode != GZ_WRITE)
421 return -1;
422
423 /* check that there's no error */
424 if (state->err != Z_OK && state->err != Z_BUF_ERROR)
425 return -1;
426
427 /* can only seek from start or relative to current position */
428 if (whence != SEEK_SET && whence != SEEK_CUR)
429 return -1;
430
431 /* normalize offset to a SEEK_CUR specification */
432 if (whence == SEEK_SET)
433 offset -= state->x.pos;
434 else if (state->seek)
435 offset += state->skip;
436 state->seek = 0;
437
438 /* if within raw area while reading, just go there */
439 if (state->mode == GZ_READ && state->how == COPY &&
440 state->x.pos + offset >= 0) {
441#ifndef IPRT_NO_CRT /* VBox */
442 ret = LSEEK(state->fd, offset - (z_off64_t)state->x.have, SEEK_CUR);
443 if (ret == -1)
444#else
445 ret = RTFileSeek(state->fd, offset - (z_off64_t)state->x.have, SEEK_CUR, NULL);
446 if (RT_FAILURE(ret))
447#endif
448 return -1;
449 state->x.have = 0;
450 state->eof = 0;
451 state->past = 0;
452 state->seek = 0;
453 gz_error(state, Z_OK, NULL);
454 state->strm.avail_in = 0;
455 state->x.pos += offset;
456 return state->x.pos;
457 }
458
459 /* calculate skip amount, rewinding if needed for back seek when reading */
460 if (offset < 0) {
461 if (state->mode != GZ_READ) /* writing -- can't go backwards */
462 return -1;
463 offset += state->x.pos;
464 if (offset < 0) /* before start of file! */
465 return -1;
466 if (gzrewind(file) == -1) /* rewind, then skip to offset */
467 return -1;
468 }
469
470 /* if reading, skip what's in output buffer (one less gzgetc() check) */
471 if (state->mode == GZ_READ) {
472 n = GT_OFF(state->x.have) || (z_off64_t)state->x.have > offset ?
473 (unsigned)offset : state->x.have;
474 state->x.have -= n;
475 state->x.next += n;
476 state->x.pos += n;
477 offset -= n;
478 }
479
480 /* request skip (if not zero) */
481 if (offset) {
482 state->seek = 1;
483 state->skip = offset;
484 }
485 return state->x.pos + offset;
486}
487
488/* -- see zlib.h -- */
489z_off_t ZEXPORT gzseek(file, offset, whence)
490 gzFile file;
491 z_off_t offset;
492 int whence;
493{
494 z_off64_t ret;
495
496 ret = gzseek64(file, (z_off64_t)offset, whence);
497 return ret == (z_off_t)ret ? (z_off_t)ret : -1;
498}
499
500/* -- see zlib.h -- */
501z_off64_t ZEXPORT gztell64(file)
502 gzFile file;
503{
504 gz_statep state;
505
506 /* get internal structure and check integrity */
507 if (file == NULL)
508 return -1;
509 state = (gz_statep)file;
510 if (state->mode != GZ_READ && state->mode != GZ_WRITE)
511 return -1;
512
513 /* return position */
514 return state->x.pos + (state->seek ? state->skip : 0);
515}
516
517/* -- see zlib.h -- */
518z_off_t ZEXPORT gztell(file)
519 gzFile file;
520{
521 z_off64_t ret;
522
523 ret = gztell64(file);
524 return ret == (z_off_t)ret ? (z_off_t)ret : -1;
525}
526
527/* -- see zlib.h -- */
528z_off64_t ZEXPORT gzoffset64(file)
529 gzFile file;
530{
531 z_off64_t offset;
532 gz_statep state;
533
534 /* get internal structure and check integrity */
535 if (file == NULL)
536 return -1;
537 state = (gz_statep)file;
538 if (state->mode != GZ_READ && state->mode != GZ_WRITE)
539 return -1;
540
541 /* compute and return effective offset in file */
542#ifndef IPRT_NO_CRT /* VBox */
543 offset = LSEEK(state->fd, 0, SEEK_CUR);
544 if (offset == -1)
545#else
546 offset = RTFileTell(state->fd);
547 if ((uint64_t)offset == UINT64_MAX)
548#endif
549 return -1;
550 if (state->mode == GZ_READ) /* reading */
551 offset -= state->strm.avail_in; /* don't count buffered input */
552 return offset;
553}
554
555/* -- see zlib.h -- */
556z_off_t ZEXPORT gzoffset(file)
557 gzFile file;
558{
559 z_off64_t ret;
560
561 ret = gzoffset64(file);
562 return ret == (z_off_t)ret ? (z_off_t)ret : -1;
563}
564
565/* -- see zlib.h -- */
566int ZEXPORT gzeof(file)
567 gzFile file;
568{
569 gz_statep state;
570
571 /* get internal structure and check integrity */
572 if (file == NULL)
573 return 0;
574 state = (gz_statep)file;
575 if (state->mode != GZ_READ && state->mode != GZ_WRITE)
576 return 0;
577
578 /* return end-of-file state */
579 return state->mode == GZ_READ ? state->past : 0;
580}
581
582/* -- see zlib.h -- */
583const char * ZEXPORT gzerror(file, errnum)
584 gzFile file;
585 int *errnum;
586{
587 gz_statep state;
588
589 /* get internal structure and check integrity */
590 if (file == NULL)
591 return NULL;
592 state = (gz_statep)file;
593 if (state->mode != GZ_READ && state->mode != GZ_WRITE)
594 return NULL;
595
596 /* return error information */
597 if (errnum != NULL)
598 *errnum = state->err;
599 return state->err == Z_MEM_ERROR ? "out of memory" :
600 (state->msg == NULL ? "" : state->msg);
601}
602
603/* -- see zlib.h -- */
604void ZEXPORT gzclearerr(file)
605 gzFile file;
606{
607 gz_statep state;
608
609 /* get internal structure and check integrity */
610 if (file == NULL)
611 return;
612 state = (gz_statep)file;
613 if (state->mode != GZ_READ && state->mode != GZ_WRITE)
614 return;
615
616 /* clear error and end-of-file */
617 if (state->mode == GZ_READ) {
618 state->eof = 0;
619 state->past = 0;
620 }
621 gz_error(state, Z_OK, NULL);
622}
623
624/* Create an error message in allocated memory and set state->err and
625 state->msg accordingly. Free any previous error message already there. Do
626 not try to free or allocate space if the error is Z_MEM_ERROR (out of
627 memory). Simply save the error message as a static string. If there is an
628 allocation failure constructing the error message, then convert the error to
629 out of memory. */
630void ZLIB_INTERNAL gz_error(state, err, msg)
631 gz_statep state;
632 int err;
633 const char *msg;
634{
635 /* free previously allocated message and clear */
636 if (state->msg != NULL) {
637 if (state->err != Z_MEM_ERROR)
638 free(state->msg);
639 state->msg = NULL;
640 }
641
642 /* if fatal, set state->x.have to 0 so that the gzgetc() macro fails */
643 if (err != Z_OK && err != Z_BUF_ERROR)
644 state->x.have = 0;
645
646 /* set error code, and if no message, then done */
647 state->err = err;
648 if (msg == NULL)
649 return;
650
651 /* for an out of memory error, return literal string when requested */
652 if (err == Z_MEM_ERROR)
653 return;
654
655 /* construct error message with path */
656 if ((state->msg = (char *)malloc(strlen(state->path) + strlen(msg) + 3)) ==
657 NULL) {
658 state->err = Z_MEM_ERROR;
659 return;
660 }
661#if !defined(NO_snprintf) && !defined(NO_vsnprintf)
662 (void)snprintf(state->msg, strlen(state->path) + strlen(msg) + 3,
663 "%s%s%s", state->path, ": ", msg);
664#else
665 strcpy(state->msg, state->path);
666 strcat(state->msg, ": ");
667 strcat(state->msg, msg);
668#endif
669}
670
671#ifndef INT_MAX
672/* portably return maximum value for an int (when limits.h presumed not
673 available) -- we need to do this to cover cases where 2's complement not
674 used, since C standard permits 1's complement and sign-bit representations,
675 otherwise we could just use ((unsigned)-1) >> 1 */
676unsigned ZLIB_INTERNAL gz_intmax()
677{
678 unsigned p, q;
679
680 p = 1;
681 do {
682 q = p;
683 p <<= 1;
684 p++;
685 } while (p > q);
686 return q >> 1;
687}
688#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