1 /* gzwrite.c -- zlib functions for writing gzip files
2 * Copyright (C) 2004, 2005, 2010, 2011, 2012, 2013, 2016 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)
78 unsigned have, put, max = ((unsigned)-1 >> 2) + 1;
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 put = strm->avail_in > max ? max : strm->avail_in;
89 writ = write(state->fd, strm->next_in, put);
91 gz_error(state, Z_ERRNO, zstrerror());
94 strm->avail_in -= (unsigned)writ;
95 strm->next_in += writ;
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 put = strm->next_out - state->x.next > (int)max ? max :
109 (unsigned)(strm->next_out - state->x.next);
110 writ = write(state->fd, state->x.next, put);
112 gz_error(state, Z_ERRNO, zstrerror());
115 state->x.next += writ;
117 if (strm->avail_out == 0) {
118 strm->avail_out = state->size;
119 strm->next_out = state->out;
124 have = strm->avail_out;
125 ret = deflate(strm, flush);
126 if (ret == Z_STREAM_ERROR) {
127 gz_error(state, Z_STREAM_ERROR,
128 "internal error: deflate stream corrupt");
131 have -= strm->avail_out;
134 /* if that completed a deflate stream, allow another to start */
135 if (flush == Z_FINISH)
138 /* all done, no errors */
142 /* Compress len zeros to output. Return -1 on a write error or memory
143 allocation failure by gz_comp(), or 0 on success. */
144 local int gz_zero(state, len)
150 z_streamp strm = &(state->strm);
152 /* consume whatever's left in the input buffer */
153 if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1)
156 /* compress len zeros (len guaranteed > 0) */
159 n = GT_OFF(state->size) || (z_off64_t)state->size > len ?
160 (unsigned)len : state->size;
162 memset(state->in, 0, n);
166 strm->next_in = state->in;
168 if (gz_comp(state, Z_NO_FLUSH) == -1)
175 /* Write len bytes from buf to file. Return the number of bytes written. If
176 the returned value is less than len, then there was an error. */
177 local z_size_t gz_write(state, buf, len)
184 /* if len is zero, avoid unnecessary operations */
188 /* allocate memory if this is the first time through */
189 if (state->size == 0 && gz_init(state) == -1)
192 /* check for seek request */
195 if (gz_zero(state, state->skip) == -1)
199 /* for small len, copy to input buffer, otherwise compress directly */
200 if (len < state->size) {
201 /* copy to input buffer, compress when full */
205 if (state->strm.avail_in == 0)
206 state->strm.next_in = state->in;
207 have = (unsigned)((state->strm.next_in + state->strm.avail_in) -
209 copy = state->size - have;
212 memcpy(state->in + have, buf, copy);
213 state->strm.avail_in += copy;
214 state->x.pos += copy;
215 buf = (const char *)buf + copy;
217 if (len && gz_comp(state, Z_NO_FLUSH) == -1)
222 /* consume whatever's left in the input buffer */
223 if (state->strm.avail_in && gz_comp(state, Z_NO_FLUSH) == -1)
226 /* directly compress user buffer to file */
227 state->strm.next_in = (z_const Bytef *)buf;
229 unsigned n = (unsigned)-1;
232 state->strm.avail_in = n;
234 if (gz_comp(state, Z_NO_FLUSH) == -1)
240 /* input was all buffered or compressed */
244 /* -- see zlib.h -- */
245 int ZEXPORT gzwrite(file, buf, len)
252 /* get internal structure */
255 state = (gz_statep)file;
257 /* check that we're writing and that there's no error */
258 if (state->mode != GZ_WRITE || state->err != Z_OK)
261 /* since an int is returned, make sure len fits in one, otherwise return
262 with an error (this avoids a flaw in the interface) */
264 gz_error(state, Z_DATA_ERROR, "requested length does not fit in int");
268 /* write len bytes from buf (the return value will fit in an int) */
269 return (int)gz_write(state, buf, len);
272 /* -- see zlib.h -- */
273 z_size_t ZEXPORT gzfwrite(buf, size, nitems, file)
282 /* get internal structure */
285 state = (gz_statep)file;
287 /* check that we're writing and that there's no error */
288 if (state->mode != GZ_WRITE || state->err != Z_OK)
291 /* compute bytes to read -- error on overflow */
293 if (size && len / size != nitems) {
294 gz_error(state, Z_STREAM_ERROR, "request does not fit in a size_t");
298 /* write len bytes to buf, return the number of full items written */
299 return len ? gz_write(state, buf, len) / size : 0;
302 /* -- see zlib.h -- */
303 int ZEXPORT gzputc(file, c)
308 unsigned char buf[1];
312 /* get internal structure */
315 state = (gz_statep)file;
316 strm = &(state->strm);
318 /* check that we're writing and that there's no error */
319 if (state->mode != GZ_WRITE || state->err != Z_OK)
322 /* check for seek request */
325 if (gz_zero(state, state->skip) == -1)
329 /* try writing to input buffer for speed (state->size == 0 if buffer not
332 if (strm->avail_in == 0)
333 strm->next_in = state->in;
334 have = (unsigned)((strm->next_in + strm->avail_in) - state->in);
335 if (have < state->size) {
336 state->in[have] = (unsigned char)c;
343 /* no room in buffer or not initialized, use gz_write() */
344 buf[0] = (unsigned char)c;
345 if (gz_write(state, buf, 1) != 1)
350 /* -- see zlib.h -- */
351 int ZEXPORT gzputs(file, str)
359 /* get internal structure */
362 state = (gz_statep)file;
364 /* check that we're writing and that there's no error */
365 if (state->mode != GZ_WRITE || state->err != Z_OK)
370 ret = gz_write(state, str, len);
371 return ret == 0 && len != 0 ? -1 : ret;
374 #if defined(STDC) || defined(Z_HAVE_STDARG_H)
377 /* -- see zlib.h -- */
378 int ZEXPORTVA gzvprintf(gzFile file, const char *format, va_list va)
386 /* get internal structure */
388 return Z_STREAM_ERROR;
389 state = (gz_statep)file;
390 strm = &(state->strm);
392 /* check that we're writing and that there's no error */
393 if (state->mode != GZ_WRITE || state->err != Z_OK)
394 return Z_STREAM_ERROR;
396 /* make sure we have some buffer space */
397 if (state->size == 0 && gz_init(state) == -1)
400 /* check for seek request */
403 if (gz_zero(state, state->skip) == -1)
407 /* do the printf() into the input buffer, put length in len -- the input
408 buffer is double-sized just for this function, so there is guaranteed to
409 be state->size bytes available after the current contents */
410 if (strm->avail_in == 0)
411 strm->next_in = state->in;
412 next = (char *)(state->in + (strm->next_in - state->in) + strm->avail_in);
413 next[state->size - 1] = 0;
415 # ifdef HAS_vsprintf_void
416 (void)vsprintf(next, format, va);
417 for (len = 0; len < state->size; len++)
418 if (next[len] == 0) break;
420 len = vsprintf(next, format, va);
423 # ifdef HAS_vsnprintf_void
424 (void)vsnprintf(next, state->size, format, va);
427 len = vsnprintf(next, state->size, format, va);
431 /* check that printf() results fit in buffer */
432 if (len == 0 || (unsigned)len >= state->size || next[state->size - 1] != 0)
435 /* update buffer and position, compress first half if past that */
436 strm->avail_in += (unsigned)len;
438 if (strm->avail_in >= state->size) {
439 left = strm->avail_in - state->size;
440 strm->avail_in = state->size;
441 if (gz_comp(state, Z_NO_FLUSH) == -1)
443 memcpy(state->in, state->in + state->size, left);
444 strm->next_in = state->in;
445 strm->avail_in = left;
450 int ZEXPORTVA gzprintf(gzFile file, const char *format, ...)
455 va_start(va, format);
456 ret = gzvprintf(file, format, va);
461 #else /* !STDC && !Z_HAVE_STDARG_H */
463 /* -- see zlib.h -- */
464 int ZEXPORTVA gzprintf (file, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10,
465 a11, a12, a13, a14, a15, a16, a17, a18, a19, a20)
468 int a1, a2, a3, a4, a5, a6, a7, a8, a9, a10,
469 a11, a12, a13, a14, a15, a16, a17, a18, a19, a20;
476 /* get internal structure */
478 return Z_STREAM_ERROR;
479 state = (gz_statep)file;
480 strm = &(state->strm);
482 /* check that can really pass pointer in ints */
483 if (sizeof(int) != sizeof(void *))
484 return Z_STREAM_ERROR;
486 /* check that we're writing and that there's no error */
487 if (state->mode != GZ_WRITE || state->err != Z_OK)
488 return Z_STREAM_ERROR;
490 /* make sure we have some buffer space */
491 if (state->size == 0 && gz_init(state) == -1)
494 /* check for seek request */
497 if (gz_zero(state, state->skip) == -1)
501 /* do the printf() into the input buffer, put length in len -- the input
502 buffer is double-sized just for this function, so there is guaranteed to
503 be state->size bytes available after the current contents */
504 if (strm->avail_in == 0)
505 strm->next_in = state->in;
506 next = (char *)(strm->next_in + strm->avail_in);
507 next[state->size - 1] = 0;
509 # ifdef HAS_sprintf_void
510 sprintf(next, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12,
511 a13, a14, a15, a16, a17, a18, a19, a20);
512 for (len = 0; len < size; len++)
516 len = sprintf(next, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11,
517 a12, a13, a14, a15, a16, a17, a18, a19, a20);
520 # ifdef HAS_snprintf_void
521 snprintf(next, state->size, format, a1, a2, a3, a4, a5, a6, a7, a8, a9,
522 a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20);
525 len = snprintf(next, state->size, format, a1, a2, a3, a4, a5, a6, a7, a8,
526 a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20);
530 /* check that printf() results fit in buffer */
531 if (len == 0 || len >= state->size || next[state->size - 1] != 0)
534 /* update buffer and position, compress first half if past that */
535 strm->avail_in += len;
537 if (strm->avail_in >= state->size) {
538 left = strm->avail_in - state->size;
539 strm->avail_in = state->size;
540 if (gz_comp(state, Z_NO_FLUSH) == -1)
542 memcpy(state->in, state->in + state->size, left);
543 strm->next_in = state->in;
544 strm->avail_in = left;
551 /* -- see zlib.h -- */
552 int ZEXPORT gzflush(file, flush)
558 /* get internal structure */
560 return Z_STREAM_ERROR;
561 state = (gz_statep)file;
563 /* check that we're writing and that there's no error */
564 if (state->mode != GZ_WRITE || state->err != Z_OK)
565 return Z_STREAM_ERROR;
567 /* check flush parameter */
568 if (flush < 0 || flush > Z_FINISH)
569 return Z_STREAM_ERROR;
571 /* check for seek request */
574 if (gz_zero(state, state->skip) == -1)
578 /* compress remaining data with requested flush */
579 (void)gz_comp(state, flush);
583 /* -- see zlib.h -- */
584 int ZEXPORT gzsetparams(file, level, strategy)
592 /* get internal structure */
594 return Z_STREAM_ERROR;
595 state = (gz_statep)file;
596 strm = &(state->strm);
598 /* check that we're writing and that there's no error */
599 if (state->mode != GZ_WRITE || state->err != Z_OK)
600 return Z_STREAM_ERROR;
602 /* if no change is requested, then do nothing */
603 if (level == state->level && strategy == state->strategy)
606 /* check for seek request */
609 if (gz_zero(state, state->skip) == -1)
613 /* change compression parameters for subsequent input */
615 /* flush previous input with previous parameters before changing */
616 if (strm->avail_in && gz_comp(state, Z_BLOCK) == -1)
618 deflateParams(strm, level, strategy);
620 state->level = level;
621 state->strategy = strategy;
625 /* -- see zlib.h -- */
626 int ZEXPORT gzclose_w(file)
632 /* get internal structure */
634 return Z_STREAM_ERROR;
635 state = (gz_statep)file;
637 /* check that we're writing */
638 if (state->mode != GZ_WRITE)
639 return Z_STREAM_ERROR;
641 /* check for seek request */
644 if (gz_zero(state, state->skip) == -1)
648 /* flush, free memory, and close file */
649 if (gz_comp(state, Z_FINISH) == -1)
652 if (!state->direct) {
653 (void)deflateEnd(&(state->strm));
658 gz_error(state, Z_OK, NULL);
660 if (close(state->fd) == -1)