1 /* gzwrite.c -- zlib functions for writing gzip files
2 * Copyright (C) 2004, 2005, 2010, 2011, 2012, 2013 Mark Adler
3 * For conditions of distribution and use, see copyright notice in zlib.h
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));
13 int ZEXPORTVA gzvprintf(gzFile file, const char *format, va_list va);
15 /* Initialize state for writing a gzip file. Mark initialization by setting
16 state->size to non-zero. Return -1 on failure or 0 on success. */
17 local int gz_init(gz_statep state)
20 z_streamp strm = &(state->strm);
22 /* allocate input buffer */
23 state->in = (unsigned char *)malloc(state->want);
24 if (state->in == NULL) {
25 gz_error(state, Z_MEM_ERROR, "out of memory");
29 /* only need output buffer and deflate state if compressing */
31 /* allocate output buffer */
32 state->out = (unsigned char *)malloc(state->want);
33 if (state->out == NULL) {
35 gz_error(state, Z_MEM_ERROR, "out of memory");
39 /* allocate deflate memory, set up for gzip compression */
40 strm->zalloc = Z_NULL;
42 strm->opaque = Z_NULL;
43 ret = deflateInit2(strm, state->level, Z_DEFLATED,
44 MAX_WBITS + 16, DEF_MEM_LEVEL, state->strategy);
48 gz_error(state, Z_MEM_ERROR, "out of memory");
53 /* mark state as initialized */
54 state->size = state->want;
56 /* initialize write buffer if compressing */
58 strm->avail_out = state->size;
59 strm->next_out = state->out;
60 state->x.next = strm->next_out;
65 /* Compress whatever is at avail_in and next_in and write to the output file.
66 Return -1 if there is an error writing to the output file, otherwise 0.
67 flush is assumed to be a valid deflate() flush value. If flush is Z_FINISH,
68 then the deflate() state is reset to start a new gzip stream. If gz->direct
69 is true, then simply write to the output file without compressing, and
71 local int gz_comp(gz_statep state, int flush)
75 z_streamp strm = &(state->strm);
77 /* allocate memory if this is the first time through */
78 if (state->size == 0 && gz_init(state) == -1)
81 /* write directly if requested */
83 got = write(state->fd, strm->next_in, strm->avail_in);
84 if (got < 0 || (unsigned)got != strm->avail_in) {
85 gz_error(state, Z_ERRNO, zstrerror());
92 /* run deflate() on provided input until it produces no more output */
95 /* write out current buffer contents if full, or if flushing, but if
96 doing Z_FINISH then don't write until we get to Z_STREAM_END */
97 if (strm->avail_out == 0 || (flush != Z_NO_FLUSH &&
98 (flush != Z_FINISH || ret == Z_STREAM_END))) {
99 have = (unsigned)(strm->next_out - state->x.next);
100 if (have && ((got = write(state->fd, state->x.next, have)) < 0 ||
101 (unsigned)got != have)) {
102 gz_error(state, Z_ERRNO, zstrerror());
105 if (strm->avail_out == 0) {
106 strm->avail_out = state->size;
107 strm->next_out = state->out;
109 state->x.next = strm->next_out;
113 have = strm->avail_out;
114 ret = deflate(strm, flush);
115 if (ret == Z_STREAM_ERROR) {
116 gz_error(state, Z_STREAM_ERROR,
117 "internal error: deflate stream corrupt");
120 have -= strm->avail_out;
123 /* if that completed a deflate stream, allow another to start */
124 if (flush == Z_FINISH)
127 /* all done, no errors */
131 /* Compress len zeros to output. Return -1 on error, 0 on success. */
132 local int gz_zero(gz_statep state, z_off64_t len)
136 z_streamp strm = &(state->strm);
138 /* consume whatever's left in the input buffer */
139 if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1)
142 /* compress len zeros (len guaranteed > 0) */
145 n = GT_OFF(state->size) || (z_off64_t)state->size > len ?
146 (unsigned)len : state->size;
148 memset(state->in, 0, n);
152 strm->next_in = state->in;
154 if (gz_comp(state, Z_NO_FLUSH) == -1)
161 /* -- see zlib.h -- */
162 int ZEXPORT gzwrite(gzFile file, voidpc buf, unsigned len)
168 /* get internal structure */
171 state = (gz_statep)file;
172 strm = &(state->strm);
174 /* check that we're writing and that there's no error */
175 if (state->mode != GZ_WRITE || state->err != Z_OK)
178 /* since an int is returned, make sure len fits in one, otherwise return
179 with an error (this avoids the flaw in the interface) */
181 gz_error(state, Z_DATA_ERROR, "requested length does not fit in int");
185 /* if len is zero, avoid unnecessary operations */
189 /* allocate memory if this is the first time through */
190 if (state->size == 0 && gz_init(state) == -1)
193 /* check for seek request */
196 if (gz_zero(state, state->skip) == -1)
200 /* for small len, copy to input buffer, otherwise compress directly */
201 if (len < state->size) {
202 /* copy to input buffer, compress when full */
206 if (strm->avail_in == 0)
207 strm->next_in = state->in;
208 have = (unsigned)((strm->next_in + strm->avail_in) - state->in);
209 copy = state->size - have;
212 memcpy(state->in + have, buf, copy);
213 strm->avail_in += copy;
214 state->x.pos += copy;
215 buf = (const char *)buf + copy;
217 if (len && gz_comp(state, Z_NO_FLUSH) == -1)
222 /* consume whatever's left in the input buffer */
223 if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1)
226 /* directly compress user buffer to file */
227 strm->avail_in = len;
228 strm->next_in = (Bytef *)buf;
230 if (gz_comp(state, Z_NO_FLUSH) == -1)
234 /* input was all buffered or compressed (put will fit in int) */
238 /* -- see zlib.h -- */
239 int ZEXPORT gzputc(gzFile file, int c)
242 unsigned char buf[1];
246 /* get internal structure */
249 state = (gz_statep)file;
250 strm = &(state->strm);
252 /* check that we're writing and that there's no error */
253 if (state->mode != GZ_WRITE || state->err != Z_OK)
256 /* check for seek request */
259 if (gz_zero(state, state->skip) == -1)
263 /* try writing to input buffer for speed (state->size == 0 if buffer not
266 if (strm->avail_in == 0)
267 strm->next_in = state->in;
268 have = (unsigned)((strm->next_in + strm->avail_in) - state->in);
269 if (have < state->size) {
277 /* no room in buffer or not initialized, use gz_write() */
279 if (gzwrite(file, buf, 1) != 1)
284 /* -- see zlib.h -- */
285 int ZEXPORT gzputs(gzFile file, const char *str)
291 len = (unsigned)strlen(str);
292 ret = gzwrite(file, str, len);
293 return ret == 0 && len != 0 ? -1 : ret;
296 #if defined(STDC) || defined(Z_HAVE_STDARG_H)
299 /* -- see zlib.h -- */
300 int ZEXPORTVA gzvprintf(gzFile file, const char *format, va_list va)
306 /* get internal structure */
309 state = (gz_statep)file;
310 strm = &(state->strm);
312 /* check that we're writing and that there's no error */
313 if (state->mode != GZ_WRITE || state->err != Z_OK)
316 /* make sure we have some buffer space */
317 if (state->size == 0 && gz_init(state) == -1)
320 /* check for seek request */
323 if (gz_zero(state, state->skip) == -1)
327 /* consume whatever's left in the input buffer */
328 if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1)
331 /* do the printf() into the input buffer, put length in len */
332 size = (int)(state->size);
333 state->in[size - 1] = 0;
335 # ifdef HAS_vsprintf_void
336 (void)vsprintf((char *)(state->in), format, va);
337 for (len = 0; len < size; len++)
338 if (state->in[len] == 0) break;
340 len = vsprintf((char *)(state->in), format, va);
343 # ifdef HAS_vsnprintf_void
344 (void)vsnprintf((char *)(state->in), size, format, va);
345 len = strlen((char *)(state->in));
347 len = vsnprintf((char *)(state->in), size, format, va);
351 /* check that printf() results fit in buffer */
352 if (len <= 0 || len >= (int)size || state->in[size - 1] != 0)
355 /* update buffer and position, defer compression until needed */
356 strm->avail_in = (unsigned)len;
357 strm->next_in = state->in;
362 int ZEXPORTVA gzprintf(gzFile file, const char *format, ...)
367 va_start(va, format);
368 ret = gzvprintf(file, format, va);
373 #else /* !STDC && !Z_HAVE_STDARG_H */
375 /* -- see zlib.h -- */
376 int ZEXPORTVA gzprintf (gzFile file, const char *format, int a1, int a2, int a3, int a4, int a5, int a6, int a7, int a8, int a9, int a10,
377 int a11, int a12, int a13, int a14, int a15, int a16, int a17, int a18, int a19, int a20)
383 /* get internal structure */
386 state = (gz_statep)file;
387 strm = &(state->strm);
389 /* check that can really pass pointer in ints */
390 if (sizeof(int) != sizeof(void *))
393 /* check that we're writing and that there's no error */
394 if (state->mode != GZ_WRITE || state->err != Z_OK)
397 /* make sure we have some buffer space */
398 if (state->size == 0 && gz_init(state) == -1)
401 /* check for seek request */
404 if (gz_zero(state, state->skip) == -1)
408 /* consume whatever's left in the input buffer */
409 if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1)
412 /* do the printf() into the input buffer, put length in len */
413 size = (int)(state->size);
414 state->in[size - 1] = 0;
416 # ifdef HAS_sprintf_void
417 sprintf((char *)(state->in), format, a1, a2, a3, a4, a5, a6, a7, a8,
418 a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20);
419 for (len = 0; len < size; len++)
420 if (state->in[len] == 0) break;
422 len = sprintf((char *)(state->in), format, a1, a2, a3, a4, a5, a6, a7, a8,
423 a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20);
426 # ifdef HAS_snprintf_void
427 snprintf((char *)(state->in), size, format, a1, a2, a3, a4, a5, a6, a7, a8,
428 a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20);
429 len = strlen((char *)(state->in));
431 len = snprintf((char *)(state->in), size, format, a1, a2, a3, a4, a5, a6,
432 a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18,
437 /* check that printf() results fit in buffer */
438 if (len <= 0 || len >= (int)size || state->in[size - 1] != 0)
441 /* update buffer and position, defer compression until needed */
442 strm->avail_in = (unsigned)len;
443 strm->next_in = state->in;
450 /* -- see zlib.h -- */
451 int ZEXPORT gzflush(gzFile file, int flush)
455 /* get internal structure */
458 state = (gz_statep)file;
460 /* check that we're writing and that there's no error */
461 if (state->mode != GZ_WRITE || state->err != Z_OK)
462 return Z_STREAM_ERROR;
464 /* check flush parameter */
465 if (flush < 0 || flush > Z_FINISH)
466 return Z_STREAM_ERROR;
468 /* check for seek request */
471 if (gz_zero(state, state->skip) == -1)
475 /* compress remaining data with requested flush */
476 gz_comp(state, flush);
480 /* -- see zlib.h -- */
481 int ZEXPORT gzsetparams(gzFile file, int level, int strategy)
486 /* get internal structure */
488 return Z_STREAM_ERROR;
489 state = (gz_statep)file;
490 strm = &(state->strm);
492 /* check that we're writing and that there's no error */
493 if (state->mode != GZ_WRITE || state->err != Z_OK)
494 return Z_STREAM_ERROR;
496 /* if no change is requested, then do nothing */
497 if (level == state->level && strategy == state->strategy)
500 /* check for seek request */
503 if (gz_zero(state, state->skip) == -1)
507 /* change compression parameters for subsequent input */
509 /* flush previous input with previous parameters before changing */
510 if (strm->avail_in && gz_comp(state, Z_PARTIAL_FLUSH) == -1)
512 deflateParams(strm, level, strategy);
514 state->level = level;
515 state->strategy = strategy;
519 /* -- see zlib.h -- */
520 int gzclose_w(gzFile file)
525 /* get internal structure */
527 return Z_STREAM_ERROR;
528 state = (gz_statep)file;
530 /* check that we're writing */
531 if (state->mode != GZ_WRITE)
532 return Z_STREAM_ERROR;
534 /* check for seek request */
537 if (gz_zero(state, state->skip) == -1)
541 /* flush, free memory, and close file */
542 if (gz_comp(state, Z_FINISH) == -1)
545 if (!state->direct) {
546 (void)deflateEnd(&(state->strm));
551 gz_error(state, Z_OK, NULL);
553 if (close(state->fd) == -1)