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
8 /* Initialize state for writing a gzip file. Mark initialization by setting
9 state->size to non-zero. Return -1 on a memory allocation failure, or 0 on
11 local int gz_init(gz_statep state) {
13 z_streamp strm = &(state->strm);
15 /* allocate input buffer (double size for gzprintf) */
16 state->in = (unsigned char *)malloc(state->want << 1);
17 if (state->in == NULL) {
18 gz_error(state, Z_MEM_ERROR, "out of memory");
22 /* only need output buffer and deflate state if compressing */
24 /* allocate output buffer */
25 state->out = (unsigned char *)malloc(state->want);
26 if (state->out == NULL) {
28 gz_error(state, Z_MEM_ERROR, "out of memory");
32 /* allocate deflate memory, set up for gzip compression */
33 strm->zalloc = Z_NULL;
35 strm->opaque = Z_NULL;
36 ret = deflateInit2(strm, state->level, Z_DEFLATED,
37 MAX_WBITS + 16, DEF_MEM_LEVEL, state->strategy);
41 gz_error(state, Z_MEM_ERROR, "out of memory");
47 /* mark state as initialized */
48 state->size = state->want;
50 /* initialize write buffer if compressing */
52 strm->avail_out = state->size;
53 strm->next_out = state->out;
54 state->x.next = strm->next_out;
59 /* Compress whatever is at avail_in and next_in and write to the output file.
60 Return -1 if there is an error writing to the output file or if gz_init()
61 fails to allocate memory, otherwise 0. flush is assumed to be a valid
62 deflate() flush value. If flush is Z_FINISH, then the deflate() state is
63 reset to start a new gzip stream. If gz->direct is true, then simply write
64 to the output file without compressing, and ignore flush. */
65 local int gz_comp(gz_statep state, int flush) {
67 unsigned have, put, max = ((unsigned)-1 >> 2) + 1;
68 z_streamp strm = &(state->strm);
70 /* allocate memory if this is the first time through */
71 if (state->size == 0 && gz_init(state) == -1)
74 /* write directly if requested */
76 while (strm->avail_in) {
77 put = strm->avail_in > max ? max : strm->avail_in;
78 writ = write(state->fd, strm->next_in, put);
80 gz_error(state, Z_ERRNO, zstrerror());
83 strm->avail_in -= (unsigned)writ;
84 strm->next_in += writ;
89 /* check for a pending reset */
91 /* don't start a new gzip member unless there is data to write */
92 if (strm->avail_in == 0)
98 /* run deflate() on provided input until it produces no more output */
101 /* write out current buffer contents if full, or if flushing, but if
102 doing Z_FINISH then don't write until we get to Z_STREAM_END */
103 if (strm->avail_out == 0 || (flush != Z_NO_FLUSH &&
104 (flush != Z_FINISH || ret == Z_STREAM_END))) {
105 while (strm->next_out > state->x.next) {
106 put = strm->next_out - state->x.next > (int)max ? max :
107 (unsigned)(strm->next_out - state->x.next);
108 writ = write(state->fd, state->x.next, put);
110 gz_error(state, Z_ERRNO, zstrerror());
113 state->x.next += writ;
115 if (strm->avail_out == 0) {
116 strm->avail_out = state->size;
117 strm->next_out = state->out;
118 state->x.next = 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(gz_statep state, z_off64_t len) {
146 z_streamp strm = &(state->strm);
148 /* consume whatever's left in the input buffer */
149 if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1)
152 /* compress len zeros (len guaranteed > 0) */
155 n = GT_OFF(state->size) || (z_off64_t)state->size > len ?
156 (unsigned)len : state->size;
158 memset(state->in, 0, n);
162 strm->next_in = state->in;
164 if (gz_comp(state, Z_NO_FLUSH) == -1)
171 /* Write len bytes from buf to file. Return the number of bytes written. If
172 the returned value is less than len, then there was an error. */
173 local z_size_t gz_write(gz_statep state, voidpc buf, z_size_t len) {
176 /* if len is zero, avoid unnecessary operations */
180 /* allocate memory if this is the first time through */
181 if (state->size == 0 && gz_init(state) == -1)
184 /* check for seek request */
187 if (gz_zero(state, state->skip) == -1)
191 /* for small len, copy to input buffer, otherwise compress directly */
192 if (len < state->size) {
193 /* copy to input buffer, compress when full */
197 if (state->strm.avail_in == 0)
198 state->strm.next_in = state->in;
199 have = (unsigned)((state->strm.next_in + state->strm.avail_in) -
201 copy = state->size - have;
203 copy = (unsigned)len;
204 memcpy(state->in + have, buf, copy);
205 state->strm.avail_in += copy;
206 state->x.pos += copy;
207 buf = (const char *)buf + copy;
209 if (len && gz_comp(state, Z_NO_FLUSH) == -1)
214 /* consume whatever's left in the input buffer */
215 if (state->strm.avail_in && gz_comp(state, Z_NO_FLUSH) == -1)
218 /* directly compress user buffer to file */
219 state->strm.next_in = (z_const Bytef *)buf;
221 unsigned n = (unsigned)-1;
224 state->strm.avail_in = n;
226 if (gz_comp(state, Z_NO_FLUSH) == -1)
232 /* input was all buffered or compressed */
236 /* -- see zlib.h -- */
237 int ZEXPORT gzwrite(gzFile file, voidpc buf, unsigned len) {
240 /* get internal structure */
243 state = (gz_statep)file;
245 /* check that we're writing and that there's no error */
246 if (state->mode != GZ_WRITE || state->err != Z_OK)
249 /* since an int is returned, make sure len fits in one, otherwise return
250 with an error (this avoids a flaw in the interface) */
252 gz_error(state, Z_DATA_ERROR, "requested length does not fit in int");
256 /* write len bytes from buf (the return value will fit in an int) */
257 return (int)gz_write(state, buf, len);
260 /* -- see zlib.h -- */
261 z_size_t ZEXPORT gzfwrite(voidpc buf, z_size_t size, z_size_t nitems,
266 /* get internal structure */
269 state = (gz_statep)file;
271 /* check that we're writing and that there's no error */
272 if (state->mode != GZ_WRITE || state->err != Z_OK)
275 /* compute bytes to read -- error on overflow */
277 if (size && len / size != nitems) {
278 gz_error(state, Z_STREAM_ERROR, "request does not fit in a size_t");
282 /* write len bytes to buf, return the number of full items written */
283 return len ? gz_write(state, buf, len) / size : 0;
286 /* -- see zlib.h -- */
287 int ZEXPORT gzputc(gzFile file, int c) {
289 unsigned char buf[1];
293 /* get internal structure */
296 state = (gz_statep)file;
297 strm = &(state->strm);
299 /* check that we're writing and that there's no error */
300 if (state->mode != GZ_WRITE || state->err != Z_OK)
303 /* check for seek request */
306 if (gz_zero(state, state->skip) == -1)
310 /* try writing to input buffer for speed (state->size == 0 if buffer not
313 if (strm->avail_in == 0)
314 strm->next_in = state->in;
315 have = (unsigned)((strm->next_in + strm->avail_in) - state->in);
316 if (have < state->size) {
317 state->in[have] = (unsigned char)c;
324 /* no room in buffer or not initialized, use gz_write() */
325 buf[0] = (unsigned char)c;
326 if (gz_write(state, buf, 1) != 1)
331 /* -- see zlib.h -- */
332 int ZEXPORT gzputs(gzFile file, const char *s) {
336 /* get internal structure */
339 state = (gz_statep)file;
341 /* check that we're writing and that there's no error */
342 if (state->mode != GZ_WRITE || state->err != Z_OK)
347 if ((int)len < 0 || (unsigned)len != len) {
348 gz_error(state, Z_STREAM_ERROR, "string length does not fit in int");
351 put = gz_write(state, s, len);
352 return put < len ? -1 : (int)len;
355 #if defined(STDC) || defined(Z_HAVE_STDARG_H)
358 /* -- see zlib.h -- */
359 int ZEXPORTVA gzvprintf(gzFile file, const char *format, va_list va) {
366 /* get internal structure */
368 return Z_STREAM_ERROR;
369 state = (gz_statep)file;
370 strm = &(state->strm);
372 /* check that we're writing and that there's no error */
373 if (state->mode != GZ_WRITE || state->err != Z_OK)
374 return Z_STREAM_ERROR;
376 /* make sure we have some buffer space */
377 if (state->size == 0 && gz_init(state) == -1)
380 /* check for seek request */
383 if (gz_zero(state, state->skip) == -1)
387 /* do the printf() into the input buffer, put length in len -- the input
388 buffer is double-sized just for this function, so there is guaranteed to
389 be state->size bytes available after the current contents */
390 if (strm->avail_in == 0)
391 strm->next_in = state->in;
392 next = (char *)(state->in + (strm->next_in - state->in) + strm->avail_in);
393 next[state->size - 1] = 0;
395 # ifdef HAS_vsprintf_void
396 (void)vsprintf(next, format, va);
397 for (len = 0; len < state->size; len++)
398 if (next[len] == 0) break;
400 len = vsprintf(next, format, va);
403 # ifdef HAS_vsnprintf_void
404 (void)vsnprintf(next, state->size, format, va);
407 len = vsnprintf(next, state->size, format, va);
411 /* check that printf() results fit in buffer */
412 if (len == 0 || (unsigned)len >= state->size || next[state->size - 1] != 0)
415 /* update buffer and position, compress first half if past that */
416 strm->avail_in += (unsigned)len;
418 if (strm->avail_in >= state->size) {
419 left = strm->avail_in - state->size;
420 strm->avail_in = state->size;
421 if (gz_comp(state, Z_NO_FLUSH) == -1)
423 memmove(state->in, state->in + state->size, left);
424 strm->next_in = state->in;
425 strm->avail_in = left;
430 int ZEXPORTVA gzprintf(gzFile file, const char *format, ...) {
434 va_start(va, format);
435 ret = gzvprintf(file, format, va);
440 #else /* !STDC && !Z_HAVE_STDARG_H */
442 /* -- see zlib.h -- */
443 int ZEXPORTVA gzprintf(gzFile file, const char *format, int a1, int a2, int a3,
444 int a4, int a5, int a6, int a7, int a8, int a9, int a10,
445 int a11, int a12, int a13, int a14, int a15, int a16,
446 int a17, int a18, int a19, int a20) {
452 /* get internal structure */
454 return Z_STREAM_ERROR;
455 state = (gz_statep)file;
456 strm = &(state->strm);
458 /* check that can really pass pointer in ints */
459 if (sizeof(int) != sizeof(void *))
460 return Z_STREAM_ERROR;
462 /* check that we're writing and that there's no error */
463 if (state->mode != GZ_WRITE || state->err != Z_OK)
464 return Z_STREAM_ERROR;
466 /* make sure we have some buffer space */
467 if (state->size == 0 && gz_init(state) == -1)
470 /* check for seek request */
473 if (gz_zero(state, state->skip) == -1)
477 /* do the printf() into the input buffer, put length in len -- the input
478 buffer is double-sized just for this function, so there is guaranteed to
479 be state->size bytes available after the current contents */
480 if (strm->avail_in == 0)
481 strm->next_in = state->in;
482 next = (char *)(strm->next_in + strm->avail_in);
483 next[state->size - 1] = 0;
485 # ifdef HAS_sprintf_void
486 sprintf(next, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12,
487 a13, a14, a15, a16, a17, a18, a19, a20);
488 for (len = 0; len < size; len++)
492 len = sprintf(next, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11,
493 a12, a13, a14, a15, a16, a17, a18, a19, a20);
496 # ifdef HAS_snprintf_void
497 snprintf(next, state->size, format, a1, a2, a3, a4, a5, a6, a7, a8, a9,
498 a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20);
501 len = snprintf(next, state->size, format, a1, a2, a3, a4, a5, a6, a7, a8,
502 a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20);
506 /* check that printf() results fit in buffer */
507 if (len == 0 || len >= state->size || next[state->size - 1] != 0)
510 /* update buffer and position, compress first half if past that */
511 strm->avail_in += len;
513 if (strm->avail_in >= state->size) {
514 left = strm->avail_in - state->size;
515 strm->avail_in = state->size;
516 if (gz_comp(state, Z_NO_FLUSH) == -1)
518 memmove(state->in, state->in + state->size, left);
519 strm->next_in = state->in;
520 strm->avail_in = left;
527 /* -- see zlib.h -- */
528 int ZEXPORT gzflush(gzFile file, int flush) {
531 /* get internal structure */
533 return Z_STREAM_ERROR;
534 state = (gz_statep)file;
536 /* check that we're writing and that there's no error */
537 if (state->mode != GZ_WRITE || state->err != Z_OK)
538 return Z_STREAM_ERROR;
540 /* check flush parameter */
541 if (flush < 0 || flush > Z_FINISH)
542 return Z_STREAM_ERROR;
544 /* check for seek request */
547 if (gz_zero(state, state->skip) == -1)
551 /* compress remaining data with requested flush */
552 (void)gz_comp(state, flush);
556 /* -- see zlib.h -- */
557 int ZEXPORT gzsetparams(gzFile file, int level, int strategy) {
561 /* get internal structure */
563 return Z_STREAM_ERROR;
564 state = (gz_statep)file;
565 strm = &(state->strm);
567 /* check that we're writing and that there's no error */
568 if (state->mode != GZ_WRITE || state->err != Z_OK || state->direct)
569 return Z_STREAM_ERROR;
571 /* if no change is requested, then do nothing */
572 if (level == state->level && strategy == state->strategy)
575 /* check for seek request */
578 if (gz_zero(state, state->skip) == -1)
582 /* change compression parameters for subsequent input */
584 /* flush previous input with previous parameters before changing */
585 if (strm->avail_in && gz_comp(state, Z_BLOCK) == -1)
587 deflateParams(strm, level, strategy);
589 state->level = level;
590 state->strategy = strategy;
594 /* -- see zlib.h -- */
595 int ZEXPORT gzclose_w(gzFile file) {
599 /* get internal structure */
601 return Z_STREAM_ERROR;
602 state = (gz_statep)file;
604 /* check that we're writing */
605 if (state->mode != GZ_WRITE)
606 return Z_STREAM_ERROR;
608 /* check for seek request */
611 if (gz_zero(state, state->skip) == -1)
615 /* flush, free memory, and close file */
616 if (gz_comp(state, Z_FINISH) == -1)
619 if (!state->direct) {
620 (void)deflateEnd(&(state->strm));
625 gz_error(state, Z_OK, NULL);
627 if (close(state->fd) == -1)