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