Annotation of embedaddon/sudo/zlib/gzwrite.c, revision 1.1
1.1 ! misho 1: /* gzwrite.c -- zlib functions for writing gzip files
! 2: * Copyright (C) 2004, 2005, 2010 Mark Adler
! 3: * For conditions of distribution and use, see copyright notice in zlib.h
! 4: */
! 5:
! 6: #include "gzguts.h"
! 7:
! 8: /* Local functions */
! 9: local int gz_init OF((gz_statep));
! 10: local int gz_comp OF((gz_statep, int));
! 11: local int gz_zero OF((gz_statep, z_off64_t));
! 12:
! 13: /* Initialize state for writing a gzip file. Mark initialization by setting
! 14: state->size to non-zero. Return -1 on failure or 0 on success. */
! 15: local int gz_init(state)
! 16: gz_statep state;
! 17: {
! 18: int ret;
! 19: z_streamp strm = &(state->strm);
! 20:
! 21: /* allocate input and output buffers */
! 22: state->in = malloc(state->want);
! 23: state->out = malloc(state->want);
! 24: if (state->in == NULL || state->out == NULL) {
! 25: if (state->out != NULL)
! 26: free(state->out);
! 27: if (state->in != NULL)
! 28: free(state->in);
! 29: gz_error(state, Z_MEM_ERROR, "out of memory");
! 30: return -1;
! 31: }
! 32:
! 33: /* allocate deflate memory, set up for gzip compression */
! 34: strm->zalloc = Z_NULL;
! 35: strm->zfree = Z_NULL;
! 36: strm->opaque = Z_NULL;
! 37: ret = deflateInit2(strm, state->level, Z_DEFLATED,
! 38: 15 + 16, 8, state->strategy);
! 39: if (ret != Z_OK) {
! 40: free(state->in);
! 41: gz_error(state, Z_MEM_ERROR, "out of memory");
! 42: return -1;
! 43: }
! 44:
! 45: /* mark state as initialized */
! 46: state->size = state->want;
! 47:
! 48: /* initialize write buffer */
! 49: strm->avail_out = state->size;
! 50: strm->next_out = state->out;
! 51: state->next = strm->next_out;
! 52: return 0;
! 53: }
! 54:
! 55: /* Compress whatever is at avail_in and next_in and write to the output file.
! 56: Return -1 if there is an error writing to the output file, otherwise 0.
! 57: flush is assumed to be a valid deflate() flush value. If flush is Z_FINISH,
! 58: then the deflate() state is reset to start a new gzip stream. */
! 59: local int gz_comp(state, flush)
! 60: gz_statep state;
! 61: int flush;
! 62: {
! 63: int ret, got;
! 64: unsigned have;
! 65: z_streamp strm = &(state->strm);
! 66:
! 67: /* allocate memory if this is the first time through */
! 68: if (state->size == 0 && gz_init(state) == -1)
! 69: return -1;
! 70:
! 71: /* run deflate() on provided input until it produces no more output */
! 72: ret = Z_OK;
! 73: do {
! 74: /* write out current buffer contents if full, or if flushing, but if
! 75: doing Z_FINISH then don't write until we get to Z_STREAM_END */
! 76: if (strm->avail_out == 0 || (flush != Z_NO_FLUSH &&
! 77: (flush != Z_FINISH || ret == Z_STREAM_END))) {
! 78: have = (unsigned)(strm->next_out - state->next);
! 79: if (have && ((got = write(state->fd, state->next, have)) < 0 ||
! 80: (unsigned)got != have)) {
! 81: gz_error(state, Z_ERRNO, zstrerror());
! 82: return -1;
! 83: }
! 84: if (strm->avail_out == 0) {
! 85: strm->avail_out = state->size;
! 86: strm->next_out = state->out;
! 87: }
! 88: state->next = strm->next_out;
! 89: }
! 90:
! 91: /* compress */
! 92: have = strm->avail_out;
! 93: ret = deflate(strm, flush);
! 94: if (ret == Z_STREAM_ERROR) {
! 95: gz_error(state, Z_STREAM_ERROR,
! 96: "internal error: deflate stream corrupt");
! 97: return -1;
! 98: }
! 99: have -= strm->avail_out;
! 100: } while (have);
! 101:
! 102: /* if that completed a deflate stream, allow another to start */
! 103: if (flush == Z_FINISH)
! 104: deflateReset(strm);
! 105:
! 106: /* all done, no errors */
! 107: return 0;
! 108: }
! 109:
! 110: /* Compress len zeros to output. Return -1 on error, 0 on success. */
! 111: local int gz_zero(state, len)
! 112: gz_statep state;
! 113: z_off64_t len;
! 114: {
! 115: int first;
! 116: unsigned n;
! 117: z_streamp strm = &(state->strm);
! 118:
! 119: /* consume whatever's left in the input buffer */
! 120: if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1)
! 121: return -1;
! 122:
! 123: /* compress len zeros (len guaranteed > 0) */
! 124: first = 1;
! 125: while (len) {
! 126: n = GT_OFF(state->size) || (z_off64_t)state->size > len ?
! 127: (unsigned)len : state->size;
! 128: if (first) {
! 129: memset(state->in, 0, n);
! 130: first = 0;
! 131: }
! 132: strm->avail_in = n;
! 133: strm->next_in = state->in;
! 134: state->pos += n;
! 135: if (gz_comp(state, Z_NO_FLUSH) == -1)
! 136: return -1;
! 137: len -= n;
! 138: }
! 139: return 0;
! 140: }
! 141:
! 142: /* -- see zlib.h -- */
! 143: int ZEXPORT gzwrite(file, buf, len)
! 144: gzFile file;
! 145: voidpc buf;
! 146: unsigned len;
! 147: {
! 148: unsigned put = len;
! 149: unsigned n;
! 150: gz_statep state;
! 151: z_streamp strm;
! 152:
! 153: /* get internal structure */
! 154: if (file == NULL)
! 155: return 0;
! 156: state = (gz_statep)file;
! 157: strm = &(state->strm);
! 158:
! 159: /* check that we're writing and that there's no error */
! 160: if (state->mode != GZ_WRITE || state->err != Z_OK)
! 161: return 0;
! 162:
! 163: /* since an int is returned, make sure len fits in one, otherwise return
! 164: with an error (this avoids the flaw in the interface) */
! 165: if ((int)len < 0) {
! 166: gz_error(state, Z_BUF_ERROR, "requested length does not fit in int");
! 167: return 0;
! 168: }
! 169:
! 170: /* if len is zero, avoid unnecessary operations */
! 171: if (len == 0)
! 172: return 0;
! 173:
! 174: /* allocate memory if this is the first time through */
! 175: if (state->size == 0 && gz_init(state) == -1)
! 176: return 0;
! 177:
! 178: /* check for seek request */
! 179: if (state->seek) {
! 180: state->seek = 0;
! 181: if (gz_zero(state, state->skip) == -1)
! 182: return 0;
! 183: }
! 184:
! 185: /* for small len, copy to input buffer, otherwise compress directly */
! 186: if (len < state->size) {
! 187: /* copy to input buffer, compress when full */
! 188: do {
! 189: if (strm->avail_in == 0)
! 190: strm->next_in = state->in;
! 191: n = state->size - strm->avail_in;
! 192: if (n > len)
! 193: n = len;
! 194: memcpy(strm->next_in + strm->avail_in, buf, n);
! 195: strm->avail_in += n;
! 196: state->pos += n;
! 197: buf = (char *)buf + n;
! 198: len -= n;
! 199: if (len && gz_comp(state, Z_NO_FLUSH) == -1)
! 200: return 0;
! 201: } while (len);
! 202: }
! 203: else {
! 204: /* consume whatever's left in the input buffer */
! 205: if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1)
! 206: return 0;
! 207:
! 208: /* directly compress user buffer to file */
! 209: strm->avail_in = len;
! 210: strm->next_in = (voidp)buf;
! 211: state->pos += len;
! 212: if (gz_comp(state, Z_NO_FLUSH) == -1)
! 213: return 0;
! 214: }
! 215:
! 216: /* input was all buffered or compressed (put will fit in int) */
! 217: return (int)put;
! 218: }
! 219:
! 220: /* -- see zlib.h -- */
! 221: int ZEXPORT gzputc(file, c)
! 222: gzFile file;
! 223: int c;
! 224: {
! 225: unsigned char buf[1];
! 226: gz_statep state;
! 227: z_streamp strm;
! 228:
! 229: /* get internal structure */
! 230: if (file == NULL)
! 231: return -1;
! 232: state = (gz_statep)file;
! 233: strm = &(state->strm);
! 234:
! 235: /* check that we're writing and that there's no error */
! 236: if (state->mode != GZ_WRITE || state->err != Z_OK)
! 237: return -1;
! 238:
! 239: /* check for seek request */
! 240: if (state->seek) {
! 241: state->seek = 0;
! 242: if (gz_zero(state, state->skip) == -1)
! 243: return -1;
! 244: }
! 245:
! 246: /* try writing to input buffer for speed (state->size == 0 if buffer not
! 247: initialized) */
! 248: if (strm->avail_in < state->size) {
! 249: if (strm->avail_in == 0)
! 250: strm->next_in = state->in;
! 251: strm->next_in[strm->avail_in++] = c;
! 252: state->pos++;
! 253: return c;
! 254: }
! 255:
! 256: /* no room in buffer or not initialized, use gz_write() */
! 257: buf[0] = c;
! 258: if (gzwrite(file, buf, 1) != 1)
! 259: return -1;
! 260: return c;
! 261: }
! 262:
! 263: /* -- see zlib.h -- */
! 264: int ZEXPORT gzputs(file, str)
! 265: gzFile file;
! 266: const char *str;
! 267: {
! 268: int ret;
! 269: unsigned len;
! 270:
! 271: /* write string */
! 272: len = (unsigned)strlen(str);
! 273: ret = gzwrite(file, str, len);
! 274: return ret == 0 && len != 0 ? -1 : ret;
! 275: }
! 276:
! 277: #ifdef STDC
! 278: #include <stdarg.h>
! 279:
! 280: /* -- see zlib.h -- */
! 281: int ZEXPORTVA gzprintf (gzFile file, const char *format, ...)
! 282: {
! 283: int size, len;
! 284: gz_statep state;
! 285: z_streamp strm;
! 286: va_list va;
! 287:
! 288: /* get internal structure */
! 289: if (file == NULL)
! 290: return -1;
! 291: state = (gz_statep)file;
! 292: strm = &(state->strm);
! 293:
! 294: /* check that we're writing and that there's no error */
! 295: if (state->mode != GZ_WRITE || state->err != Z_OK)
! 296: return 0;
! 297:
! 298: /* make sure we have some buffer space */
! 299: if (state->size == 0 && gz_init(state) == -1)
! 300: return 0;
! 301:
! 302: /* check for seek request */
! 303: if (state->seek) {
! 304: state->seek = 0;
! 305: if (gz_zero(state, state->skip) == -1)
! 306: return 0;
! 307: }
! 308:
! 309: /* consume whatever's left in the input buffer */
! 310: if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1)
! 311: return 0;
! 312:
! 313: /* do the printf() into the input buffer, put length in len */
! 314: size = (int)(state->size);
! 315: state->in[size - 1] = 0;
! 316: va_start(va, format);
! 317: #ifdef NO_vsnprintf
! 318: # ifdef HAS_vsprintf_void
! 319: (void)vsprintf(state->in, format, va);
! 320: va_end(va);
! 321: for (len = 0; len < size; len++)
! 322: if (state->in[len] == 0) break;
! 323: # else
! 324: len = vsprintf(state->in, format, va);
! 325: va_end(va);
! 326: # endif
! 327: #else
! 328: # ifdef HAS_vsnprintf_void
! 329: (void)vsnprintf(state->in, size, format, va);
! 330: va_end(va);
! 331: len = strlen(state->in);
! 332: # else
! 333: len = vsnprintf((char *)(state->in), size, format, va);
! 334: va_end(va);
! 335: # endif
! 336: #endif
! 337:
! 338: /* check that printf() results fit in buffer */
! 339: if (len <= 0 || len >= (int)size || state->in[size - 1] != 0)
! 340: return 0;
! 341:
! 342: /* update buffer and position, defer compression until needed */
! 343: strm->avail_in = (unsigned)len;
! 344: strm->next_in = state->in;
! 345: state->pos += len;
! 346: return len;
! 347: }
! 348:
! 349: #else /* !STDC */
! 350:
! 351: /* -- see zlib.h -- */
! 352: int ZEXPORTVA gzprintf (file, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10,
! 353: a11, a12, a13, a14, a15, a16, a17, a18, a19, a20)
! 354: gzFile file;
! 355: const char *format;
! 356: int a1, a2, a3, a4, a5, a6, a7, a8, a9, a10,
! 357: a11, a12, a13, a14, a15, a16, a17, a18, a19, a20;
! 358: {
! 359: int size, len;
! 360: gz_statep state;
! 361: z_streamp strm;
! 362:
! 363: /* get internal structure */
! 364: if (file == NULL)
! 365: return -1;
! 366: state = (gz_statep)file;
! 367: strm = &(state->strm);
! 368:
! 369: /* check that we're writing and that there's no error */
! 370: if (state->mode != GZ_WRITE || state->err != Z_OK)
! 371: return 0;
! 372:
! 373: /* make sure we have some buffer space */
! 374: if (state->size == 0 && gz_init(state) == -1)
! 375: return 0;
! 376:
! 377: /* check for seek request */
! 378: if (state->seek) {
! 379: state->seek = 0;
! 380: if (gz_zero(state, state->skip) == -1)
! 381: return 0;
! 382: }
! 383:
! 384: /* consume whatever's left in the input buffer */
! 385: if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1)
! 386: return 0;
! 387:
! 388: /* do the printf() into the input buffer, put length in len */
! 389: size = (int)(state->size);
! 390: state->in[size - 1] = 0;
! 391: #ifdef NO_snprintf
! 392: # ifdef HAS_sprintf_void
! 393: sprintf(state->in, format, a1, a2, a3, a4, a5, a6, a7, a8,
! 394: a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20);
! 395: for (len = 0; len < size; len++)
! 396: if (state->in[len] == 0) break;
! 397: # else
! 398: len = sprintf(state->in, format, a1, a2, a3, a4, a5, a6, a7, a8,
! 399: a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20);
! 400: # endif
! 401: #else
! 402: # ifdef HAS_snprintf_void
! 403: snprintf(state->in, size, format, a1, a2, a3, a4, a5, a6, a7, a8,
! 404: a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20);
! 405: len = strlen(state->in);
! 406: # else
! 407: len = snprintf(state->in, size, format, a1, a2, a3, a4, a5, a6, a7, a8,
! 408: a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20);
! 409: # endif
! 410: #endif
! 411:
! 412: /* check that printf() results fit in buffer */
! 413: if (len <= 0 || len >= (int)size || state->in[size - 1] != 0)
! 414: return 0;
! 415:
! 416: /* update buffer and position, defer compression until needed */
! 417: strm->avail_in = (unsigned)len;
! 418: strm->next_in = state->in;
! 419: state->pos += len;
! 420: return len;
! 421: }
! 422:
! 423: #endif
! 424:
! 425: /* -- see zlib.h -- */
! 426: int ZEXPORT gzflush(file, flush)
! 427: gzFile file;
! 428: int flush;
! 429: {
! 430: gz_statep state;
! 431:
! 432: /* get internal structure */
! 433: if (file == NULL)
! 434: return -1;
! 435: state = (gz_statep)file;
! 436:
! 437: /* check that we're writing and that there's no error */
! 438: if (state->mode != GZ_WRITE || state->err != Z_OK)
! 439: return Z_STREAM_ERROR;
! 440:
! 441: /* check flush parameter */
! 442: if (flush < 0 || flush > Z_FINISH)
! 443: return Z_STREAM_ERROR;
! 444:
! 445: /* check for seek request */
! 446: if (state->seek) {
! 447: state->seek = 0;
! 448: if (gz_zero(state, state->skip) == -1)
! 449: return -1;
! 450: }
! 451:
! 452: /* compress remaining data with requested flush */
! 453: gz_comp(state, flush);
! 454: return state->err;
! 455: }
! 456:
! 457: /* -- see zlib.h -- */
! 458: int ZEXPORT gzsetparams(file, level, strategy)
! 459: gzFile file;
! 460: int level;
! 461: int strategy;
! 462: {
! 463: gz_statep state;
! 464: z_streamp strm;
! 465:
! 466: /* get internal structure */
! 467: if (file == NULL)
! 468: return Z_STREAM_ERROR;
! 469: state = (gz_statep)file;
! 470: strm = &(state->strm);
! 471:
! 472: /* check that we're writing and that there's no error */
! 473: if (state->mode != GZ_WRITE || state->err != Z_OK)
! 474: return Z_STREAM_ERROR;
! 475:
! 476: /* if no change is requested, then do nothing */
! 477: if (level == state->level && strategy == state->strategy)
! 478: return Z_OK;
! 479:
! 480: /* check for seek request */
! 481: if (state->seek) {
! 482: state->seek = 0;
! 483: if (gz_zero(state, state->skip) == -1)
! 484: return -1;
! 485: }
! 486:
! 487: /* change compression parameters for subsequent input */
! 488: if (state->size) {
! 489: /* flush previous input with previous parameters before changing */
! 490: if (strm->avail_in && gz_comp(state, Z_PARTIAL_FLUSH) == -1)
! 491: return state->err;
! 492: deflateParams(strm, level, strategy);
! 493: }
! 494: state->level = level;
! 495: state->strategy = strategy;
! 496: return Z_OK;
! 497: }
! 498:
! 499: /* -- see zlib.h -- */
! 500: int ZEXPORT gzclose_w(file)
! 501: gzFile file;
! 502: {
! 503: int ret = 0;
! 504: gz_statep state;
! 505:
! 506: /* get internal structure */
! 507: if (file == NULL)
! 508: return Z_STREAM_ERROR;
! 509: state = (gz_statep)file;
! 510:
! 511: /* check that we're writing */
! 512: if (state->mode != GZ_WRITE)
! 513: return Z_STREAM_ERROR;
! 514:
! 515: /* check for seek request */
! 516: if (state->seek) {
! 517: state->seek = 0;
! 518: ret += gz_zero(state, state->skip);
! 519: }
! 520:
! 521: /* flush, free memory, and close file */
! 522: ret += gz_comp(state, Z_FINISH);
! 523: (void)deflateEnd(&(state->strm));
! 524: free(state->out);
! 525: free(state->in);
! 526: gz_error(state, Z_OK, NULL);
! 527: free(state->path);
! 528: ret += close(state->fd);
! 529: free(state);
! 530: return ret ? Z_ERRNO : Z_OK;
! 531: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>