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
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 /* run deflate() on provided input until it produces no more output */
103 /* write out current buffer contents if full, or if flushing, but if
104 doing Z_FINISH then don't write until we get to Z_STREAM_END */
105 if (strm->avail_out == 0 || (flush != Z_NO_FLUSH &&
106 (flush != Z_FINISH || ret == Z_STREAM_END))) {
107 while (strm->next_out > state->x.next) {
108 put = strm->next_out - state->x.next > (int)max ? max :
109 (unsigned)(strm->next_out - state->x.next);
110 writ = write(state->fd, state->x.next, put);
112 gz_error(state, Z_ERRNO, zstrerror());
115 state->x.next += writ;
117 if (strm->avail_out == 0) {
118 strm->avail_out = state->size;
119 strm->next_out = state->out;
120 state->x.next = state->out;
125 have = strm->avail_out;
126 ret = deflate(strm, flush);
127 if (ret == Z_STREAM_ERROR) {
128 gz_error(state, Z_STREAM_ERROR,
129 "internal error: deflate stream corrupt");
132 have -= strm->avail_out;
135 /* if that completed a deflate stream, allow another to start */
136 if (flush == Z_FINISH)
139 /* all done, no errors */
143 /* Compress len zeros to output. Return -1 on a write error or memory
144 allocation failure by gz_comp(), or 0 on success. */
145 local int gz_zero(state, len)
151 z_streamp strm = &(state->strm);
153 /* consume whatever's left in the input buffer */
154 if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1)
157 /* compress len zeros (len guaranteed > 0) */
160 n = GT_OFF(state->size) || (z_off64_t)state->size > len ?
161 (unsigned)len : state->size;
163 memset(state->in, 0, n);
167 strm->next_in = state->in;
169 if (gz_comp(state, Z_NO_FLUSH) == -1)
176 /* Write len bytes from buf to file. Return the number of bytes written. If
177 the returned value is less than len, then there was an error. */
178 local z_size_t gz_write(state, buf, len)
185 /* if len is zero, avoid unnecessary operations */
189 /* allocate memory if this is the first time through */
190 if (state->size == 0 && gz_init(state) == -1)
193 /* check for seek request */
196 if (gz_zero(state, state->skip) == -1)
200 /* for small len, copy to input buffer, otherwise compress directly */
201 if (len < state->size) {
202 /* copy to input buffer, compress when full */
206 if (state->strm.avail_in == 0)
207 state->strm.next_in = state->in;
208 have = (unsigned)((state->strm.next_in + state->strm.avail_in) -
210 copy = state->size - have;
212 copy = (unsigned)len;
213 memcpy(state->in + have, buf, copy);
214 state->strm.avail_in += copy;
215 state->x.pos += copy;
216 buf = (const char *)buf + copy;
218 if (len && gz_comp(state, Z_NO_FLUSH) == -1)
223 /* consume whatever's left in the input buffer */
224 if (state->strm.avail_in && gz_comp(state, Z_NO_FLUSH) == -1)
227 /* directly compress user buffer to file */
228 state->strm.next_in = (z_const Bytef *)buf;
230 unsigned n = (unsigned)-1;
233 state->strm.avail_in = n;
235 if (gz_comp(state, Z_NO_FLUSH) == -1)
241 /* input was all buffered or compressed */
245 /* -- see zlib.h -- */
246 int ZEXPORT gzwrite(file, buf, len)
253 /* get internal structure */
256 state = (gz_statep)file;
258 /* check that we're writing and that there's no error */
259 if (state->mode != GZ_WRITE || state->err != Z_OK)
262 /* since an int is returned, make sure len fits in one, otherwise return
263 with an error (this avoids a flaw in the interface) */
265 gz_error(state, Z_DATA_ERROR, "requested length does not fit in int");
269 /* write len bytes from buf (the return value will fit in an int) */
270 return (int)gz_write(state, buf, len);
273 /* -- see zlib.h -- */
274 z_size_t ZEXPORT gzfwrite(buf, size, nitems, file)
283 /* get internal structure */
286 state = (gz_statep)file;
288 /* check that we're writing and that there's no error */
289 if (state->mode != GZ_WRITE || state->err != Z_OK)
292 /* compute bytes to read -- error on overflow */
294 if (size && len / size != nitems) {
295 gz_error(state, Z_STREAM_ERROR, "request does not fit in a size_t");
299 /* write len bytes to buf, return the number of full items written */
300 return len ? gz_write(state, buf, len) / size : 0;
303 /* -- see zlib.h -- */
304 int ZEXPORT gzputc(file, c)
309 unsigned char buf[1];
313 /* get internal structure */
316 state = (gz_statep)file;
317 strm = &(state->strm);
319 /* check that we're writing and that there's no error */
320 if (state->mode != GZ_WRITE || state->err != Z_OK)
323 /* check for seek request */
326 if (gz_zero(state, state->skip) == -1)
330 /* try writing to input buffer for speed (state->size == 0 if buffer not
333 if (strm->avail_in == 0)
334 strm->next_in = state->in;
335 have = (unsigned)((strm->next_in + strm->avail_in) - state->in);
336 if (have < state->size) {
337 state->in[have] = (unsigned char)c;
344 /* no room in buffer or not initialized, use gz_write() */
345 buf[0] = (unsigned char)c;
346 if (gz_write(state, buf, 1) != 1)
351 /* -- see zlib.h -- */
352 int ZEXPORT gzputs(file, s)
359 /* get internal structure */
362 state = (gz_statep)file;
364 /* check that we're writing and that there's no error */
365 if (state->mode != GZ_WRITE || state->err != Z_OK)
370 if ((int)len < 0 || (unsigned)len != len) {
371 gz_error(state, Z_STREAM_ERROR, "string length does not fit in int");
374 put = gz_write(state, s, len);
375 return put < len ? -1 : (int)len;
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 memmove(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 memmove(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)