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");
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)
174 /* get internal structure */
177 state = (gz_statep)file;
178 strm = &(state->strm);
180 /* check that we're writing and that there's no error */
181 if (state->mode != GZ_WRITE || state->err != Z_OK)
184 /* since an int is returned, make sure len fits in one, otherwise return
185 with an error (this avoids the flaw in the interface) */
187 gz_error(state, Z_DATA_ERROR, "requested length does not fit in int");
191 /* if len is zero, avoid unnecessary operations */
195 /* allocate memory if this is the first time through */
196 if (state->size == 0 && gz_init(state) == -1)
199 /* check for seek request */
202 if (gz_zero(state, state->skip) == -1)
206 /* for small len, copy to input buffer, otherwise compress directly */
207 if (len < state->size) {
208 /* copy to input buffer, compress when full */
212 if (strm->avail_in == 0)
213 strm->next_in = state->in;
214 have = (unsigned)((strm->next_in + strm->avail_in) - state->in);
215 copy = state->size - have;
218 memcpy(state->in + have, buf, copy);
219 strm->avail_in += copy;
220 state->x.pos += copy;
221 buf = (const char *)buf + copy;
223 if (len && gz_comp(state, Z_NO_FLUSH) == -1)
228 /* consume whatever's left in the input buffer */
229 if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1)
232 /* directly compress user buffer to file */
233 strm->avail_in = len;
234 strm->next_in = (z_const Bytef *)buf;
236 if (gz_comp(state, Z_NO_FLUSH) == -1)
240 /* input was all buffered or compressed (put will fit in int) */
244 /* -- see zlib.h -- */
245 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
274 if (strm->avail_in == 0)
275 strm->next_in = state->in;
276 have = (unsigned)((strm->next_in + strm->avail_in) - state->in);
277 if (have < state->size) {
285 /* no room in buffer or not initialized, use gz_write() */
287 if (gzwrite(file, buf, 1) != 1)
292 /* -- see zlib.h -- */
293 int ZEXPORT gzputs(file, str)
301 len = (unsigned)strlen(str);
302 ret = gzwrite(file, str, len);
303 return ret == 0 && len != 0 ? -1 : ret;
306 #if defined(STDC) || defined(Z_HAVE_STDARG_H)
309 /* -- see zlib.h -- */
310 int ZEXPORTVA gzvprintf(gzFile file, const char *format, va_list va)
317 /* get internal structure */
320 state = (gz_statep)file;
321 strm = &(state->strm);
323 /* check that we're writing and that there's no error */
324 if (state->mode != GZ_WRITE || state->err != Z_OK)
327 /* make sure we have some buffer space */
328 if (state->size == 0 && gz_init(state) == -1)
331 /* check for seek request */
334 if (gz_zero(state, state->skip) == -1)
338 /* do the printf() into the input buffer, put length in len -- the input
339 buffer is double-sized just for this function, so there is guaranteed to
340 be state->size bytes available after the current contents */
341 if (strm->avail_in == 0)
342 strm->next_in = state->in;
343 next = (char *)(strm->next_in + strm->avail_in);
344 next[state->size - 1] = 0;
346 # ifdef HAS_vsprintf_void
347 (void)vsprintf(next, format, va);
348 for (len = 0; len < state->size; len++)
349 if (next[len] == 0) break;
351 len = vsprintf(next, format, va);
354 # ifdef HAS_vsnprintf_void
355 (void)vsnprintf(next, state->size, format, va);
358 len = vsnprintf(next, state->size, format, va);
362 /* check that printf() results fit in buffer */
363 if (len == 0 || len >= state->size || next[state->size - 1] != 0)
366 /* update buffer and position, compress first half if past that */
367 strm->avail_in += len;
369 if (strm->avail_in >= state->size) {
370 left = strm->avail_in - state->size;
371 strm->avail_in = state->size;
372 if (gz_comp(state, Z_NO_FLUSH) == -1)
374 memcpy(state->in, state->in + state->size, left);
375 strm->next_in = state->in;
376 strm->avail_in = left;
381 int ZEXPORTVA gzprintf(gzFile file, const char *format, ...)
386 va_start(va, format);
387 ret = gzvprintf(file, format, va);
392 #else /* !STDC && !Z_HAVE_STDARG_H */
394 /* -- see zlib.h -- */
395 int ZEXPORTVA gzprintf (file, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10,
396 a11, a12, a13, a14, a15, a16, a17, a18, a19, a20)
399 int a1, a2, a3, a4, a5, a6, a7, a8, a9, a10,
400 a11, a12, a13, a14, a15, a16, a17, a18, a19, a20;
407 /* get internal structure */
410 state = (gz_statep)file;
411 strm = &(state->strm);
413 /* check that can really pass pointer in ints */
414 if (sizeof(int) != sizeof(void *))
417 /* check that we're writing and that there's no error */
418 if (state->mode != GZ_WRITE || state->err != Z_OK)
421 /* make sure we have some buffer space */
422 if (state->size == 0 && gz_init(state) == -1)
425 /* check for seek request */
428 if (gz_zero(state, state->skip) == -1)
432 /* do the printf() into the input buffer, put length in len -- the input
433 buffer is double-sized just for this function, so there is guaranteed to
434 be state->size bytes available after the current contents */
435 if (strm->avail_in == 0)
436 strm->next_in = state->in;
437 next = (char *)(strm->next_in + strm->avail_in);
438 next[state->size - 1] = 0;
440 # ifdef HAS_sprintf_void
441 sprintf(next, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12,
442 a13, a14, a15, a16, a17, a18, a19, a20);
443 for (len = 0; len < size; len++)
447 len = sprintf(next, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11,
448 a12, a13, a14, a15, a16, a17, a18, a19, a20);
451 # ifdef HAS_snprintf_void
452 snprintf(next, state->size, format, a1, a2, a3, a4, a5, a6, a7, a8, a9,
453 a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20);
456 len = snprintf(next, state->size, format, a1, a2, a3, a4, a5, a6, a7, a8,
457 a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20);
461 /* check that printf() results fit in buffer */
462 if (len == 0 || len >= state->size || next[state->size - 1] != 0)
465 /* update buffer and position, compress first half if past that */
466 strm->avail_in += len;
468 if (strm->avail_in >= state->size) {
469 left = strm->avail_in - state->size;
470 strm->avail_in = state->size;
471 if (gz_comp(state, Z_NO_FLUSH) == -1)
473 memcpy(state->in, state->in + state->size, left);
474 strm->next_in = state->in;
475 strm->avail_in = left;
482 /* -- see zlib.h -- */
483 int ZEXPORT gzflush(file, flush)
489 /* get internal structure */
492 state = (gz_statep)file;
494 /* check that we're writing and that there's no error */
495 if (state->mode != GZ_WRITE || state->err != Z_OK)
496 return Z_STREAM_ERROR;
498 /* check flush parameter */
499 if (flush < 0 || flush > Z_FINISH)
500 return Z_STREAM_ERROR;
502 /* check for seek request */
505 if (gz_zero(state, state->skip) == -1)
509 /* compress remaining data with requested flush */
510 gz_comp(state, flush);
514 /* -- see zlib.h -- */
515 int ZEXPORT gzsetparams(file, level, strategy)
523 /* get internal structure */
525 return Z_STREAM_ERROR;
526 state = (gz_statep)file;
527 strm = &(state->strm);
529 /* check that we're writing and that there's no error */
530 if (state->mode != GZ_WRITE || state->err != Z_OK)
531 return Z_STREAM_ERROR;
533 /* if no change is requested, then do nothing */
534 if (level == state->level && strategy == state->strategy)
537 /* check for seek request */
540 if (gz_zero(state, state->skip) == -1)
544 /* change compression parameters for subsequent input */
546 /* flush previous input with previous parameters before changing */
547 if (strm->avail_in && gz_comp(state, Z_PARTIAL_FLUSH) == -1)
549 deflateParams(strm, level, strategy);
551 state->level = level;
552 state->strategy = strategy;
556 /* -- see zlib.h -- */
557 int ZEXPORT gzclose_w(file)
563 /* get internal structure */
565 return Z_STREAM_ERROR;
566 state = (gz_statep)file;
568 /* check that we're writing */
569 if (state->mode != GZ_WRITE)
570 return Z_STREAM_ERROR;
572 /* check for seek request */
575 if (gz_zero(state, state->skip) == -1)
579 /* flush, free memory, and close file */
580 if (gz_comp(state, Z_FINISH) == -1)
583 if (!state->direct) {
584 (void)deflateEnd(&(state->strm));
589 gz_error(state, Z_OK, NULL);
591 if (close(state->fd) == -1)