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 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 /* check for a pending reset */
102 /* don't start a new gzip member unless there is data to write */
103 if (strm
->avail_in
== 0)
109 /* run deflate() on provided input until it produces no more output */
112 /* write out current buffer contents if full, or if flushing, but if
113 doing Z_FINISH then don't write until we get to Z_STREAM_END */
114 if (strm
->avail_out
== 0 || (flush
!= Z_NO_FLUSH
&&
115 (flush
!= Z_FINISH
|| ret
== Z_STREAM_END
))) {
116 while (strm
->next_out
> state
->x
.next
) {
117 put
= strm
->next_out
- state
->x
.next
> (int)max
? max
:
118 (unsigned)(strm
->next_out
- state
->x
.next
);
119 writ
= write(state
->fd
, state
->x
.next
, put
);
121 gz_error(state
, Z_ERRNO
, zstrerror());
124 state
->x
.next
+= writ
;
126 if (strm
->avail_out
== 0) {
127 strm
->avail_out
= state
->size
;
128 strm
->next_out
= state
->out
;
129 state
->x
.next
= state
->out
;
134 have
= strm
->avail_out
;
135 ret
= deflate(strm
, flush
);
136 if (ret
== Z_STREAM_ERROR
) {
137 gz_error(state
, Z_STREAM_ERROR
,
138 "internal error: deflate stream corrupt");
141 have
-= strm
->avail_out
;
144 /* if that completed a deflate stream, allow another to start */
145 if (flush
== Z_FINISH
)
148 /* all done, no errors */
152 /* Compress len zeros to output. Return -1 on a write error or memory
153 allocation failure by gz_comp(), or 0 on success. */
154 local
int gz_zero(state
, len
)
160 z_streamp strm
= &(state
->strm
);
162 /* consume whatever's left in the input buffer */
163 if (strm
->avail_in
&& gz_comp(state
, Z_NO_FLUSH
) == -1)
166 /* compress len zeros (len guaranteed > 0) */
169 n
= GT_OFF(state
->size
) || (z_off64_t
)state
->size
> len
?
170 (unsigned)len
: state
->size
;
172 memset(state
->in
, 0, n
);
176 strm
->next_in
= state
->in
;
178 if (gz_comp(state
, Z_NO_FLUSH
) == -1)
185 /* Write len bytes from buf to file. Return the number of bytes written. If
186 the returned value is less than len, then there was an error. */
187 local z_size_t
gz_write(state
, buf
, len
)
194 /* if len is zero, avoid unnecessary operations */
198 /* allocate memory if this is the first time through */
199 if (state
->size
== 0 && gz_init(state
) == -1)
202 /* check for seek request */
205 if (gz_zero(state
, state
->skip
) == -1)
209 /* for small len, copy to input buffer, otherwise compress directly */
210 if (len
< state
->size
) {
211 /* copy to input buffer, compress when full */
215 if (state
->strm
.avail_in
== 0)
216 state
->strm
.next_in
= state
->in
;
217 have
= (unsigned)((state
->strm
.next_in
+ state
->strm
.avail_in
) -
219 copy
= state
->size
- have
;
221 copy
= (unsigned)len
;
222 memcpy(state
->in
+ have
, buf
, copy
);
223 state
->strm
.avail_in
+= copy
;
224 state
->x
.pos
+= copy
;
225 buf
= (const char *)buf
+ copy
;
227 if (len
&& gz_comp(state
, Z_NO_FLUSH
) == -1)
232 /* consume whatever's left in the input buffer */
233 if (state
->strm
.avail_in
&& gz_comp(state
, Z_NO_FLUSH
) == -1)
236 /* directly compress user buffer to file */
237 state
->strm
.next_in
= (z_const Bytef
*)buf
;
239 unsigned n
= (unsigned)-1;
242 state
->strm
.avail_in
= n
;
244 if (gz_comp(state
, Z_NO_FLUSH
) == -1)
250 /* input was all buffered or compressed */
254 /* -- see zlib.h -- */
255 int ZEXPORT
gzwrite(file
, buf
, len
)
262 /* get internal structure */
265 state
= (gz_statep
)file
;
267 /* check that we're writing and that there's no error */
268 if (state
->mode
!= GZ_WRITE
|| state
->err
!= Z_OK
)
271 /* since an int is returned, make sure len fits in one, otherwise return
272 with an error (this avoids a flaw in the interface) */
274 gz_error(state
, Z_DATA_ERROR
, "requested length does not fit in int");
278 /* write len bytes from buf (the return value will fit in an int) */
279 return (int)gz_write(state
, buf
, len
);
282 /* -- see zlib.h -- */
283 z_size_t ZEXPORT
gzfwrite(buf
, size
, nitems
, file
)
292 /* get internal structure */
295 state
= (gz_statep
)file
;
297 /* check that we're writing and that there's no error */
298 if (state
->mode
!= GZ_WRITE
|| state
->err
!= Z_OK
)
301 /* compute bytes to read -- error on overflow */
303 if (size
&& len
/ size
!= nitems
) {
304 gz_error(state
, Z_STREAM_ERROR
, "request does not fit in a size_t");
308 /* write len bytes to buf, return the number of full items written */
309 return len
? gz_write(state
, buf
, len
) / size
: 0;
312 /* -- see zlib.h -- */
313 int ZEXPORT
gzputc(file
, c
)
318 unsigned char buf
[1];
322 /* get internal structure */
325 state
= (gz_statep
)file
;
326 strm
= &(state
->strm
);
328 /* check that we're writing and that there's no error */
329 if (state
->mode
!= GZ_WRITE
|| state
->err
!= Z_OK
)
332 /* check for seek request */
335 if (gz_zero(state
, state
->skip
) == -1)
339 /* try writing to input buffer for speed (state->size == 0 if buffer not
342 if (strm
->avail_in
== 0)
343 strm
->next_in
= state
->in
;
344 have
= (unsigned)((strm
->next_in
+ strm
->avail_in
) - state
->in
);
345 if (have
< state
->size
) {
346 state
->in
[have
] = (unsigned char)c
;
353 /* no room in buffer or not initialized, use gz_write() */
354 buf
[0] = (unsigned char)c
;
355 if (gz_write(state
, buf
, 1) != 1)
360 /* -- see zlib.h -- */
361 int ZEXPORT
gzputs(file
, s
)
368 /* get internal structure */
371 state
= (gz_statep
)file
;
373 /* check that we're writing and that there's no error */
374 if (state
->mode
!= GZ_WRITE
|| state
->err
!= Z_OK
)
379 if ((int)len
< 0 || (unsigned)len
!= len
) {
380 gz_error(state
, Z_STREAM_ERROR
, "string length does not fit in int");
383 put
= gz_write(state
, s
, len
);
384 return put
< len
? -1 : (int)len
;
387 #if defined(STDC) || defined(Z_HAVE_STDARG_H)
390 /* -- see zlib.h -- */
391 int ZEXPORTVA
gzvprintf(gzFile file
, const char *format
, va_list va
)
399 /* get internal structure */
401 return Z_STREAM_ERROR
;
402 state
= (gz_statep
)file
;
403 strm
= &(state
->strm
);
405 /* check that we're writing and that there's no error */
406 if (state
->mode
!= GZ_WRITE
|| state
->err
!= Z_OK
)
407 return Z_STREAM_ERROR
;
409 /* make sure we have some buffer space */
410 if (state
->size
== 0 && gz_init(state
) == -1)
413 /* check for seek request */
416 if (gz_zero(state
, state
->skip
) == -1)
420 /* do the printf() into the input buffer, put length in len -- the input
421 buffer is double-sized just for this function, so there is guaranteed to
422 be state->size bytes available after the current contents */
423 if (strm
->avail_in
== 0)
424 strm
->next_in
= state
->in
;
425 next
= (char *)(state
->in
+ (strm
->next_in
- state
->in
) + strm
->avail_in
);
426 next
[state
->size
- 1] = 0;
428 # ifdef HAS_vsprintf_void
429 (void)vsprintf(next
, format
, va
);
430 for (len
= 0; len
< state
->size
; len
++)
431 if (next
[len
] == 0) break;
433 len
= vsprintf(next
, format
, va
);
436 # ifdef HAS_vsnprintf_void
437 (void)vsnprintf(next
, state
->size
, format
, va
);
440 len
= vsnprintf(next
, state
->size
, format
, va
);
444 /* check that printf() results fit in buffer */
445 if (len
== 0 || (unsigned)len
>= state
->size
|| next
[state
->size
- 1] != 0)
448 /* update buffer and position, compress first half if past that */
449 strm
->avail_in
+= (unsigned)len
;
451 if (strm
->avail_in
>= state
->size
) {
452 left
= strm
->avail_in
- state
->size
;
453 strm
->avail_in
= state
->size
;
454 if (gz_comp(state
, Z_NO_FLUSH
) == -1)
456 memmove(state
->in
, state
->in
+ state
->size
, left
);
457 strm
->next_in
= state
->in
;
458 strm
->avail_in
= left
;
463 int ZEXPORTVA
gzprintf(gzFile file
, const char *format
, ...)
468 va_start(va
, format
);
469 ret
= gzvprintf(file
, format
, va
);
474 #else /* !STDC && !Z_HAVE_STDARG_H */
476 /* -- see zlib.h -- */
477 int ZEXPORTVA
gzprintf (file
, format
, a1
, a2
, a3
, a4
, a5
, a6
, a7
, a8
, a9
, a10
,
478 a11
, a12
, a13
, a14
, a15
, a16
, a17
, a18
, a19
, a20
)
481 int a1
, a2
, a3
, a4
, a5
, a6
, a7
, a8
, a9
, a10
,
482 a11
, a12
, a13
, a14
, a15
, a16
, a17
, a18
, a19
, a20
;
489 /* get internal structure */
491 return Z_STREAM_ERROR
;
492 state
= (gz_statep
)file
;
493 strm
= &(state
->strm
);
495 /* check that can really pass pointer in ints */
496 if (sizeof(int) != sizeof(void *))
497 return Z_STREAM_ERROR
;
499 /* check that we're writing and that there's no error */
500 if (state
->mode
!= GZ_WRITE
|| state
->err
!= Z_OK
)
501 return Z_STREAM_ERROR
;
503 /* make sure we have some buffer space */
504 if (state
->size
== 0 && gz_init(state
) == -1)
507 /* check for seek request */
510 if (gz_zero(state
, state
->skip
) == -1)
514 /* do the printf() into the input buffer, put length in len -- the input
515 buffer is double-sized just for this function, so there is guaranteed to
516 be state->size bytes available after the current contents */
517 if (strm
->avail_in
== 0)
518 strm
->next_in
= state
->in
;
519 next
= (char *)(strm
->next_in
+ strm
->avail_in
);
520 next
[state
->size
- 1] = 0;
522 # ifdef HAS_sprintf_void
523 sprintf(next
, format
, a1
, a2
, a3
, a4
, a5
, a6
, a7
, a8
, a9
, a10
, a11
, a12
,
524 a13
, a14
, a15
, a16
, a17
, a18
, a19
, a20
);
525 for (len
= 0; len
< size
; len
++)
529 len
= sprintf(next
, format
, a1
, a2
, a3
, a4
, a5
, a6
, a7
, a8
, a9
, a10
, a11
,
530 a12
, a13
, a14
, a15
, a16
, a17
, a18
, a19
, a20
);
533 # ifdef HAS_snprintf_void
534 snprintf(next
, state
->size
, format
, a1
, a2
, a3
, a4
, a5
, a6
, a7
, a8
, a9
,
535 a10
, a11
, a12
, a13
, a14
, a15
, a16
, a17
, a18
, a19
, a20
);
538 len
= snprintf(next
, state
->size
, format
, a1
, a2
, a3
, a4
, a5
, a6
, a7
, a8
,
539 a9
, a10
, a11
, a12
, a13
, a14
, a15
, a16
, a17
, a18
, a19
, a20
);
543 /* check that printf() results fit in buffer */
544 if (len
== 0 || len
>= state
->size
|| next
[state
->size
- 1] != 0)
547 /* update buffer and position, compress first half if past that */
548 strm
->avail_in
+= len
;
550 if (strm
->avail_in
>= state
->size
) {
551 left
= strm
->avail_in
- state
->size
;
552 strm
->avail_in
= state
->size
;
553 if (gz_comp(state
, Z_NO_FLUSH
) == -1)
555 memmove(state
->in
, state
->in
+ state
->size
, left
);
556 strm
->next_in
= state
->in
;
557 strm
->avail_in
= left
;
564 /* -- see zlib.h -- */
565 int ZEXPORT
gzflush(file
, flush
)
571 /* get internal structure */
573 return Z_STREAM_ERROR
;
574 state
= (gz_statep
)file
;
576 /* check that we're writing and that there's no error */
577 if (state
->mode
!= GZ_WRITE
|| state
->err
!= Z_OK
)
578 return Z_STREAM_ERROR
;
580 /* check flush parameter */
581 if (flush
< 0 || flush
> Z_FINISH
)
582 return Z_STREAM_ERROR
;
584 /* check for seek request */
587 if (gz_zero(state
, state
->skip
) == -1)
591 /* compress remaining data with requested flush */
592 (void)gz_comp(state
, flush
);
596 /* -- see zlib.h -- */
597 int ZEXPORT
gzsetparams(file
, level
, strategy
)
605 /* get internal structure */
607 return Z_STREAM_ERROR
;
608 state
= (gz_statep
)file
;
609 strm
= &(state
->strm
);
611 /* check that we're writing and that there's no error */
612 if (state
->mode
!= GZ_WRITE
|| state
->err
!= Z_OK
)
613 return Z_STREAM_ERROR
;
615 /* if no change is requested, then do nothing */
616 if (level
== state
->level
&& strategy
== state
->strategy
)
619 /* check for seek request */
622 if (gz_zero(state
, state
->skip
) == -1)
626 /* change compression parameters for subsequent input */
628 /* flush previous input with previous parameters before changing */
629 if (strm
->avail_in
&& gz_comp(state
, Z_BLOCK
) == -1)
631 deflateParams(strm
, level
, strategy
);
633 state
->level
= level
;
634 state
->strategy
= strategy
;
638 /* -- see zlib.h -- */
639 int ZEXPORT
gzclose_w(file
)
645 /* get internal structure */
647 return Z_STREAM_ERROR
;
648 state
= (gz_statep
)file
;
650 /* check that we're writing */
651 if (state
->mode
!= GZ_WRITE
)
652 return Z_STREAM_ERROR
;
654 /* check for seek request */
657 if (gz_zero(state
, state
->skip
) == -1)
661 /* flush, free memory, and close file */
662 if (gz_comp(state
, Z_FINISH
) == -1)
665 if (!state
->direct
) {
666 (void)deflateEnd(&(state
->strm
));
671 gz_error(state
, Z_OK
, NULL
);
673 if (close(state
->fd
) == -1)