VirtualBox

source: vbox/trunk/src/libs/zlib-1.2.6/gzlib.c@ 43391

Last change on this file since 43391 was 40354, checked in by vboxsync, 13 years ago

libs/zlib-1.2.6: fix OSE

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 14.5 KB
Line 
1/* gzlib.c -- zlib functions common to reading and writing gzip files
2 * Copyright (C) 2004, 2010, 2011 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 char *, 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 state->seek = 0; /* no seek request pending */
85 gz_error(state, Z_OK, NULL); /* clear error */
86 state->x.pos = 0; /* no uncompressed data yet */
87 state->strm.avail_in = 0; /* no input data yet */
88}
89
90/* Open a gzip file either by name or file descriptor. */
91local gzFile gz_open(path, fd, mode)
92 const char *path;
93 int fd;
94 const char *mode;
95{
96 gz_statep state;
97
98 /* check input */
99 if (path == NULL)
100 return NULL;
101
102 /* allocate gzFile structure to return */
103 state = malloc(sizeof(gz_state));
104 if (state == NULL)
105 return NULL;
106 state->size = 0; /* no buffers allocated yet */
107 state->want = GZBUFSIZE; /* requested buffer size */
108 state->msg = NULL; /* no error message yet */
109
110 /* interpret mode */
111 state->mode = GZ_NONE;
112 state->level = Z_DEFAULT_COMPRESSION;
113 state->strategy = Z_DEFAULT_STRATEGY;
114 state->direct = 0;
115 while (*mode) {
116 if (*mode >= '0' && *mode <= '9')
117 state->level = *mode - '0';
118 else
119 switch (*mode) {
120 case 'r':
121 state->mode = GZ_READ;
122 break;
123#ifndef NO_GZCOMPRESS
124 case 'w':
125 state->mode = GZ_WRITE;
126 break;
127 case 'a':
128 state->mode = GZ_APPEND;
129 break;
130#endif
131 case '+': /* can't read and write at the same time */
132 free(state);
133 return NULL;
134 case 'b': /* ignore -- will request binary anyway */
135 break;
136 case 'f':
137 state->strategy = Z_FILTERED;
138 break;
139 case 'h':
140 state->strategy = Z_HUFFMAN_ONLY;
141 break;
142 case 'R':
143 state->strategy = Z_RLE;
144 break;
145 case 'F':
146 state->strategy = Z_FIXED;
147 case 'T':
148 state->direct = 1;
149 default: /* could consider as an error, but just ignore */
150 ;
151 }
152 mode++;
153 }
154
155 /* must provide an "r", "w", or "a" */
156 if (state->mode == GZ_NONE) {
157 free(state);
158 return NULL;
159 }
160
161 /* can't force transparent read */
162 if (state->mode == GZ_READ) {
163 if (state->direct) {
164 free(state);
165 return NULL;
166 }
167 state->direct = 1; /* for empty file */
168 }
169
170 /* save the path name for error messages */
171 state->path = malloc(strlen(path) + 1);
172 if (state->path == NULL) {
173 free(state);
174 return NULL;
175 }
176 strcpy(state->path, path);
177
178 /* open the file with the appropriate mode (or just use fd) */
179 state->fd = fd != -1 ? fd :
180 open(path,
181#ifdef O_LARGEFILE
182 O_LARGEFILE |
183#endif
184#ifdef O_BINARY
185 O_BINARY |
186#endif
187 (state->mode == GZ_READ ?
188 O_RDONLY :
189 (O_WRONLY | O_CREAT | (
190 state->mode == GZ_WRITE ?
191 O_TRUNC :
192 O_APPEND))),
193 0666);
194 if (state->fd == -1) {
195 free(state->path);
196 free(state);
197 return NULL;
198 }
199 if (state->mode == GZ_APPEND)
200 state->mode = GZ_WRITE; /* simplify later checks */
201
202 /* save the current position for rewinding (only if reading) */
203 if (state->mode == GZ_READ) {
204 state->start = LSEEK(state->fd, 0, SEEK_CUR);
205 if (state->start == -1) state->start = 0;
206 }
207
208 /* initialize stream */
209 gz_reset(state);
210
211 /* return stream */
212 return (gzFile)state;
213}
214
215/* -- see zlib.h -- */
216gzFile ZEXPORT gzopen(path, mode)
217 const char *path;
218 const char *mode;
219{
220 return gz_open(path, -1, mode);
221}
222
223/* -- see zlib.h -- */
224gzFile ZEXPORT gzopen64(path, mode)
225 const char *path;
226 const char *mode;
227{
228 return gz_open(path, -1, mode);
229}
230
231/* -- see zlib.h -- */
232gzFile ZEXPORT gzdopen(fd, mode)
233 int fd;
234 const char *mode;
235{
236 char *path; /* identifier for error messages */
237 gzFile gz;
238
239 if (fd == -1 || (path = malloc(7 + 3 * sizeof(int))) == NULL)
240 return NULL;
241 sprintf(path, "<fd:%d>", fd); /* for debugging */
242 gz = gz_open(path, fd, mode);
243 free(path);
244 return gz;
245}
246
247/* -- see zlib.h -- */
248int ZEXPORT gzbuffer(file, size)
249 gzFile file;
250 unsigned size;
251{
252 gz_statep state;
253
254 /* get internal structure and check integrity */
255 if (file == NULL)
256 return -1;
257 state = (gz_statep)file;
258 if (state->mode != GZ_READ && state->mode != GZ_WRITE)
259 return -1;
260
261 /* make sure we haven't already allocated memory */
262 if (state->size != 0)
263 return -1;
264
265 /* check and set requested size */
266 if (size < 2)
267 size = 2; /* need two bytes to check magic header */
268 state->want = size;
269 return 0;
270}
271
272/* -- see zlib.h -- */
273int ZEXPORT gzrewind(file)
274 gzFile file;
275{
276 gz_statep state;
277
278 /* get internal structure */
279 if (file == NULL)
280 return -1;
281 state = (gz_statep)file;
282
283 /* check that we're reading and that there's no error */
284 if (state->mode != GZ_READ ||
285 (state->err != Z_OK && state->err != Z_BUF_ERROR))
286 return -1;
287
288 /* back up and start over */
289 if (LSEEK(state->fd, state->start, SEEK_SET) == -1)
290 return -1;
291 gz_reset(state);
292 return 0;
293}
294
295/* -- see zlib.h -- */
296z_off64_t ZEXPORT gzseek64(file, offset, whence)
297 gzFile file;
298 z_off64_t offset;
299 int whence;
300{
301 unsigned n;
302 z_off64_t ret;
303 gz_statep state;
304
305 /* get internal structure and check integrity */
306 if (file == NULL)
307 return -1;
308 state = (gz_statep)file;
309 if (state->mode != GZ_READ && state->mode != GZ_WRITE)
310 return -1;
311
312 /* check that there's no error */
313 if (state->err != Z_OK && state->err != Z_BUF_ERROR)
314 return -1;
315
316 /* can only seek from start or relative to current position */
317 if (whence != SEEK_SET && whence != SEEK_CUR)
318 return -1;
319
320 /* normalize offset to a SEEK_CUR specification */
321 if (whence == SEEK_SET)
322 offset -= state->x.pos;
323 else if (state->seek)
324 offset += state->skip;
325 state->seek = 0;
326
327 /* if within raw area while reading, just go there */
328 if (state->mode == GZ_READ && state->how == COPY &&
329 state->x.pos + offset >= 0) {
330 ret = LSEEK(state->fd, offset - state->x.have, SEEK_CUR);
331 if (ret == -1)
332 return -1;
333 state->x.have = 0;
334 state->eof = 0;
335 state->past = 0;
336 state->seek = 0;
337 gz_error(state, Z_OK, NULL);
338 state->strm.avail_in = 0;
339 state->x.pos += offset;
340 return state->x.pos;
341 }
342
343 /* calculate skip amount, rewinding if needed for back seek when reading */
344 if (offset < 0) {
345 if (state->mode != GZ_READ) /* writing -- can't go backwards */
346 return -1;
347 offset += state->x.pos;
348 if (offset < 0) /* before start of file! */
349 return -1;
350 if (gzrewind(file) == -1) /* rewind, then skip to offset */
351 return -1;
352 }
353
354 /* if reading, skip what's in output buffer (one less gzgetc() check) */
355 if (state->mode == GZ_READ) {
356 n = GT_OFF(state->x.have) || (z_off64_t)state->x.have > offset ?
357 (unsigned)offset : state->x.have;
358 state->x.have -= n;
359 state->x.next += n;
360 state->x.pos += n;
361 offset -= n;
362 }
363
364 /* request skip (if not zero) */
365 if (offset) {
366 state->seek = 1;
367 state->skip = offset;
368 }
369 return state->x.pos + offset;
370}
371
372/* -- see zlib.h -- */
373z_off_t ZEXPORT gzseek(file, offset, whence)
374 gzFile file;
375 z_off_t offset;
376 int whence;
377{
378 z_off64_t ret;
379
380 ret = gzseek64(file, (z_off64_t)offset, whence);
381 return ret == (z_off_t)ret ? (z_off_t)ret : -1;
382}
383
384/* -- see zlib.h -- */
385z_off64_t ZEXPORT gztell64(file)
386 gzFile file;
387{
388 gz_statep state;
389
390 /* get internal structure and check integrity */
391 if (file == NULL)
392 return -1;
393 state = (gz_statep)file;
394 if (state->mode != GZ_READ && state->mode != GZ_WRITE)
395 return -1;
396
397 /* return position */
398 return state->x.pos + (state->seek ? state->skip : 0);
399}
400
401/* -- see zlib.h -- */
402z_off_t ZEXPORT gztell(file)
403 gzFile file;
404{
405 z_off64_t ret;
406
407 ret = gztell64(file);
408 return ret == (z_off_t)ret ? (z_off_t)ret : -1;
409}
410
411/* -- see zlib.h -- */
412z_off64_t ZEXPORT gzoffset64(file)
413 gzFile file;
414{
415 z_off64_t offset;
416 gz_statep state;
417
418 /* get internal structure and check integrity */
419 if (file == NULL)
420 return -1;
421 state = (gz_statep)file;
422 if (state->mode != GZ_READ && state->mode != GZ_WRITE)
423 return -1;
424
425 /* compute and return effective offset in file */
426 offset = LSEEK(state->fd, 0, SEEK_CUR);
427 if (offset == -1)
428 return -1;
429 if (state->mode == GZ_READ) /* reading */
430 offset -= state->strm.avail_in; /* don't count buffered input */
431 return offset;
432}
433
434/* -- see zlib.h -- */
435z_off_t ZEXPORT gzoffset(file)
436 gzFile file;
437{
438 z_off64_t ret;
439
440 ret = gzoffset64(file);
441 return ret == (z_off_t)ret ? (z_off_t)ret : -1;
442}
443
444/* -- see zlib.h -- */
445int ZEXPORT gzeof(file)
446 gzFile file;
447{
448 gz_statep state;
449
450 /* get internal structure and check integrity */
451 if (file == NULL)
452 return 0;
453 state = (gz_statep)file;
454 if (state->mode != GZ_READ && state->mode != GZ_WRITE)
455 return 0;
456
457 /* return end-of-file state */
458 return state->mode == GZ_READ ? state->past : 0;
459}
460
461/* -- see zlib.h -- */
462const char * ZEXPORT gzerror(file, errnum)
463 gzFile file;
464 int *errnum;
465{
466 gz_statep state;
467
468 /* get internal structure and check integrity */
469 if (file == NULL)
470 return NULL;
471 state = (gz_statep)file;
472 if (state->mode != GZ_READ && state->mode != GZ_WRITE)
473 return NULL;
474
475 /* return error information */
476 if (errnum != NULL)
477 *errnum = state->err;
478 return state->msg == NULL ? "" : state->msg;
479}
480
481/* -- see zlib.h -- */
482void ZEXPORT gzclearerr(file)
483 gzFile file;
484{
485 gz_statep state;
486
487 /* get internal structure and check integrity */
488 if (file == NULL)
489 return;
490 state = (gz_statep)file;
491 if (state->mode != GZ_READ && state->mode != GZ_WRITE)
492 return;
493
494 /* clear error and end-of-file */
495 if (state->mode == GZ_READ) {
496 state->eof = 0;
497 state->past = 0;
498 }
499 gz_error(state, Z_OK, NULL);
500}
501
502/* Create an error message in allocated memory and set state->err and
503 state->msg accordingly. Free any previous error message already there. Do
504 not try to free or allocate space if the error is Z_MEM_ERROR (out of
505 memory). Simply save the error message as a static string. If there is an
506 allocation failure constructing the error message, then convert the error to
507 out of memory. */
508void ZLIB_INTERNAL gz_error(state, err, msg)
509 gz_statep state;
510 int err;
511 const char *msg;
512{
513 /* free previously allocated message and clear */
514 if (state->msg != NULL) {
515 if (state->err != Z_MEM_ERROR)
516 free(state->msg);
517 state->msg = NULL;
518 }
519
520 /* if fatal, set state->x.have to 0 so that the gzgetc() macro fails */
521 if (err != Z_OK && err != Z_BUF_ERROR)
522 state->x.have = 0;
523
524 /* set error code, and if no message, then done */
525 state->err = err;
526 if (msg == NULL)
527 return;
528
529 /* for an out of memory error, save as static string */
530 if (err == Z_MEM_ERROR) {
531 state->msg = (char *)msg;
532 return;
533 }
534
535 /* construct error message with path */
536 if ((state->msg = malloc(strlen(state->path) + strlen(msg) + 3)) == NULL) {
537 state->err = Z_MEM_ERROR;
538 state->msg = (char *)"out of memory";
539 return;
540 }
541 strcpy(state->msg, state->path);
542 strcat(state->msg, ": ");
543 strcat(state->msg, msg);
544 return;
545}
546
547#ifndef INT_MAX
548/* portably return maximum value for an int (when limits.h presumed not
549 available) -- we need to do this to cover cases where 2's complement not
550 used, since C standard permits 1's complement and sign-bit representations,
551 otherwise we could just use ((unsigned)-1) >> 1 */
552unsigned ZLIB_INTERNAL gz_intmax()
553{
554 unsigned p, q;
555
556 p = 1;
557 do {
558 q = p;
559 p <<= 1;
560 p++;
561 } while (p > q);
562 return q >> 1;
563}
564#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