1 /* gzwrite.c contains minimal changes required to be compiled with zlibWrapper: 2 * - gz_statep was converted to union to work with -Wstrict-aliasing=1 */ 3 4 /* gzwrite.c -- zlib functions for writing gzip files 5 * Copyright (C) 2004-2017 Mark Adler 6 * For conditions of distribution and use, see http://www.zlib.net/zlib_license.html 7 */ 8 9 #include "gzguts.h" 10 11 /* Local functions */ 12 local int gz_init OF((gz_statep)); 13 local int gz_comp OF((gz_statep, int)); 14 local int gz_zero OF((gz_statep, z_off64_t)); 15 local z_size_t gz_write OF((gz_statep, voidpc, z_size_t)); 16 17 /* Initialize state for writing a gzip file. Mark initialization by setting 18 state.state->size to non-zero. Return -1 on a memory allocation failure, or 0 on 19 success. */ 20 local int gz_init(state) 21 gz_statep state; 22 { 23 int ret; 24 z_streamp strm = &(state.state->strm); 25 26 /* allocate input buffer (double size for gzprintf) */ 27 state.state->in = (unsigned char *)malloc(state.state->want << 1); 28 if (state.state->in == NULL) { 29 gz_error(state, Z_MEM_ERROR, "out of memory"); 30 return -1; 31 } 32 33 /* only need output buffer and deflate state if compressing */ 34 if (!state.state->direct) { 35 /* allocate output buffer */ 36 state.state->out = (unsigned char *)malloc(state.state->want); 37 if (state.state->out == NULL) { 38 free(state.state->in); 39 gz_error(state, Z_MEM_ERROR, "out of memory"); 40 return -1; 41 } 42 43 /* allocate deflate memory, set up for gzip compression */ 44 strm->zalloc = Z_NULL; 45 strm->zfree = Z_NULL; 46 strm->opaque = Z_NULL; 47 ret = deflateInit2(strm, state.state->level, Z_DEFLATED, 48 MAX_WBITS + 16, DEF_MEM_LEVEL, state.state->strategy); 49 if (ret != Z_OK) { 50 free(state.state->out); 51 free(state.state->in); 52 gz_error(state, Z_MEM_ERROR, "out of memory"); 53 return -1; 54 } 55 strm->next_in = NULL; 56 } 57 58 /* mark state as initialized */ 59 state.state->size = state.state->want; 60 61 /* initialize write buffer if compressing */ 62 if (!state.state->direct) { 63 strm->avail_out = state.state->size; 64 strm->next_out = state.state->out; 65 state.state->x.next = strm->next_out; 66 } 67 return 0; 68 } 69 70 /* Compress whatever is at avail_in and next_in and write to the output file. 71 Return -1 if there is an error writing to the output file or if gz_init() 72 fails to allocate memory, otherwise 0. flush is assumed to be a valid 73 deflate() flush value. If flush is Z_FINISH, then the deflate() state is 74 reset to start a new gzip stream. If gz->direct is true, then simply write 75 to the output file without compressing, and ignore flush. */ 76 local int gz_comp(state, flush) 77 gz_statep state; 78 int flush; 79 { 80 int ret, writ; 81 unsigned have, put, max = ((unsigned)-1 >> 2) + 1; 82 z_streamp strm = &(state.state->strm); 83 84 /* allocate memory if this is the first time through */ 85 if (state.state->size == 0 && gz_init(state) == -1) 86 return -1; 87 88 /* write directly if requested */ 89 if (state.state->direct) { 90 while (strm->avail_in) { 91 put = strm->avail_in > max ? max : strm->avail_in; 92 writ = (int)write(state.state->fd, strm->next_in, put); 93 if (writ < 0) { 94 gz_error(state, Z_ERRNO, zstrerror()); 95 return -1; 96 } 97 strm->avail_in -= (unsigned)writ; 98 strm->next_in += writ; 99 } 100 return 0; 101 } 102 103 /* run deflate() on provided input until it produces no more output */ 104 ret = Z_OK; 105 do { 106 /* write out current buffer contents if full, or if flushing, but if 107 doing Z_FINISH then don't write until we get to Z_STREAM_END */ 108 if (strm->avail_out == 0 || (flush != Z_NO_FLUSH && 109 (flush != Z_FINISH || ret == Z_STREAM_END))) { 110 while (strm->next_out > state.state->x.next) { 111 put = strm->next_out - state.state->x.next > (int)max ? max : 112 (unsigned)(strm->next_out - state.state->x.next); 113 writ = (int)write(state.state->fd, state.state->x.next, put); 114 if (writ < 0) { 115 gz_error(state, Z_ERRNO, zstrerror()); 116 return -1; 117 } 118 state.state->x.next += writ; 119 } 120 if (strm->avail_out == 0) { 121 strm->avail_out = state.state->size; 122 strm->next_out = state.state->out; 123 state.state->x.next = state.state->out; 124 } 125 } 126 127 /* compress */ 128 have = strm->avail_out; 129 ret = deflate(strm, flush); 130 if (ret == Z_STREAM_ERROR) { 131 gz_error(state, Z_STREAM_ERROR, 132 "internal error: deflate stream corrupt"); 133 return -1; 134 } 135 have -= strm->avail_out; 136 } while (have); 137 138 /* if that completed a deflate stream, allow another to start */ 139 if (flush == Z_FINISH) 140 deflateReset(strm); 141 142 /* all done, no errors */ 143 return 0; 144 } 145 146 /* Compress len zeros to output. Return -1 on a write error or memory 147 allocation failure by gz_comp(), or 0 on success. */ 148 local int gz_zero(state, len) 149 gz_statep state; 150 z_off64_t len; 151 { 152 int first; 153 unsigned n; 154 z_streamp strm = &(state.state->strm); 155 156 /* consume whatever's left in the input buffer */ 157 if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1) 158 return -1; 159 160 /* compress len zeros (len guaranteed > 0) */ 161 first = 1; 162 while (len) { 163 n = GT_OFF(state.state->size) || (z_off64_t)state.state->size > len ? 164 (unsigned)len : state.state->size; 165 if (first) { 166 memset(state.state->in, 0, n); 167 first = 0; 168 } 169 strm->avail_in = n; 170 strm->next_in = state.state->in; 171 state.state->x.pos += n; 172 if (gz_comp(state, Z_NO_FLUSH) == -1) 173 return -1; 174 len -= n; 175 } 176 return 0; 177 } 178 179 /* Write len bytes from buf to file. Return the number of bytes written. If 180 the returned value is less than len, then there was an error. */ 181 local z_size_t gz_write(state, buf, len) 182 gz_statep state; 183 voidpc buf; 184 z_size_t len; 185 { 186 z_size_t put = len; 187 188 /* if len is zero, avoid unnecessary operations */ 189 if (len == 0) 190 return 0; 191 192 /* allocate memory if this is the first time through */ 193 if (state.state->size == 0 && gz_init(state) == -1) 194 return 0; 195 196 /* check for seek request */ 197 if (state.state->seek) { 198 state.state->seek = 0; 199 if (gz_zero(state, state.state->skip) == -1) 200 return 0; 201 } 202 203 /* for small len, copy to input buffer, otherwise compress directly */ 204 if (len < state.state->size) { 205 /* copy to input buffer, compress when full */ 206 do { 207 z_size_t have, copy; 208 209 if (state.state->strm.avail_in == 0) 210 state.state->strm.next_in = state.state->in; 211 have = (unsigned)((state.state->strm.next_in + state.state->strm.avail_in) - 212 state.state->in); 213 copy = state.state->size - have; 214 if (copy > len) 215 copy = len; 216 memcpy(state.state->in + have, buf, copy); 217 state.state->strm.avail_in += copy; 218 state.state->x.pos += copy; 219 buf = (const char *)buf + copy; 220 len -= copy; 221 if (len && gz_comp(state, Z_NO_FLUSH) == -1) 222 return 0; 223 } while (len); 224 } 225 else { 226 /* consume whatever's left in the input buffer */ 227 if (state.state->strm.avail_in && gz_comp(state, Z_NO_FLUSH) == -1) 228 return 0; 229 230 /* directly compress user buffer to file */ 231 state.state->strm.next_in = (z_const Bytef *)buf; 232 do { 233 z_size_t n = (unsigned)-1; 234 if (n > len) 235 n = len; 236 state.state->strm.avail_in = (z_uInt)n; 237 state.state->x.pos += n; 238 if (gz_comp(state, Z_NO_FLUSH) == -1) 239 return 0; 240 len -= n; 241 } while (len); 242 } 243 244 /* input was all buffered or compressed */ 245 return put; 246 } 247 248 /* -- see zlib.h -- */ 249 int ZEXPORT gzwrite(file, buf, len) 250 gzFile file; 251 voidpc buf; 252 unsigned len; 253 { 254 gz_statep state; 255 256 /* get internal structure */ 257 if (file == NULL) 258 return 0; 259 state = (gz_statep)file; 260 261 /* check that we're writing and that there's no error */ 262 if (state.state->mode != GZ_WRITE || state.state->err != Z_OK) 263 return 0; 264 265 /* since an int is returned, make sure len fits in one, otherwise return 266 with an error (this avoids a flaw in the interface) */ 267 if ((int)len < 0) { 268 gz_error(state, Z_DATA_ERROR, "requested length does not fit in int"); 269 return 0; 270 } 271 272 /* write len bytes from buf (the return value will fit in an int) */ 273 return (int)gz_write(state, buf, len); 274 } 275 276 /* -- see zlib.h -- */ 277 z_size_t ZEXPORT gzfwrite(buf, size, nitems, file) 278 voidpc buf; 279 z_size_t size; 280 z_size_t nitems; 281 gzFile file; 282 { 283 z_size_t len; 284 gz_statep state; 285 286 /* get internal structure */ 287 if (file == NULL) 288 return 0; 289 state = (gz_statep)file; 290 291 /* check that we're writing and that there's no error */ 292 if (state.state->mode != GZ_WRITE || state.state->err != Z_OK) 293 return 0; 294 295 /* compute bytes to read -- error on overflow */ 296 len = nitems * size; 297 if (size && len / size != nitems) { 298 gz_error(state, Z_STREAM_ERROR, "request does not fit in a size_t"); 299 return 0; 300 } 301 302 /* write len bytes to buf, return the number of full items written */ 303 return len ? gz_write(state, buf, len) / size : 0; 304 } 305 306 /* -- see zlib.h -- */ 307 int ZEXPORT gzputc(file, c) 308 gzFile file; 309 int c; 310 { 311 unsigned have; 312 unsigned char buf[1]; 313 gz_statep state; 314 z_streamp strm; 315 316 /* get internal structure */ 317 if (file == NULL) 318 return -1; 319 state = (gz_statep)file; 320 strm = &(state.state->strm); 321 322 /* check that we're writing and that there's no error */ 323 if (state.state->mode != GZ_WRITE || state.state->err != Z_OK) 324 return -1; 325 326 /* check for seek request */ 327 if (state.state->seek) { 328 state.state->seek = 0; 329 if (gz_zero(state, state.state->skip) == -1) 330 return -1; 331 } 332 333 /* try writing to input buffer for speed (state.state->size == 0 if buffer not 334 initialized) */ 335 if (state.state->size) { 336 if (strm->avail_in == 0) 337 strm->next_in = state.state->in; 338 have = (unsigned)((strm->next_in + strm->avail_in) - state.state->in); 339 if (have < state.state->size) { 340 state.state->in[have] = (unsigned char)c; 341 strm->avail_in++; 342 state.state->x.pos++; 343 return c & 0xff; 344 } 345 } 346 347 /* no room in buffer or not initialized, use gz_write() */ 348 buf[0] = (unsigned char)c; 349 if (gz_write(state, buf, 1) != 1) 350 return -1; 351 return c & 0xff; 352 } 353 354 /* -- see zlib.h -- */ 355 int ZEXPORT gzputs(file, str) 356 gzFile file; 357 const char *str; 358 { 359 int ret; 360 z_size_t len; 361 gz_statep state; 362 363 /* get internal structure */ 364 if (file == NULL) 365 return -1; 366 state = (gz_statep)file; 367 368 /* check that we're writing and that there's no error */ 369 if (state.state->mode != GZ_WRITE || state.state->err != Z_OK) 370 return -1; 371 372 /* write string */ 373 len = strlen(str); 374 ret = (int)gz_write(state, str, len); 375 return ret == 0 && len != 0 ? -1 : ret; 376 } 377 378 #if defined(STDC) || defined(Z_HAVE_STDARG_H) 379 #include <stdarg.h> 380 381 /* -- see zlib.h -- */ 382 int ZEXPORTVA gzvprintf(gzFile file, const char *format, va_list va) 383 { 384 int len; 385 unsigned left; 386 char *next; 387 gz_statep state; 388 z_streamp strm; 389 390 /* get internal structure */ 391 if (file == NULL) 392 return Z_STREAM_ERROR; 393 state = (gz_statep)file; 394 strm = &(state.state->strm); 395 396 /* check that we're writing and that there's no error */ 397 if (state.state->mode != GZ_WRITE || state.state->err != Z_OK) 398 return Z_STREAM_ERROR; 399 400 /* make sure we have some buffer space */ 401 if (state.state->size == 0 && gz_init(state) == -1) 402 return state.state->err; 403 404 /* check for seek request */ 405 if (state.state->seek) { 406 state.state->seek = 0; 407 if (gz_zero(state, state.state->skip) == -1) 408 return state.state->err; 409 } 410 411 /* do the printf() into the input buffer, put length in len -- the input 412 buffer is double-sized just for this function, so there is guaranteed to 413 be state.state->size bytes available after the current contents */ 414 if (strm->avail_in == 0) 415 strm->next_in = state.state->in; 416 next = (char *)(state.state->in + (strm->next_in - state.state->in) + strm->avail_in); 417 next[state.state->size - 1] = 0; 418 #ifdef NO_vsnprintf 419 # ifdef HAS_vsprintf_void 420 (void)vsprintf(next, format, va); 421 for (len = 0; len < state.state->size; len++) 422 if (next[len] == 0) break; 423 # else 424 len = vsprintf(next, format, va); 425 # endif 426 #else 427 # ifdef HAS_vsnprintf_void 428 (void)vsnprintf(next, state.state->size, format, va); 429 len = strlen(next); 430 # else 431 len = vsnprintf(next, state.state->size, format, va); 432 # endif 433 #endif 434 435 /* check that printf() results fit in buffer */ 436 if (len == 0 || (unsigned)len >= state.state->size || next[state.state->size - 1] != 0) 437 return 0; 438 439 /* update buffer and position, compress first half if past that */ 440 strm->avail_in += (unsigned)len; 441 state.state->x.pos += len; 442 if (strm->avail_in >= state.state->size) { 443 left = strm->avail_in - state.state->size; 444 strm->avail_in = state.state->size; 445 if (gz_comp(state, Z_NO_FLUSH) == -1) 446 return state.state->err; 447 memcpy(state.state->in, state.state->in + state.state->size, left); 448 strm->next_in = state.state->in; 449 strm->avail_in = left; 450 } 451 return len; 452 } 453 454 int ZEXPORTVA gzprintf(gzFile file, const char *format, ...) 455 { 456 va_list va; 457 int ret; 458 459 va_start(va, format); 460 ret = gzvprintf(file, format, va); 461 va_end(va); 462 return ret; 463 } 464 465 #else /* !STDC && !Z_HAVE_STDARG_H */ 466 467 /* -- see zlib.h -- */ 468 int ZEXPORTVA gzprintf (file, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, 469 a11, a12, a13, a14, a15, a16, a17, a18, a19, a20) 470 gzFile file; 471 const char *format; 472 int a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, 473 a11, a12, a13, a14, a15, a16, a17, a18, a19, a20; 474 { 475 unsigned len, left; 476 char *next; 477 gz_statep state; 478 z_streamp strm; 479 480 /* get internal structure */ 481 if (file == NULL) 482 return Z_STREAM_ERROR; 483 state = (gz_statep)file; 484 strm = &(state.state->strm); 485 486 /* check that can really pass pointer in ints */ 487 if (sizeof(int) != sizeof(void *)) 488 return Z_STREAM_ERROR; 489 490 /* check that we're writing and that there's no error */ 491 if (state.state->mode != GZ_WRITE || state.state->err != Z_OK) 492 return Z_STREAM_ERROR; 493 494 /* make sure we have some buffer space */ 495 if (state.state->size == 0 && gz_init(state) == -1) 496 return state.state->error; 497 498 /* check for seek request */ 499 if (state.state->seek) { 500 state.state->seek = 0; 501 if (gz_zero(state, state.state->skip) == -1) 502 return state.state->error; 503 } 504 505 /* do the printf() into the input buffer, put length in len -- the input 506 buffer is double-sized just for this function, so there is guaranteed to 507 be state.state->size bytes available after the current contents */ 508 if (strm->avail_in == 0) 509 strm->next_in = state.state->in; 510 next = (char *)(strm->next_in + strm->avail_in); 511 next[state.state->size - 1] = 0; 512 #ifdef NO_snprintf 513 # ifdef HAS_sprintf_void 514 sprintf(next, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, 515 a13, a14, a15, a16, a17, a18, a19, a20); 516 for (len = 0; len < size; len++) 517 if (next[len] == 0) 518 break; 519 # else 520 len = sprintf(next, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, 521 a12, a13, a14, a15, a16, a17, a18, a19, a20); 522 # endif 523 #else 524 # ifdef HAS_snprintf_void 525 snprintf(next, state.state->size, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, 526 a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20); 527 len = strlen(next); 528 # else 529 len = snprintf(next, state.state->size, format, a1, a2, a3, a4, a5, a6, a7, a8, 530 a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20); 531 # endif 532 #endif 533 534 /* check that printf() results fit in buffer */ 535 if (len == 0 || len >= state.state->size || next[state.state->size - 1] != 0) 536 return 0; 537 538 /* update buffer and position, compress first half if past that */ 539 strm->avail_in += len; 540 state.state->x.pos += len; 541 if (strm->avail_in >= state.state->size) { 542 left = strm->avail_in - state.state->size; 543 strm->avail_in = state.state->size; 544 if (gz_comp(state, Z_NO_FLUSH) == -1) 545 return state.state->err; 546 memcpy(state.state->in, state.state->in + state.state->size, left); 547 strm->next_in = state.state->in; 548 strm->avail_in = left; 549 } 550 return (int)len; 551 } 552 553 #endif 554 555 /* -- see zlib.h -- */ 556 int ZEXPORT gzflush(file, flush) 557 gzFile file; 558 int flush; 559 { 560 gz_statep state; 561 562 /* get internal structure */ 563 if (file == NULL) 564 return Z_STREAM_ERROR; 565 state = (gz_statep)file; 566 567 /* check that we're writing and that there's no error */ 568 if (state.state->mode != GZ_WRITE || state.state->err != Z_OK) 569 return Z_STREAM_ERROR; 570 571 /* check flush parameter */ 572 if (flush < 0 || flush > Z_FINISH) 573 return Z_STREAM_ERROR; 574 575 /* check for seek request */ 576 if (state.state->seek) { 577 state.state->seek = 0; 578 if (gz_zero(state, state.state->skip) == -1) 579 return state.state->err; 580 } 581 582 /* compress remaining data with requested flush */ 583 (void)gz_comp(state, flush); 584 return state.state->err; 585 } 586 587 /* -- see zlib.h -- */ 588 int ZEXPORT gzsetparams(file, level, strategy) 589 gzFile file; 590 int level; 591 int strategy; 592 { 593 gz_statep state; 594 z_streamp strm; 595 596 /* get internal structure */ 597 if (file == NULL) 598 return Z_STREAM_ERROR; 599 state = (gz_statep)file; 600 strm = &(state.state->strm); 601 602 /* check that we're writing and that there's no error */ 603 if (state.state->mode != GZ_WRITE || state.state->err != Z_OK) 604 return Z_STREAM_ERROR; 605 606 /* if no change is requested, then do nothing */ 607 if (level == state.state->level && strategy == state.state->strategy) 608 return Z_OK; 609 610 /* check for seek request */ 611 if (state.state->seek) { 612 state.state->seek = 0; 613 if (gz_zero(state, state.state->skip) == -1) 614 return state.state->err; 615 } 616 617 /* change compression parameters for subsequent input */ 618 if (state.state->size) { 619 /* flush previous input with previous parameters before changing */ 620 if (strm->avail_in && gz_comp(state, Z_BLOCK) == -1) 621 return state.state->err; 622 deflateParams(strm, level, strategy); 623 } 624 state.state->level = level; 625 state.state->strategy = strategy; 626 return Z_OK; 627 } 628 629 /* -- see zlib.h -- */ 630 int ZEXPORT gzclose_w(file) 631 gzFile file; 632 { 633 int ret = Z_OK; 634 gz_statep state; 635 636 /* get internal structure */ 637 if (file == NULL) 638 return Z_STREAM_ERROR; 639 state = (gz_statep)file; 640 641 /* check that we're writing */ 642 if (state.state->mode != GZ_WRITE) 643 return Z_STREAM_ERROR; 644 645 /* check for seek request */ 646 if (state.state->seek) { 647 state.state->seek = 0; 648 if (gz_zero(state, state.state->skip) == -1) 649 ret = state.state->err; 650 } 651 652 /* flush, free memory, and close file */ 653 if (gz_comp(state, Z_FINISH) == -1) 654 ret = state.state->err; 655 if (state.state->size) { 656 if (!state.state->direct) { 657 (void)deflateEnd(&(state.state->strm)); 658 free(state.state->out); 659 } 660 free(state.state->in); 661 } 662 gz_error(state, Z_OK, NULL); 663 free(state.state->path); 664 if (close(state.state->fd) == -1) 665 ret = Z_ERRNO; 666 free(state.state); 667 return ret; 668 } 669