199767f8919635c4928607450d9e0abb932109ceToomas Soome/* gzwrite.c -- zlib functions for writing gzip files
199767f8919635c4928607450d9e0abb932109ceToomas Soome * Copyright (C) 2004, 2005, 2010, 2011, 2012, 2013 Mark Adler
199767f8919635c4928607450d9e0abb932109ceToomas Soome * For conditions of distribution and use, see copyright notice in zlib.h
199767f8919635c4928607450d9e0abb932109ceToomas Soome/* $FreeBSD$ */
199767f8919635c4928607450d9e0abb932109ceToomas Soome/* Local functions */
199767f8919635c4928607450d9e0abb932109ceToomas Soome/* Initialize state for writing a gzip file. Mark initialization by setting
199767f8919635c4928607450d9e0abb932109ceToomas Soome state->size to non-zero. Return -1 on failure or 0 on success. */
199767f8919635c4928607450d9e0abb932109ceToomas Soome /* allocate input buffer */
199767f8919635c4928607450d9e0abb932109ceToomas Soome state->in = (unsigned char *)malloc(state->want);
199767f8919635c4928607450d9e0abb932109ceToomas Soome /* only need output buffer and deflate state if compressing */
199767f8919635c4928607450d9e0abb932109ceToomas Soome /* allocate output buffer */
199767f8919635c4928607450d9e0abb932109ceToomas Soome state->out = (unsigned char *)malloc(state->want);
199767f8919635c4928607450d9e0abb932109ceToomas Soome /* allocate deflate memory, set up for gzip compression */
199767f8919635c4928607450d9e0abb932109ceToomas Soome ret = deflateInit2(strm, state->level, Z_DEFLATED,
199767f8919635c4928607450d9e0abb932109ceToomas Soome MAX_WBITS + 16, DEF_MEM_LEVEL, state->strategy);
199767f8919635c4928607450d9e0abb932109ceToomas Soome /* mark state as initialized */
199767f8919635c4928607450d9e0abb932109ceToomas Soome /* initialize write buffer if compressing */
199767f8919635c4928607450d9e0abb932109ceToomas Soome/* Compress whatever is at avail_in and next_in and write to the output file.
199767f8919635c4928607450d9e0abb932109ceToomas Soome Return -1 if there is an error writing to the output file, otherwise 0.
199767f8919635c4928607450d9e0abb932109ceToomas Soome flush is assumed to be a valid deflate() flush value. If flush is Z_FINISH,
199767f8919635c4928607450d9e0abb932109ceToomas Soome then the deflate() state is reset to start a new gzip stream. If gz->direct
199767f8919635c4928607450d9e0abb932109ceToomas Soome is true, then simply write to the output file without compressing, and
199767f8919635c4928607450d9e0abb932109ceToomas Soome ignore flush. */
199767f8919635c4928607450d9e0abb932109ceToomas Soome /* allocate memory if this is the first time through */
199767f8919635c4928607450d9e0abb932109ceToomas Soome /* write directly if requested */
199767f8919635c4928607450d9e0abb932109ceToomas Soome got = write(state->fd, strm->next_in, strm->avail_in);
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (got < 0 || (unsigned)got != strm->avail_in) {
199767f8919635c4928607450d9e0abb932109ceToomas Soome /* run deflate() on provided input until it produces no more output */
199767f8919635c4928607450d9e0abb932109ceToomas Soome /* write out current buffer contents if full, or if flushing, but if
199767f8919635c4928607450d9e0abb932109ceToomas Soome doing Z_FINISH then don't write until we get to Z_STREAM_END */
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (strm->avail_out == 0 || (flush != Z_NO_FLUSH &&
199767f8919635c4928607450d9e0abb932109ceToomas Soome have = (unsigned)(strm->next_out - state->x.next);
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (have && ((got = write(state->fd, state->x.next, have)) < 0 ||
199767f8919635c4928607450d9e0abb932109ceToomas Soome /* compress */
199767f8919635c4928607450d9e0abb932109ceToomas Soome "internal error: deflate stream corrupt");
199767f8919635c4928607450d9e0abb932109ceToomas Soome /* if that completed a deflate stream, allow another to start */
199767f8919635c4928607450d9e0abb932109ceToomas Soome /* all done, no errors */
199767f8919635c4928607450d9e0abb932109ceToomas Soome/* Compress len zeros to output. Return -1 on error, 0 on success. */
199767f8919635c4928607450d9e0abb932109ceToomas Soome /* consume whatever's left in the input buffer */
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1)
199767f8919635c4928607450d9e0abb932109ceToomas Soome /* compress len zeros (len guaranteed > 0) */
199767f8919635c4928607450d9e0abb932109ceToomas Soome n = GT_OFF(state->size) || (z_off64_t)state->size > len ?
199767f8919635c4928607450d9e0abb932109ceToomas Soome/* -- see zlib.h -- */
199767f8919635c4928607450d9e0abb932109ceToomas Soome /* get internal structure */
199767f8919635c4928607450d9e0abb932109ceToomas Soome /* check that we're writing and that there's no error */
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (state->mode != GZ_WRITE || state->err != Z_OK)
199767f8919635c4928607450d9e0abb932109ceToomas Soome /* since an int is returned, make sure len fits in one, otherwise return
199767f8919635c4928607450d9e0abb932109ceToomas Soome with an error (this avoids the flaw in the interface) */
199767f8919635c4928607450d9e0abb932109ceToomas Soome if ((int)len < 0) {
199767f8919635c4928607450d9e0abb932109ceToomas Soome gz_error(state, Z_DATA_ERROR, "requested length does not fit in int");
199767f8919635c4928607450d9e0abb932109ceToomas Soome /* if len is zero, avoid unnecessary operations */
199767f8919635c4928607450d9e0abb932109ceToomas Soome /* allocate memory if this is the first time through */
199767f8919635c4928607450d9e0abb932109ceToomas Soome /* check for seek request */
199767f8919635c4928607450d9e0abb932109ceToomas Soome /* for small len, copy to input buffer, otherwise compress directly */
199767f8919635c4928607450d9e0abb932109ceToomas Soome /* copy to input buffer, compress when full */
199767f8919635c4928607450d9e0abb932109ceToomas Soome have = (unsigned)((strm->next_in + strm->avail_in) - state->in);
199767f8919635c4928607450d9e0abb932109ceToomas Soome /* consume whatever's left in the input buffer */
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1)
199767f8919635c4928607450d9e0abb932109ceToomas Soome /* directly compress user buffer to file */
199767f8919635c4928607450d9e0abb932109ceToomas Soome /* input was all buffered or compressed (put will fit in int) */
199767f8919635c4928607450d9e0abb932109ceToomas Soome return (int)put;
199767f8919635c4928607450d9e0abb932109ceToomas Soome/* -- see zlib.h -- */
199767f8919635c4928607450d9e0abb932109ceToomas Soome /* get internal structure */
199767f8919635c4928607450d9e0abb932109ceToomas Soome /* check that we're writing and that there's no error */
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (state->mode != GZ_WRITE || state->err != Z_OK)
199767f8919635c4928607450d9e0abb932109ceToomas Soome /* check for seek request */
199767f8919635c4928607450d9e0abb932109ceToomas Soome /* try writing to input buffer for speed (state->size == 0 if buffer not
199767f8919635c4928607450d9e0abb932109ceToomas Soome initialized) */
199767f8919635c4928607450d9e0abb932109ceToomas Soome have = (unsigned)((strm->next_in + strm->avail_in) - state->in);
199767f8919635c4928607450d9e0abb932109ceToomas Soome return c & 0xff;
199767f8919635c4928607450d9e0abb932109ceToomas Soome /* no room in buffer or not initialized, use gz_write() */
199767f8919635c4928607450d9e0abb932109ceToomas Soome return c & 0xff;
199767f8919635c4928607450d9e0abb932109ceToomas Soome/* -- see zlib.h -- */
199767f8919635c4928607450d9e0abb932109ceToomas Soome const char *str;
199767f8919635c4928607450d9e0abb932109ceToomas Soome /* write string */
199767f8919635c4928607450d9e0abb932109ceToomas Soome/* -- see zlib.h -- */
199767f8919635c4928607450d9e0abb932109ceToomas Soomeint ZEXPORTVA gzvprintf(gzFile file, const char *format, va_list va)
199767f8919635c4928607450d9e0abb932109ceToomas Soome /* get internal structure */
199767f8919635c4928607450d9e0abb932109ceToomas Soome /* check that we're writing and that there's no error */
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (state->mode != GZ_WRITE || state->err != Z_OK)
199767f8919635c4928607450d9e0abb932109ceToomas Soome /* make sure we have some buffer space */
199767f8919635c4928607450d9e0abb932109ceToomas Soome /* check for seek request */
199767f8919635c4928607450d9e0abb932109ceToomas Soome /* consume whatever's left in the input buffer */
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1)
199767f8919635c4928607450d9e0abb932109ceToomas Soome /* do the printf() into the input buffer, put length in len */
199767f8919635c4928607450d9e0abb932109ceToomas Soome (void)vsprintf((char *)(state->in), format, va);
199767f8919635c4928607450d9e0abb932109ceToomas Soome len = vsprintf((char *)(state->in), format, va);
199767f8919635c4928607450d9e0abb932109ceToomas Soome (void)vsnprintf((char *)(state->in), size, format, va);
199767f8919635c4928607450d9e0abb932109ceToomas Soome len = vsnprintf((char *)(state->in), size, format, va);
199767f8919635c4928607450d9e0abb932109ceToomas Soome /* check that printf() results fit in buffer */
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (len <= 0 || len >= (int)size || state->in[size - 1] != 0)
199767f8919635c4928607450d9e0abb932109ceToomas Soome /* update buffer and position, defer compression until needed */
199767f8919635c4928607450d9e0abb932109ceToomas Soomeint ZEXPORTVA gzprintf(gzFile file, const char *format, ...)
199767f8919635c4928607450d9e0abb932109ceToomas Soome#else /* !STDC && !Z_HAVE_STDARG_H */
199767f8919635c4928607450d9e0abb932109ceToomas Soome/* -- see zlib.h -- */
199767f8919635c4928607450d9e0abb932109ceToomas Soomeint ZEXPORTVA gzprintf (file, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10,
199767f8919635c4928607450d9e0abb932109ceToomas Soome a11, a12, a13, a14, a15, a16, a17, a18, a19, a20)
199767f8919635c4928607450d9e0abb932109ceToomas Soome a11, a12, a13, a14, a15, a16, a17, a18, a19, a20;
199767f8919635c4928607450d9e0abb932109ceToomas Soome /* get internal structure */
199767f8919635c4928607450d9e0abb932109ceToomas Soome /* check that can really pass pointer in ints */
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (sizeof(int) != sizeof(void *))
199767f8919635c4928607450d9e0abb932109ceToomas Soome /* check that we're writing and that there's no error */
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (state->mode != GZ_WRITE || state->err != Z_OK)
199767f8919635c4928607450d9e0abb932109ceToomas Soome /* make sure we have some buffer space */
199767f8919635c4928607450d9e0abb932109ceToomas Soome /* check for seek request */
199767f8919635c4928607450d9e0abb932109ceToomas Soome /* consume whatever's left in the input buffer */
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1)
199767f8919635c4928607450d9e0abb932109ceToomas Soome /* do the printf() into the input buffer, put length in len */
199767f8919635c4928607450d9e0abb932109ceToomas Soome sprintf((char *)(state->in), format, a1, a2, a3, a4, a5, a6, a7, a8,
199767f8919635c4928607450d9e0abb932109ceToomas Soome a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20);
199767f8919635c4928607450d9e0abb932109ceToomas Soome len = sprintf((char *)(state->in), format, a1, a2, a3, a4, a5, a6, a7, a8,
199767f8919635c4928607450d9e0abb932109ceToomas Soome a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20);
199767f8919635c4928607450d9e0abb932109ceToomas Soome snprintf((char *)(state->in), size, format, a1, a2, a3, a4, a5, a6, a7, a8,
199767f8919635c4928607450d9e0abb932109ceToomas Soome a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20);
199767f8919635c4928607450d9e0abb932109ceToomas Soome len = snprintf((char *)(state->in), size, format, a1, a2, a3, a4, a5, a6,
199767f8919635c4928607450d9e0abb932109ceToomas Soome a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18,
199767f8919635c4928607450d9e0abb932109ceToomas Soome /* check that printf() results fit in buffer */
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (len <= 0 || len >= (int)size || state->in[size - 1] != 0)
199767f8919635c4928607450d9e0abb932109ceToomas Soome /* update buffer and position, defer compression until needed */
199767f8919635c4928607450d9e0abb932109ceToomas Soome/* -- see zlib.h -- */
199767f8919635c4928607450d9e0abb932109ceToomas Soome /* get internal structure */
199767f8919635c4928607450d9e0abb932109ceToomas Soome /* check that we're writing and that there's no error */
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (state->mode != GZ_WRITE || state->err != Z_OK)
199767f8919635c4928607450d9e0abb932109ceToomas Soome /* check flush parameter */
199767f8919635c4928607450d9e0abb932109ceToomas Soome /* check for seek request */
199767f8919635c4928607450d9e0abb932109ceToomas Soome /* compress remaining data with requested flush */
199767f8919635c4928607450d9e0abb932109ceToomas Soome/* -- see zlib.h -- */
199767f8919635c4928607450d9e0abb932109ceToomas Soome /* get internal structure */
199767f8919635c4928607450d9e0abb932109ceToomas Soome /* check that we're writing and that there's no error */
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (state->mode != GZ_WRITE || state->err != Z_OK)
199767f8919635c4928607450d9e0abb932109ceToomas Soome /* if no change is requested, then do nothing */
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (level == state->level && strategy == state->strategy)
199767f8919635c4928607450d9e0abb932109ceToomas Soome /* check for seek request */
199767f8919635c4928607450d9e0abb932109ceToomas Soome /* change compression parameters for subsequent input */
199767f8919635c4928607450d9e0abb932109ceToomas Soome /* flush previous input with previous parameters before changing */
199767f8919635c4928607450d9e0abb932109ceToomas Soome if (strm->avail_in && gz_comp(state, Z_PARTIAL_FLUSH) == -1)
199767f8919635c4928607450d9e0abb932109ceToomas Soome/* -- see zlib.h -- */
199767f8919635c4928607450d9e0abb932109ceToomas Soome /* get internal structure */
199767f8919635c4928607450d9e0abb932109ceToomas Soome /* check that we're writing */
199767f8919635c4928607450d9e0abb932109ceToomas Soome /* check for seek request */
199767f8919635c4928607450d9e0abb932109ceToomas Soome /* flush, free memory, and close file */