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 }