1 /* gzwrite.c -- zlib functions for writing gzip files
2 * Copyright (C) 2004, 2005, 2010 Mark Adler
3 * For conditions of distribution and use, see copyright notice in zlib.h
11 local int gz_init OF((gz_statep));
12 local int gz_comp OF((gz_statep, int));
13 local int gz_zero OF((gz_statep, z_off_t));
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(state)
21 z_streamp strm = &(state->strm);
23 /* allocate input and output buffers */
24 state->in = malloc(state->want);
25 state->out = malloc(state->want);
26 if (state->in == NULL || state->out == NULL) {
27 if (state->out != NULL)
29 if (state->in != NULL)
31 gz_error(state, Z_MEM_ERROR, "out of memory");
35 /* allocate deflate memory, set up for gzip compression */
36 strm->zalloc = Z_NULL;
38 strm->opaque = Z_NULL;
39 ret = deflateInit2(strm, state->level, Z_DEFLATED,
40 15 + 16, 8, state->strategy);
43 gz_error(state, Z_MEM_ERROR, "out of memory");
47 /* mark state as initialized */
48 state->size = state->want;
50 /* initialize write buffer */
51 strm->avail_out = state->size;
52 strm->next_out = state->out;
53 state->next = strm->next_out;
57 /* Compress whatever is at avail_in and next_in and write to the output file.
58 Return -1 if there is an error writing to the output file, otherwise 0.
59 flush is assumed to be a valid deflate() flush value. If flush is Z_FINISH,
60 then the deflate() state is reset to start a new gzip stream. */
61 local int gz_comp(state, flush)
67 z_streamp strm = &(state->strm);
69 /* allocate memory if this is the first time through */
70 if (state->size == 0 && gz_init(state) == -1)
73 /* run deflate() on provided input until it produces no more output */
76 /* write out current buffer contents if full, or if flushing, but if
77 doing Z_FINISH then don't write until we get to Z_STREAM_END */
78 if (strm->avail_out == 0 || (flush != Z_NO_FLUSH &&
79 (flush != Z_FINISH || ret == Z_STREAM_END))) {
80 have = strm->next_out - state->next;
81 if (have && write(state->fd, state->next, have) != have) {
82 gz_error(state, Z_ERRNO, zstrerror());
85 if (strm->avail_out == 0) {
86 strm->avail_out = state->size;
87 strm->next_out = state->out;
89 state->next = strm->next_out;
93 have = strm->avail_out;
94 ret = deflate(strm, flush);
95 if (ret == Z_STREAM_ERROR) {
96 gz_error(state, Z_STREAM_ERROR,
97 "internal error: deflate stream corrupt");
100 have -= strm->avail_out;
103 /* if that completed a deflate stream, allow another to start */
104 if (flush == Z_FINISH)
107 /* all done, no errors */
111 /* Compress len zeros to output. Return -1 on error, 0 on success. */
112 local int gz_zero(state, len)
118 z_streamp strm = &(state->strm);
120 /* consume whatever's left in the input buffer */
121 if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1)
124 /* compress len zeros */
127 n = len < state->size ? (unsigned)len : state->size;
129 memset(state->in, 0, n);
133 strm->next_in = state->in;
135 if (gz_comp(state, Z_NO_FLUSH) == -1)
142 /* -- see zlib.h -- */
143 int ZEXPORT gzwrite(file, buf, len)
153 /* get internal structure */
156 state = (gz_statep)file;
157 strm = &(state->strm);
159 /* check that we're writing and that there's no error */
160 if (state->mode != GZ_WRITE || state->err != Z_OK)
163 /* since an int is returned, make sure len fits in one, otherwise return
164 with an error (this avoids the flaw in the interface) */
166 gz_error(state, Z_BUF_ERROR, "requested length does not fit in int");
170 /* if len is zero, avoid unnecessary operations */
174 /* allocate memory if this is the first time through */
175 if (state->size == 0 && gz_init(state) == -1)
178 /* check for seek request */
181 if (gz_zero(state, state->skip) == -1)
185 /* for small len, copy to input buffer, otherwise compress directly */
186 if (len < state->size) {
187 /* copy to input buffer, compress when full */
189 if (strm->avail_in == 0)
190 strm->next_in = state->in;
191 n = state->size - strm->avail_in;
194 memcpy(strm->next_in + strm->avail_in, buf, n);
197 buf = (char *)buf + n;
199 if (len && gz_comp(state, Z_NO_FLUSH) == -1)
204 /* consume whatever's left in the input buffer */
205 if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1)
208 /* directly compress user buffer to file */
209 strm->avail_in = len;
210 strm->next_in = (voidp)buf;
212 if (gz_comp(state, Z_NO_FLUSH) == -1)
216 /* input was all buffered or compressed (put will fit in int) */
220 /* -- see zlib.h -- */
221 int ZEXPORT gzputc(file, c)
225 unsigned char buf[1];
229 /* get internal structure */
232 state = (gz_statep)file;
233 strm = &(state->strm);
235 /* check that we're writing and that there's no error */
236 if (state->mode != GZ_WRITE || state->err != Z_OK)
239 /* check for seek request */
242 if (gz_zero(state, state->skip) == -1)
246 /* try writing to input buffer for speed (state->size == 0 if buffer not
248 if (strm->avail_in < state->size) {
249 if (strm->avail_in == 0)
250 strm->next_in = state->in;
251 strm->next_in[strm->avail_in++] = c;
256 /* no room in buffer or not initialized, use gz_write() */
258 if (gzwrite(file, buf, 1) != 1)
263 /* -- see zlib.h -- */
264 int ZEXPORT gzputs(file, str)
273 ret = gzwrite(file, str, len);
274 return ret == 0 && len != 0 ? -1 : ret;
280 /* -- see zlib.h -- */
281 int ZEXPORTVA gzprintf (gzFile file, const char *format, ...)
288 /* get internal structure */
291 state = (gz_statep)file;
292 strm = &(state->strm);
294 /* check that we're writing and that there's no error */
295 if (state->mode != GZ_WRITE || state->err != Z_OK)
298 /* make sure we have some buffer space */
299 if (state->size == 0 && gz_init(state) == -1)
302 /* check for seek request */
305 if (gz_zero(state, state->skip) == -1)
309 /* consume whatever's left in the input buffer */
310 if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1)
313 /* do the printf() into the input buffer, put length in len */
314 size = (int)(state->size);
315 state->in[size - 1] = 0;
316 va_start(va, format);
318 # ifdef HAS_vsprintf_void
319 (void)vsprintf(state->in, format, va);
321 for (len = 0; len < state->in; len++)
322 if (state->in[len] == 0) break;
324 len = vsprintf(state->in, format, va);
328 # ifdef HAS_vsnprintf_void
329 (void)vsnprintf(state->in, size, format, va);
331 len = strlen(state->in);
333 len = vsnprintf((char *)(state->in), size, format, va);
338 /* check that printf() results fit in buffer */
339 if (len <= 0 || len >= (int)size || state->in[size - 1] != 0)
342 /* update buffer and position, defer compression until needed */
343 strm->avail_in = (unsigned)len;
344 strm->next_in = state->in;
351 /* -- see zlib.h -- */
352 int ZEXPORTVA gzprintf (file, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10,
353 a11, a12, a13, a14, a15, a16, a17, a18, a19, a20)
356 int a1, a2, a3, a4, a5, a6, a7, a8, a9, a10,
357 a11, a12, a13, a14, a15, a16, a17, a18, a19, a20;
363 /* get internal structure */
366 state = (gz_statep)file;
367 strm = &(state->strm);
369 /* check that we're writing and that there's no error */
370 if (state->mode != GZ_WRITE || state->err != Z_OK)
373 /* make sure we have some buffer space */
374 if (state->size == 0 && gz_init(state) == -1)
377 /* check for seek request */
380 if (gz_zero(state, state->skip) == -1)
384 /* consume whatever's left in the input buffer */
385 if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1)
388 /* do the printf() into the input buffer, put length in len */
389 size = (int)(state->size);
390 state->in[size - 1] = 0;
392 # ifdef HAS_sprintf_void
393 sprintf(state->in, format, a1, a2, a3, a4, a5, a6, a7, a8,
394 a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20);
395 for (len = 0; len < size; len++)
396 if (state->in[len] == 0) break;
398 len = sprintf(state->in, format, a1, a2, a3, a4, a5, a6, a7, a8,
399 a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20);
402 # ifdef HAS_snprintf_void
403 snprintf(state->in, size, format, a1, a2, a3, a4, a5, a6, a7, a8,
404 a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20);
405 len = strlen(state->in);
407 len = snprintf(state->in, size, format, a1, a2, a3, a4, a5, a6, a7, a8,
408 a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20);
412 /* check that printf() results fit in buffer */
413 if (len <= 0 || len >= (int)size || state->in[size - 1] != 0)
416 /* update buffer and position, defer compression until needed */
417 strm->avail_in = (unsigned)len;
418 strm->next_in = state->in;
425 /* -- see zlib.h -- */
426 int ZEXPORT gzflush(file, flush)
432 /* get internal structure */
435 state = (gz_statep)file;
437 /* check that we're writing and that there's no error */
438 if (state->mode != GZ_WRITE|| state->err != Z_OK)
440 /* check flush parameter */
441 if (flush < 0 || flush > Z_FINISH)
442 return Z_STREAM_ERROR;
444 /* check for seek request */
447 if (gz_zero(state, state->skip) == -1)
451 /* compress remaining data with requested flush */
452 gz_comp(state, flush);
456 /* -- see zlib.h -- */
457 int ZEXPORT gzsetparams(file, level, strategy)
465 /* get internal structure */
467 return Z_STREAM_ERROR;
468 state = (gz_statep)file;
469 strm = &(state->strm);
471 /* check that we're writing and that there's no error */
472 if (state->mode != GZ_WRITE || state->err != Z_OK)
473 return Z_STREAM_ERROR;
475 /* if no change is requested, then do nothing */
476 if (level == state->level && strategy == state->strategy)
479 /* check for seek request */
482 if (gz_zero(state, state->skip) == -1)
486 /* change compression parameters for subsequent input */
488 /* flush previous input with previous parameters before changing */
489 if (strm->avail_in && gz_comp(state, Z_PARTIAL_FLUSH) == -1)
491 deflateParams(strm, level, strategy);
493 state->level = level;
494 state->strategy = strategy;
498 /* -- see zlib.h -- */
499 int ZEXPORT gzclose_w(file)
505 /* get internal structure */
507 return Z_STREAM_ERROR;
508 state = (gz_statep)file;
510 /* check that we're writing */
511 if (state->mode != GZ_WRITE)
512 return Z_STREAM_ERROR;
514 /* check for seek request */
517 ret += gz_zero(state, state->skip);
520 /* flush, free memory, and close file */
521 ret += gz_comp(state, Z_FINISH);
522 (void)deflateEnd(&(state->strm));
525 ret += close(state->fd);
526 gz_error(state, Z_OK, NULL);
528 return ret ? Z_ERRNO : Z_OK;
531 #endif /* !OLD_GZIO */