1 /* gzwrite.c -- zlib functions for writing gzip files
2 * Copyright (C) 2004-2017 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 /* run deflate() on provided input until it produces no more output */
106 /* write out current buffer contents if full, or if flushing, but if
107 doing Z_FINISH then don't write until we get to Z_STREAM_END */
108 if (strm->avail_out == 0 || (flush != Z_NO_FLUSH &&
109 (flush != Z_FINISH || ret == Z_STREAM_END))) {
110 while (strm->next_out > state->x.next) {
111 put = strm->next_out - state->x.next > (int)max ? max :
112 (unsigned)(strm->next_out - state->x.next);
113 writ = write(state->fd, state->x.next, put);
115 gz_error(state, Z_ERRNO, zstrerror());
118 state->x.next += writ;
120 if (strm->avail_out == 0) {
121 strm->avail_out = state->size;
122 strm->next_out = state->out;
123 state->x.next = state->out;
128 have = strm->avail_out;
129 ret = deflate(strm, flush);
130 if (ret == Z_STREAM_ERROR) {
131 gz_error(state, Z_STREAM_ERROR,
132 "internal error: deflate stream corrupt");
135 have -= strm->avail_out;
138 /* if that completed a deflate stream, allow another to start */
139 if (flush == Z_FINISH)
142 /* all done, no errors */
146 /* Compress len zeros to output. Return -1 on a write error or memory
147 allocation failure by gz_comp(), or 0 on success. */
148 local int gz_zero(state, len)
154 z_streamp strm = &(state->strm);
156 /* consume whatever's left in the input buffer */
157 if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1)
160 /* compress len zeros (len guaranteed > 0) */
163 n = GT_OFF(state->size) || (z_off64_t)state->size > len ?
164 (unsigned)len : state->size;
166 memset(state->in, 0, n);
170 strm->next_in = state->in;
172 if (gz_comp(state, Z_NO_FLUSH) == -1)
179 /* Write len bytes from buf to file. Return the number of bytes written. If
180 the returned value is less than len, then there was an error. */
181 local z_size_t gz_write(state, buf, len)
188 /* if len is zero, avoid unnecessary operations */
192 /* allocate memory if this is the first time through */
193 if (state->size == 0 && gz_init(state) == -1)
196 /* check for seek request */
199 if (gz_zero(state, state->skip) == -1)
203 /* for small len, copy to input buffer, otherwise compress directly */
204 if (len < state->size) {
205 /* copy to input buffer, compress when full */
209 if (state->strm.avail_in == 0)
210 state->strm.next_in = state->in;
211 have = (unsigned)((state->strm.next_in + state->strm.avail_in) -
213 copy = state->size - have;
216 memcpy(state->in + have, buf, copy);
217 state->strm.avail_in += copy;
218 state->x.pos += copy;
219 buf = (const char *)buf + copy;
221 if (len && gz_comp(state, Z_NO_FLUSH) == -1)
226 /* consume whatever's left in the input buffer */
227 if (state->strm.avail_in && gz_comp(state, Z_NO_FLUSH) == -1)
230 /* directly compress user buffer to file */
231 state->strm.next_in = (z_const Bytef *)buf;
233 unsigned n = (unsigned)-1;
236 state->strm.avail_in = n;
238 if (gz_comp(state, Z_NO_FLUSH) == -1)
244 /* input was all buffered or compressed */
248 /* -- see zlib.h -- */
249 int ZEXPORT gzwrite(file, buf, len)
256 /* get internal structure */
259 state = (gz_statep)file;
261 /* check that we're writing and that there's no error */
262 if (state->mode != GZ_WRITE || state->err != Z_OK)
265 /* since an int is returned, make sure len fits in one, otherwise return
266 with an error (this avoids a flaw in the interface) */
268 gz_error(state, Z_DATA_ERROR, "requested length does not fit in int");
272 /* write len bytes from buf (the return value will fit in an int) */
273 return (int)gz_write(state, buf, len);
276 /* -- see zlib.h -- */
277 z_size_t ZEXPORT gzfwrite(buf, size, nitems, file)
286 /* get internal structure */
289 state = (gz_statep)file;
291 /* check that we're writing and that there's no error */
292 if (state->mode != GZ_WRITE || state->err != Z_OK)
295 /* compute bytes to read -- error on overflow */
297 if (size && len / size != nitems) {
298 gz_error(state, Z_STREAM_ERROR, "request does not fit in a size_t");
302 /* write len bytes to buf, return the number of full items written */
303 return len ? gz_write(state, buf, len) / size : 0;
306 /* -- see zlib.h -- */
307 int ZEXPORT gzputc(file, c)
312 unsigned char buf[1];
316 /* get internal structure */
319 state = (gz_statep)file;
320 strm = &(state->strm);
322 /* check that we're writing and that there's no error */
323 if (state->mode != GZ_WRITE || state->err != Z_OK)
326 /* check for seek request */
329 if (gz_zero(state, state->skip) == -1)
333 /* try writing to input buffer for speed (state->size == 0 if buffer not
336 if (strm->avail_in == 0)
337 strm->next_in = state->in;
338 have = (unsigned)((strm->next_in + strm->avail_in) - state->in);
339 if (have < state->size) {
340 state->in[have] = (unsigned char)c;
347 /* no room in buffer or not initialized, use gz_write() */
348 buf[0] = (unsigned char)c;
349 if (gz_write(state, buf, 1) != 1)
354 /* -- see zlib.h -- */
355 int ZEXPORT gzputs(file, str)
363 /* get internal structure */
366 state = (gz_statep)file;
368 /* check that we're writing and that there's no error */
369 if (state->mode != GZ_WRITE || state->err != Z_OK)
374 ret = gz_write(state, str, len);
375 return ret == 0 && len != 0 ? -1 : ret;
378 #if defined(STDC) || defined(Z_HAVE_STDARG_H)
381 /* -- see zlib.h -- */
382 int ZEXPORTVA gzvprintf(gzFile file, const char *format, va_list va)
390 /* get internal structure */
392 return Z_STREAM_ERROR;
393 state = (gz_statep)file;
394 strm = &(state->strm);
396 /* check that we're writing and that there's no error */
397 if (state->mode != GZ_WRITE || state->err != Z_OK)
398 return Z_STREAM_ERROR;
400 /* make sure we have some buffer space */
401 if (state->size == 0 && gz_init(state) == -1)
404 /* check for seek request */
407 if (gz_zero(state, state->skip) == -1)
411 /* do the printf() into the input buffer, put length in len -- the input
412 buffer is double-sized just for this function, so there is guaranteed to
413 be state->size bytes available after the current contents */
414 if (strm->avail_in == 0)
415 strm->next_in = state->in;
416 next = (char *)(state->in + (strm->next_in - state->in) + strm->avail_in);
417 next[state->size - 1] = 0;
419 # ifdef HAS_vsprintf_void
420 (void)vsprintf(next, format, va);
421 for (len = 0; len < state->size; len++)
422 if (next[len] == 0) break;
424 len = vsprintf(next, format, va);
427 # ifdef HAS_vsnprintf_void
428 (void)vsnprintf(next, state->size, format, va);
431 len = vsnprintf(next, state->size, format, va);
435 /* check that printf() results fit in buffer */
436 if (len == 0 || (unsigned)len >= state->size || next[state->size - 1] != 0)
439 /* update buffer and position, compress first half if past that */
440 strm->avail_in += (unsigned)len;
442 if (strm->avail_in >= state->size) {
443 left = strm->avail_in - state->size;
444 strm->avail_in = state->size;
445 if (gz_comp(state, Z_NO_FLUSH) == -1)
447 memcpy(state->in, state->in + state->size, left);
448 strm->next_in = state->in;
449 strm->avail_in = left;
454 int ZEXPORTVA gzprintf(gzFile file, const char *format, ...)
459 va_start(va, format);
460 ret = gzvprintf(file, format, va);
465 #else /* !STDC && !Z_HAVE_STDARG_H */
467 /* -- see zlib.h -- */
468 int ZEXPORTVA gzprintf (file, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10,
469 a11, a12, a13, a14, a15, a16, a17, a18, a19, a20)
472 int a1, a2, a3, a4, a5, a6, a7, a8, a9, a10,
473 a11, a12, a13, a14, a15, a16, a17, a18, a19, a20;
480 /* get internal structure */
482 return Z_STREAM_ERROR;
483 state = (gz_statep)file;
484 strm = &(state->strm);
486 /* check that can really pass pointer in ints */
487 if (sizeof(int) != sizeof(void *))
488 return Z_STREAM_ERROR;
490 /* check that we're writing and that there's no error */
491 if (state->mode != GZ_WRITE || state->err != Z_OK)
492 return Z_STREAM_ERROR;
494 /* make sure we have some buffer space */
495 if (state->size == 0 && gz_init(state) == -1)
498 /* check for seek request */
501 if (gz_zero(state, state->skip) == -1)
505 /* do the printf() into the input buffer, put length in len -- the input
506 buffer is double-sized just for this function, so there is guaranteed to
507 be state->size bytes available after the current contents */
508 if (strm->avail_in == 0)
509 strm->next_in = state->in;
510 next = (char *)(strm->next_in + strm->avail_in);
511 next[state->size - 1] = 0;
513 # ifdef HAS_sprintf_void
514 sprintf(next, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12,
515 a13, a14, a15, a16, a17, a18, a19, a20);
516 for (len = 0; len < size; len++)
520 len = sprintf(next, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11,
521 a12, a13, a14, a15, a16, a17, a18, a19, a20);
524 # ifdef HAS_snprintf_void
525 snprintf(next, state->size, format, a1, a2, a3, a4, a5, a6, a7, a8, a9,
526 a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20);
529 len = snprintf(next, state->size, format, a1, a2, a3, a4, a5, a6, a7, a8,
530 a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20);
534 /* check that printf() results fit in buffer */
535 if (len == 0 || len >= state->size || next[state->size - 1] != 0)
538 /* update buffer and position, compress first half if past that */
539 strm->avail_in += len;
541 if (strm->avail_in >= state->size) {
542 left = strm->avail_in - state->size;
543 strm->avail_in = state->size;
544 if (gz_comp(state, Z_NO_FLUSH) == -1)
546 memcpy(state->in, state->in + state->size, left);
547 strm->next_in = state->in;
548 strm->avail_in = left;
555 /* -- see zlib.h -- */
556 int ZEXPORT gzflush(file, flush)
562 /* get internal structure */
564 return Z_STREAM_ERROR;
565 state = (gz_statep)file;
567 /* check that we're writing and that there's no error */
568 if (state->mode != GZ_WRITE || state->err != Z_OK)
569 return Z_STREAM_ERROR;
571 /* check flush parameter */
572 if (flush < 0 || flush > Z_FINISH)
573 return Z_STREAM_ERROR;
575 /* check for seek request */
578 if (gz_zero(state, state->skip) == -1)
582 /* compress remaining data with requested flush */
583 (void)gz_comp(state, flush);
587 /* -- see zlib.h -- */
588 int ZEXPORT gzsetparams(file, level, strategy)
596 /* get internal structure */
598 return Z_STREAM_ERROR;
599 state = (gz_statep)file;
600 strm = &(state->strm);
602 /* check that we're writing and that there's no error */
603 if (state->mode != GZ_WRITE || state->err != Z_OK)
604 return Z_STREAM_ERROR;
606 /* if no change is requested, then do nothing */
607 if (level == state->level && strategy == state->strategy)
610 /* check for seek request */
613 if (gz_zero(state, state->skip) == -1)
617 /* change compression parameters for subsequent input */
619 /* flush previous input with previous parameters before changing */
620 if (strm->avail_in && gz_comp(state, Z_BLOCK) == -1)
622 deflateParams(strm, level, strategy);
624 state->level = level;
625 state->strategy = strategy;
629 /* -- see zlib.h -- */
630 int ZEXPORT gzclose_w(file)
636 /* get internal structure */
638 return Z_STREAM_ERROR;
639 state = (gz_statep)file;
641 /* check that we're writing */
642 if (state->mode != GZ_WRITE)
643 return Z_STREAM_ERROR;
645 /* check for seek request */
648 if (gz_zero(state, state->skip) == -1)
652 /* flush, free memory, and close file */
653 if (gz_comp(state, Z_FINISH) == -1)
656 if (!state->direct) {
657 (void)deflateEnd(&(state->strm));
662 gz_error(state, Z_OK, NULL);
664 if (close(state->fd) == -1)