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