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
11 local int gz_init OF((gz_statep));
12 local int gz_comp OF((gz_statep, int));
13 local int gz_zero OF((gz_statep, z_off64_t));
15 /* Initialize state for writing a gzip file. Mark initialization by setting
16 state->size to non-zero. Return -1 on failure or 0 on success. */
17 local int gz_init(state)
21 z_streamp strm = &(state->strm);
23 /* allocate input and output buffers */
24 state->in = malloc(state->want);
25 state->out = malloc(state->want);
26 if (state->in == NULL || state->out == NULL) {
27 if (state->out != NULL)
29 if (state->in != NULL)
31 gz_error(state, Z_MEM_ERROR, "out of memory");
35 /* allocate deflate memory, set up for gzip compression */
36 strm->zalloc = Z_NULL;
38 strm->opaque = Z_NULL;
39 ret = deflateInit2(strm, state->level, Z_DEFLATED,
40 15 + 16, 8, state->strategy);
43 gz_error(state, Z_MEM_ERROR, "out of memory");
47 /* mark state as initialized */
48 state->size = state->want;
50 /* initialize write buffer */
51 strm->avail_out = state->size;
52 strm->next_out = state->out;
53 state->next = strm->next_out;
57 /* Compress whatever is at avail_in and next_in and write to the output file.
58 Return -1 if there is an error writing to the output file, otherwise 0.
59 flush is assumed to be a valid deflate() flush value. If flush is Z_FINISH,
60 then the deflate() state is reset to start a new gzip stream. */
61 local int gz_comp(state, flush)
67 z_streamp strm = &(state->strm);
69 /* allocate memory if this is the first time through */
70 if (state->size == 0 && gz_init(state) == -1)
73 /* run deflate() on provided input until it produces no more output */
76 /* write out current buffer contents if full, or if flushing, but if
77 doing Z_FINISH then don't write until we get to Z_STREAM_END */
78 if (strm->avail_out == 0 || (flush != Z_NO_FLUSH &&
79 (flush != Z_FINISH || ret == Z_STREAM_END))) {
80 have = strm->next_out - state->next;
81 if (have && ((got = write(state->fd, state->next, have)) < 0 ||
82 (unsigned)got != have)) {
83 gz_error(state, Z_ERRNO, zstrerror());
86 if (strm->avail_out == 0) {
87 strm->avail_out = state->size;
88 strm->next_out = state->out;
90 state->next = strm->next_out;
94 have = strm->avail_out;
95 ret = deflate(strm, flush);
96 if (ret == Z_STREAM_ERROR) {
97 gz_error(state, Z_STREAM_ERROR,
98 "internal error: deflate stream corrupt");
101 have -= strm->avail_out;
104 /* if that completed a deflate stream, allow another to start */
105 if (flush == Z_FINISH)
108 /* all done, no errors */
112 /* Compress len zeros to output. Return -1 on error, 0 on success. */
113 local int gz_zero(state, len)
119 z_streamp strm = &(state->strm);
121 /* consume whatever's left in the input buffer */
122 if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1)
125 /* compress len zeros (len guaranteed > 0) */
128 n = GT_OFF(state->size) || (z_off64_t)state->size > len ?
129 (unsigned)len : state->size;
131 memset(state->in, 0, n);
135 strm->next_in = state->in;
137 if (gz_comp(state, Z_NO_FLUSH) == -1)
144 /* -- see zlib.h -- */
145 int ZEXPORT gzwrite(file, buf, len)
155 /* get internal structure */
158 state = (gz_statep)file;
159 strm = &(state->strm);
161 /* check that we're writing and that there's no error */
162 if (state->mode != GZ_WRITE || state->err != Z_OK)
165 /* since an int is returned, make sure len fits in one, otherwise return
166 with an error (this avoids the flaw in the interface) */
168 gz_error(state, Z_BUF_ERROR, "requested length does not fit in int");
172 /* if len is zero, avoid unnecessary operations */
176 /* allocate memory if this is the first time through */
177 if (state->size == 0 && gz_init(state) == -1)
180 /* check for seek request */
183 if (gz_zero(state, state->skip) == -1)
187 /* for small len, copy to input buffer, otherwise compress directly */
188 if (len < state->size) {
189 /* copy to input buffer, compress when full */
191 if (strm->avail_in == 0)
192 strm->next_in = state->in;
193 n = state->size - strm->avail_in;
196 memcpy(strm->next_in + strm->avail_in, buf, n);
199 buf = (char *)buf + n;
201 if (len && gz_comp(state, Z_NO_FLUSH) == -1)
206 /* consume whatever's left in the input buffer */
207 if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1)
210 /* directly compress user buffer to file */
211 strm->avail_in = len;
212 strm->next_in = (voidp)buf;
214 if (gz_comp(state, Z_NO_FLUSH) == -1)
218 /* input was all buffered or compressed (put will fit in int) */
222 /* -- see zlib.h -- */
223 int ZEXPORT gzputc(file, c)
227 unsigned char buf[1];
231 /* get internal structure */
234 state = (gz_statep)file;
235 strm = &(state->strm);
237 /* check that we're writing and that there's no error */
238 if (state->mode != GZ_WRITE || state->err != Z_OK)
241 /* check for seek request */
244 if (gz_zero(state, state->skip) == -1)
248 /* try writing to input buffer for speed (state->size == 0 if buffer not
250 if (strm->avail_in < state->size) {
251 if (strm->avail_in == 0)
252 strm->next_in = state->in;
253 strm->next_in[strm->avail_in++] = c;
258 /* no room in buffer or not initialized, use gz_write() */
260 if (gzwrite(file, buf, 1) != 1)
265 /* -- see zlib.h -- */
266 int ZEXPORT gzputs(file, str)
275 ret = gzwrite(file, str, len);
276 return ret == 0 && len != 0 ? -1 : ret;
282 /* -- see zlib.h -- */
283 int ZEXPORTVA gzprintf (gzFile file, const char *format, ...)
290 /* get internal structure */
293 state = (gz_statep)file;
294 strm = &(state->strm);
296 /* check that we're writing and that there's no error */
297 if (state->mode != GZ_WRITE || state->err != Z_OK)
300 /* make sure we have some buffer space */
301 if (state->size == 0 && gz_init(state) == -1)
304 /* check for seek request */
307 if (gz_zero(state, state->skip) == -1)
311 /* consume whatever's left in the input buffer */
312 if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1)
315 /* do the printf() into the input buffer, put length in len */
316 size = (int)(state->size);
317 state->in[size - 1] = 0;
318 va_start(va, format);
320 # ifdef HAS_vsprintf_void
321 (void)vsprintf(state->in, format, va);
323 for (len = 0; len < state->in; len++)
324 if (state->in[len] == 0) break;
326 len = vsprintf(state->in, format, va);
330 # ifdef HAS_vsnprintf_void
331 (void)vsnprintf(state->in, size, format, va);
333 len = strlen(state->in);
335 len = vsnprintf((char *)(state->in), size, format, va);
340 /* check that printf() results fit in buffer */
341 if (len <= 0 || len >= (int)size || state->in[size - 1] != 0)
344 /* update buffer and position, defer compression until needed */
345 strm->avail_in = (unsigned)len;
346 strm->next_in = state->in;
353 /* -- see zlib.h -- */
354 int ZEXPORTVA gzprintf (file, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10,
355 a11, a12, a13, a14, a15, a16, a17, a18, a19, a20)
358 int a1, a2, a3, a4, a5, a6, a7, a8, a9, a10,
359 a11, a12, a13, a14, a15, a16, a17, a18, a19, a20;
365 /* get internal structure */
368 state = (gz_statep)file;
369 strm = &(state->strm);
371 /* check that we're writing and that there's no error */
372 if (state->mode != GZ_WRITE || state->err != Z_OK)
375 /* make sure we have some buffer space */
376 if (state->size == 0 && gz_init(state) == -1)
379 /* check for seek request */
382 if (gz_zero(state, state->skip) == -1)
386 /* consume whatever's left in the input buffer */
387 if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1)
390 /* do the printf() into the input buffer, put length in len */
391 size = (int)(state->size);
392 state->in[size - 1] = 0;
394 # ifdef HAS_sprintf_void
395 sprintf(state->in, format, a1, a2, a3, a4, a5, a6, a7, a8,
396 a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20);
397 for (len = 0; len < size; len++)
398 if (state->in[len] == 0) break;
400 len = sprintf(state->in, format, a1, a2, a3, a4, a5, a6, a7, a8,
401 a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20);
404 # ifdef HAS_snprintf_void
405 snprintf(state->in, size, format, a1, a2, a3, a4, a5, a6, a7, a8,
406 a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20);
407 len = strlen(state->in);
409 len = snprintf(state->in, size, format, a1, a2, a3, a4, a5, a6, a7, a8,
410 a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20);
414 /* check that printf() results fit in buffer */
415 if (len <= 0 || len >= (int)size || state->in[size - 1] != 0)
418 /* update buffer and position, defer compression until needed */
419 strm->avail_in = (unsigned)len;
420 strm->next_in = state->in;
427 /* -- see zlib.h -- */
428 int ZEXPORT gzflush(file, flush)
434 /* get internal structure */
437 state = (gz_statep)file;
439 /* check that we're writing and that there's no error */
440 if (state->mode != GZ_WRITE || state->err != Z_OK)
441 return Z_STREAM_ERROR;
443 /* check flush parameter */
444 if (flush < 0 || flush > Z_FINISH)
445 return Z_STREAM_ERROR;
447 /* check for seek request */
450 if (gz_zero(state, state->skip) == -1)
454 /* compress remaining data with requested flush */
455 gz_comp(state, flush);
459 /* -- see zlib.h -- */
460 int ZEXPORT gzsetparams(file, level, strategy)
468 /* get internal structure */
470 return Z_STREAM_ERROR;
471 state = (gz_statep)file;
472 strm = &(state->strm);
474 /* check that we're writing and that there's no error */
475 if (state->mode != GZ_WRITE || state->err != Z_OK)
476 return Z_STREAM_ERROR;
478 /* if no change is requested, then do nothing */
479 if (level == state->level && strategy == state->strategy)
482 /* check for seek request */
485 if (gz_zero(state, state->skip) == -1)
489 /* change compression parameters for subsequent input */
491 /* flush previous input with previous parameters before changing */
492 if (strm->avail_in && gz_comp(state, Z_PARTIAL_FLUSH) == -1)
494 deflateParams(strm, level, strategy);
496 state->level = level;
497 state->strategy = strategy;
501 /* -- see zlib.h -- */
502 int ZEXPORT gzclose_w(file)
508 /* get internal structure */
510 return Z_STREAM_ERROR;
511 state = (gz_statep)file;
513 /* check that we're writing */
514 if (state->mode != GZ_WRITE)
515 return Z_STREAM_ERROR;
517 /* check for seek request */
520 ret += gz_zero(state, state->skip);
523 /* flush, free memory, and close file */
524 ret += gz_comp(state, Z_FINISH);
525 (void)deflateEnd(&(state->strm));
528 ret += close(state->fd);
529 gz_error(state, Z_OK, NULL);
531 return ret ? Z_ERRNO : Z_OK;
534 #endif /* !OLD_GZIO */