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
12 local int gz_init OF((gz_statep));
13 local int gz_comp OF((gz_statep, int));
14 local int gz_zero OF((gz_statep, z_off64_t));
15 local z_size_t gz_write OF((gz_statep, voidpc, z_size_t));
17 /* Initialize state for writing a gzip file. Mark initialization by setting
18 state->size to non-zero. Return -1 on a memory allocation failure, or 0 on
20 local int gz_init(state)
24 z_streamp strm = &(state->strm);
26 /* allocate input buffer (double size for gzprintf) */
27 state->in = (unsigned char *)malloc(state->want << 1);
28 if (state->in == NULL) {
29 gz_error(state, Z_MEM_ERROR, "out of memory");
33 /* only need output buffer and deflate state if compressing */
35 /* allocate output buffer */
36 state->out = (unsigned char *)malloc(state->want);
37 if (state->out == NULL) {
39 gz_error(state, Z_MEM_ERROR, "out of memory");
43 /* allocate deflate memory, set up for gzip compression */
44 strm->zalloc = Z_NULL;
46 strm->opaque = Z_NULL;
47 ret = deflateInit2(strm, state->level, Z_DEFLATED,
48 MAX_WBITS + 16, DEF_MEM_LEVEL, state->strategy);
52 gz_error(state, Z_MEM_ERROR, "out of memory");
58 /* mark state as initialized */
59 state->size = state->want;
61 /* initialize write buffer if compressing */
63 strm->avail_out = state->size;
64 strm->next_out = state->out;
65 state->x.next = strm->next_out;
70 /* Compress whatever is at avail_in and next_in and write to the output file.
71 Return -1 if there is an error writing to the output file or if gz_init()
72 fails to allocate memory, otherwise 0. flush is assumed to be a valid
73 deflate() flush value. If flush is Z_FINISH, then the deflate() state is
74 reset to start a new gzip stream. If gz->direct is true, then simply write
75 to the output file without compressing, and ignore flush. */
76 local int gz_comp(state, flush)
81 unsigned have, put, max = ((unsigned)-1 >> 2) + 1;
82 z_streamp strm = &(state->strm);
84 /* allocate memory if this is the first time through */
85 if (state->size == 0 && gz_init(state) == -1)
88 /* write directly if requested */
90 while (strm->avail_in) {
91 put = strm->avail_in > max ? max : strm->avail_in;
92 writ = write(state->fd, strm->next_in, put);
94 gz_error(state, Z_ERRNO, zstrerror());
97 strm->avail_in -= (unsigned)writ;
98 strm->next_in += writ;
103 /* check for a pending reset */
105 /* don't start a new gzip member unless there is data to write */
106 if (strm->avail_in == 0)
112 /* run deflate() on provided input until it produces no more output */
115 /* write out current buffer contents if full, or if flushing, but if
116 doing Z_FINISH then don't write until we get to Z_STREAM_END */
117 if (strm->avail_out == 0 || (flush != Z_NO_FLUSH &&
118 (flush != Z_FINISH || ret == Z_STREAM_END))) {
119 while (strm->next_out > state->x.next) {
120 put = strm->next_out - state->x.next > (int)max ? max :
121 (unsigned)(strm->next_out - state->x.next);
122 writ = write(state->fd, state->x.next, put);
124 gz_error(state, Z_ERRNO, zstrerror());
127 state->x.next += writ;
129 if (strm->avail_out == 0) {
130 strm->avail_out = state->size;
131 strm->next_out = state->out;
132 state->x.next = state->out;
137 have = strm->avail_out;
138 ret = deflate(strm, flush);
139 if (ret == Z_STREAM_ERROR) {
140 gz_error(state, Z_STREAM_ERROR,
141 "internal error: deflate stream corrupt");
144 have -= strm->avail_out;
147 /* if that completed a deflate stream, allow another to start */
148 if (flush == Z_FINISH)
151 /* all done, no errors */
155 /* Compress len zeros to output. Return -1 on a write error or memory
156 allocation failure by gz_comp(), or 0 on success. */
157 local int gz_zero(state, len)
163 z_streamp strm = &(state->strm);
165 /* consume whatever's left in the input buffer */
166 if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1)
169 /* compress len zeros (len guaranteed > 0) */
172 n = GT_OFF(state->size) || (z_off64_t)state->size > len ?
173 (unsigned)len : state->size;
175 memset(state->in, 0, n);
179 strm->next_in = state->in;
181 if (gz_comp(state, Z_NO_FLUSH) == -1)
188 /* Write len bytes from buf to file. Return the number of bytes written. If
189 the returned value is less than len, then there was an error. */
190 local z_size_t gz_write(state, buf, len)
197 /* if len is zero, avoid unnecessary operations */
201 /* allocate memory if this is the first time through */
202 if (state->size == 0 && gz_init(state) == -1)
205 /* check for seek request */
208 if (gz_zero(state, state->skip) == -1)
212 /* for small len, copy to input buffer, otherwise compress directly */
213 if (len < state->size) {
214 /* copy to input buffer, compress when full */
218 if (state->strm.avail_in == 0)
219 state->strm.next_in = state->in;
220 have = (unsigned)((state->strm.next_in + state->strm.avail_in) -
222 copy = state->size - have;
224 copy = (unsigned)len;
225 memcpy(state->in + have, buf, copy);
226 state->strm.avail_in += copy;
227 state->x.pos += copy;
228 buf = (const char *)buf + copy;
230 if (len && gz_comp(state, Z_NO_FLUSH) == -1)
235 /* consume whatever's left in the input buffer */
236 if (state->strm.avail_in && gz_comp(state, Z_NO_FLUSH) == -1)
239 /* directly compress user buffer to file */
240 state->strm.next_in = (z_const Bytef *)buf;
242 unsigned n = (unsigned)-1;
245 state->strm.avail_in = n;
247 if (gz_comp(state, Z_NO_FLUSH) == -1)
253 /* input was all buffered or compressed */
257 /* -- see zlib.h -- */
258 int ZEXPORT gzwrite(file, buf, len)
265 /* get internal structure */
268 state = (gz_statep)file;
270 /* check that we're writing and that there's no error */
271 if (state->mode != GZ_WRITE || state->err != Z_OK)
274 /* since an int is returned, make sure len fits in one, otherwise return
275 with an error (this avoids a flaw in the interface) */
277 gz_error(state, Z_DATA_ERROR, "requested length does not fit in int");
281 /* write len bytes from buf (the return value will fit in an int) */
282 return (int)gz_write(state, buf, len);
285 /* -- see zlib.h -- */
286 z_size_t ZEXPORT gzfwrite(buf, size, nitems, file)
295 /* get internal structure */
298 state = (gz_statep)file;
300 /* check that we're writing and that there's no error */
301 if (state->mode != GZ_WRITE || state->err != Z_OK)
304 /* compute bytes to read -- error on overflow */
306 if (size && len / size != nitems) {
307 gz_error(state, Z_STREAM_ERROR, "request does not fit in a size_t");
311 /* write len bytes to buf, return the number of full items written */
312 return len ? gz_write(state, buf, len) / size : 0;
315 /* -- see zlib.h -- */
316 int ZEXPORT gzputc(file, c)
321 unsigned char buf[1];
325 /* get internal structure */
328 state = (gz_statep)file;
329 strm = &(state->strm);
331 /* check that we're writing and that there's no error */
332 if (state->mode != GZ_WRITE || state->err != Z_OK)
335 /* check for seek request */
338 if (gz_zero(state, state->skip) == -1)
342 /* try writing to input buffer for speed (state->size == 0 if buffer not
345 if (strm->avail_in == 0)
346 strm->next_in = state->in;
347 have = (unsigned)((strm->next_in + strm->avail_in) - state->in);
348 if (have < state->size) {
349 state->in[have] = (unsigned char)c;
356 /* no room in buffer or not initialized, use gz_write() */
357 buf[0] = (unsigned char)c;
358 if (gz_write(state, buf, 1) != 1)
363 /* -- see zlib.h -- */
364 int ZEXPORT gzputs(file, s)
371 /* get internal structure */
374 state = (gz_statep)file;
376 /* check that we're writing and that there's no error */
377 if (state->mode != GZ_WRITE || state->err != Z_OK)
382 if ((int)len < 0 || (unsigned)len != len) {
383 gz_error(state, Z_STREAM_ERROR, "string length does not fit in int");
386 put = gz_write(state, s, len);
387 return put < len ? -1 : (int)len;
390 #if defined(STDC) || defined(Z_HAVE_STDARG_H)
393 /* -- see zlib.h -- */
394 int ZEXPORTVA gzvprintf(gzFile file, const char *format, va_list va)
402 /* get internal structure */
404 return Z_STREAM_ERROR;
405 state = (gz_statep)file;
406 strm = &(state->strm);
408 /* check that we're writing and that there's no error */
409 if (state->mode != GZ_WRITE || state->err != Z_OK)
410 return Z_STREAM_ERROR;
412 /* make sure we have some buffer space */
413 if (state->size == 0 && gz_init(state) == -1)
416 /* check for seek request */
419 if (gz_zero(state, state->skip) == -1)
423 /* do the printf() into the input buffer, put length in len -- the input
424 buffer is double-sized just for this function, so there is guaranteed to
425 be state->size bytes available after the current contents */
426 if (strm->avail_in == 0)
427 strm->next_in = state->in;
428 next = (char *)(state->in + (strm->next_in - state->in) + strm->avail_in);
429 next[state->size - 1] = 0;
431 # ifdef HAS_vsprintf_void
432 (void)vsprintf(next, format, va);
433 for (len = 0; len < state->size; len++)
434 if (next[len] == 0) break;
436 len = vsprintf(next, format, va);
439 # ifdef HAS_vsnprintf_void
440 (void)vsnprintf(next, state->size, format, va);
443 len = vsnprintf(next, state->size, format, va);
447 /* check that printf() results fit in buffer */
448 if (len == 0 || (unsigned)len >= state->size || next[state->size - 1] != 0)
451 /* update buffer and position, compress first half if past that */
452 strm->avail_in += (unsigned)len;
454 if (strm->avail_in >= state->size) {
455 left = strm->avail_in - state->size;
456 strm->avail_in = state->size;
457 if (gz_comp(state, Z_NO_FLUSH) == -1)
459 memmove(state->in, state->in + state->size, left);
460 strm->next_in = state->in;
461 strm->avail_in = left;
466 int ZEXPORTVA gzprintf(gzFile file, const char *format, ...)
471 va_start(va, format);
472 ret = gzvprintf(file, format, va);
477 #else /* !STDC && !Z_HAVE_STDARG_H */
479 /* -- see zlib.h -- */
480 int ZEXPORTVA gzprintf (file, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10,
481 a11, a12, a13, a14, a15, a16, a17, a18, a19, a20)
484 int a1, a2, a3, a4, a5, a6, a7, a8, a9, a10,
485 a11, a12, a13, a14, a15, a16, a17, a18, a19, a20;
492 /* get internal structure */
494 return Z_STREAM_ERROR;
495 state = (gz_statep)file;
496 strm = &(state->strm);
498 /* check that can really pass pointer in ints */
499 if (sizeof(int) != sizeof(void *))
500 return Z_STREAM_ERROR;
502 /* check that we're writing and that there's no error */
503 if (state->mode != GZ_WRITE || state->err != Z_OK)
504 return Z_STREAM_ERROR;
506 /* make sure we have some buffer space */
507 if (state->size == 0 && gz_init(state) == -1)
510 /* check for seek request */
513 if (gz_zero(state, state->skip) == -1)
517 /* do the printf() into the input buffer, put length in len -- the input
518 buffer is double-sized just for this function, so there is guaranteed to
519 be state->size bytes available after the current contents */
520 if (strm->avail_in == 0)
521 strm->next_in = state->in;
522 next = (char *)(strm->next_in + strm->avail_in);
523 next[state->size - 1] = 0;
525 # ifdef HAS_sprintf_void
526 sprintf(next, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12,
527 a13, a14, a15, a16, a17, a18, a19, a20);
528 for (len = 0; len < size; len++)
532 len = sprintf(next, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11,
533 a12, a13, a14, a15, a16, a17, a18, a19, a20);
536 # ifdef HAS_snprintf_void
537 snprintf(next, state->size, format, a1, a2, a3, a4, a5, a6, a7, a8, a9,
538 a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20);
541 len = snprintf(next, state->size, format, a1, a2, a3, a4, a5, a6, a7, a8,
542 a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20);
546 /* check that printf() results fit in buffer */
547 if (len == 0 || len >= state->size || next[state->size - 1] != 0)
550 /* update buffer and position, compress first half if past that */
551 strm->avail_in += len;
553 if (strm->avail_in >= state->size) {
554 left = strm->avail_in - state->size;
555 strm->avail_in = state->size;
556 if (gz_comp(state, Z_NO_FLUSH) == -1)
558 memmove(state->in, state->in + state->size, left);
559 strm->next_in = state->in;
560 strm->avail_in = left;
567 /* -- see zlib.h -- */
568 int ZEXPORT gzflush(file, flush)
574 /* get internal structure */
576 return Z_STREAM_ERROR;
577 state = (gz_statep)file;
579 /* check that we're writing and that there's no error */
580 if (state->mode != GZ_WRITE || state->err != Z_OK)
581 return Z_STREAM_ERROR;
583 /* check flush parameter */
584 if (flush < 0 || flush > Z_FINISH)
585 return Z_STREAM_ERROR;
587 /* check for seek request */
590 if (gz_zero(state, state->skip) == -1)
594 /* compress remaining data with requested flush */
595 (void)gz_comp(state, flush);
599 /* -- see zlib.h -- */
600 int ZEXPORT gzsetparams(file, level, strategy)
608 /* get internal structure */
610 return Z_STREAM_ERROR;
611 state = (gz_statep)file;
612 strm = &(state->strm);
614 /* check that we're writing and that there's no error */
615 if (state->mode != GZ_WRITE || state->err != Z_OK)
616 return Z_STREAM_ERROR;
618 /* if no change is requested, then do nothing */
619 if (level == state->level && strategy == state->strategy)
622 /* check for seek request */
625 if (gz_zero(state, state->skip) == -1)
629 /* change compression parameters for subsequent input */
631 /* flush previous input with previous parameters before changing */
632 if (strm->avail_in && gz_comp(state, Z_BLOCK) == -1)
634 deflateParams(strm, level, strategy);
636 state->level = level;
637 state->strategy = strategy;
641 /* -- see zlib.h -- */
642 int ZEXPORT gzclose_w(file)
648 /* get internal structure */
650 return Z_STREAM_ERROR;
651 state = (gz_statep)file;
653 /* check that we're writing */
654 if (state->mode != GZ_WRITE)
655 return Z_STREAM_ERROR;
657 /* check for seek request */
660 if (gz_zero(state, state->skip) == -1)
664 /* flush, free memory, and close file */
665 if (gz_comp(state, Z_FINISH) == -1)
668 if (!state->direct) {
669 (void)deflateEnd(&(state->strm));
674 gz_error(state, Z_OK, NULL);
676 if (close(state->fd) == -1)