1 /* gzwrite.c -- zlib functions for writing gzip files
2 * Copyright (C) 2004, 2005, 2010 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
));
13 /* Initialize state for writing a gzip file. Mark initialization by setting
14 state->size to non-zero. Return -1 on failure or 0 on success. */
15 local
int gz_init(state
)
19 z_streamp strm
= &(state
->strm
);
21 /* allocate input and output buffers */
22 state
->in
= malloc(state
->want
);
23 state
->out
= malloc(state
->want
);
24 if (state
->in
== NULL
|| state
->out
== NULL
) {
25 if (state
->out
!= NULL
)
27 if (state
->in
!= NULL
)
29 gz_error(state
, Z_MEM_ERROR
, "out of memory");
33 /* allocate deflate memory, set up for gzip compression */
34 strm
->zalloc
= Z_NULL
;
36 strm
->opaque
= Z_NULL
;
37 ret
= deflateInit2(strm
, state
->level
, Z_DEFLATED
,
38 15 + 16, 8, state
->strategy
);
41 gz_error(state
, Z_MEM_ERROR
, "out of memory");
45 /* mark state as initialized */
46 state
->size
= state
->want
;
48 /* initialize write buffer */
49 strm
->avail_out
= state
->size
;
50 strm
->next_out
= state
->out
;
51 state
->next
= strm
->next_out
;
55 /* Compress whatever is at avail_in and next_in and write to the output file.
56 Return -1 if there is an error writing to the output file, otherwise 0.
57 flush is assumed to be a valid deflate() flush value. If flush is Z_FINISH,
58 then the deflate() state is reset to start a new gzip stream. */
59 local
int gz_comp(state
, flush
)
65 z_streamp strm
= &(state
->strm
);
67 /* allocate memory if this is the first time through */
68 if (state
->size
== 0 && gz_init(state
) == -1)
71 /* run deflate() on provided input until it produces no more output */
74 /* write out current buffer contents if full, or if flushing, but if
75 doing Z_FINISH then don't write until we get to Z_STREAM_END */
76 if (strm
->avail_out
== 0 || (flush
!= Z_NO_FLUSH
&&
77 (flush
!= Z_FINISH
|| ret
== Z_STREAM_END
))) {
78 have
= (unsigned)(strm
->next_out
- state
->next
);
79 if (have
&& ((got
= write(state
->fd
, state
->next
, have
)) < 0 ||
80 (unsigned)got
!= have
)) {
81 gz_error(state
, Z_ERRNO
, zstrerror());
84 if (strm
->avail_out
== 0) {
85 strm
->avail_out
= state
->size
;
86 strm
->next_out
= state
->out
;
88 state
->next
= strm
->next_out
;
92 have
= strm
->avail_out
;
93 ret
= deflate(strm
, flush
);
94 if (ret
== Z_STREAM_ERROR
) {
95 gz_error(state
, Z_STREAM_ERROR
,
96 "internal error: deflate stream corrupt");
99 have
-= strm
->avail_out
;
102 /* if that completed a deflate stream, allow another to start */
103 if (flush
== Z_FINISH
)
106 /* all done, no errors */
110 /* Compress len zeros to output. Return -1 on error, 0 on success. */
111 local
int gz_zero(state
, len
)
117 z_streamp strm
= &(state
->strm
);
119 /* consume whatever's left in the input buffer */
120 if (strm
->avail_in
&& gz_comp(state
, Z_NO_FLUSH
) == -1)
123 /* compress len zeros (len guaranteed > 0) */
126 n
= GT_OFF(state
->size
) || (z_off64_t
)state
->size
> len
?
127 (unsigned)len
: state
->size
;
129 memset(state
->in
, 0, n
);
133 strm
->next_in
= state
->in
;
135 if (gz_comp(state
, Z_NO_FLUSH
) == -1)
142 /* -- see zlib.h -- */
143 int ZEXPORT
gzwrite(file
, buf
, len
)
153 /* get internal structure */
156 state
= (gz_statep
)file
;
157 strm
= &(state
->strm
);
159 /* check that we're writing and that there's no error */
160 if (state
->mode
!= GZ_WRITE
|| state
->err
!= Z_OK
)
163 /* since an int is returned, make sure len fits in one, otherwise return
164 with an error (this avoids the flaw in the interface) */
166 gz_error(state
, Z_BUF_ERROR
, "requested length does not fit in int");
170 /* if len is zero, avoid unnecessary operations */
174 /* allocate memory if this is the first time through */
175 if (state
->size
== 0 && gz_init(state
) == -1)
178 /* check for seek request */
181 if (gz_zero(state
, state
->skip
) == -1)
185 /* for small len, copy to input buffer, otherwise compress directly */
186 if (len
< state
->size
) {
187 /* copy to input buffer, compress when full */
189 if (strm
->avail_in
== 0)
190 strm
->next_in
= state
->in
;
191 n
= state
->size
- strm
->avail_in
;
194 memcpy(strm
->next_in
+ strm
->avail_in
, buf
, n
);
197 buf
= (char *)buf
+ n
;
199 if (len
&& gz_comp(state
, Z_NO_FLUSH
) == -1)
204 /* consume whatever's left in the input buffer */
205 if (strm
->avail_in
&& gz_comp(state
, Z_NO_FLUSH
) == -1)
208 /* directly compress user buffer to file */
209 strm
->avail_in
= len
;
210 strm
->next_in
= (voidp
)buf
;
212 if (gz_comp(state
, Z_NO_FLUSH
) == -1)
216 /* input was all buffered or compressed (put will fit in int) */
220 /* -- see zlib.h -- */
221 int ZEXPORT
gzputc(file
, c
)
225 unsigned char buf
[1];
229 /* get internal structure */
232 state
= (gz_statep
)file
;
233 strm
= &(state
->strm
);
235 /* check that we're writing and that there's no error */
236 if (state
->mode
!= GZ_WRITE
|| state
->err
!= Z_OK
)
239 /* check for seek request */
242 if (gz_zero(state
, state
->skip
) == -1)
246 /* try writing to input buffer for speed (state->size == 0 if buffer not
248 if (strm
->avail_in
< state
->size
) {
249 if (strm
->avail_in
== 0)
250 strm
->next_in
= state
->in
;
251 strm
->next_in
[strm
->avail_in
++] = c
;
256 /* no room in buffer or not initialized, use gz_write() */
258 if (gzwrite(file
, buf
, 1) != 1)
263 /* -- see zlib.h -- */
264 int ZEXPORT
gzputs(file
, str
)
272 len
= (unsigned)strlen(str
);
273 ret
= gzwrite(file
, str
, len
);
274 return ret
== 0 && len
!= 0 ? -1 : ret
;
280 /* -- see zlib.h -- */
281 int ZEXPORTVA
gzprintf (gzFile file
, const char *format
, ...)
288 /* get internal structure */
291 state
= (gz_statep
)file
;
292 strm
= &(state
->strm
);
294 /* check that we're writing and that there's no error */
295 if (state
->mode
!= GZ_WRITE
|| state
->err
!= Z_OK
)
298 /* make sure we have some buffer space */
299 if (state
->size
== 0 && gz_init(state
) == -1)
302 /* check for seek request */
305 if (gz_zero(state
, state
->skip
) == -1)
309 /* consume whatever's left in the input buffer */
310 if (strm
->avail_in
&& gz_comp(state
, Z_NO_FLUSH
) == -1)
313 /* do the printf() into the input buffer, put length in len */
314 size
= (int)(state
->size
);
315 state
->in
[size
- 1] = 0;
316 va_start(va
, format
);
318 # ifdef HAS_vsprintf_void
319 (void)vsprintf(state
->in
, format
, va
);
321 for (len
= 0; len
< size
; len
++)
322 if (state
->in
[len
] == 0) break;
324 len
= vsprintf(state
->in
, format
, va
);
328 # ifdef HAS_vsnprintf_void
329 (void)vsnprintf(state
->in
, size
, format
, va
);
331 len
= strlen(state
->in
);
333 len
= vsnprintf((char *)(state
->in
), size
, format
, va
);
338 /* check that printf() results fit in buffer */
339 if (len
<= 0 || len
>= (int)size
|| state
->in
[size
- 1] != 0)
342 /* update buffer and position, defer compression until needed */
343 strm
->avail_in
= (unsigned)len
;
344 strm
->next_in
= state
->in
;
351 /* -- see zlib.h -- */
352 int ZEXPORTVA
gzprintf (file
, format
, a1
, a2
, a3
, a4
, a5
, a6
, a7
, a8
, a9
, a10
,
353 a11
, a12
, a13
, a14
, a15
, a16
, a17
, a18
, a19
, a20
)
356 int a1
, a2
, a3
, a4
, a5
, a6
, a7
, a8
, a9
, a10
,
357 a11
, a12
, a13
, a14
, a15
, a16
, a17
, a18
, a19
, a20
;
363 /* get internal structure */
366 state
= (gz_statep
)file
;
367 strm
= &(state
->strm
);
369 /* check that we're writing and that there's no error */
370 if (state
->mode
!= GZ_WRITE
|| state
->err
!= Z_OK
)
373 /* make sure we have some buffer space */
374 if (state
->size
== 0 && gz_init(state
) == -1)
377 /* check for seek request */
380 if (gz_zero(state
, state
->skip
) == -1)
384 /* consume whatever's left in the input buffer */
385 if (strm
->avail_in
&& gz_comp(state
, Z_NO_FLUSH
) == -1)
388 /* do the printf() into the input buffer, put length in len */
389 size
= (int)(state
->size
);
390 state
->in
[size
- 1] = 0;
392 # ifdef HAS_sprintf_void
393 sprintf(state
->in
, format
, a1
, a2
, a3
, a4
, a5
, a6
, a7
, a8
,
394 a9
, a10
, a11
, a12
, a13
, a14
, a15
, a16
, a17
, a18
, a19
, a20
);
395 for (len
= 0; len
< size
; len
++)
396 if (state
->in
[len
] == 0) break;
398 len
= sprintf(state
->in
, format
, a1
, a2
, a3
, a4
, a5
, a6
, a7
, a8
,
399 a9
, a10
, a11
, a12
, a13
, a14
, a15
, a16
, a17
, a18
, a19
, a20
);
402 # ifdef HAS_snprintf_void
403 snprintf(state
->in
, size
, format
, a1
, a2
, a3
, a4
, a5
, a6
, a7
, a8
,
404 a9
, a10
, a11
, a12
, a13
, a14
, a15
, a16
, a17
, a18
, a19
, a20
);
405 len
= strlen(state
->in
);
407 len
= snprintf(state
->in
, size
, format
, a1
, a2
, a3
, a4
, a5
, a6
, a7
, a8
,
408 a9
, a10
, a11
, a12
, a13
, a14
, a15
, a16
, a17
, a18
, a19
, a20
);
412 /* check that printf() results fit in buffer */
413 if (len
<= 0 || len
>= (int)size
|| state
->in
[size
- 1] != 0)
416 /* update buffer and position, defer compression until needed */
417 strm
->avail_in
= (unsigned)len
;
418 strm
->next_in
= state
->in
;
425 /* -- see zlib.h -- */
426 int ZEXPORT
gzflush(file
, flush
)
432 /* get internal structure */
435 state
= (gz_statep
)file
;
437 /* check that we're writing and that there's no error */
438 if (state
->mode
!= GZ_WRITE
|| state
->err
!= Z_OK
)
439 return Z_STREAM_ERROR
;
441 /* check flush parameter */
442 if (flush
< 0 || flush
> Z_FINISH
)
443 return Z_STREAM_ERROR
;
445 /* check for seek request */
448 if (gz_zero(state
, state
->skip
) == -1)
452 /* compress remaining data with requested flush */
453 gz_comp(state
, flush
);
457 /* -- see zlib.h -- */
458 int ZEXPORT
gzsetparams(file
, level
, strategy
)
466 /* get internal structure */
468 return Z_STREAM_ERROR
;
469 state
= (gz_statep
)file
;
470 strm
= &(state
->strm
);
472 /* check that we're writing and that there's no error */
473 if (state
->mode
!= GZ_WRITE
|| state
->err
!= Z_OK
)
474 return Z_STREAM_ERROR
;
476 /* if no change is requested, then do nothing */
477 if (level
== state
->level
&& strategy
== state
->strategy
)
480 /* check for seek request */
483 if (gz_zero(state
, state
->skip
) == -1)
487 /* change compression parameters for subsequent input */
489 /* flush previous input with previous parameters before changing */
490 if (strm
->avail_in
&& gz_comp(state
, Z_PARTIAL_FLUSH
) == -1)
492 deflateParams(strm
, level
, strategy
);
494 state
->level
= level
;
495 state
->strategy
= strategy
;
499 /* -- see zlib.h -- */
500 int ZEXPORT
gzclose_w(file
)
506 /* get internal structure */
508 return Z_STREAM_ERROR
;
509 state
= (gz_statep
)file
;
511 /* check that we're writing */
512 if (state
->mode
!= GZ_WRITE
)
513 return Z_STREAM_ERROR
;
515 /* check for seek request */
518 ret
+= gz_zero(state
, state
->skip
);
521 /* flush, free memory, and close file */
522 ret
+= gz_comp(state
, Z_FINISH
);
523 (void)deflateEnd(&(state
->strm
));
526 gz_error(state
, Z_OK
, NULL
);
528 ret
+= close(state
->fd
);
530 return ret
? Z_ERRNO
: Z_OK
;