Annotation of embedaddon/sudo/zlib/gzlib.c, revision 1.1.1.2
1.1 misho 1: /* gzlib.c -- zlib functions common to reading and writing gzip files
1.1.1.2 ! misho 2: * Copyright (C) 2004, 2010, 2011 Mark Adler
1.1 misho 3: * For conditions of distribution and use, see copyright notice in zlib.h
4: */
5:
6: #include "gzguts.h"
7:
1.1.1.2 ! misho 8: #if defined(_WIN32) && !defined(__BORLANDC__)
! 9: # define LSEEK _lseeki64
! 10: #else
1.1 misho 11: #if defined(_LARGEFILE64_SOURCE) && _LFS64_LARGEFILE-0
12: # define LSEEK lseek64
13: #else
14: # define LSEEK lseek
15: #endif
1.1.1.2 ! misho 16: #endif
1.1 misho 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: {
1.1.1.2 ! misho 78: state->x.have = 0; /* no output data available */
1.1 misho 79: if (state->mode == GZ_READ) { /* for reading ... */
80: state->eof = 0; /* not at end of file */
1.1.1.2 ! misho 81: state->past = 0; /* have not read past end yet */
1.1 misho 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 */
1.1.1.2 ! misho 86: state->x.pos = 0; /* no uncompressed data yet */
1.1 misho 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:
1.1.1.2 ! misho 98: /* check input */
! 99: if (path == NULL)
! 100: return NULL;
! 101:
1.1 misho 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;
1.1.1.2 ! misho 114: state->direct = 0;
1.1 misho 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;
1.1.1.2 ! misho 147: case 'T':
! 148: state->direct = 1;
1.1 misho 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:
1.1.1.2 ! misho 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:
1.1 misho 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 */
1.1.1.2 ! misho 266: if (size < 2)
! 267: size = 2; /* need two bytes to check magic header */
1.1 misho 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 */
1.1.1.2 ! misho 284: if (state->mode != GZ_READ ||
! 285: (state->err != Z_OK && state->err != Z_BUF_ERROR))
1.1 misho 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 */
1.1.1.2 ! misho 313: if (state->err != Z_OK && state->err != Z_BUF_ERROR)
1.1 misho 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)
1.1.1.2 ! misho 322: offset -= state->x.pos;
1.1 misho 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 &&
1.1.1.2 ! misho 329: state->x.pos + offset >= 0) {
! 330: ret = LSEEK(state->fd, offset - state->x.have, SEEK_CUR);
1.1 misho 331: if (ret == -1)
332: return -1;
1.1.1.2 ! misho 333: state->x.have = 0;
1.1 misho 334: state->eof = 0;
1.1.1.2 ! misho 335: state->past = 0;
1.1 misho 336: state->seek = 0;
337: gz_error(state, Z_OK, NULL);
338: state->strm.avail_in = 0;
1.1.1.2 ! misho 339: state->x.pos += offset;
! 340: return state->x.pos;
1.1 misho 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;
1.1.1.2 ! misho 347: offset += state->x.pos;
1.1 misho 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) {
1.1.1.2 ! misho 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;
1.1 misho 361: offset -= n;
362: }
363:
364: /* request skip (if not zero) */
365: if (offset) {
366: state->seek = 1;
367: state->skip = offset;
368: }
1.1.1.2 ! misho 369: return state->x.pos + offset;
1.1 misho 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 */
1.1.1.2 ! misho 398: return state->x.pos + (state->seek ? state->skip : 0);
1.1 misho 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 */
1.1.1.2 ! misho 458: return state->mode == GZ_READ ? state->past : 0;
1.1 misho 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 */
1.1.1.2 ! misho 495: if (state->mode == GZ_READ) {
1.1 misho 496: state->eof = 0;
1.1.1.2 ! misho 497: state->past = 0;
! 498: }
1.1 misho 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:
1.1.1.2 ! misho 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:
1.1 misho 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>