1 /* gzwrite.c -- zlib functions for writing gzip files
2 * Copyright (C) 2004, 2005, 2010, 2011, 2012 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 */
22 state->in = malloc(state->want);
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 = 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");
52 /* mark state as initialized */
53 state->size = state->want;
55 /* initialize write buffer if compressing */
57 strm->avail_out = state->size;
58 strm->next_out = state->out;
59 state->x.next = strm->next_out;
64 /* Compress whatever is at avail_in and next_in and write to the output file.
65 Return -1 if there is an error writing to the output file, otherwise 0.
66 flush is assumed to be a valid deflate() flush value. If flush is Z_FINISH,
67 then the deflate() state is reset to start a new gzip stream. If gz->direct
68 is true, then simply write to the output file without compressing, and
70 local int gz_comp(state, flush)
76 z_streamp strm = &(state->strm);
78 /* allocate memory if this is the first time through */
79 if (state->size == 0 && gz_init(state) == -1)
82 /* write directly if requested */
84 got = write(state->fd, strm->next_in, strm->avail_in);
85 if (got < 0 || (unsigned)got != strm->avail_in) {
86 gz_error(state, Z_ERRNO, zstrerror());
93 /* run deflate() on provided input until it produces no more output */
96 /* write out current buffer contents if full, or if flushing, but if
97 doing Z_FINISH then don't write until we get to Z_STREAM_END */
98 if (strm->avail_out == 0 || (flush != Z_NO_FLUSH &&
99 (flush != Z_FINISH || ret == Z_STREAM_END))) {
100 have = (unsigned)(strm->next_out - state->x.next);
101 if (have && ((got = write(state->fd, state->x.next, have)) < 0 ||
102 (unsigned)got != have)) {
103 gz_error(state, Z_ERRNO, zstrerror());
106 if (strm->avail_out == 0) {
107 strm->avail_out = state->size;
108 strm->next_out = state->out;
110 state->x.next = strm->next_out;
114 have = strm->avail_out;
115 ret = deflate(strm, flush);
116 if (ret == Z_STREAM_ERROR) {
117 gz_error(state, Z_STREAM_ERROR,
118 "internal error: deflate stream corrupt");
121 have -= strm->avail_out;
124 /* if that completed a deflate stream, allow another to start */
125 if (flush == Z_FINISH)
128 /* all done, no errors */
132 /* Compress len zeros to output. Return -1 on error, 0 on success. */
133 local int gz_zero(state, len)
139 z_streamp strm = &(state->strm);
141 /* consume whatever's left in the input buffer */
142 if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1)
145 /* compress len zeros (len guaranteed > 0) */
148 n = GT_OFF(state->size) || (z_off64_t)state->size > len ?
149 (unsigned)len : state->size;
151 memset(state->in, 0, n);
155 strm->next_in = state->in;
157 if (gz_comp(state, Z_NO_FLUSH) == -1)
164 /* -- see zlib.h -- */
165 int ZEXPORT gzwrite(file, buf, len)
175 /* get internal structure */
178 state = (gz_statep)file;
179 strm = &(state->strm);
181 /* check that we're writing and that there's no error */
182 if (state->mode != GZ_WRITE || state->err != Z_OK)
185 /* since an int is returned, make sure len fits in one, otherwise return
186 with an error (this avoids the flaw in the interface) */
188 gz_error(state, Z_DATA_ERROR, "requested length does not fit in int");
192 /* if len is zero, avoid unnecessary operations */
196 /* allocate memory if this is the first time through */
197 if (state->size == 0 && gz_init(state) == -1)
200 /* check for seek request */
203 if (gz_zero(state, state->skip) == -1)
207 /* for small len, copy to input buffer, otherwise compress directly */
208 if (len < state->size) {
209 /* copy to input buffer, compress when full */
211 if (strm->avail_in == 0)
212 strm->next_in = state->in;
213 n = state->size - strm->avail_in;
216 memcpy(strm->next_in + strm->avail_in, buf, n);
219 buf = (char *)buf + n;
221 if (len && gz_comp(state, Z_NO_FLUSH) == -1)
226 /* consume whatever's left in the input buffer */
227 if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1)
230 /* directly compress user buffer to file */
231 strm->avail_in = len;
232 strm->next_in = (voidp)buf;
234 if (gz_comp(state, Z_NO_FLUSH) == -1)
238 /* input was all buffered or compressed (put will fit in int) */
242 /* -- see zlib.h -- */
243 int ZEXPORT gzputc(file, c)
247 unsigned char buf[1];
251 /* get internal structure */
254 state = (gz_statep)file;
255 strm = &(state->strm);
257 /* check that we're writing and that there's no error */
258 if (state->mode != GZ_WRITE || state->err != Z_OK)
261 /* check for seek request */
264 if (gz_zero(state, state->skip) == -1)
268 /* try writing to input buffer for speed (state->size == 0 if buffer not
270 if (strm->avail_in < state->size) {
271 if (strm->avail_in == 0)
272 strm->next_in = state->in;
273 strm->next_in[strm->avail_in++] = c;
278 /* no room in buffer or not initialized, use gz_write() */
280 if (gzwrite(file, buf, 1) != 1)
285 /* -- see zlib.h -- */
286 int ZEXPORT gzputs(file, str)
294 len = (unsigned)strlen(str);
295 ret = gzwrite(file, str, len);
296 return ret == 0 && len != 0 ? -1 : ret;
299 #if defined(STDC) || defined(Z_HAVE_STDARG_H)
302 /* -- see zlib.h -- */
303 int ZEXPORTVA gzprintf (gzFile file, const char *format, ...)
310 /* get internal structure */
313 state = (gz_statep)file;
314 strm = &(state->strm);
316 /* check that we're writing and that there's no error */
317 if (state->mode != GZ_WRITE || state->err != Z_OK)
320 /* make sure we have some buffer space */
321 if (state->size == 0 && gz_init(state) == -1)
324 /* check for seek request */
327 if (gz_zero(state, state->skip) == -1)
331 /* consume whatever's left in the input buffer */
332 if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1)
335 /* do the printf() into the input buffer, put length in len */
336 size = (int)(state->size);
337 state->in[size - 1] = 0;
338 va_start(va, format);
340 # ifdef HAS_vsprintf_void
341 (void)vsprintf((char *)(state->in), format, va);
343 for (len = 0; len < size; len++)
344 if (state->in[len] == 0) break;
346 len = vsprintf((char *)(state->in), format, va);
350 # ifdef HAS_vsnprintf_void
351 (void)vsnprintf((char *)(state->in), size, format, va);
353 len = strlen((char *)(state->in));
355 len = vsnprintf((char *)(state->in), size, format, va);
360 /* check that printf() results fit in buffer */
361 if (len <= 0 || len >= (int)size || state->in[size - 1] != 0)
364 /* update buffer and position, defer compression until needed */
365 strm->avail_in = (unsigned)len;
366 strm->next_in = state->in;
371 #else /* !STDC && !Z_HAVE_STDARG_H */
373 /* -- see zlib.h -- */
374 int ZEXPORTVA gzprintf (file, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10,
375 a11, a12, a13, a14, a15, a16, a17, a18, a19, a20)
378 int a1, a2, a3, a4, a5, a6, a7, a8, a9, a10,
379 a11, a12, a13, a14, a15, a16, a17, a18, a19, a20;
385 /* get internal structure */
388 state = (gz_statep)file;
389 strm = &(state->strm);
391 /* check that can really pass pointer in ints */
392 if (sizeof(int) != sizeof(void *))
395 /* check that we're writing and that there's no error */
396 if (state->mode != GZ_WRITE || state->err != Z_OK)
399 /* make sure we have some buffer space */
400 if (state->size == 0 && gz_init(state) == -1)
403 /* check for seek request */
406 if (gz_zero(state, state->skip) == -1)
410 /* consume whatever's left in the input buffer */
411 if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1)
414 /* do the printf() into the input buffer, put length in len */
415 size = (int)(state->size);
416 state->in[size - 1] = 0;
418 # ifdef HAS_sprintf_void
419 sprintf((char *)(state->in), format, a1, a2, a3, a4, a5, a6, a7, a8,
420 a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20);
421 for (len = 0; len < size; len++)
422 if (state->in[len] == 0) break;
424 len = sprintf((char *)(state->in), format, a1, a2, a3, a4, a5, a6, a7, a8,
425 a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20);
428 # ifdef HAS_snprintf_void
429 snprintf((char *)(state->in), size, format, a1, a2, a3, a4, a5, a6, a7, a8,
430 a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20);
431 len = strlen((char *)(state->in));
433 len = snprintf((char *)(state->in), size, format, a1, a2, a3, a4, a5, a6,
434 a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18,
439 /* check that printf() results fit in buffer */
440 if (len <= 0 || len >= (int)size || state->in[size - 1] != 0)
443 /* update buffer and position, defer compression until needed */
444 strm->avail_in = (unsigned)len;
445 strm->next_in = state->in;
452 /* -- see zlib.h -- */
453 int ZEXPORT gzflush(file, flush)
459 /* get internal structure */
462 state = (gz_statep)file;
464 /* check that we're writing and that there's no error */
465 if (state->mode != GZ_WRITE || state->err != Z_OK)
466 return Z_STREAM_ERROR;
468 /* check flush parameter */
469 if (flush < 0 || flush > Z_FINISH)
470 return Z_STREAM_ERROR;
472 /* check for seek request */
475 if (gz_zero(state, state->skip) == -1)
479 /* compress remaining data with requested flush */
480 gz_comp(state, flush);
484 /* -- see zlib.h -- */
485 int ZEXPORT gzsetparams(file, level, strategy)
493 /* get internal structure */
495 return Z_STREAM_ERROR;
496 state = (gz_statep)file;
497 strm = &(state->strm);
499 /* check that we're writing and that there's no error */
500 if (state->mode != GZ_WRITE || state->err != Z_OK)
501 return Z_STREAM_ERROR;
503 /* if no change is requested, then do nothing */
504 if (level == state->level && strategy == state->strategy)
507 /* check for seek request */
510 if (gz_zero(state, state->skip) == -1)
514 /* change compression parameters for subsequent input */
516 /* flush previous input with previous parameters before changing */
517 if (strm->avail_in && gz_comp(state, Z_PARTIAL_FLUSH) == -1)
519 deflateParams(strm, level, strategy);
521 state->level = level;
522 state->strategy = strategy;
526 /* -- see zlib.h -- */
527 int ZEXPORT gzclose_w(file)
533 /* get internal structure */
535 return Z_STREAM_ERROR;
536 state = (gz_statep)file;
538 /* check that we're writing */
539 if (state->mode != GZ_WRITE)
540 return Z_STREAM_ERROR;
542 /* check for seek request */
545 if (gz_zero(state, state->skip) == -1)
549 /* flush, free memory, and close file */
551 if (gz_comp(state, Z_FINISH) == -1)
553 if (!state->direct) {
554 (void)deflateEnd(&(state->strm));
559 gz_error(state, Z_OK, NULL);
561 if (close(state->fd) == -1)