1 /* gzwrite.c -- zlib functions for writing gzip files
2 * Copyright (C) 2004, 2005, 2010, 2011 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 and output buffers */
22 state->in = malloc(state->want);
23 state->out = malloc(state->want);
24 if (state->in == NULL || state->out == NULL) {
25 if (state->out != NULL)
27 if (state->in != NULL)
29 gz_error(state, Z_MEM_ERROR, "out of memory");
33 /* allocate deflate memory, set up for gzip compression */
34 strm->zalloc = Z_NULL;
36 strm->opaque = Z_NULL;
37 ret = deflateInit2(strm, state->level, Z_DEFLATED,
38 15 + 16, 8, state->strategy);
41 gz_error(state, Z_MEM_ERROR, "out of memory");
45 /* mark state as initialized */
46 state->size = state->want;
48 /* initialize write buffer */
49 strm->avail_out = state->size;
50 strm->next_out = state->out;
51 state->x.next = strm->next_out;
55 /* Compress whatever is at avail_in and next_in and write to the output file.
56 Return -1 if there is an error writing to the output file, otherwise 0.
57 flush is assumed to be a valid deflate() flush value. If flush is Z_FINISH,
58 then the deflate() state is reset to start a new gzip stream. */
59 local int gz_comp(state, flush)
65 z_streamp strm = &(state->strm);
67 /* allocate memory if this is the first time through */
68 if (state->size == 0 && gz_init(state) == -1)
71 /* run deflate() on provided input until it produces no more output */
74 /* write out current buffer contents if full, or if flushing, but if
75 doing Z_FINISH then don't write until we get to Z_STREAM_END */
76 if (strm->avail_out == 0 || (flush != Z_NO_FLUSH &&
77 (flush != Z_FINISH || ret == Z_STREAM_END))) {
78 have = (unsigned)(strm->next_out - state->x.next);
79 if (have && ((got = write(state->fd, state->x.next, have)) < 0 ||
80 (unsigned)got != have)) {
81 gz_error(state, Z_ERRNO, zstrerror());
84 if (strm->avail_out == 0) {
85 strm->avail_out = state->size;
86 strm->next_out = state->out;
88 state->x.next = strm->next_out;
92 have = strm->avail_out;
93 ret = deflate(strm, flush);
94 if (ret == Z_STREAM_ERROR) {
95 gz_error(state, Z_STREAM_ERROR,
96 "internal error: deflate stream corrupt");
99 have -= strm->avail_out;
102 /* if that completed a deflate stream, allow another to start */
103 if (flush == Z_FINISH)
106 /* all done, no errors */
110 /* Compress len zeros to output. Return -1 on error, 0 on success. */
111 local int gz_zero(state, len)
117 z_streamp strm = &(state->strm);
119 /* consume whatever's left in the input buffer */
120 if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1)
123 /* compress len zeros (len guaranteed > 0) */
126 n = GT_OFF(state->size) || (z_off64_t)state->size > len ?
127 (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)
272 len = (unsigned)strlen(str);
273 ret = gzwrite(file, str, len);
274 return ret == 0 && len != 0 ? -1 : ret;
277 #if defined(STDC) || defined(Z_HAVE_STDARG_H)
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 < size; 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;
349 #else /* !STDC && !Z_HAVE_STDARG_H */
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 can really pass pointer in ints */
370 if (sizeof(int) != sizeof(void *))
373 /* check that we're writing and that there's no error */
374 if (state->mode != GZ_WRITE || state->err != Z_OK)
377 /* make sure we have some buffer space */
378 if (state->size == 0 && gz_init(state) == -1)
381 /* check for seek request */
384 if (gz_zero(state, state->skip) == -1)
388 /* consume whatever's left in the input buffer */
389 if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1)
392 /* do the printf() into the input buffer, put length in len */
393 size = (int)(state->size);
394 state->in[size - 1] = 0;
396 # ifdef HAS_sprintf_void
397 sprintf(state->in, format, a1, a2, a3, a4, a5, a6, a7, a8,
398 a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20);
399 for (len = 0; len < size; len++)
400 if (state->in[len] == 0) break;
402 len = sprintf(state->in, format, a1, a2, a3, a4, a5, a6, a7, a8,
403 a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20);
406 # ifdef HAS_snprintf_void
407 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);
409 len = strlen(state->in);
411 len = snprintf(state->in, size, format, a1, a2, a3, a4, a5, a6, a7, a8,
412 a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20);
416 /* check that printf() results fit in buffer */
417 if (len <= 0 || len >= (int)size || state->in[size - 1] != 0)
420 /* update buffer and position, defer compression until needed */
421 strm->avail_in = (unsigned)len;
422 strm->next_in = state->in;
429 /* -- see zlib.h -- */
430 int ZEXPORT gzflush(file, flush)
436 /* get internal structure */
439 state = (gz_statep)file;
441 /* check that we're writing and that there's no error */
442 if (state->mode != GZ_WRITE || state->err != Z_OK)
443 return Z_STREAM_ERROR;
445 /* check flush parameter */
446 if (flush < 0 || flush > Z_FINISH)
447 return Z_STREAM_ERROR;
449 /* check for seek request */
452 if (gz_zero(state, state->skip) == -1)
456 /* compress remaining data with requested flush */
457 gz_comp(state, flush);
461 /* -- see zlib.h -- */
462 int ZEXPORT gzsetparams(file, level, strategy)
470 /* get internal structure */
472 return Z_STREAM_ERROR;
473 state = (gz_statep)file;
474 strm = &(state->strm);
476 /* check that we're writing and that there's no error */
477 if (state->mode != GZ_WRITE || state->err != Z_OK)
478 return Z_STREAM_ERROR;
480 /* if no change is requested, then do nothing */
481 if (level == state->level && strategy == state->strategy)
484 /* check for seek request */
487 if (gz_zero(state, state->skip) == -1)
491 /* change compression parameters for subsequent input */
493 /* flush previous input with previous parameters before changing */
494 if (strm->avail_in && gz_comp(state, Z_PARTIAL_FLUSH) == -1)
496 deflateParams(strm, level, strategy);
498 state->level = level;
499 state->strategy = strategy;
503 /* -- see zlib.h -- */
504 int ZEXPORT gzclose_w(file)
510 /* get internal structure */
512 return Z_STREAM_ERROR;
513 state = (gz_statep)file;
515 /* check that we're writing */
516 if (state->mode != GZ_WRITE)
517 return Z_STREAM_ERROR;
519 /* check for seek request */
522 ret += gz_zero(state, state->skip);
525 /* flush, free memory, and close file */
526 ret += gz_comp(state, Z_FINISH);
527 (void)deflateEnd(&(state->strm));
530 gz_error(state, Z_OK, NULL);
532 ret += close(state->fd);
534 return ret ? Z_ERRNO : Z_OK;