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