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
12 local int gz_init OF((gz_statep));
13 local int gz_comp OF((gz_statep, int));
14 local int gz_zero OF((gz_statep, z_off64_t));
16 /* Initialize state for writing a gzip file. Mark initialization by setting
17 state->size to non-zero. Return -1 on failure or 0 on success. */
18 local int gz_init(state)
22 z_streamp strm = &(state->strm);
24 /* allocate input buffer */
25 state->in = malloc(state->want);
26 if (state->in == NULL) {
27 gz_error(state, Z_MEM_ERROR, "out of memory");
31 /* only need output buffer and deflate state if compressing */
33 /* allocate output buffer */
34 state->out = malloc(state->want);
35 if (state->out == NULL) {
37 gz_error(state, Z_MEM_ERROR, "out of memory");
41 /* allocate deflate memory, set up for gzip compression */
42 strm->zalloc = Z_NULL;
44 strm->opaque = Z_NULL;
45 ret = deflateInit2(strm, state->level, Z_DEFLATED,
46 MAX_WBITS + 16, DEF_MEM_LEVEL, state->strategy);
50 gz_error(state, Z_MEM_ERROR, "out of memory");
55 /* mark state as initialized */
56 state->size = state->want;
58 /* initialize write buffer if compressing */
60 strm->avail_out = state->size;
61 strm->next_out = state->out;
62 state->x.next = strm->next_out;
67 /* Compress whatever is at avail_in and next_in and write to the output file.
68 Return -1 if there is an error writing to the output file, otherwise 0.
69 flush is assumed to be a valid deflate() flush value. If flush is Z_FINISH,
70 then the deflate() state is reset to start a new gzip stream. If gz->direct
71 is true, then simply write to the output file without compressing, and
73 local int gz_comp(state, flush)
79 z_streamp strm = &(state->strm);
81 /* allocate memory if this is the first time through */
82 if (state->size == 0 && gz_init(state) == -1)
85 /* write directly if requested */
87 got = write(state->fd, strm->next_in, strm->avail_in);
88 if (got < 0 || (unsigned)got != strm->avail_in) {
89 gz_error(state, Z_ERRNO, zstrerror());
96 /* run deflate() on provided input until it produces no more output */
99 /* write out current buffer contents if full, or if flushing, but if
100 doing Z_FINISH then don't write until we get to Z_STREAM_END */
101 if (strm->avail_out == 0 || (flush != Z_NO_FLUSH &&
102 (flush != Z_FINISH || ret == Z_STREAM_END))) {
103 have = (unsigned)(strm->next_out - state->x.next);
104 if (have && ((got = write(state->fd, state->x.next, have)) < 0 ||
105 (unsigned)got != have)) {
106 gz_error(state, Z_ERRNO, zstrerror());
109 if (strm->avail_out == 0) {
110 strm->avail_out = state->size;
111 strm->next_out = state->out;
113 state->x.next = strm->next_out;
117 have = strm->avail_out;
118 ret = deflate(strm, flush);
119 if (ret == Z_STREAM_ERROR) {
120 gz_error(state, Z_STREAM_ERROR,
121 "internal error: deflate stream corrupt");
124 have -= strm->avail_out;
127 /* if that completed a deflate stream, allow another to start */
128 if (flush == Z_FINISH)
131 /* all done, no errors */
135 /* Compress len zeros to output. Return -1 on error, 0 on success. */
136 local int gz_zero(state, len)
142 z_streamp strm = &(state->strm);
144 /* consume whatever's left in the input buffer */
145 if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1)
148 /* compress len zeros (len guaranteed > 0) */
151 n = GT_OFF(state->size) || (z_off64_t)state->size > len ?
152 (unsigned)len : state->size;
154 memset(state->in, 0, n);
158 strm->next_in = state->in;
160 if (gz_comp(state, Z_NO_FLUSH) == -1)
167 /* -- see zlib.h -- */
168 int ZEXPORT gzwrite(file, buf, len)
178 /* get internal structure */
181 state = (gz_statep)file;
182 strm = &(state->strm);
184 /* check that we're writing and that there's no error */
185 if (state->mode != GZ_WRITE || state->err != Z_OK)
188 /* since an int is returned, make sure len fits in one, otherwise return
189 with an error (this avoids the flaw in the interface) */
191 gz_error(state, Z_DATA_ERROR, "requested length does not fit in int");
195 /* if len is zero, avoid unnecessary operations */
199 /* allocate memory if this is the first time through */
200 if (state->size == 0 && gz_init(state) == -1)
203 /* check for seek request */
206 if (gz_zero(state, state->skip) == -1)
210 /* for small len, copy to input buffer, otherwise compress directly */
211 if (len < state->size) {
212 /* copy to input buffer, compress when full */
214 if (strm->avail_in == 0)
215 strm->next_in = state->in;
216 n = state->size - strm->avail_in;
219 memcpy(strm->next_in + strm->avail_in, buf, n);
222 buf = (char *)buf + n;
224 if (len && gz_comp(state, Z_NO_FLUSH) == -1)
229 /* consume whatever's left in the input buffer */
230 if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1)
233 /* directly compress user buffer to file */
234 strm->avail_in = len;
235 strm->next_in = (voidp)buf;
237 if (gz_comp(state, Z_NO_FLUSH) == -1)
241 /* input was all buffered or compressed (put will fit in int) */
245 /* -- see zlib.h -- */
246 int ZEXPORT gzputc(file, c)
250 unsigned char buf[1];
254 /* get internal structure */
257 state = (gz_statep)file;
258 strm = &(state->strm);
260 /* check that we're writing and that there's no error */
261 if (state->mode != GZ_WRITE || state->err != Z_OK)
264 /* check for seek request */
267 if (gz_zero(state, state->skip) == -1)
271 /* try writing to input buffer for speed (state->size == 0 if buffer not
273 if (strm->avail_in < state->size) {
274 if (strm->avail_in == 0)
275 strm->next_in = state->in;
276 strm->next_in[strm->avail_in++] = c;
281 /* no room in buffer or not initialized, use gz_write() */
283 if (gzwrite(file, buf, 1) != 1)
288 /* -- see zlib.h -- */
289 int ZEXPORT gzputs(file, str)
297 len = (unsigned)strlen(str);
298 ret = gzwrite(file, str, len);
299 return ret == 0 && len != 0 ? -1 : ret;
302 #if defined(STDC) || defined(Z_HAVE_STDARG_H)
305 /* -- see zlib.h -- */
306 int ZEXPORTVA gzprintf (gzFile file, const char *format, ...)
313 /* get internal structure */
316 state = (gz_statep)file;
317 strm = &(state->strm);
319 /* check that we're writing and that there's no error */
320 if (state->mode != GZ_WRITE || state->err != Z_OK)
323 /* make sure we have some buffer space */
324 if (state->size == 0 && gz_init(state) == -1)
327 /* check for seek request */
330 if (gz_zero(state, state->skip) == -1)
334 /* consume whatever's left in the input buffer */
335 if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1)
338 /* do the printf() into the input buffer, put length in len */
339 size = (int)(state->size);
340 state->in[size - 1] = 0;
341 va_start(va, format);
343 # ifdef HAS_vsprintf_void
344 (void)vsprintf((char *)(state->in), format, va);
346 for (len = 0; len < size; len++)
347 if (state->in[len] == 0) break;
349 len = vsprintf((char *)(state->in), format, va);
353 # ifdef HAS_vsnprintf_void
354 (void)vsnprintf((char *)(state->in), size, format, va);
356 len = strlen((char *)(state->in));
358 len = vsnprintf((char *)(state->in), size, format, va);
363 /* check that printf() results fit in buffer */
364 if (len <= 0 || len >= (int)size || state->in[size - 1] != 0)
367 /* update buffer and position, defer compression until needed */
368 strm->avail_in = (unsigned)len;
369 strm->next_in = state->in;
374 #else /* !STDC && !Z_HAVE_STDARG_H */
376 /* -- see zlib.h -- */
377 int ZEXPORTVA gzprintf (file, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10,
378 a11, a12, a13, a14, a15, a16, a17, a18, a19, a20)
381 int a1, a2, a3, a4, a5, a6, a7, a8, a9, a10,
382 a11, a12, a13, a14, a15, a16, a17, a18, a19, a20;
388 /* get internal structure */
391 state = (gz_statep)file;
392 strm = &(state->strm);
394 /* check that can really pass pointer in ints */
395 if (sizeof(int) != sizeof(void *))
398 /* check that we're writing and that there's no error */
399 if (state->mode != GZ_WRITE || state->err != Z_OK)
402 /* make sure we have some buffer space */
403 if (state->size == 0 && gz_init(state) == -1)
406 /* check for seek request */
409 if (gz_zero(state, state->skip) == -1)
413 /* consume whatever's left in the input buffer */
414 if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1)
417 /* do the printf() into the input buffer, put length in len */
418 size = (int)(state->size);
419 state->in[size - 1] = 0;
421 # ifdef HAS_sprintf_void
422 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);
424 for (len = 0; len < size; len++)
425 if (state->in[len] == 0) break;
427 len = sprintf((char *)(state->in), format, a1, a2, a3, a4, a5, a6, a7, a8,
428 a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20);
431 # ifdef HAS_snprintf_void
432 snprintf((char *)(state->in), size, format, a1, a2, a3, a4, a5, a6, a7, a8,
433 a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20);
434 len = strlen((char *)(state->in));
436 len = snprintf((char *)(state->in), size, format, a1, a2, a3, a4, a5, a6,
437 a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18,
442 /* check that printf() results fit in buffer */
443 if (len <= 0 || len >= (int)size || state->in[size - 1] != 0)
446 /* update buffer and position, defer compression until needed */
447 strm->avail_in = (unsigned)len;
448 strm->next_in = state->in;
455 /* -- see zlib.h -- */
456 int ZEXPORT gzflush(file, flush)
462 /* get internal structure */
465 state = (gz_statep)file;
467 /* check that we're writing and that there's no error */
468 if (state->mode != GZ_WRITE || state->err != Z_OK)
469 return Z_STREAM_ERROR;
471 /* check flush parameter */
472 if (flush < 0 || flush > Z_FINISH)
473 return Z_STREAM_ERROR;
475 /* check for seek request */
478 if (gz_zero(state, state->skip) == -1)
482 /* compress remaining data with requested flush */
483 gz_comp(state, flush);
487 /* -- see zlib.h -- */
488 int ZEXPORT gzsetparams(file, level, strategy)
496 /* get internal structure */
498 return Z_STREAM_ERROR;
499 state = (gz_statep)file;
500 strm = &(state->strm);
502 /* check that we're writing and that there's no error */
503 if (state->mode != GZ_WRITE || state->err != Z_OK)
504 return Z_STREAM_ERROR;
506 /* if no change is requested, then do nothing */
507 if (level == state->level && strategy == state->strategy)
510 /* check for seek request */
513 if (gz_zero(state, state->skip) == -1)
517 /* change compression parameters for subsequent input */
519 /* flush previous input with previous parameters before changing */
520 if (strm->avail_in && gz_comp(state, Z_PARTIAL_FLUSH) == -1)
522 deflateParams(strm, level, strategy);
524 state->level = level;
525 state->strategy = strategy;
529 /* -- see zlib.h -- */
530 int ZEXPORT gzclose_w(file)
536 /* get internal structure */
538 return Z_STREAM_ERROR;
539 state = (gz_statep)file;
541 /* check that we're writing */
542 if (state->mode != GZ_WRITE)
543 return Z_STREAM_ERROR;
545 /* check for seek request */
548 if (gz_zero(state, state->skip) == -1)
552 /* flush, free memory, and close file */
554 if (gz_comp(state, Z_FINISH) == -1)
556 if (!state->direct) {
557 (void)deflateEnd(&(state->strm));
562 gz_error(state, Z_OK, NULL);
564 if (close(state->fd) == -1)