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
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->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->next);
79 if (have && ((got = write(state->fd, state->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->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;
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;
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)
439 return Z_STREAM_ERROR;
441 /* check flush parameter */
442 if (flush < 0 || flush > Z_FINISH)
443 return Z_STREAM_ERROR;
445 /* check for seek request */
448 if (gz_zero(state, state->skip) == -1)
452 /* compress remaining data with requested flush */
453 gz_comp(state, flush);
457 /* -- see zlib.h -- */
458 int ZEXPORT gzsetparams(file, level, strategy)
466 /* get internal structure */
468 return Z_STREAM_ERROR;
469 state = (gz_statep)file;
470 strm = &(state->strm);
472 /* check that we're writing and that there's no error */
473 if (state->mode != GZ_WRITE || state->err != Z_OK)
474 return Z_STREAM_ERROR;
476 /* if no change is requested, then do nothing */
477 if (level == state->level && strategy == state->strategy)
480 /* check for seek request */
483 if (gz_zero(state, state->skip) == -1)
487 /* change compression parameters for subsequent input */
489 /* flush previous input with previous parameters before changing */
490 if (strm->avail_in && gz_comp(state, Z_PARTIAL_FLUSH) == -1)
492 deflateParams(strm, level, strategy);
494 state->level = level;
495 state->strategy = strategy;
499 /* -- see zlib.h -- */
500 int ZEXPORT gzclose_w(file)
506 /* get internal structure */
508 return Z_STREAM_ERROR;
509 state = (gz_statep)file;
511 /* check that we're writing */
512 if (state->mode != GZ_WRITE)
513 return Z_STREAM_ERROR;
515 /* check for seek request */
518 ret += gz_zero(state, state->skip);
521 /* flush, free memory, and close file */
522 ret += gz_comp(state, Z_FINISH);
523 (void)deflateEnd(&(state->strm));
526 gz_error(state, Z_OK, NULL);
528 ret += close(state->fd);
530 return ret ? Z_ERRNO : Z_OK;