Annotation of embedaddon/sudo/zlib/gzlib.c, revision 1.1.1.1
1.1 misho 1: /* gzlib.c -- zlib functions common to reading and writing gzip files
2: * Copyright (C) 2004, 2010 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(_LARGEFILE64_SOURCE) && _LFS64_LARGEFILE-0
9: # define LSEEK lseek64
10: #else
11: # define LSEEK lseek
12: #endif
13:
14: /* Local functions */
15: local void gz_reset OF((gz_statep));
16: local gzFile gz_open OF((const char *, int, const char *));
17:
18: #if defined UNDER_CE
19:
20: /* Map the Windows error number in ERROR to a locale-dependent error message
21: string and return a pointer to it. Typically, the values for ERROR come
22: from GetLastError.
23:
24: The string pointed to shall not be modified by the application, but may be
25: overwritten by a subsequent call to gz_strwinerror
26:
27: The gz_strwinerror function does not change the current setting of
28: GetLastError. */
29: char ZLIB_INTERNAL *gz_strwinerror (error)
30: DWORD error;
31: {
32: static char buf[1024];
33:
34: wchar_t *msgbuf;
35: DWORD lasterr = GetLastError();
36: DWORD chars = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM
37: | FORMAT_MESSAGE_ALLOCATE_BUFFER,
38: NULL,
39: error,
40: 0, /* Default language */
41: (LPVOID)&msgbuf,
42: 0,
43: NULL);
44: if (chars != 0) {
45: /* If there is an \r\n appended, zap it. */
46: if (chars >= 2
47: && msgbuf[chars - 2] == '\r' && msgbuf[chars - 1] == '\n') {
48: chars -= 2;
49: msgbuf[chars] = 0;
50: }
51:
52: if (chars > sizeof (buf) - 1) {
53: chars = sizeof (buf) - 1;
54: msgbuf[chars] = 0;
55: }
56:
57: wcstombs(buf, msgbuf, chars + 1);
58: LocalFree(msgbuf);
59: }
60: else {
61: sprintf(buf, "unknown win32 error (%ld)", error);
62: }
63:
64: SetLastError(lasterr);
65: return buf;
66: }
67:
68: #endif /* UNDER_CE */
69:
70: /* Reset gzip file state */
71: local void gz_reset(state)
72: gz_statep state;
73: {
74: if (state->mode == GZ_READ) { /* for reading ... */
75: state->have = 0; /* no output data available */
76: state->eof = 0; /* not at end of file */
77: state->how = LOOK; /* look for gzip header */
78: state->direct = 1; /* default for empty file */
79: }
80: state->seek = 0; /* no seek request pending */
81: gz_error(state, Z_OK, NULL); /* clear error */
82: state->pos = 0; /* no uncompressed data yet */
83: state->strm.avail_in = 0; /* no input data yet */
84: }
85:
86: /* Open a gzip file either by name or file descriptor. */
87: local gzFile gz_open(path, fd, mode)
88: const char *path;
89: int fd;
90: const char *mode;
91: {
92: gz_statep state;
93:
94: /* allocate gzFile structure to return */
95: state = malloc(sizeof(gz_state));
96: if (state == NULL)
97: return NULL;
98: state->size = 0; /* no buffers allocated yet */
99: state->want = GZBUFSIZE; /* requested buffer size */
100: state->msg = NULL; /* no error message yet */
101:
102: /* interpret mode */
103: state->mode = GZ_NONE;
104: state->level = Z_DEFAULT_COMPRESSION;
105: state->strategy = Z_DEFAULT_STRATEGY;
106: while (*mode) {
107: if (*mode >= '0' && *mode <= '9')
108: state->level = *mode - '0';
109: else
110: switch (*mode) {
111: case 'r':
112: state->mode = GZ_READ;
113: break;
114: #ifndef NO_GZCOMPRESS
115: case 'w':
116: state->mode = GZ_WRITE;
117: break;
118: case 'a':
119: state->mode = GZ_APPEND;
120: break;
121: #endif
122: case '+': /* can't read and write at the same time */
123: free(state);
124: return NULL;
125: case 'b': /* ignore -- will request binary anyway */
126: break;
127: case 'f':
128: state->strategy = Z_FILTERED;
129: break;
130: case 'h':
131: state->strategy = Z_HUFFMAN_ONLY;
132: break;
133: case 'R':
134: state->strategy = Z_RLE;
135: break;
136: case 'F':
137: state->strategy = Z_FIXED;
138: default: /* could consider as an error, but just ignore */
139: ;
140: }
141: mode++;
142: }
143:
144: /* must provide an "r", "w", or "a" */
145: if (state->mode == GZ_NONE) {
146: free(state);
147: return NULL;
148: }
149:
150: /* save the path name for error messages */
151: state->path = malloc(strlen(path) + 1);
152: if (state->path == NULL) {
153: free(state);
154: return NULL;
155: }
156: strcpy(state->path, path);
157:
158: /* open the file with the appropriate mode (or just use fd) */
159: state->fd = fd != -1 ? fd :
160: open(path,
161: #ifdef O_LARGEFILE
162: O_LARGEFILE |
163: #endif
164: #ifdef O_BINARY
165: O_BINARY |
166: #endif
167: (state->mode == GZ_READ ?
168: O_RDONLY :
169: (O_WRONLY | O_CREAT | (
170: state->mode == GZ_WRITE ?
171: O_TRUNC :
172: O_APPEND))),
173: 0666);
174: if (state->fd == -1) {
175: free(state->path);
176: free(state);
177: return NULL;
178: }
179: if (state->mode == GZ_APPEND)
180: state->mode = GZ_WRITE; /* simplify later checks */
181:
182: /* save the current position for rewinding (only if reading) */
183: if (state->mode == GZ_READ) {
184: state->start = LSEEK(state->fd, 0, SEEK_CUR);
185: if (state->start == -1) state->start = 0;
186: }
187:
188: /* initialize stream */
189: gz_reset(state);
190:
191: /* return stream */
192: return (gzFile)state;
193: }
194:
195: /* -- see zlib.h -- */
196: gzFile ZEXPORT gzopen(path, mode)
197: const char *path;
198: const char *mode;
199: {
200: return gz_open(path, -1, mode);
201: }
202:
203: /* -- see zlib.h -- */
204: gzFile ZEXPORT gzopen64(path, mode)
205: const char *path;
206: const char *mode;
207: {
208: return gz_open(path, -1, mode);
209: }
210:
211: /* -- see zlib.h -- */
212: gzFile ZEXPORT gzdopen(fd, mode)
213: int fd;
214: const char *mode;
215: {
216: char *path; /* identifier for error messages */
217: gzFile gz;
218:
219: if (fd == -1 || (path = malloc(7 + 3 * sizeof(int))) == NULL)
220: return NULL;
221: sprintf(path, "<fd:%d>", fd); /* for debugging */
222: gz = gz_open(path, fd, mode);
223: free(path);
224: return gz;
225: }
226:
227: /* -- see zlib.h -- */
228: int ZEXPORT gzbuffer(file, size)
229: gzFile file;
230: unsigned size;
231: {
232: gz_statep state;
233:
234: /* get internal structure and check integrity */
235: if (file == NULL)
236: return -1;
237: state = (gz_statep)file;
238: if (state->mode != GZ_READ && state->mode != GZ_WRITE)
239: return -1;
240:
241: /* make sure we haven't already allocated memory */
242: if (state->size != 0)
243: return -1;
244:
245: /* check and set requested size */
246: if (size == 0)
247: return -1;
248: state->want = size;
249: return 0;
250: }
251:
252: /* -- see zlib.h -- */
253: int ZEXPORT gzrewind(file)
254: gzFile file;
255: {
256: gz_statep state;
257:
258: /* get internal structure */
259: if (file == NULL)
260: return -1;
261: state = (gz_statep)file;
262:
263: /* check that we're reading and that there's no error */
264: if (state->mode != GZ_READ || state->err != Z_OK)
265: return -1;
266:
267: /* back up and start over */
268: if (LSEEK(state->fd, state->start, SEEK_SET) == -1)
269: return -1;
270: gz_reset(state);
271: return 0;
272: }
273:
274: /* -- see zlib.h -- */
275: z_off64_t ZEXPORT gzseek64(file, offset, whence)
276: gzFile file;
277: z_off64_t offset;
278: int whence;
279: {
280: unsigned n;
281: z_off64_t ret;
282: gz_statep state;
283:
284: /* get internal structure and check integrity */
285: if (file == NULL)
286: return -1;
287: state = (gz_statep)file;
288: if (state->mode != GZ_READ && state->mode != GZ_WRITE)
289: return -1;
290:
291: /* check that there's no error */
292: if (state->err != Z_OK)
293: return -1;
294:
295: /* can only seek from start or relative to current position */
296: if (whence != SEEK_SET && whence != SEEK_CUR)
297: return -1;
298:
299: /* normalize offset to a SEEK_CUR specification */
300: if (whence == SEEK_SET)
301: offset -= state->pos;
302: else if (state->seek)
303: offset += state->skip;
304: state->seek = 0;
305:
306: /* if within raw area while reading, just go there */
307: if (state->mode == GZ_READ && state->how == COPY &&
308: state->pos + offset >= state->raw) {
309: ret = LSEEK(state->fd, offset - state->have, SEEK_CUR);
310: if (ret == -1)
311: return -1;
312: state->have = 0;
313: state->eof = 0;
314: state->seek = 0;
315: gz_error(state, Z_OK, NULL);
316: state->strm.avail_in = 0;
317: state->pos += offset;
318: return state->pos;
319: }
320:
321: /* calculate skip amount, rewinding if needed for back seek when reading */
322: if (offset < 0) {
323: if (state->mode != GZ_READ) /* writing -- can't go backwards */
324: return -1;
325: offset += state->pos;
326: if (offset < 0) /* before start of file! */
327: return -1;
328: if (gzrewind(file) == -1) /* rewind, then skip to offset */
329: return -1;
330: }
331:
332: /* if reading, skip what's in output buffer (one less gzgetc() check) */
333: if (state->mode == GZ_READ) {
334: n = GT_OFF(state->have) || (z_off64_t)state->have > offset ?
335: (unsigned)offset : state->have;
336: state->have -= n;
337: state->next += n;
338: state->pos += n;
339: offset -= n;
340: }
341:
342: /* request skip (if not zero) */
343: if (offset) {
344: state->seek = 1;
345: state->skip = offset;
346: }
347: return state->pos + offset;
348: }
349:
350: /* -- see zlib.h -- */
351: z_off_t ZEXPORT gzseek(file, offset, whence)
352: gzFile file;
353: z_off_t offset;
354: int whence;
355: {
356: z_off64_t ret;
357:
358: ret = gzseek64(file, (z_off64_t)offset, whence);
359: return ret == (z_off_t)ret ? (z_off_t)ret : -1;
360: }
361:
362: /* -- see zlib.h -- */
363: z_off64_t ZEXPORT gztell64(file)
364: gzFile file;
365: {
366: gz_statep state;
367:
368: /* get internal structure and check integrity */
369: if (file == NULL)
370: return -1;
371: state = (gz_statep)file;
372: if (state->mode != GZ_READ && state->mode != GZ_WRITE)
373: return -1;
374:
375: /* return position */
376: return state->pos + (state->seek ? state->skip : 0);
377: }
378:
379: /* -- see zlib.h -- */
380: z_off_t ZEXPORT gztell(file)
381: gzFile file;
382: {
383: z_off64_t ret;
384:
385: ret = gztell64(file);
386: return ret == (z_off_t)ret ? (z_off_t)ret : -1;
387: }
388:
389: /* -- see zlib.h -- */
390: z_off64_t ZEXPORT gzoffset64(file)
391: gzFile file;
392: {
393: z_off64_t offset;
394: gz_statep state;
395:
396: /* get internal structure and check integrity */
397: if (file == NULL)
398: return -1;
399: state = (gz_statep)file;
400: if (state->mode != GZ_READ && state->mode != GZ_WRITE)
401: return -1;
402:
403: /* compute and return effective offset in file */
404: offset = LSEEK(state->fd, 0, SEEK_CUR);
405: if (offset == -1)
406: return -1;
407: if (state->mode == GZ_READ) /* reading */
408: offset -= state->strm.avail_in; /* don't count buffered input */
409: return offset;
410: }
411:
412: /* -- see zlib.h -- */
413: z_off_t ZEXPORT gzoffset(file)
414: gzFile file;
415: {
416: z_off64_t ret;
417:
418: ret = gzoffset64(file);
419: return ret == (z_off_t)ret ? (z_off_t)ret : -1;
420: }
421:
422: /* -- see zlib.h -- */
423: int ZEXPORT gzeof(file)
424: gzFile file;
425: {
426: gz_statep state;
427:
428: /* get internal structure and check integrity */
429: if (file == NULL)
430: return 0;
431: state = (gz_statep)file;
432: if (state->mode != GZ_READ && state->mode != GZ_WRITE)
433: return 0;
434:
435: /* return end-of-file state */
436: return state->mode == GZ_READ ?
437: (state->eof && state->strm.avail_in == 0 && state->have == 0) : 0;
438: }
439:
440: /* -- see zlib.h -- */
441: const char * ZEXPORT gzerror(file, errnum)
442: gzFile file;
443: int *errnum;
444: {
445: gz_statep state;
446:
447: /* get internal structure and check integrity */
448: if (file == NULL)
449: return NULL;
450: state = (gz_statep)file;
451: if (state->mode != GZ_READ && state->mode != GZ_WRITE)
452: return NULL;
453:
454: /* return error information */
455: if (errnum != NULL)
456: *errnum = state->err;
457: return state->msg == NULL ? "" : state->msg;
458: }
459:
460: /* -- see zlib.h -- */
461: void ZEXPORT gzclearerr(file)
462: gzFile file;
463: {
464: gz_statep state;
465:
466: /* get internal structure and check integrity */
467: if (file == NULL)
468: return;
469: state = (gz_statep)file;
470: if (state->mode != GZ_READ && state->mode != GZ_WRITE)
471: return;
472:
473: /* clear error and end-of-file */
474: if (state->mode == GZ_READ)
475: state->eof = 0;
476: gz_error(state, Z_OK, NULL);
477: }
478:
479: /* Create an error message in allocated memory and set state->err and
480: state->msg accordingly. Free any previous error message already there. Do
481: not try to free or allocate space if the error is Z_MEM_ERROR (out of
482: memory). Simply save the error message as a static string. If there is an
483: allocation failure constructing the error message, then convert the error to
484: out of memory. */
485: void ZLIB_INTERNAL gz_error(state, err, msg)
486: gz_statep state;
487: int err;
488: const char *msg;
489: {
490: /* free previously allocated message and clear */
491: if (state->msg != NULL) {
492: if (state->err != Z_MEM_ERROR)
493: free(state->msg);
494: state->msg = NULL;
495: }
496:
497: /* set error code, and if no message, then done */
498: state->err = err;
499: if (msg == NULL)
500: return;
501:
502: /* for an out of memory error, save as static string */
503: if (err == Z_MEM_ERROR) {
504: state->msg = (char *)msg;
505: return;
506: }
507:
508: /* construct error message with path */
509: if ((state->msg = malloc(strlen(state->path) + strlen(msg) + 3)) == NULL) {
510: state->err = Z_MEM_ERROR;
511: state->msg = (char *)"out of memory";
512: return;
513: }
514: strcpy(state->msg, state->path);
515: strcat(state->msg, ": ");
516: strcat(state->msg, msg);
517: return;
518: }
519:
520: #ifndef INT_MAX
521: /* portably return maximum value for an int (when limits.h presumed not
522: available) -- we need to do this to cover cases where 2's complement not
523: used, since C standard permits 1's complement and sign-bit representations,
524: otherwise we could just use ((unsigned)-1) >> 1 */
525: unsigned ZLIB_INTERNAL gz_intmax()
526: {
527: unsigned p, q;
528:
529: p = 1;
530: do {
531: q = p;
532: p <<= 1;
533: p++;
534: } while (p > q);
535: return q >> 1;
536: }
537: #endif
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>