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