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));
12 local z_size_t gz_write OF((gz_statep, voidpc, z_size_t));
14 /* Initialize state for writing a gzip file. Mark initialization by setting
15 state->size to non-zero. Return -1 on a memory allocation failure, or 0 on
17 local int gz_init(state)
21 z_streamp strm = &(state->strm);
23 /* allocate input buffer (double size for gzprintf) */
24 state->in = (unsigned char *)malloc(state->want << 1);
25 if (state->in == NULL) {
26 gz_error(state, Z_MEM_ERROR, "out of memory");
30 /* only need output buffer and deflate state if compressing */
32 /* allocate output buffer */
33 state->out = (unsigned char *)malloc(state->want);
34 if (state->out == NULL) {
36 gz_error(state, Z_MEM_ERROR, "out of memory");
40 /* allocate deflate memory, set up for gzip compression */
41 strm->zalloc = Z_NULL;
43 strm->opaque = Z_NULL;
44 ret = deflateInit2(strm, state->level, Z_DEFLATED,
45 MAX_WBITS + 16, DEF_MEM_LEVEL, state->strategy);
49 gz_error(state, Z_MEM_ERROR, "out of memory");
55 /* mark state as initialized */
56 state->size = state->want;
58 /* initialize write buffer if compressing */
60 strm->avail_out = state->size;
61 strm->next_out = state->out;
62 state->x.next = strm->next_out;
67 /* Compress whatever is at avail_in and next_in and write to the output file.
68 Return -1 if there is an error writing to the output file or if gz_init()
69 fails to allocate memory, otherwise 0. flush is assumed to be a valid
70 deflate() flush value. If flush is Z_FINISH, then the deflate() state is
71 reset to start a new gzip stream. If gz->direct is true, then simply write
72 to the output file without compressing, and ignore flush. */
73 local int gz_comp(state, flush)
80 z_streamp strm = &(state->strm);
82 /* allocate memory if this is the first time through */
83 if (state->size == 0 && gz_init(state) == -1)
86 /* write directly if requested */
88 while (strm->avail_in) {
89 got = write(state->fd, strm->next_in, strm->avail_in);
91 gz_error(state, Z_ERRNO, zstrerror());
94 strm->avail_in -= (unsigned)got;
100 /* run deflate() on provided input until it produces no more output */
103 /* write out current buffer contents if full, or if flushing, but if
104 doing Z_FINISH then don't write until we get to Z_STREAM_END */
105 if (strm->avail_out == 0 || (flush != Z_NO_FLUSH &&
106 (flush != Z_FINISH || ret == Z_STREAM_END))) {
107 while (strm->next_out > state->x.next) {
108 got = write(state->fd, state->x.next,
109 (unsigned long)(strm->next_out - state->x.next));
111 gz_error(state, Z_ERRNO, zstrerror());
114 state->x.next += got;
116 if (strm->avail_out == 0) {
117 strm->avail_out = state->size;
118 strm->next_out = state->out;
123 have = strm->avail_out;
124 ret = deflate(strm, flush);
125 if (ret == Z_STREAM_ERROR) {
126 gz_error(state, Z_STREAM_ERROR,
127 "internal error: deflate stream corrupt");
130 have -= strm->avail_out;
133 /* if that completed a deflate stream, allow another to start */
134 if (flush == Z_FINISH)
137 /* all done, no errors */
141 /* Compress len zeros to output. Return -1 on a write error or memory
142 allocation failure by gz_comp(), or 0 on success. */
143 local int gz_zero(state, len)
149 z_streamp strm = &(state->strm);
151 /* consume whatever's left in the input buffer */
152 if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1)
155 /* compress len zeros (len guaranteed > 0) */
158 n = GT_OFF(state->size) || (z_off64_t)state->size > len ?
159 (unsigned)len : state->size;
161 memset(state->in, 0, n);
165 strm->next_in = state->in;
167 if (gz_comp(state, Z_NO_FLUSH) == -1)
174 /* Write len bytes from buf to file. Return the number of bytes written. If
175 the returned value is less than len, then there was an error. */
176 local z_size_t gz_write(state, buf, len)
183 /* if len is zero, avoid unnecessary operations */
187 /* allocate memory if this is the first time through */
188 if (state->size == 0 && gz_init(state) == -1)
191 /* check for seek request */
194 if (gz_zero(state, state->skip) == -1)
198 /* for small len, copy to input buffer, otherwise compress directly */
199 if (len < state->size) {
200 /* copy to input buffer, compress when full */
204 if (state->strm.avail_in == 0)
205 state->strm.next_in = state->in;
206 have = (unsigned)((state->strm.next_in + state->strm.avail_in) -
208 copy = state->size - have;
211 memcpy(state->in + have, buf, copy);
212 state->strm.avail_in += copy;
213 state->x.pos += copy;
214 buf = (const char *)buf + copy;
216 if (len && gz_comp(state, Z_NO_FLUSH) == -1)
221 /* consume whatever's left in the input buffer */
222 if (state->strm.avail_in && gz_comp(state, Z_NO_FLUSH) == -1)
225 /* directly compress user buffer to file */
226 state->strm.next_in = (z_const Bytef *)buf;
231 state->strm.avail_in = n;
233 if (gz_comp(state, Z_NO_FLUSH) == -1)
239 /* input was all buffered or compressed */
243 /* -- see zlib.h -- */
244 int ZEXPORT gzwrite(file, buf, len)
251 /* get internal structure */
254 state = (gz_statep)file;
256 /* check that we're writing and that there's no error */
257 if (state->mode != GZ_WRITE || state->err != Z_OK)
260 /* since an int is returned, make sure len fits in one, otherwise return
261 with an error (this avoids a flaw in the interface) */
263 gz_error(state, Z_DATA_ERROR, "requested length does not fit in int");
267 /* write len bytes from buf (the return value will fit in an int) */
268 return (int)gz_write(state, buf, len);
271 /* -- see zlib.h -- */
272 z_size_t ZEXPORT gzfwrite(buf, size, nitems, file)
281 /* get internal structure */
284 state = (gz_statep)file;
286 /* check that we're writing and that there's no error */
287 if (state->mode != GZ_WRITE || state->err != Z_OK)
290 /* compute bytes to read -- error on overflow */
292 if (size && len / size != nitems) {
293 gz_error(state, Z_STREAM_ERROR, "request does not fit in a size_t");
297 /* write len bytes to buf, return the number of full items written */
298 return len ? gz_write(state, buf, len) / size : 0;
301 /* -- see zlib.h -- */
302 int ZEXPORT gzputc(file, c)
307 unsigned char buf[1];
311 /* get internal structure */
314 state = (gz_statep)file;
315 strm = &(state->strm);
317 /* check that we're writing and that there's no error */
318 if (state->mode != GZ_WRITE || state->err != Z_OK)
321 /* check for seek request */
324 if (gz_zero(state, state->skip) == -1)
328 /* try writing to input buffer for speed (state->size == 0 if buffer not
331 if (strm->avail_in == 0)
332 strm->next_in = state->in;
333 have = (unsigned)((strm->next_in + strm->avail_in) - state->in);
334 if (have < state->size) {
335 state->in[have] = (unsigned char)c;
342 /* no room in buffer or not initialized, use gz_write() */
343 buf[0] = (unsigned char)c;
344 if (gz_write(state, buf, 1) != 1)
349 /* -- see zlib.h -- */
350 int ZEXPORT gzputs(file, str)
358 /* get internal structure */
361 state = (gz_statep)file;
363 /* check that we're writing and that there's no error */
364 if (state->mode != GZ_WRITE || state->err != Z_OK)
369 ret = gz_write(state, str, len);
370 return ret == 0 && len != 0 ? -1 : ret;
373 #if defined(STDC) || defined(Z_HAVE_STDARG_H)
376 /* -- see zlib.h -- */
377 int ZEXPORTVA gzvprintf(gzFile file, const char *format, va_list va)
385 /* get internal structure */
387 return Z_STREAM_ERROR;
388 state = (gz_statep)file;
389 strm = &(state->strm);
391 /* check that we're writing and that there's no error */
392 if (state->mode != GZ_WRITE || state->err != Z_OK)
393 return Z_STREAM_ERROR;
395 /* make sure we have some buffer space */
396 if (state->size == 0 && gz_init(state) == -1)
399 /* check for seek request */
402 if (gz_zero(state, state->skip) == -1)
406 /* do the printf() into the input buffer, put length in len -- the input
407 buffer is double-sized just for this function, so there is guaranteed to
408 be state->size bytes available after the current contents */
409 if (strm->avail_in == 0)
410 strm->next_in = state->in;
411 next = (char *)(state->in + (strm->next_in - state->in) + strm->avail_in);
412 next[state->size - 1] = 0;
414 # ifdef HAS_vsprintf_void
415 (void)vsprintf(next, format, va);
416 for (len = 0; len < state->size; len++)
417 if (next[len] == 0) break;
419 len = vsprintf(next, format, va);
422 # ifdef HAS_vsnprintf_void
423 (void)vsnprintf(next, state->size, format, va);
426 len = vsnprintf(next, state->size, format, va);
430 /* check that printf() results fit in buffer */
431 if (len == 0 || (unsigned)len >= state->size || next[state->size - 1] != 0)
434 /* update buffer and position, compress first half if past that */
435 strm->avail_in += (unsigned)len;
437 if (strm->avail_in >= state->size) {
438 left = strm->avail_in - state->size;
439 strm->avail_in = state->size;
440 if (gz_comp(state, Z_NO_FLUSH) == -1)
442 memcpy(state->in, state->in + state->size, left);
443 strm->next_in = state->in;
444 strm->avail_in = left;
449 int ZEXPORTVA gzprintf(gzFile file, const char *format, ...)
454 va_start(va, format);
455 ret = gzvprintf(file, format, va);
460 #else /* !STDC && !Z_HAVE_STDARG_H */
462 /* -- see zlib.h -- */
463 int ZEXPORTVA gzprintf (file, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10,
464 a11, a12, a13, a14, a15, a16, a17, a18, a19, a20)
467 int a1, a2, a3, a4, a5, a6, a7, a8, a9, a10,
468 a11, a12, a13, a14, a15, a16, a17, a18, a19, a20;
475 /* get internal structure */
477 return Z_STREAM_ERROR;
478 state = (gz_statep)file;
479 strm = &(state->strm);
481 /* check that can really pass pointer in ints */
482 if (sizeof(int) != sizeof(void *))
483 return Z_STREAM_ERROR;
485 /* check that we're writing and that there's no error */
486 if (state->mode != GZ_WRITE || state->err != Z_OK)
487 return Z_STREAM_ERROR;
489 /* make sure we have some buffer space */
490 if (state->size == 0 && gz_init(state) == -1)
493 /* check for seek request */
496 if (gz_zero(state, state->skip) == -1)
500 /* do the printf() into the input buffer, put length in len -- the input
501 buffer is double-sized just for this function, so there is guaranteed to
502 be state->size bytes available after the current contents */
503 if (strm->avail_in == 0)
504 strm->next_in = state->in;
505 next = (char *)(strm->next_in + strm->avail_in);
506 next[state->size - 1] = 0;
508 # ifdef HAS_sprintf_void
509 sprintf(next, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12,
510 a13, a14, a15, a16, a17, a18, a19, a20);
511 for (len = 0; len < size; len++)
515 len = sprintf(next, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11,
516 a12, a13, a14, a15, a16, a17, a18, a19, a20);
519 # ifdef HAS_snprintf_void
520 snprintf(next, state->size, format, a1, a2, a3, a4, a5, a6, a7, a8, a9,
521 a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20);
524 len = snprintf(next, state->size, format, a1, a2, a3, a4, a5, a6, a7, a8,
525 a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20);
529 /* check that printf() results fit in buffer */
530 if (len == 0 || len >= state->size || next[state->size - 1] != 0)
533 /* update buffer and position, compress first half if past that */
534 strm->avail_in += len;
536 if (strm->avail_in >= state->size) {
537 left = strm->avail_in - state->size;
538 strm->avail_in = state->size;
539 if (gz_comp(state, Z_NO_FLUSH) == -1)
541 memcpy(state->in, state->in + state->size, left);
542 strm->next_in = state->in;
543 strm->avail_in = left;
550 /* -- see zlib.h -- */
551 int ZEXPORT gzflush(file, flush)
557 /* get internal structure */
559 return Z_STREAM_ERROR;
560 state = (gz_statep)file;
562 /* check that we're writing and that there's no error */
563 if (state->mode != GZ_WRITE || state->err != Z_OK)
564 return Z_STREAM_ERROR;
566 /* check flush parameter */
567 if (flush < 0 || flush > Z_FINISH)
568 return Z_STREAM_ERROR;
570 /* check for seek request */
573 if (gz_zero(state, state->skip) == -1)
577 /* compress remaining data with requested flush */
578 (void)gz_comp(state, flush);
582 /* -- see zlib.h -- */
583 int ZEXPORT gzsetparams(file, level, strategy)
591 /* get internal structure */
593 return Z_STREAM_ERROR;
594 state = (gz_statep)file;
595 strm = &(state->strm);
597 /* check that we're writing and that there's no error */
598 if (state->mode != GZ_WRITE || state->err != Z_OK)
599 return Z_STREAM_ERROR;
601 /* if no change is requested, then do nothing */
602 if (level == state->level && strategy == state->strategy)
605 /* check for seek request */
608 if (gz_zero(state, state->skip) == -1)
612 /* change compression parameters for subsequent input */
614 /* flush previous input with previous parameters before changing */
615 if (strm->avail_in && gz_comp(state, Z_BLOCK) == -1)
617 deflateParams(strm, level, strategy);
619 state->level = level;
620 state->strategy = strategy;
624 /* -- see zlib.h -- */
625 int ZEXPORT gzclose_w(file)
631 /* get internal structure */
633 return Z_STREAM_ERROR;
634 state = (gz_statep)file;
636 /* check that we're writing */
637 if (state->mode != GZ_WRITE)
638 return Z_STREAM_ERROR;
640 /* check for seek request */
643 if (gz_zero(state, state->skip) == -1)
647 /* flush, free memory, and close file */
648 if (gz_comp(state, Z_FINISH) == -1)
651 if (!state->direct) {
652 (void)deflateEnd(&(state->strm));
657 gz_error(state, Z_OK, NULL);
659 if (close(state->fd) == -1)