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 /* Initialize state for writing a gzip file. Mark initialization by setting
10 state->size to non-zero. Return -1 on a memory allocation failure, or 0 on
12 local int gz_init(gz_statep state) {
14 z_streamp strm = &(state->strm);
16 /* allocate input buffer (double size for gzprintf) */
17 state->in = (unsigned char *)malloc(state->want << 1);
18 if (state->in == NULL) {
19 gz_error(state, Z_MEM_ERROR, "out of memory");
23 /* only need output buffer and deflate state if compressing */
25 /* allocate output buffer */
26 state->out = (unsigned char *)malloc(state->want);
27 if (state->out == NULL) {
29 gz_error(state, Z_MEM_ERROR, "out of memory");
33 /* allocate deflate memory, set up for gzip compression */
34 strm->zalloc = Z_NULL;
36 strm->opaque = Z_NULL;
37 ret = deflateInit2(strm, state->level, Z_DEFLATED,
38 MAX_WBITS + 16, DEF_MEM_LEVEL, state->strategy);
42 gz_error(state, Z_MEM_ERROR, "out of memory");
48 /* mark state as initialized */
49 state->size = state->want;
51 /* initialize write buffer if compressing */
53 strm->avail_out = state->size;
54 strm->next_out = state->out;
55 state->x.next = strm->next_out;
60 /* Compress whatever is at avail_in and next_in and write to the output file.
61 Return -1 if there is an error writing to the output file or if gz_init()
62 fails to allocate memory, otherwise 0. flush is assumed to be a valid
63 deflate() flush value. If flush is Z_FINISH, then the deflate() state is
64 reset to start a new gzip stream. If gz->direct is true, then simply write
65 to the output file without compressing, and ignore flush. */
66 local int gz_comp(gz_statep state, int flush) {
68 unsigned have, put, max = ((unsigned)-1 >> 2) + 1;
69 z_streamp strm = &(state->strm);
71 /* allocate memory if this is the first time through */
72 if (state->size == 0 && gz_init(state) == -1)
75 /* write directly if requested */
77 while (strm->avail_in) {
78 put = strm->avail_in > max ? max : strm->avail_in;
79 writ = write(state->fd, strm->next_in, put);
81 gz_error(state, Z_ERRNO, zstrerror());
84 strm->avail_in -= (unsigned)writ;
85 strm->next_in += writ;
90 /* check for a pending reset */
92 /* don't start a new gzip member unless there is data to write */
93 if (strm->avail_in == 0)
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 put = strm->next_out - state->x.next > (int)max ? max :
108 (unsigned)(strm->next_out - state->x.next);
109 writ = write(state->fd, state->x.next, put);
111 gz_error(state, Z_ERRNO, zstrerror());
114 state->x.next += writ;
116 if (strm->avail_out == 0) {
117 strm->avail_out = state->size;
118 strm->next_out = state->out;
119 state->x.next = 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(gz_statep state, z_off64_t len) {
147 z_streamp strm = &(state->strm);
149 /* consume whatever's left in the input buffer */
150 if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1)
153 /* compress len zeros (len guaranteed > 0) */
156 n = GT_OFF(state->size) || (z_off64_t)state->size > len ?
157 (unsigned)len : state->size;
159 memset(state->in, 0, n);
163 strm->next_in = state->in;
165 if (gz_comp(state, Z_NO_FLUSH) == -1)
172 /* Write len bytes from buf to file. Return the number of bytes written. If
173 the returned value is less than len, then there was an error. */
174 local z_size_t gz_write(gz_statep state, voidpc buf, z_size_t len) {
177 /* if len is zero, avoid unnecessary operations */
181 /* allocate memory if this is the first time through */
182 if (state->size == 0 && gz_init(state) == -1)
185 /* check for seek request */
188 if (gz_zero(state, state->skip) == -1)
192 /* for small len, copy to input buffer, otherwise compress directly */
193 if (len < state->size) {
194 /* copy to input buffer, compress when full */
198 if (state->strm.avail_in == 0)
199 state->strm.next_in = state->in;
200 have = (unsigned)((state->strm.next_in + state->strm.avail_in) -
202 copy = state->size - have;
204 copy = (unsigned)len;
205 memcpy(state->in + have, buf, copy);
206 state->strm.avail_in += copy;
207 state->x.pos += copy;
208 buf = (const char *)buf + copy;
210 if (len && gz_comp(state, Z_NO_FLUSH) == -1)
215 /* consume whatever's left in the input buffer */
216 if (state->strm.avail_in && gz_comp(state, Z_NO_FLUSH) == -1)
219 /* directly compress user buffer to file */
220 state->strm.next_in = (z_const Bytef *)buf;
222 unsigned n = (unsigned)-1;
225 state->strm.avail_in = n;
227 if (gz_comp(state, Z_NO_FLUSH) == -1)
233 /* input was all buffered or compressed */
237 /* -- see zlib.h -- */
238 int ZEXPORT gzwrite(gzFile file, voidpc buf, unsigned len) {
241 /* get internal structure */
244 state = (gz_statep)file;
246 /* check that we're writing and that there's no error */
247 if (state->mode != GZ_WRITE || state->err != Z_OK)
250 /* since an int is returned, make sure len fits in one, otherwise return
251 with an error (this avoids a flaw in the interface) */
253 gz_error(state, Z_DATA_ERROR, "requested length does not fit in int");
257 /* write len bytes from buf (the return value will fit in an int) */
258 return (int)gz_write(state, buf, len);
261 /* -- see zlib.h -- */
262 z_size_t ZEXPORT gzfwrite(voidpc buf, z_size_t size, z_size_t nitems,
267 /* get internal structure */
270 state = (gz_statep)file;
272 /* check that we're writing and that there's no error */
273 if (state->mode != GZ_WRITE || state->err != Z_OK)
276 /* compute bytes to read -- error on overflow */
278 if (size && len / size != nitems) {
279 gz_error(state, Z_STREAM_ERROR, "request does not fit in a size_t");
283 /* write len bytes to buf, return the number of full items written */
284 return len ? gz_write(state, buf, len) / size : 0;
287 /* -- see zlib.h -- */
288 int ZEXPORT gzputc(gzFile file, int c) {
290 unsigned char buf[1];
294 /* get internal structure */
297 state = (gz_statep)file;
298 strm = &(state->strm);
300 /* check that we're writing and that there's no error */
301 if (state->mode != GZ_WRITE || state->err != Z_OK)
304 /* check for seek request */
307 if (gz_zero(state, state->skip) == -1)
311 /* try writing to input buffer for speed (state->size == 0 if buffer not
314 if (strm->avail_in == 0)
315 strm->next_in = state->in;
316 have = (unsigned)((strm->next_in + strm->avail_in) - state->in);
317 if (have < state->size) {
318 state->in[have] = (unsigned char)c;
325 /* no room in buffer or not initialized, use gz_write() */
326 buf[0] = (unsigned char)c;
327 if (gz_write(state, buf, 1) != 1)
332 /* -- see zlib.h -- */
333 int ZEXPORT gzputs(gzFile file, const char *s) {
337 /* get internal structure */
340 state = (gz_statep)file;
342 /* check that we're writing and that there's no error */
343 if (state->mode != GZ_WRITE || state->err != Z_OK)
348 if ((int)len < 0 || (unsigned)len != len) {
349 gz_error(state, Z_STREAM_ERROR, "string length does not fit in int");
352 put = gz_write(state, s, len);
353 return put < len ? -1 : (int)len;
356 #if defined(STDC) || defined(Z_HAVE_STDARG_H)
359 /* -- see zlib.h -- */
360 int ZEXPORTVA gzvprintf(gzFile file, const char *format, va_list va) {
367 /* get internal structure */
369 return Z_STREAM_ERROR;
370 state = (gz_statep)file;
371 strm = &(state->strm);
373 /* check that we're writing and that there's no error */
374 if (state->mode != GZ_WRITE || state->err != Z_OK)
375 return Z_STREAM_ERROR;
377 /* make sure we have some buffer space */
378 if (state->size == 0 && gz_init(state) == -1)
381 /* check for seek request */
384 if (gz_zero(state, state->skip) == -1)
388 /* do the printf() into the input buffer, put length in len -- the input
389 buffer is double-sized just for this function, so there is guaranteed to
390 be state->size bytes available after the current contents */
391 if (strm->avail_in == 0)
392 strm->next_in = state->in;
393 next = (char *)(state->in + (strm->next_in - state->in) + strm->avail_in);
394 next[state->size - 1] = 0;
396 # ifdef HAS_vsprintf_void
397 (void)vsprintf(next, format, va);
398 for (len = 0; len < state->size; len++)
399 if (next[len] == 0) break;
401 len = vsprintf(next, format, va);
404 # ifdef HAS_vsnprintf_void
405 (void)vsnprintf(next, state->size, format, va);
408 len = vsnprintf(next, state->size, format, va);
412 /* check that printf() results fit in buffer */
413 if (len == 0 || (unsigned)len >= state->size || next[state->size - 1] != 0)
416 /* update buffer and position, compress first half if past that */
417 strm->avail_in += (unsigned)len;
419 if (strm->avail_in >= state->size) {
420 left = strm->avail_in - state->size;
421 strm->avail_in = state->size;
422 if (gz_comp(state, Z_NO_FLUSH) == -1)
424 memmove(state->in, state->in + state->size, left);
425 strm->next_in = state->in;
426 strm->avail_in = left;
431 int ZEXPORTVA gzprintf(gzFile file, const char *format, ...) {
435 va_start(va, format);
436 ret = gzvprintf(file, format, va);
441 #else /* !STDC && !Z_HAVE_STDARG_H */
443 /* -- see zlib.h -- */
444 int ZEXPORTVA gzprintf(gzFile file, const char *format, int a1, int a2, int a3,
445 int a4, int a5, int a6, int a7, int a8, int a9, int a10,
446 int a11, int a12, int a13, int a14, int a15, int a16,
447 int a17, int a18, int a19, int a20) {
453 /* get internal structure */
455 return Z_STREAM_ERROR;
456 state = (gz_statep)file;
457 strm = &(state->strm);
459 /* check that can really pass pointer in ints */
460 if (sizeof(int) != sizeof(void *))
461 return Z_STREAM_ERROR;
463 /* check that we're writing and that there's no error */
464 if (state->mode != GZ_WRITE || state->err != Z_OK)
465 return Z_STREAM_ERROR;
467 /* make sure we have some buffer space */
468 if (state->size == 0 && gz_init(state) == -1)
471 /* check for seek request */
474 if (gz_zero(state, state->skip) == -1)
478 /* do the printf() into the input buffer, put length in len -- the input
479 buffer is double-sized just for this function, so there is guaranteed to
480 be state->size bytes available after the current contents */
481 if (strm->avail_in == 0)
482 strm->next_in = state->in;
483 next = (char *)(strm->next_in + strm->avail_in);
484 next[state->size - 1] = 0;
486 # ifdef HAS_sprintf_void
487 sprintf(next, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12,
488 a13, a14, a15, a16, a17, a18, a19, a20);
489 for (len = 0; len < size; len++)
493 len = sprintf(next, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11,
494 a12, a13, a14, a15, a16, a17, a18, a19, a20);
497 # ifdef HAS_snprintf_void
498 snprintf(next, state->size, format, a1, a2, a3, a4, a5, a6, a7, a8, a9,
499 a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20);
502 len = snprintf(next, state->size, format, a1, a2, a3, a4, a5, a6, a7, a8,
503 a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20);
507 /* check that printf() results fit in buffer */
508 if (len == 0 || len >= state->size || next[state->size - 1] != 0)
511 /* update buffer and position, compress first half if past that */
512 strm->avail_in += len;
514 if (strm->avail_in >= state->size) {
515 left = strm->avail_in - state->size;
516 strm->avail_in = state->size;
517 if (gz_comp(state, Z_NO_FLUSH) == -1)
519 memmove(state->in, state->in + state->size, left);
520 strm->next_in = state->in;
521 strm->avail_in = left;
528 /* -- see zlib.h -- */
529 int ZEXPORT gzflush(gzFile file, int flush) {
532 /* get internal structure */
534 return Z_STREAM_ERROR;
535 state = (gz_statep)file;
537 /* check that we're writing and that there's no error */
538 if (state->mode != GZ_WRITE || state->err != Z_OK)
539 return Z_STREAM_ERROR;
541 /* check flush parameter */
542 if (flush < 0 || flush > Z_FINISH)
543 return Z_STREAM_ERROR;
545 /* check for seek request */
548 if (gz_zero(state, state->skip) == -1)
552 /* compress remaining data with requested flush */
553 (void)gz_comp(state, flush);
557 /* -- see zlib.h -- */
558 int ZEXPORT gzsetparams(gzFile file, int level, int strategy) {
562 /* get internal structure */
564 return Z_STREAM_ERROR;
565 state = (gz_statep)file;
566 strm = &(state->strm);
568 /* check that we're writing and that there's no error */
569 if (state->mode != GZ_WRITE || state->err != Z_OK || state->direct)
570 return Z_STREAM_ERROR;
572 /* if no change is requested, then do nothing */
573 if (level == state->level && strategy == state->strategy)
576 /* check for seek request */
579 if (gz_zero(state, state->skip) == -1)
583 /* change compression parameters for subsequent input */
585 /* flush previous input with previous parameters before changing */
586 if (strm->avail_in && gz_comp(state, Z_BLOCK) == -1)
588 deflateParams(strm, level, strategy);
590 state->level = level;
591 state->strategy = strategy;
595 /* -- see zlib.h -- */
596 int ZEXPORT gzclose_w(gzFile file) {
600 /* get internal structure */
602 return Z_STREAM_ERROR;
603 state = (gz_statep)file;
605 /* check that we're writing */
606 if (state->mode != GZ_WRITE)
607 return Z_STREAM_ERROR;
609 /* check for seek request */
612 if (gz_zero(state, state->skip) == -1)
616 /* flush, free memory, and close file */
617 if (gz_comp(state, Z_FINISH) == -1)
620 if (!state->direct) {
621 (void)deflateEnd(&(state->strm));
626 gz_error(state, Z_OK, NULL);
628 if (close(state->fd) == -1)