Annotation of embedaddon/sudo/zlib/gzlib.c, revision 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>