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 /* Initialize state for writing a gzip file. Mark initialization by setting
14 state->size to non-zero. Return -1 on failure or 0 on success. */
15 local int gz_init(state)
19 z_streamp strm = &(state->strm);
21 /* allocate input buffer (double size for gzprintf) */
22 state->in = (unsigned char *)malloc(state->want << 1);
23 if (state->in == NULL) {
24 gz_error(state, Z_MEM_ERROR, "out of memory");
28 /* only need output buffer and deflate state if compressing */
30 /* allocate output buffer */
31 state->out = (unsigned char *)malloc(state->want);
32 if (state->out == NULL) {
34 gz_error(state, Z_MEM_ERROR, "out of memory");
38 /* allocate deflate memory, set up for gzip compression */
39 strm->zalloc = Z_NULL;
41 strm->opaque = Z_NULL;
42 ret = deflateInit2(strm, state->level, Z_DEFLATED,
43 MAX_WBITS + 16, DEF_MEM_LEVEL, state->strategy);
47 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(state, flush)
77 z_streamp strm = &(state->strm);
79 /* allocate memory if this is the first time through */
80 if (state->size == 0 && gz_init(state) == -1)
83 /* write directly if requested */
85 while (strm->avail_in) {
86 got = write(state->fd, strm->next_in, strm->avail_in);
88 gz_error(state, Z_ERRNO, zstrerror());
91 strm->avail_in -= got;
97 /* run deflate() on provided input until it produces no more output */
100 /* write out current buffer contents if full, or if flushing, but if
101 doing Z_FINISH then don't write until we get to Z_STREAM_END */
102 if (strm->avail_out == 0 || (flush != Z_NO_FLUSH &&
103 (flush != Z_FINISH || ret == Z_STREAM_END))) {
104 while (strm->next_out > state->x.next) {
105 got = write(state->fd, state->x.next,
106 strm->next_out - state->x.next);
108 gz_error(state, Z_ERRNO, zstrerror());
111 state->x.next += got;
113 if (strm->avail_out == 0) {
114 strm->avail_out = state->size;
115 strm->next_out = state->out;
120 have = strm->avail_out;
121 ret = deflate(strm, flush);
122 if (ret == Z_STREAM_ERROR) {
123 gz_error(state, Z_STREAM_ERROR,
124 "internal error: deflate stream corrupt");
127 have -= strm->avail_out;
130 /* if that completed a deflate stream, allow another to start */
131 if (flush == Z_FINISH)
134 /* all done, no errors */
138 /* Compress len zeros to output. Return -1 on error, 0 on success. */
139 local int gz_zero(state, len)
145 z_streamp strm = &(state->strm);
147 /* consume whatever's left in the input buffer */
148 if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1)
151 /* compress len zeros (len guaranteed > 0) */
154 n = GT_OFF(state->size) || (z_off64_t)state->size > len ?
155 (unsigned)len : state->size;
157 memset(state->in, 0, n);
161 strm->next_in = state->in;
163 if (gz_comp(state, Z_NO_FLUSH) == -1)
170 /* -- see zlib.h -- */
171 int ZEXPORT gzwrite(file, buf, len)
180 /* get internal structure */
183 state = (gz_statep)file;
184 strm = &(state->strm);
186 /* check that we're writing and that there's no error */
187 if (state->mode != GZ_WRITE || state->err != Z_OK)
190 /* since an int is returned, make sure len fits in one, otherwise return
191 with an error (this avoids the flaw in the interface) */
193 gz_error(state, Z_DATA_ERROR, "requested length does not fit in int");
197 /* if len is zero, avoid unnecessary operations */
201 /* allocate memory if this is the first time through */
202 if (state->size == 0 && gz_init(state) == -1)
205 /* check for seek request */
208 if (gz_zero(state, state->skip) == -1)
212 /* for small len, copy to input buffer, otherwise compress directly */
213 if (len < state->size) {
214 /* copy to input buffer, compress when full */
218 if (strm->avail_in == 0)
219 strm->next_in = state->in;
220 have = (unsigned)((strm->next_in + strm->avail_in) - state->in);
221 copy = state->size - have;
224 memcpy(state->in + have, buf, copy);
225 strm->avail_in += copy;
226 state->x.pos += copy;
227 buf = (const char *)buf + copy;
229 if (len && gz_comp(state, Z_NO_FLUSH) == -1)
234 /* consume whatever's left in the input buffer */
235 if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1)
238 /* directly compress user buffer to file */
239 strm->avail_in = len;
240 strm->next_in = (z_const Bytef *)buf;
242 if (gz_comp(state, Z_NO_FLUSH) == -1)
246 /* input was all buffered or compressed (put will fit in int) */
250 /* -- see zlib.h -- */
251 int ZEXPORT gzputc(file, c)
256 unsigned char buf[1];
260 /* get internal structure */
263 state = (gz_statep)file;
264 strm = &(state->strm);
266 /* check that we're writing and that there's no error */
267 if (state->mode != GZ_WRITE || state->err != Z_OK)
270 /* check for seek request */
273 if (gz_zero(state, state->skip) == -1)
277 /* try writing to input buffer for speed (state->size == 0 if buffer not
280 if (strm->avail_in == 0)
281 strm->next_in = state->in;
282 have = (unsigned)((strm->next_in + strm->avail_in) - state->in);
283 if (have < state->size) {
291 /* no room in buffer or not initialized, use gz_write() */
293 if (gzwrite(file, buf, 1) != 1)
298 /* -- see zlib.h -- */
299 int ZEXPORT gzputs(file, str)
307 len = (unsigned)strlen(str);
308 ret = gzwrite(file, str, len);
309 return ret == 0 && len != 0 ? -1 : ret;
312 #if defined(STDC) || defined(Z_HAVE_STDARG_H)
315 /* -- see zlib.h -- */
316 int ZEXPORTVA gzvprintf(gzFile file, const char *format, va_list va)
323 /* get internal structure */
326 state = (gz_statep)file;
327 strm = &(state->strm);
329 /* check that we're writing and that there's no error */
330 if (state->mode != GZ_WRITE || state->err != Z_OK)
333 /* make sure we have some buffer space */
334 if (state->size == 0 && gz_init(state) == -1)
337 /* check for seek request */
340 if (gz_zero(state, state->skip) == -1)
344 /* do the printf() into the input buffer, put length in len -- the input
345 buffer is double-sized just for this function, so there is guaranteed to
346 be state->size bytes available after the current contents */
347 if (strm->avail_in == 0)
348 strm->next_in = state->in;
349 next = (char *)(strm->next_in + strm->avail_in);
350 next[state->size - 1] = 0;
352 # ifdef HAS_vsprintf_void
353 (void)vsprintf(next, format, va);
354 for (len = 0; len < state->size; len++)
355 if (next[len] == 0) break;
357 len = vsprintf(next, format, va);
360 # ifdef HAS_vsnprintf_void
361 (void)vsnprintf(next, state->size, format, va);
364 len = vsnprintf(next, state->size, format, va);
368 /* check that printf() results fit in buffer */
369 if (len == 0 || len >= state->size || next[state->size - 1] != 0)
372 /* update buffer and position, compress first half if past that */
373 strm->avail_in += len;
375 if (strm->avail_in >= state->size) {
376 left = strm->avail_in - state->size;
377 strm->avail_in = state->size;
378 if (gz_comp(state, Z_NO_FLUSH) == -1)
380 memcpy(state->in, state->in + state->size, left);
381 strm->next_in = state->in;
382 strm->avail_in = left;
387 int ZEXPORTVA gzprintf(gzFile file, const char *format, ...)
392 va_start(va, format);
393 ret = gzvprintf(file, format, va);
398 #else /* !STDC && !Z_HAVE_STDARG_H */
400 /* -- see zlib.h -- */
401 int ZEXPORTVA gzprintf (file, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10,
402 a11, a12, a13, a14, a15, a16, a17, a18, a19, a20)
405 int a1, a2, a3, a4, a5, a6, a7, a8, a9, a10,
406 a11, a12, a13, a14, a15, a16, a17, a18, a19, a20;
413 /* get internal structure */
416 state = (gz_statep)file;
417 strm = &(state->strm);
419 /* check that can really pass pointer in ints */
420 if (sizeof(int) != sizeof(void *))
423 /* check that we're writing and that there's no error */
424 if (state->mode != GZ_WRITE || state->err != Z_OK)
427 /* make sure we have some buffer space */
428 if (state->size == 0 && gz_init(state) == -1)
431 /* check for seek request */
434 if (gz_zero(state, state->skip) == -1)
438 /* do the printf() into the input buffer, put length in len -- the input
439 buffer is double-sized just for this function, so there is guaranteed to
440 be state->size bytes available after the current contents */
441 if (strm->avail_in == 0)
442 strm->next_in = state->in;
443 next = (char *)(strm->next_in + strm->avail_in);
444 next[state->size - 1] = 0;
446 # ifdef HAS_sprintf_void
447 sprintf(next, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12,
448 a13, a14, a15, a16, a17, a18, a19, a20);
449 for (len = 0; len < size; len++)
453 len = sprintf(next, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11,
454 a12, a13, a14, a15, a16, a17, a18, a19, a20);
457 # ifdef HAS_snprintf_void
458 snprintf(next, state->size, format, a1, a2, a3, a4, a5, a6, a7, a8, a9,
459 a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20);
462 len = snprintf(next, state->size, format, a1, a2, a3, a4, a5, a6, a7, a8,
463 a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20);
467 /* check that printf() results fit in buffer */
468 if (len == 0 || len >= state->size || next[state->size - 1] != 0)
471 /* update buffer and position, compress first half if past that */
472 strm->avail_in += len;
474 if (strm->avail_in >= state->size) {
475 left = strm->avail_in - state->size;
476 strm->avail_in = state->size;
477 if (gz_comp(state, Z_NO_FLUSH) == -1)
479 memcpy(state->in, state->in + state->size, left);
480 strm->next_in = state->in;
481 strm->avail_in = left;
488 /* -- see zlib.h -- */
489 int ZEXPORT gzflush(file, flush)
495 /* get internal structure */
498 state = (gz_statep)file;
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;
504 /* check flush parameter */
505 if (flush < 0 || flush > Z_FINISH)
506 return Z_STREAM_ERROR;
508 /* check for seek request */
511 if (gz_zero(state, state->skip) == -1)
515 /* compress remaining data with requested flush */
516 gz_comp(state, flush);
520 /* -- see zlib.h -- */
521 int ZEXPORT gzsetparams(file, level, strategy)
529 /* get internal structure */
531 return Z_STREAM_ERROR;
532 state = (gz_statep)file;
533 strm = &(state->strm);
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;
539 /* if no change is requested, then do nothing */
540 if (level == state->level && strategy == state->strategy)
543 /* check for seek request */
546 if (gz_zero(state, state->skip) == -1)
550 /* change compression parameters for subsequent input */
552 /* flush previous input with previous parameters before changing */
553 if (strm->avail_in && gz_comp(state, Z_PARTIAL_FLUSH) == -1)
555 deflateParams(strm, level, strategy);
557 state->level = level;
558 state->strategy = strategy;
562 /* -- see zlib.h -- */
563 int ZEXPORT gzclose_w(file)
569 /* get internal structure */
571 return Z_STREAM_ERROR;
572 state = (gz_statep)file;
574 /* check that we're writing */
575 if (state->mode != GZ_WRITE)
576 return Z_STREAM_ERROR;
578 /* check for seek request */
581 if (gz_zero(state, state->skip) == -1)
585 /* flush, free memory, and close file */
586 if (gz_comp(state, Z_FINISH) == -1)
589 if (!state->direct) {
590 (void)deflateEnd(&(state->strm));
595 gz_error(state, Z_OK, NULL);
597 if (close(state->fd) == -1)