1 /* gzwrite.c -- zlib functions for writing gzip files
2 * Copyright (C) 2004-2019 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 /* check for a pending reset */
102 /* don't start a new gzip member unless there is data to write */
103 if (strm->avail_in == 0)
109 /* run deflate() on provided input until it produces no more output */
112 /* write out current buffer contents if full, or if flushing, but if
113 doing Z_FINISH then don't write until we get to Z_STREAM_END */
114 if (strm->avail_out == 0 || (flush != Z_NO_FLUSH &&
115 (flush != Z_FINISH || ret == Z_STREAM_END))) {
116 while (strm->next_out > state->x.next) {
117 put = strm->next_out - state->x.next > (int)max ? max :
118 (unsigned)(strm->next_out - state->x.next);
119 writ = write(state->fd, state->x.next, put);
121 gz_error(state, Z_ERRNO, zstrerror());
124 state->x.next += writ;
126 if (strm->avail_out == 0) {
127 strm->avail_out = state->size;
128 strm->next_out = state->out;
129 state->x.next = state->out;
134 have = strm->avail_out;
135 ret = deflate(strm, flush);
136 if (ret == Z_STREAM_ERROR) {
137 gz_error(state, Z_STREAM_ERROR,
138 "internal error: deflate stream corrupt");
141 have -= strm->avail_out;
144 /* if that completed a deflate stream, allow another to start */
145 if (flush == Z_FINISH)
148 /* all done, no errors */
152 /* Compress len zeros to output. Return -1 on a write error or memory
153 allocation failure by gz_comp(), or 0 on success. */
154 local int gz_zero(state, len)
160 z_streamp strm = &(state->strm);
162 /* consume whatever's left in the input buffer */
163 if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1)
166 /* compress len zeros (len guaranteed > 0) */
169 n = GT_OFF(state->size) || (z_off64_t)state->size > len ?
170 (unsigned)len : state->size;
172 memset(state->in, 0, n);
176 strm->next_in = state->in;
178 if (gz_comp(state, Z_NO_FLUSH) == -1)
185 /* Write len bytes from buf to file. Return the number of bytes written. If
186 the returned value is less than len, then there was an error. */
187 local z_size_t gz_write(state, buf, len)
194 /* if len is zero, avoid unnecessary operations */
198 /* allocate memory if this is the first time through */
199 if (state->size == 0 && gz_init(state) == -1)
202 /* check for seek request */
205 if (gz_zero(state, state->skip) == -1)
209 /* for small len, copy to input buffer, otherwise compress directly */
210 if (len < state->size) {
211 /* copy to input buffer, compress when full */
215 if (state->strm.avail_in == 0)
216 state->strm.next_in = state->in;
217 have = (unsigned)((state->strm.next_in + state->strm.avail_in) -
219 copy = state->size - have;
221 copy = (unsigned)len;
222 memcpy(state->in + have, buf, copy);
223 state->strm.avail_in += copy;
224 state->x.pos += copy;
225 buf = (const char *)buf + copy;
227 if (len && gz_comp(state, Z_NO_FLUSH) == -1)
232 /* consume whatever's left in the input buffer */
233 if (state->strm.avail_in && gz_comp(state, Z_NO_FLUSH) == -1)
236 /* directly compress user buffer to file */
237 state->strm.next_in = (z_const Bytef *)buf;
239 unsigned n = (unsigned)-1;
242 state->strm.avail_in = n;
244 if (gz_comp(state, Z_NO_FLUSH) == -1)
250 /* input was all buffered or compressed */
254 /* -- see zlib.h -- */
255 int ZEXPORT gzwrite(file, buf, len)
262 /* get internal structure */
265 state = (gz_statep)file;
267 /* check that we're writing and that there's no error */
268 if (state->mode != GZ_WRITE || state->err != Z_OK)
271 /* since an int is returned, make sure len fits in one, otherwise return
272 with an error (this avoids a flaw in the interface) */
274 gz_error(state, Z_DATA_ERROR, "requested length does not fit in int");
278 /* write len bytes from buf (the return value will fit in an int) */
279 return (int)gz_write(state, buf, len);
282 /* -- see zlib.h -- */
283 z_size_t ZEXPORT gzfwrite(buf, size, nitems, file)
292 /* get internal structure */
295 state = (gz_statep)file;
297 /* check that we're writing and that there's no error */
298 if (state->mode != GZ_WRITE || state->err != Z_OK)
301 /* compute bytes to read -- error on overflow */
303 if (size && len / size != nitems) {
304 gz_error(state, Z_STREAM_ERROR, "request does not fit in a size_t");
308 /* write len bytes to buf, return the number of full items written */
309 return len ? gz_write(state, buf, len) / size : 0;
312 /* -- see zlib.h -- */
313 int ZEXPORT gzputc(file, c)
318 unsigned char buf[1];
322 /* get internal structure */
325 state = (gz_statep)file;
326 strm = &(state->strm);
328 /* check that we're writing and that there's no error */
329 if (state->mode != GZ_WRITE || state->err != Z_OK)
332 /* check for seek request */
335 if (gz_zero(state, state->skip) == -1)
339 /* try writing to input buffer for speed (state->size == 0 if buffer not
342 if (strm->avail_in == 0)
343 strm->next_in = state->in;
344 have = (unsigned)((strm->next_in + strm->avail_in) - state->in);
345 if (have < state->size) {
346 state->in[have] = (unsigned char)c;
353 /* no room in buffer or not initialized, use gz_write() */
354 buf[0] = (unsigned char)c;
355 if (gz_write(state, buf, 1) != 1)
360 /* -- see zlib.h -- */
361 int ZEXPORT gzputs(file, s)
368 /* get internal structure */
371 state = (gz_statep)file;
373 /* check that we're writing and that there's no error */
374 if (state->mode != GZ_WRITE || state->err != Z_OK)
379 if ((int)len < 0 || (unsigned)len != len) {
380 gz_error(state, Z_STREAM_ERROR, "string length does not fit in int");
383 put = gz_write(state, s, len);
384 return put < len ? -1 : (int)len;
387 #if defined(STDC) || defined(Z_HAVE_STDARG_H)
390 /* -- see zlib.h -- */
391 int ZEXPORTVA gzvprintf(gzFile file, const char *format, va_list va)
399 /* get internal structure */
401 return Z_STREAM_ERROR;
402 state = (gz_statep)file;
403 strm = &(state->strm);
405 /* check that we're writing and that there's no error */
406 if (state->mode != GZ_WRITE || state->err != Z_OK)
407 return Z_STREAM_ERROR;
409 /* make sure we have some buffer space */
410 if (state->size == 0 && gz_init(state) == -1)
413 /* check for seek request */
416 if (gz_zero(state, state->skip) == -1)
420 /* do the printf() into the input buffer, put length in len -- the input
421 buffer is double-sized just for this function, so there is guaranteed to
422 be state->size bytes available after the current contents */
423 if (strm->avail_in == 0)
424 strm->next_in = state->in;
425 next = (char *)(state->in + (strm->next_in - state->in) + strm->avail_in);
426 next[state->size - 1] = 0;
428 # ifdef HAS_vsprintf_void
429 (void)vsprintf(next, format, va);
430 for (len = 0; len < state->size; len++)
431 if (next[len] == 0) break;
433 len = vsprintf(next, format, va);
436 # ifdef HAS_vsnprintf_void
437 (void)vsnprintf(next, state->size, format, va);
440 len = vsnprintf(next, state->size, format, va);
444 /* check that printf() results fit in buffer */
445 if (len == 0 || (unsigned)len >= state->size || next[state->size - 1] != 0)
448 /* update buffer and position, compress first half if past that */
449 strm->avail_in += (unsigned)len;
451 if (strm->avail_in >= state->size) {
452 left = strm->avail_in - state->size;
453 strm->avail_in = state->size;
454 if (gz_comp(state, Z_NO_FLUSH) == -1)
456 memmove(state->in, state->in + state->size, left);
457 strm->next_in = state->in;
458 strm->avail_in = left;
463 int ZEXPORTVA gzprintf(gzFile file, const char *format, ...)
468 va_start(va, format);
469 ret = gzvprintf(file, format, va);
474 #else /* !STDC && !Z_HAVE_STDARG_H */
476 /* -- see zlib.h -- */
477 int ZEXPORTVA gzprintf (file, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10,
478 a11, a12, a13, a14, a15, a16, a17, a18, a19, a20)
481 int a1, a2, a3, a4, a5, a6, a7, a8, a9, a10,
482 a11, a12, a13, a14, a15, a16, a17, a18, a19, a20;
489 /* get internal structure */
491 return Z_STREAM_ERROR;
492 state = (gz_statep)file;
493 strm = &(state->strm);
495 /* check that can really pass pointer in ints */
496 if (sizeof(int) != sizeof(void *))
497 return Z_STREAM_ERROR;
499 /* check that we're writing and that there's no error */
500 if (state->mode != GZ_WRITE || state->err != Z_OK)
501 return Z_STREAM_ERROR;
503 /* make sure we have some buffer space */
504 if (state->size == 0 && gz_init(state) == -1)
507 /* check for seek request */
510 if (gz_zero(state, state->skip) == -1)
514 /* do the printf() into the input buffer, put length in len -- the input
515 buffer is double-sized just for this function, so there is guaranteed to
516 be state->size bytes available after the current contents */
517 if (strm->avail_in == 0)
518 strm->next_in = state->in;
519 next = (char *)(strm->next_in + strm->avail_in);
520 next[state->size - 1] = 0;
522 # ifdef HAS_sprintf_void
523 sprintf(next, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12,
524 a13, a14, a15, a16, a17, a18, a19, a20);
525 for (len = 0; len < size; len++)
529 len = sprintf(next, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11,
530 a12, a13, a14, a15, a16, a17, a18, a19, a20);
533 # ifdef HAS_snprintf_void
534 snprintf(next, state->size, format, a1, a2, a3, a4, a5, a6, a7, a8, a9,
535 a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20);
538 len = snprintf(next, state->size, format, a1, a2, a3, a4, a5, a6, a7, a8,
539 a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20);
543 /* check that printf() results fit in buffer */
544 if (len == 0 || len >= state->size || next[state->size - 1] != 0)
547 /* update buffer and position, compress first half if past that */
548 strm->avail_in += len;
550 if (strm->avail_in >= state->size) {
551 left = strm->avail_in - state->size;
552 strm->avail_in = state->size;
553 if (gz_comp(state, Z_NO_FLUSH) == -1)
555 memmove(state->in, state->in + state->size, left);
556 strm->next_in = state->in;
557 strm->avail_in = left;
564 /* -- see zlib.h -- */
565 int ZEXPORT gzflush(file, flush)
571 /* get internal structure */
573 return Z_STREAM_ERROR;
574 state = (gz_statep)file;
576 /* check that we're writing and that there's no error */
577 if (state->mode != GZ_WRITE || state->err != Z_OK)
578 return Z_STREAM_ERROR;
580 /* check flush parameter */
581 if (flush < 0 || flush > Z_FINISH)
582 return Z_STREAM_ERROR;
584 /* check for seek request */
587 if (gz_zero(state, state->skip) == -1)
591 /* compress remaining data with requested flush */
592 (void)gz_comp(state, flush);
596 /* -- see zlib.h -- */
597 int ZEXPORT gzsetparams(file, level, strategy)
605 /* get internal structure */
607 return Z_STREAM_ERROR;
608 state = (gz_statep)file;
609 strm = &(state->strm);
611 /* check that we're writing and that there's no error */
612 if (state->mode != GZ_WRITE || state->err != Z_OK)
613 return Z_STREAM_ERROR;
615 /* if no change is requested, then do nothing */
616 if (level == state->level && strategy == state->strategy)
619 /* check for seek request */
622 if (gz_zero(state, state->skip) == -1)
626 /* change compression parameters for subsequent input */
628 /* flush previous input with previous parameters before changing */
629 if (strm->avail_in && gz_comp(state, Z_BLOCK) == -1)
631 deflateParams(strm, level, strategy);
633 state->level = level;
634 state->strategy = strategy;
638 /* -- see zlib.h -- */
639 int ZEXPORT gzclose_w(file)
645 /* get internal structure */
647 return Z_STREAM_ERROR;
648 state = (gz_statep)file;
650 /* check that we're writing */
651 if (state->mode != GZ_WRITE)
652 return Z_STREAM_ERROR;
654 /* check for seek request */
657 if (gz_zero(state, state->skip) == -1)
661 /* flush, free memory, and close file */
662 if (gz_comp(state, Z_FINISH) == -1)
665 if (!state->direct) {
666 (void)deflateEnd(&(state->strm));
671 gz_error(state, Z_OK, NULL);
673 if (close(state->fd) == -1)