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 a memory allocation failure, or 0 on
16 local int gz_init(state)
20 z_streamp strm = &(state->strm);
22 /* allocate input buffer (double size for gzprintf) */
23 state->in = (unsigned char *)malloc(state->want << 1);
24 if (state->in == NULL) {
25 gz_error(state, Z_MEM_ERROR, "out of memory");
29 /* only need output buffer and deflate state if compressing */
31 /* allocate output buffer */
32 state->out = (unsigned char *)malloc(state->want);
33 if (state->out == NULL) {
35 gz_error(state, Z_MEM_ERROR, "out of memory");
39 /* allocate deflate memory, set up for gzip compression */
40 strm->zalloc = Z_NULL;
42 strm->opaque = Z_NULL;
43 ret = deflateInit2(strm, state->level, Z_DEFLATED,
44 MAX_WBITS + 16, DEF_MEM_LEVEL, state->strategy);
48 gz_error(state, Z_MEM_ERROR, "out of memory");
54 /* mark state as initialized */
55 state->size = state->want;
57 /* initialize write buffer if compressing */
59 strm->avail_out = state->size;
60 strm->next_out = state->out;
61 state->x.next = strm->next_out;
66 /* Compress whatever is at avail_in and next_in and write to the output file.
67 Return -1 if there is an error writing to the output file or if gz_init()
68 fails to allocate memory, otherwise 0. flush is assumed to be a valid
69 deflate() flush value. If flush is Z_FINISH, then the deflate() state is
70 reset to start a new gzip stream. If gz->direct is true, then simply write
71 to the output file without compressing, and ignore flush. */
72 local int gz_comp(state, flush)
79 z_streamp strm = &(state->strm);
81 /* allocate memory if this is the first time through */
82 if (state->size == 0 && gz_init(state) == -1)
85 /* write directly if requested */
87 while (strm->avail_in) {
88 got = write(state->fd, strm->next_in, strm->avail_in);
90 gz_error(state, Z_ERRNO, zstrerror());
93 strm->avail_in -= (unsigned)got;
99 /* run deflate() on provided input until it produces no more output */
102 /* write out current buffer contents if full, or if flushing, but if
103 doing Z_FINISH then don't write until we get to Z_STREAM_END */
104 if (strm->avail_out == 0 || (flush != Z_NO_FLUSH &&
105 (flush != Z_FINISH || ret == Z_STREAM_END))) {
106 while (strm->next_out > state->x.next) {
107 got = write(state->fd, state->x.next,
108 (unsigned long)(strm->next_out - state->x.next));
110 gz_error(state, Z_ERRNO, zstrerror());
113 state->x.next += got;
115 if (strm->avail_out == 0) {
116 strm->avail_out = state->size;
117 strm->next_out = state->out;
122 have = strm->avail_out;
123 ret = deflate(strm, flush);
124 if (ret == Z_STREAM_ERROR) {
125 gz_error(state, Z_STREAM_ERROR,
126 "internal error: deflate stream corrupt");
129 have -= strm->avail_out;
132 /* if that completed a deflate stream, allow another to start */
133 if (flush == Z_FINISH)
136 /* all done, no errors */
140 /* Compress len zeros to output. Return -1 on a write error or memory
141 allocation failure by gz_comp(), or 0 on success. */
142 local int gz_zero(state, len)
148 z_streamp strm = &(state->strm);
150 /* consume whatever's left in the input buffer */
151 if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1)
154 /* compress len zeros (len guaranteed > 0) */
157 n = GT_OFF(state->size) || (z_off64_t)state->size > len ?
158 (unsigned)len : state->size;
160 memset(state->in, 0, n);
164 strm->next_in = state->in;
166 if (gz_comp(state, Z_NO_FLUSH) == -1)
173 /* -- see zlib.h -- */
174 int ZEXPORT gzwrite(file, buf, len)
183 /* get internal structure */
186 state = (gz_statep)file;
187 strm = &(state->strm);
189 /* check that we're writing and that there's no error */
190 if (state->mode != GZ_WRITE || state->err != Z_OK)
193 /* since an int is returned, make sure len fits in one, otherwise return
194 with an error (this avoids the flaw in the interface) */
196 gz_error(state, Z_DATA_ERROR, "requested length does not fit in int");
200 /* if len is zero, avoid unnecessary operations */
204 /* allocate memory if this is the first time through */
205 if (state->size == 0 && gz_init(state) == -1)
208 /* check for seek request */
211 if (gz_zero(state, state->skip) == -1)
215 /* for small len, copy to input buffer, otherwise compress directly */
216 if (len < state->size) {
217 /* copy to input buffer, compress when full */
221 if (strm->avail_in == 0)
222 strm->next_in = state->in;
223 have = (unsigned)((strm->next_in + strm->avail_in) - state->in);
224 copy = state->size - have;
227 memcpy(state->in + have, buf, copy);
228 strm->avail_in += copy;
229 state->x.pos += copy;
230 buf = (const char *)buf + copy;
232 if (len && gz_comp(state, Z_NO_FLUSH) == -1)
237 /* consume whatever's left in the input buffer */
238 if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1)
241 /* directly compress user buffer to file */
242 strm->avail_in = len;
243 strm->next_in = (z_const Bytef *)buf;
245 if (gz_comp(state, Z_NO_FLUSH) == -1)
249 /* input was all buffered or compressed (put will fit in int) */
253 /* -- see zlib.h -- */
254 int ZEXPORT gzputc(file, c)
259 unsigned char buf[1];
263 /* get internal structure */
266 state = (gz_statep)file;
267 strm = &(state->strm);
269 /* check that we're writing and that there's no error */
270 if (state->mode != GZ_WRITE || state->err != Z_OK)
273 /* check for seek request */
276 if (gz_zero(state, state->skip) == -1)
280 /* try writing to input buffer for speed (state->size == 0 if buffer not
283 if (strm->avail_in == 0)
284 strm->next_in = state->in;
285 have = (unsigned)((strm->next_in + strm->avail_in) - state->in);
286 if (have < state->size) {
287 state->in[have] = (unsigned char)c;
294 /* no room in buffer or not initialized, use gz_write() */
295 buf[0] = (unsigned char)c;
296 if (gzwrite(file, buf, 1) != 1)
301 /* -- see zlib.h -- */
302 int ZEXPORT gzputs(file, str)
310 len = (unsigned)strlen(str);
311 ret = gzwrite(file, str, len);
312 return ret == 0 && len != 0 ? -1 : ret;
315 #if defined(STDC) || defined(Z_HAVE_STDARG_H)
318 /* -- see zlib.h -- */
319 int ZEXPORTVA gzvprintf(gzFile file, const char *format, va_list va)
327 /* get internal structure */
329 return Z_STREAM_ERROR;
330 state = (gz_statep)file;
331 strm = &(state->strm);
333 /* check that we're writing and that there's no error */
334 if (state->mode != GZ_WRITE || state->err != Z_OK)
335 return Z_STREAM_ERROR;
337 /* make sure we have some buffer space */
338 if (state->size == 0 && gz_init(state) == -1)
341 /* check for seek request */
344 if (gz_zero(state, state->skip) == -1)
348 /* do the printf() into the input buffer, put length in len -- the input
349 buffer is double-sized just for this function, so there is guaranteed to
350 be state->size bytes available after the current contents */
351 if (strm->avail_in == 0)
352 strm->next_in = state->in;
353 next = (char *)(state->in + (strm->next_in - state->in) + strm->avail_in);
354 next[state->size - 1] = 0;
356 # ifdef HAS_vsprintf_void
357 (void)vsprintf(next, format, va);
358 for (len = 0; len < state->size; len++)
359 if (next[len] == 0) break;
361 len = vsprintf(next, format, va);
364 # ifdef HAS_vsnprintf_void
365 (void)vsnprintf(next, state->size, format, va);
368 len = vsnprintf(next, state->size, format, va);
372 /* check that printf() results fit in buffer */
373 if (len == 0 || (unsigned)len >= state->size || next[state->size - 1] != 0)
376 /* update buffer and position, compress first half if past that */
377 strm->avail_in += (unsigned)len;
379 if (strm->avail_in >= state->size) {
380 left = strm->avail_in - state->size;
381 strm->avail_in = state->size;
382 if (gz_comp(state, Z_NO_FLUSH) == -1)
384 memcpy(state->in, state->in + state->size, left);
385 strm->next_in = state->in;
386 strm->avail_in = left;
391 int ZEXPORTVA gzprintf(gzFile file, const char *format, ...)
396 va_start(va, format);
397 ret = gzvprintf(file, format, va);
402 #else /* !STDC && !Z_HAVE_STDARG_H */
404 /* -- see zlib.h -- */
405 int ZEXPORTVA gzprintf (file, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10,
406 a11, a12, a13, a14, a15, a16, a17, a18, a19, a20)
409 int a1, a2, a3, a4, a5, a6, a7, a8, a9, a10,
410 a11, a12, a13, a14, a15, a16, a17, a18, a19, a20;
417 /* get internal structure */
419 return Z_STREAM_ERROR;
420 state = (gz_statep)file;
421 strm = &(state->strm);
423 /* check that can really pass pointer in ints */
424 if (sizeof(int) != sizeof(void *))
425 return Z_STREAM_ERROR;
427 /* check that we're writing and that there's no error */
428 if (state->mode != GZ_WRITE || state->err != Z_OK)
429 return Z_STREAM_ERROR;
431 /* make sure we have some buffer space */
432 if (state->size == 0 && gz_init(state) == -1)
435 /* check for seek request */
438 if (gz_zero(state, state->skip) == -1)
442 /* do the printf() into the input buffer, put length in len -- the input
443 buffer is double-sized just for this function, so there is guaranteed to
444 be state->size bytes available after the current contents */
445 if (strm->avail_in == 0)
446 strm->next_in = state->in;
447 next = (char *)(strm->next_in + strm->avail_in);
448 next[state->size - 1] = 0;
450 # ifdef HAS_sprintf_void
451 sprintf(next, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12,
452 a13, a14, a15, a16, a17, a18, a19, a20);
453 for (len = 0; len < size; len++)
457 len = sprintf(next, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11,
458 a12, a13, a14, a15, a16, a17, a18, a19, a20);
461 # ifdef HAS_snprintf_void
462 snprintf(next, state->size, format, a1, a2, a3, a4, a5, a6, a7, a8, a9,
463 a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20);
466 len = snprintf(next, state->size, format, a1, a2, a3, a4, a5, a6, a7, a8,
467 a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20);
471 /* check that printf() results fit in buffer */
472 if (len == 0 || len >= state->size || next[state->size - 1] != 0)
475 /* update buffer and position, compress first half if past that */
476 strm->avail_in += len;
478 if (strm->avail_in >= state->size) {
479 left = strm->avail_in - state->size;
480 strm->avail_in = state->size;
481 if (gz_comp(state, Z_NO_FLUSH) == -1)
483 memcpy(state->in, state->in + state->size, left);
484 strm->next_in = state->in;
485 strm->avail_in = left;
492 /* -- see zlib.h -- */
493 int ZEXPORT gzflush(file, flush)
499 /* get internal structure */
501 return Z_STREAM_ERROR;
502 state = (gz_statep)file;
504 /* check that we're writing and that there's no error */
505 if (state->mode != GZ_WRITE || state->err != Z_OK)
506 return Z_STREAM_ERROR;
508 /* check flush parameter */
509 if (flush < 0 || flush > Z_FINISH)
510 return Z_STREAM_ERROR;
512 /* check for seek request */
515 if (gz_zero(state, state->skip) == -1)
519 /* compress remaining data with requested flush */
520 (void)gz_comp(state, flush);
524 /* -- see zlib.h -- */
525 int ZEXPORT gzsetparams(file, level, strategy)
533 /* get internal structure */
535 return Z_STREAM_ERROR;
536 state = (gz_statep)file;
537 strm = &(state->strm);
539 /* check that we're writing and that there's no error */
540 if (state->mode != GZ_WRITE || state->err != Z_OK)
541 return Z_STREAM_ERROR;
543 /* if no change is requested, then do nothing */
544 if (level == state->level && strategy == state->strategy)
547 /* check for seek request */
550 if (gz_zero(state, state->skip) == -1)
554 /* change compression parameters for subsequent input */
556 /* flush previous input with previous parameters before changing */
557 if (strm->avail_in && gz_comp(state, Z_BLOCK) == -1)
559 deflateParams(strm, level, strategy);
561 state->level = level;
562 state->strategy = strategy;
566 /* -- see zlib.h -- */
567 int ZEXPORT gzclose_w(file)
573 /* get internal structure */
575 return Z_STREAM_ERROR;
576 state = (gz_statep)file;
578 /* check that we're writing */
579 if (state->mode != GZ_WRITE)
580 return Z_STREAM_ERROR;
582 /* check for seek request */
585 if (gz_zero(state, state->skip) == -1)
589 /* flush, free memory, and close file */
590 if (gz_comp(state, Z_FINISH) == -1)
593 if (!state->direct) {
594 (void)deflateEnd(&(state->strm));
599 gz_error(state, Z_OK, NULL);
601 if (close(state->fd) == -1)