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)
78 z_streamp strm = &(state->strm);
80 /* allocate memory if this is the first time through */
81 if (state->size == 0 && gz_init(state) == -1)
84 /* write directly if requested */
86 while (strm->avail_in) {
87 got = write(state->fd, strm->next_in, strm->avail_in);
89 gz_error(state, Z_ERRNO, zstrerror());
92 strm->avail_in -= (unsigned)got;
98 /* run deflate() on provided input until it produces no more output */
101 /* write out current buffer contents if full, or if flushing, but if
102 doing Z_FINISH then don't write until we get to Z_STREAM_END */
103 if (strm->avail_out == 0 || (flush != Z_NO_FLUSH &&
104 (flush != Z_FINISH || ret == Z_STREAM_END))) {
105 while (strm->next_out > state->x.next) {
106 got = write(state->fd, state->x.next,
107 (unsigned long)(strm->next_out - state->x.next));
109 gz_error(state, Z_ERRNO, zstrerror());
112 state->x.next += got;
114 if (strm->avail_out == 0) {
115 strm->avail_out = state->size;
116 strm->next_out = state->out;
121 have = strm->avail_out;
122 ret = deflate(strm, flush);
123 if (ret == Z_STREAM_ERROR) {
124 gz_error(state, Z_STREAM_ERROR,
125 "internal error: deflate stream corrupt");
128 have -= strm->avail_out;
131 /* if that completed a deflate stream, allow another to start */
132 if (flush == Z_FINISH)
135 /* all done, no errors */
139 /* Compress len zeros to output. Return -1 on error, 0 on success. */
140 local int gz_zero(state, len)
146 z_streamp strm = &(state->strm);
148 /* consume whatever's left in the input buffer */
149 if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1)
152 /* compress len zeros (len guaranteed > 0) */
155 n = GT_OFF(state->size) || (z_off64_t)state->size > len ?
156 (unsigned)len : state->size;
158 memset(state->in, 0, n);
162 strm->next_in = state->in;
164 if (gz_comp(state, Z_NO_FLUSH) == -1)
171 /* -- see zlib.h -- */
172 int ZEXPORT gzwrite(file, buf, len)
181 /* get internal structure */
184 state = (gz_statep)file;
185 strm = &(state->strm);
187 /* check that we're writing and that there's no error */
188 if (state->mode != GZ_WRITE || state->err != Z_OK)
191 /* since an int is returned, make sure len fits in one, otherwise return
192 with an error (this avoids the flaw in the interface) */
194 gz_error(state, Z_DATA_ERROR, "requested length does not fit in int");
198 /* if len is zero, avoid unnecessary operations */
202 /* allocate memory if this is the first time through */
203 if (state->size == 0 && gz_init(state) == -1)
206 /* check for seek request */
209 if (gz_zero(state, state->skip) == -1)
213 /* for small len, copy to input buffer, otherwise compress directly */
214 if (len < state->size) {
215 /* copy to input buffer, compress when full */
219 if (strm->avail_in == 0)
220 strm->next_in = state->in;
221 have = (unsigned)((strm->next_in + strm->avail_in) - state->in);
222 copy = state->size - have;
225 memcpy(state->in + have, buf, copy);
226 strm->avail_in += copy;
227 state->x.pos += copy;
228 buf = (const char *)buf + copy;
230 if (len && gz_comp(state, Z_NO_FLUSH) == -1)
235 /* consume whatever's left in the input buffer */
236 if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1)
239 /* directly compress user buffer to file */
240 strm->avail_in = len;
241 strm->next_in = (z_const Bytef *)buf;
243 if (gz_comp(state, Z_NO_FLUSH) == -1)
247 /* input was all buffered or compressed (put will fit in int) */
251 /* -- see zlib.h -- */
252 int ZEXPORT gzputc(file, c)
257 unsigned char buf[1];
261 /* get internal structure */
264 state = (gz_statep)file;
265 strm = &(state->strm);
267 /* check that we're writing and that there's no error */
268 if (state->mode != GZ_WRITE || state->err != Z_OK)
271 /* check for seek request */
274 if (gz_zero(state, state->skip) == -1)
278 /* try writing to input buffer for speed (state->size == 0 if buffer not
281 if (strm->avail_in == 0)
282 strm->next_in = state->in;
283 have = (unsigned)((strm->next_in + strm->avail_in) - state->in);
284 if (have < state->size) {
285 state->in[have] = (unsigned char)c;
292 /* no room in buffer or not initialized, use gz_write() */
293 buf[0] = (unsigned char)c;
294 if (gzwrite(file, buf, 1) != 1)
299 /* -- see zlib.h -- */
300 int ZEXPORT gzputs(file, str)
308 len = (unsigned)strlen(str);
309 ret = gzwrite(file, str, len);
310 return ret == 0 && len != 0 ? -1 : ret;
313 #if defined(STDC) || defined(Z_HAVE_STDARG_H)
316 /* -- see zlib.h -- */
317 int ZEXPORTVA gzvprintf(gzFile file, const char *format, va_list va)
325 /* get internal structure */
328 state = (gz_statep)file;
329 strm = &(state->strm);
331 /* check that we're writing and that there's no error */
332 if (state->mode != GZ_WRITE || state->err != Z_OK)
335 /* make sure we have some buffer space */
336 if (state->size == 0 && gz_init(state) == -1)
339 /* check for seek request */
342 if (gz_zero(state, state->skip) == -1)
346 /* do the printf() into the input buffer, put length in len -- the input
347 buffer is double-sized just for this function, so there is guaranteed to
348 be state->size bytes available after the current contents */
349 if (strm->avail_in == 0)
350 strm->next_in = state->in;
351 next = (char *)(state->in + (strm->next_in - state->in) + strm->avail_in);
352 next[state->size - 1] = 0;
354 # ifdef HAS_vsprintf_void
355 (void)vsprintf(next, format, va);
356 for (len = 0; len < state->size; len++)
357 if (next[len] == 0) break;
359 len = vsprintf(next, format, va);
362 # ifdef HAS_vsnprintf_void
363 (void)vsnprintf(next, state->size, format, va);
366 len = vsnprintf(next, state->size, format, va);
370 /* check that printf() results fit in buffer */
371 if (len == 0 || (unsigned)len >= state->size || next[state->size - 1] != 0)
374 /* update buffer and position, compress first half if past that */
375 strm->avail_in += (unsigned)len;
377 if (strm->avail_in >= state->size) {
378 left = strm->avail_in - state->size;
379 strm->avail_in = state->size;
380 if (gz_comp(state, Z_NO_FLUSH) == -1)
382 memcpy(state->in, state->in + state->size, left);
383 strm->next_in = state->in;
384 strm->avail_in = left;
389 int ZEXPORTVA gzprintf(gzFile file, const char *format, ...)
394 va_start(va, format);
395 ret = gzvprintf(file, format, va);
400 #else /* !STDC && !Z_HAVE_STDARG_H */
402 /* -- see zlib.h -- */
403 int ZEXPORTVA gzprintf (file, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10,
404 a11, a12, a13, a14, a15, a16, a17, a18, a19, a20)
407 int a1, a2, a3, a4, a5, a6, a7, a8, a9, a10,
408 a11, a12, a13, a14, a15, a16, a17, a18, a19, a20;
415 /* get internal structure */
418 state = (gz_statep)file;
419 strm = &(state->strm);
421 /* check that can really pass pointer in ints */
422 if (sizeof(int) != sizeof(void *))
425 /* check that we're writing and that there's no error */
426 if (state->mode != GZ_WRITE || state->err != Z_OK)
429 /* make sure we have some buffer space */
430 if (state->size == 0 && gz_init(state) == -1)
433 /* check for seek request */
436 if (gz_zero(state, state->skip) == -1)
440 /* do the printf() into the input buffer, put length in len -- the input
441 buffer is double-sized just for this function, so there is guaranteed to
442 be state->size bytes available after the current contents */
443 if (strm->avail_in == 0)
444 strm->next_in = state->in;
445 next = (char *)(strm->next_in + strm->avail_in);
446 next[state->size - 1] = 0;
448 # ifdef HAS_sprintf_void
449 sprintf(next, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12,
450 a13, a14, a15, a16, a17, a18, a19, a20);
451 for (len = 0; len < size; len++)
455 len = sprintf(next, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11,
456 a12, a13, a14, a15, a16, a17, a18, a19, a20);
459 # ifdef HAS_snprintf_void
460 snprintf(next, state->size, format, a1, a2, a3, a4, a5, a6, a7, a8, a9,
461 a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20);
464 len = snprintf(next, state->size, format, a1, a2, a3, a4, a5, a6, a7, a8,
465 a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20);
469 /* check that printf() results fit in buffer */
470 if (len == 0 || len >= state->size || next[state->size - 1] != 0)
473 /* update buffer and position, compress first half if past that */
474 strm->avail_in += len;
476 if (strm->avail_in >= state->size) {
477 left = strm->avail_in - state->size;
478 strm->avail_in = state->size;
479 if (gz_comp(state, Z_NO_FLUSH) == -1)
481 memcpy(state->in, state->in + state->size, left);
482 strm->next_in = state->in;
483 strm->avail_in = left;
490 /* -- see zlib.h -- */
491 int ZEXPORT gzflush(file, flush)
497 /* get internal structure */
500 state = (gz_statep)file;
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 /* check flush parameter */
507 if (flush < 0 || flush > Z_FINISH)
508 return Z_STREAM_ERROR;
510 /* check for seek request */
513 if (gz_zero(state, state->skip) == -1)
517 /* compress remaining data with requested flush */
518 (void)gz_comp(state, flush);
522 /* -- see zlib.h -- */
523 int ZEXPORT gzsetparams(file, level, strategy)
531 /* get internal structure */
533 return Z_STREAM_ERROR;
534 state = (gz_statep)file;
535 strm = &(state->strm);
537 /* check that we're writing and that there's no error */
538 if (state->mode != GZ_WRITE || state->err != Z_OK)
539 return Z_STREAM_ERROR;
541 /* if no change is requested, then do nothing */
542 if (level == state->level && strategy == state->strategy)
545 /* check for seek request */
548 if (gz_zero(state, state->skip) == -1)
552 /* change compression parameters for subsequent input */
554 /* flush previous input with previous parameters before changing */
555 if (strm->avail_in && gz_comp(state, Z_PARTIAL_FLUSH) == -1)
557 deflateParams(strm, level, strategy);
559 state->level = level;
560 state->strategy = strategy;
564 /* -- see zlib.h -- */
565 int ZEXPORT gzclose_w(file)
571 /* get internal structure */
573 return Z_STREAM_ERROR;
574 state = (gz_statep)file;
576 /* check that we're writing */
577 if (state->mode != GZ_WRITE)
578 return Z_STREAM_ERROR;
580 /* check for seek request */
583 if (gz_zero(state, state->skip) == -1)
587 /* flush, free memory, and close file */
588 if (gz_comp(state, Z_FINISH) == -1)
591 if (!state->direct) {
592 (void)deflateEnd(&(state->strm));
597 gz_error(state, Z_OK, NULL);
599 if (close(state->fd) == -1)