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
;
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
, str
)
360 /* get internal structure */
363 state
= (gz_statep
)file
;
365 /* check that we're writing and that there's no error */
366 if (state
->mode
!= GZ_WRITE
|| state
->err
!= Z_OK
)
371 ret
= gz_write(state
, str
, len
);
372 return ret
== 0 && len
!= 0 ? -1 : ret
;
375 #if defined(STDC) || defined(Z_HAVE_STDARG_H)
378 /* -- see zlib.h -- */
379 int ZEXPORTVA
gzvprintf(gzFile file
, const char *format
, va_list va
)
387 /* get internal structure */
389 return Z_STREAM_ERROR
;
390 state
= (gz_statep
)file
;
391 strm
= &(state
->strm
);
393 /* check that we're writing and that there's no error */
394 if (state
->mode
!= GZ_WRITE
|| state
->err
!= Z_OK
)
395 return Z_STREAM_ERROR
;
397 /* make sure we have some buffer space */
398 if (state
->size
== 0 && gz_init(state
) == -1)
401 /* check for seek request */
404 if (gz_zero(state
, state
->skip
) == -1)
408 /* do the printf() into the input buffer, put length in len -- the input
409 buffer is double-sized just for this function, so there is guaranteed to
410 be state->size bytes available after the current contents */
411 if (strm
->avail_in
== 0)
412 strm
->next_in
= state
->in
;
413 next
= (char *)(state
->in
+ (strm
->next_in
- state
->in
) + strm
->avail_in
);
414 next
[state
->size
- 1] = 0;
416 # ifdef HAS_vsprintf_void
417 (void)vsprintf(next
, format
, va
);
418 for (len
= 0; len
< state
->size
; len
++)
419 if (next
[len
] == 0) break;
421 len
= vsprintf(next
, format
, va
);
424 # ifdef HAS_vsnprintf_void
425 (void)vsnprintf(next
, state
->size
, format
, va
);
428 len
= vsnprintf(next
, state
->size
, format
, va
);
432 /* check that printf() results fit in buffer */
433 if (len
== 0 || (unsigned)len
>= state
->size
|| next
[state
->size
- 1] != 0)
436 /* update buffer and position, compress first half if past that */
437 strm
->avail_in
+= (unsigned)len
;
439 if (strm
->avail_in
>= state
->size
) {
440 left
= strm
->avail_in
- state
->size
;
441 strm
->avail_in
= state
->size
;
442 if (gz_comp(state
, Z_NO_FLUSH
) == -1)
444 memcpy(state
->in
, state
->in
+ state
->size
, left
);
445 strm
->next_in
= state
->in
;
446 strm
->avail_in
= left
;
451 int ZEXPORTVA
gzprintf(gzFile file
, const char *format
, ...)
456 va_start(va
, format
);
457 ret
= gzvprintf(file
, format
, va
);
462 #else /* !STDC && !Z_HAVE_STDARG_H */
464 /* -- see zlib.h -- */
465 int ZEXPORTVA
gzprintf (file
, format
, a1
, a2
, a3
, a4
, a5
, a6
, a7
, a8
, a9
, a10
,
466 a11
, a12
, a13
, a14
, a15
, a16
, a17
, a18
, a19
, a20
)
469 int a1
, a2
, a3
, a4
, a5
, a6
, a7
, a8
, a9
, a10
,
470 a11
, a12
, a13
, a14
, a15
, a16
, a17
, a18
, a19
, a20
;
477 /* get internal structure */
479 return Z_STREAM_ERROR
;
480 state
= (gz_statep
)file
;
481 strm
= &(state
->strm
);
483 /* check that can really pass pointer in ints */
484 if (sizeof(int) != sizeof(void *))
485 return Z_STREAM_ERROR
;
487 /* check that we're writing and that there's no error */
488 if (state
->mode
!= GZ_WRITE
|| state
->err
!= Z_OK
)
489 return Z_STREAM_ERROR
;
491 /* make sure we have some buffer space */
492 if (state
->size
== 0 && gz_init(state
) == -1)
495 /* check for seek request */
498 if (gz_zero(state
, state
->skip
) == -1)
502 /* do the printf() into the input buffer, put length in len -- the input
503 buffer is double-sized just for this function, so there is guaranteed to
504 be state->size bytes available after the current contents */
505 if (strm
->avail_in
== 0)
506 strm
->next_in
= state
->in
;
507 next
= (char *)(strm
->next_in
+ strm
->avail_in
);
508 next
[state
->size
- 1] = 0;
510 # ifdef HAS_sprintf_void
511 sprintf(next
, format
, a1
, a2
, a3
, a4
, a5
, a6
, a7
, a8
, a9
, a10
, a11
, a12
,
512 a13
, a14
, a15
, a16
, a17
, a18
, a19
, a20
);
513 for (len
= 0; len
< size
; len
++)
517 len
= sprintf(next
, format
, a1
, a2
, a3
, a4
, a5
, a6
, a7
, a8
, a9
, a10
, a11
,
518 a12
, a13
, a14
, a15
, a16
, a17
, a18
, a19
, a20
);
521 # ifdef HAS_snprintf_void
522 snprintf(next
, state
->size
, format
, a1
, a2
, a3
, a4
, a5
, a6
, a7
, a8
, a9
,
523 a10
, a11
, a12
, a13
, a14
, a15
, a16
, a17
, a18
, a19
, a20
);
526 len
= snprintf(next
, state
->size
, format
, a1
, a2
, a3
, a4
, a5
, a6
, a7
, a8
,
527 a9
, a10
, a11
, a12
, a13
, a14
, a15
, a16
, a17
, a18
, a19
, a20
);
531 /* check that printf() results fit in buffer */
532 if (len
== 0 || len
>= state
->size
|| next
[state
->size
- 1] != 0)
535 /* update buffer and position, compress first half if past that */
536 strm
->avail_in
+= len
;
538 if (strm
->avail_in
>= state
->size
) {
539 left
= strm
->avail_in
- state
->size
;
540 strm
->avail_in
= state
->size
;
541 if (gz_comp(state
, Z_NO_FLUSH
) == -1)
543 memcpy(state
->in
, state
->in
+ state
->size
, left
);
544 strm
->next_in
= state
->in
;
545 strm
->avail_in
= left
;
552 /* -- see zlib.h -- */
553 int ZEXPORT
gzflush(file
, flush
)
559 /* get internal structure */
561 return Z_STREAM_ERROR
;
562 state
= (gz_statep
)file
;
564 /* check that we're writing and that there's no error */
565 if (state
->mode
!= GZ_WRITE
|| state
->err
!= Z_OK
)
566 return Z_STREAM_ERROR
;
568 /* check flush parameter */
569 if (flush
< 0 || flush
> Z_FINISH
)
570 return Z_STREAM_ERROR
;
572 /* check for seek request */
575 if (gz_zero(state
, state
->skip
) == -1)
579 /* compress remaining data with requested flush */
580 (void)gz_comp(state
, flush
);
584 /* -- see zlib.h -- */
585 int ZEXPORT
gzsetparams(file
, level
, strategy
)
593 /* get internal structure */
595 return Z_STREAM_ERROR
;
596 state
= (gz_statep
)file
;
597 strm
= &(state
->strm
);
599 /* check that we're writing and that there's no error */
600 if (state
->mode
!= GZ_WRITE
|| state
->err
!= Z_OK
)
601 return Z_STREAM_ERROR
;
603 /* if no change is requested, then do nothing */
604 if (level
== state
->level
&& strategy
== state
->strategy
)
607 /* check for seek request */
610 if (gz_zero(state
, state
->skip
) == -1)
614 /* change compression parameters for subsequent input */
616 /* flush previous input with previous parameters before changing */
617 if (strm
->avail_in
&& gz_comp(state
, Z_BLOCK
) == -1)
619 deflateParams(strm
, level
, strategy
);
621 state
->level
= level
;
622 state
->strategy
= strategy
;
626 /* -- see zlib.h -- */
627 int ZEXPORT
gzclose_w(file
)
633 /* get internal structure */
635 return Z_STREAM_ERROR
;
636 state
= (gz_statep
)file
;
638 /* check that we're writing */
639 if (state
->mode
!= GZ_WRITE
)
640 return Z_STREAM_ERROR
;
642 /* check for seek request */
645 if (gz_zero(state
, state
->skip
) == -1)
649 /* flush, free memory, and close file */
650 if (gz_comp(state
, Z_FINISH
) == -1)
653 if (!state
->direct
) {
654 (void)deflateEnd(&(state
->strm
));
659 gz_error(state
, Z_OK
, NULL
);
661 if (close(state
->fd
) == -1)