File:
[ELWIX - Embedded LightWeight unIX -] /
embedaddon /
sudo /
zlib /
gzlib.c
Revision
1.1.1.2 (vendor branch):
download - view:
text,
annotated -
select for diffs -
revision graph
Mon Jul 22 10:46:14 2013 UTC (11 years, 1 month ago) by
misho
Branches:
sudo,
MAIN
CVS tags:
v1_8_8p0,
v1_8_8,
v1_8_7p0,
v1_8_7,
v1_8_5p1,
v1_8_10p3_0,
v1_8_10p3,
HEAD
1.8.7
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 */
19: local void gz_reset OF((gz_statep));
20: local 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. */
33: char 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 */
75: local 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. */
91: local 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 -- */
216: gzFile 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 -- */
224: gzFile 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 -- */
232: gzFile 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 -- */
248: int 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 -- */
273: int 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 -- */
296: z_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 -- */
373: z_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 -- */
385: z_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 -- */
402: z_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 -- */
412: z_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 -- */
435: z_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 -- */
445: int 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 -- */
462: const 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 -- */
482: void 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. */
508: void 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 */
552: unsigned 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
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>