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
10 local int gz_init OF((gz_statep));
11 local int gz_comp OF((gz_statep, int));
12 local int gz_zero OF((gz_statep, z_off64_t));
14 /* Initialize state for writing a gzip file. Mark initialization by setting
15 state->size to non-zero. Return -1 on failure or 0 on success. */
16 local int gz_init(state)
20 z_streamp strm = &(state->strm);
22 /* allocate input and output buffers */
23 state->in = malloc(state->want);
24 state->out = malloc(state->want);
25 if (state->in == NULL || state->out == NULL) {
26 if (state->out != NULL)
28 if (state->in != NULL)
30 gz_error(state, Z_MEM_ERROR, "out of memory");
34 /* allocate deflate memory, set up for gzip compression */
35 strm->zalloc = Z_NULL;
37 strm->opaque = Z_NULL;
38 ret = deflateInit2(strm, state->level, Z_DEFLATED,
39 15 + 16, 8, state->strategy);
42 gz_error(state, Z_MEM_ERROR, "out of memory");
46 /* mark state as initialized */
47 state->size = state->want;
49 /* initialize write buffer */
50 strm->avail_out = state->size;
51 strm->next_out = state->out;
52 state->next = strm->next_out;
56 /* Compress whatever is at avail_in and next_in and write to the output file.
57 Return -1 if there is an error writing to the output file, otherwise 0.
58 flush is assumed to be a valid deflate() flush value. If flush is Z_FINISH,
59 then the deflate() state is reset to start a new gzip stream. */
60 local int gz_comp(state, flush)
66 z_streamp strm = &(state->strm);
68 /* allocate memory if this is the first time through */
69 if (state->size == 0 && gz_init(state) == -1)
72 /* run deflate() on provided input until it produces no more output */
75 /* write out current buffer contents if full, or if flushing, but if
76 doing Z_FINISH then don't write until we get to Z_STREAM_END */
77 if (strm->avail_out == 0 || (flush != Z_NO_FLUSH &&
78 (flush != Z_FINISH || ret == Z_STREAM_END))) {
79 have = (unsigned)(strm->next_out - state->next);
80 if (have && ((got = write(state->fd, state->next, have)) < 0 ||
81 (unsigned)got != have)) {
82 gz_error(state, Z_ERRNO, zstrerror());
85 if (strm->avail_out == 0) {
86 strm->avail_out = state->size;
87 strm->next_out = state->out;
89 state->next = strm->next_out;
93 have = strm->avail_out;
94 ret = deflate(strm, flush);
95 if (ret == Z_STREAM_ERROR) {
96 gz_error(state, Z_STREAM_ERROR,
97 "internal error: deflate stream corrupt");
100 have -= strm->avail_out;
103 /* if that completed a deflate stream, allow another to start */
104 if (flush == Z_FINISH)
107 /* all done, no errors */
111 /* Compress len zeros to output. Return -1 on error, 0 on success. */
112 local int gz_zero(state, len)
118 z_streamp strm = &(state->strm);
120 /* consume whatever's left in the input buffer */
121 if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1)
124 /* compress len zeros (len guaranteed > 0) */
127 n = GT_OFF(state->size) || (z_off64_t)state->size > len ?
128 (unsigned)len : state->size;
130 memset(state->in, 0, n);
134 strm->next_in = state->in;
136 if (gz_comp(state, Z_NO_FLUSH) == -1)
143 /* -- see zlib.h -- */
144 int ZEXPORT gzwrite(file, buf, len)
154 /* get internal structure */
157 state = (gz_statep)file;
158 strm = &(state->strm);
160 /* check that we're writing and that there's no error */
161 if (state->mode != GZ_WRITE || state->err != Z_OK)
164 /* since an int is returned, make sure len fits in one, otherwise return
165 with an error (this avoids the flaw in the interface) */
167 gz_error(state, Z_BUF_ERROR, "requested length does not fit in int");
171 /* if len is zero, avoid unnecessary operations */
175 /* allocate memory if this is the first time through */
176 if (state->size == 0 && gz_init(state) == -1)
179 /* check for seek request */
182 if (gz_zero(state, state->skip) == -1)
186 /* for small len, copy to input buffer, otherwise compress directly */
187 if (len < state->size) {
188 /* copy to input buffer, compress when full */
190 if (strm->avail_in == 0)
191 strm->next_in = state->in;
192 n = state->size - strm->avail_in;
195 memcpy(strm->next_in + strm->avail_in, buf, n);
198 buf = (char *)buf + n;
200 if (len && gz_comp(state, Z_NO_FLUSH) == -1)
205 /* consume whatever's left in the input buffer */
206 if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1)
209 /* directly compress user buffer to file */
210 strm->avail_in = len;
211 strm->next_in = (voidp)buf;
213 if (gz_comp(state, Z_NO_FLUSH) == -1)
217 /* input was all buffered or compressed (put will fit in int) */
221 /* -- see zlib.h -- */
222 int ZEXPORT gzputc(file, c)
226 unsigned char buf[1];
230 /* get internal structure */
233 state = (gz_statep)file;
234 strm = &(state->strm);
236 /* check that we're writing and that there's no error */
237 if (state->mode != GZ_WRITE || state->err != Z_OK)
240 /* check for seek request */
243 if (gz_zero(state, state->skip) == -1)
247 /* try writing to input buffer for speed (state->size == 0 if buffer not
249 if (strm->avail_in < state->size) {
250 if (strm->avail_in == 0)
251 strm->next_in = state->in;
252 strm->next_in[strm->avail_in++] = c;
257 /* no room in buffer or not initialized, use gz_write() */
259 if (gzwrite(file, buf, 1) != 1)
264 /* -- see zlib.h -- */
265 int ZEXPORT gzputs(file, str)
273 len = (unsigned)strlen(str);
274 ret = gzwrite(file, str, len);
275 return ret == 0 && len != 0 ? -1 : ret;
281 /* -- see zlib.h -- */
282 int ZEXPORTVA gzprintf (gzFile file, const char *format, ...)
289 /* get internal structure */
292 state = (gz_statep)file;
293 strm = &(state->strm);
295 /* check that we're writing and that there's no error */
296 if (state->mode != GZ_WRITE || state->err != Z_OK)
299 /* make sure we have some buffer space */
300 if (state->size == 0 && gz_init(state) == -1)
303 /* check for seek request */
306 if (gz_zero(state, state->skip) == -1)
310 /* consume whatever's left in the input buffer */
311 if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1)
314 /* do the printf() into the input buffer, put length in len */
315 size = (int)(state->size);
316 state->in[size - 1] = 0;
317 va_start(va, format);
319 # ifdef HAS_vsprintf_void
320 (void)vsprintf(state->in, format, va);
322 for (len = 0; len < size; len++)
323 if (state->in[len] == 0) break;
325 len = vsprintf(state->in, format, va);
329 # ifdef HAS_vsnprintf_void
330 (void)vsnprintf(state->in, size, format, va);
332 len = strlen(state->in);
334 len = vsnprintf((char *)(state->in), size, format, va);
339 /* check that printf() results fit in buffer */
340 if (len <= 0 || len >= (int)size || state->in[size - 1] != 0)
343 /* update buffer and position, defer compression until needed */
344 strm->avail_in = (unsigned)len;
345 strm->next_in = state->in;
352 /* -- see zlib.h -- */
353 int ZEXPORTVA gzprintf (file, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10,
354 a11, a12, a13, a14, a15, a16, a17, a18, a19, a20)
357 int a1, a2, a3, a4, a5, a6, a7, a8, a9, a10,
358 a11, a12, a13, a14, a15, a16, a17, a18, a19, a20;
364 /* get internal structure */
367 state = (gz_statep)file;
368 strm = &(state->strm);
370 /* check that we're writing and that there's no error */
371 if (state->mode != GZ_WRITE || state->err != Z_OK)
374 /* make sure we have some buffer space */
375 if (state->size == 0 && gz_init(state) == -1)
378 /* check for seek request */
381 if (gz_zero(state, state->skip) == -1)
385 /* consume whatever's left in the input buffer */
386 if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1)
389 /* do the printf() into the input buffer, put length in len */
390 size = (int)(state->size);
391 state->in[size - 1] = 0;
393 # ifdef HAS_sprintf_void
394 sprintf(state->in, format, a1, a2, a3, a4, a5, a6, a7, a8,
395 a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20);
396 for (len = 0; len < size; len++)
397 if (state->in[len] == 0) break;
399 len = sprintf(state->in, format, a1, a2, a3, a4, a5, a6, a7, a8,
400 a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20);
403 # ifdef HAS_snprintf_void
404 snprintf(state->in, size, format, a1, a2, a3, a4, a5, a6, a7, a8,
405 a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20);
406 len = strlen(state->in);
408 len = snprintf(state->in, size, format, a1, a2, a3, a4, a5, a6, a7, a8,
409 a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20);
413 /* check that printf() results fit in buffer */
414 if (len <= 0 || len >= (int)size || state->in[size - 1] != 0)
417 /* update buffer and position, defer compression until needed */
418 strm->avail_in = (unsigned)len;
419 strm->next_in = state->in;
426 /* -- see zlib.h -- */
427 int ZEXPORT gzflush(file, flush)
433 /* get internal structure */
436 state = (gz_statep)file;
438 /* check that we're writing and that there's no error */
439 if (state->mode != GZ_WRITE || state->err != Z_OK)
440 return Z_STREAM_ERROR;
442 /* check flush parameter */
443 if (flush < 0 || flush > Z_FINISH)
444 return Z_STREAM_ERROR;
446 /* check for seek request */
449 if (gz_zero(state, state->skip) == -1)
453 /* compress remaining data with requested flush */
454 gz_comp(state, flush);
458 /* -- see zlib.h -- */
459 int ZEXPORT gzsetparams(file, level, strategy)
467 /* get internal structure */
469 return Z_STREAM_ERROR;
470 state = (gz_statep)file;
471 strm = &(state->strm);
473 /* check that we're writing and that there's no error */
474 if (state->mode != GZ_WRITE || state->err != Z_OK)
475 return Z_STREAM_ERROR;
477 /* if no change is requested, then do nothing */
478 if (level == state->level && strategy == state->strategy)
481 /* check for seek request */
484 if (gz_zero(state, state->skip) == -1)
488 /* change compression parameters for subsequent input */
490 /* flush previous input with previous parameters before changing */
491 if (strm->avail_in && gz_comp(state, Z_PARTIAL_FLUSH) == -1)
493 deflateParams(strm, level, strategy);
495 state->level = level;
496 state->strategy = strategy;
500 /* -- see zlib.h -- */
501 int ZEXPORT gzclose_w(file)
507 /* get internal structure */
509 return Z_STREAM_ERROR;
510 state = (gz_statep)file;
512 /* check that we're writing */
513 if (state->mode != GZ_WRITE)
514 return Z_STREAM_ERROR;
516 /* check for seek request */
519 ret += gz_zero(state, state->skip);
522 /* flush, free memory, and close file */
523 ret += gz_comp(state, Z_FINISH);
524 (void)deflateEnd(&(state->strm));
527 gz_error(state, Z_OK, NULL);
529 ret += close(state->fd);
531 return ret ? Z_ERRNO : Z_OK;