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
11 local
int gz_init
OF((gz_statep
));
12 local
int gz_comp
OF((gz_statep
, int));
13 local
int gz_zero
OF((gz_statep
, z_off64_t
));
15 /* Initialize state for writing a gzip file. Mark initialization by setting
16 state->size to non-zero. Return -1 on failure or 0 on success. */
17 local
int gz_init(state
)
21 z_streamp strm
= &(state
->strm
);
23 /* allocate input and output buffers */
24 state
->in
= malloc(state
->want
);
25 state
->out
= malloc(state
->want
);
26 if (state
->in
== NULL
|| state
->out
== NULL
) {
27 if (state
->out
!= NULL
)
29 if (state
->in
!= NULL
)
31 gz_error(state
, Z_MEM_ERROR
, "out of memory");
35 /* allocate deflate memory, set up for gzip compression */
36 strm
->zalloc
= Z_NULL
;
38 strm
->opaque
= Z_NULL
;
39 ret
= deflateInit2(strm
, state
->level
, Z_DEFLATED
,
40 15 + 16, 8, state
->strategy
);
43 gz_error(state
, Z_MEM_ERROR
, "out of memory");
47 /* mark state as initialized */
48 state
->size
= state
->want
;
50 /* initialize write buffer */
51 strm
->avail_out
= state
->size
;
52 strm
->next_out
= state
->out
;
53 state
->next
= strm
->next_out
;
57 /* Compress whatever is at avail_in and next_in and write to the output file.
58 Return -1 if there is an error writing to the output file, otherwise 0.
59 flush is assumed to be a valid deflate() flush value. If flush is Z_FINISH,
60 then the deflate() state is reset to start a new gzip stream. */
61 local
int gz_comp(state
, flush
)
67 z_streamp strm
= &(state
->strm
);
69 /* allocate memory if this is the first time through */
70 if (state
->size
== 0 && gz_init(state
) == -1)
73 /* run deflate() on provided input until it produces no more output */
76 /* write out current buffer contents if full, or if flushing, but if
77 doing Z_FINISH then don't write until we get to Z_STREAM_END */
78 if (strm
->avail_out
== 0 || (flush
!= Z_NO_FLUSH
&&
79 (flush
!= Z_FINISH
|| ret
== Z_STREAM_END
))) {
80 have
= (unsigned)(strm
->next_out
- state
->next
);
81 if (have
&& ((got
= write(state
->fd
, state
->next
, have
)) < 0 ||
82 (unsigned)got
!= have
)) {
83 gz_error(state
, Z_ERRNO
, zstrerror());
86 if (strm
->avail_out
== 0) {
87 strm
->avail_out
= state
->size
;
88 strm
->next_out
= state
->out
;
90 state
->next
= strm
->next_out
;
94 have
= strm
->avail_out
;
95 ret
= deflate(strm
, flush
);
96 if (ret
== Z_STREAM_ERROR
) {
97 gz_error(state
, Z_STREAM_ERROR
,
98 "internal error: deflate stream corrupt");
101 have
-= strm
->avail_out
;
104 /* if that completed a deflate stream, allow another to start */
105 if (flush
== Z_FINISH
)
108 /* all done, no errors */
112 /* Compress len zeros to output. Return -1 on error, 0 on success. */
113 local
int gz_zero(state
, len
)
119 z_streamp strm
= &(state
->strm
);
121 /* consume whatever's left in the input buffer */
122 if (strm
->avail_in
&& gz_comp(state
, Z_NO_FLUSH
) == -1)
125 /* compress len zeros (len guaranteed > 0) */
128 n
= GT_OFF(state
->size
) || (z_off64_t
)state
->size
> len
?
129 (unsigned)len
: state
->size
;
131 memset(state
->in
, 0, n
);
135 strm
->next_in
= state
->in
;
137 if (gz_comp(state
, Z_NO_FLUSH
) == -1)
144 /* -- see zlib.h -- */
145 int ZEXPORT
gzwrite(file
, buf
, len
)
155 /* get internal structure */
158 state
= (gz_statep
)file
;
159 strm
= &(state
->strm
);
161 /* check that we're writing and that there's no error */
162 if (state
->mode
!= GZ_WRITE
|| state
->err
!= Z_OK
)
165 /* since an int is returned, make sure len fits in one, otherwise return
166 with an error (this avoids the flaw in the interface) */
168 gz_error(state
, Z_BUF_ERROR
, "requested length does not fit in int");
172 /* if len is zero, avoid unnecessary operations */
176 /* allocate memory if this is the first time through */
177 if (state
->size
== 0 && gz_init(state
) == -1)
180 /* check for seek request */
183 if (gz_zero(state
, state
->skip
) == -1)
187 /* for small len, copy to input buffer, otherwise compress directly */
188 if (len
< state
->size
) {
189 /* copy to input buffer, compress when full */
191 if (strm
->avail_in
== 0)
192 strm
->next_in
= state
->in
;
193 n
= state
->size
- strm
->avail_in
;
196 memcpy(strm
->next_in
+ strm
->avail_in
, buf
, n
);
199 buf
= (char *)buf
+ n
;
201 if (len
&& gz_comp(state
, Z_NO_FLUSH
) == -1)
206 /* consume whatever's left in the input buffer */
207 if (strm
->avail_in
&& gz_comp(state
, Z_NO_FLUSH
) == -1)
210 /* directly compress user buffer to file */
211 strm
->avail_in
= len
;
212 strm
->next_in
= (voidp
)buf
;
214 if (gz_comp(state
, Z_NO_FLUSH
) == -1)
218 /* input was all buffered or compressed (put will fit in int) */
222 /* -- see zlib.h -- */
223 int ZEXPORT
gzputc(file
, c
)
227 unsigned char buf
[1];
231 /* get internal structure */
234 state
= (gz_statep
)file
;
235 strm
= &(state
->strm
);
237 /* check that we're writing and that there's no error */
238 if (state
->mode
!= GZ_WRITE
|| state
->err
!= Z_OK
)
241 /* check for seek request */
244 if (gz_zero(state
, state
->skip
) == -1)
248 /* try writing to input buffer for speed (state->size == 0 if buffer not
250 if (strm
->avail_in
< state
->size
) {
251 if (strm
->avail_in
== 0)
252 strm
->next_in
= state
->in
;
253 strm
->next_in
[strm
->avail_in
++] = c
;
258 /* no room in buffer or not initialized, use gz_write() */
260 if (gzwrite(file
, buf
, 1) != 1)
265 /* -- see zlib.h -- */
266 int ZEXPORT
gzputs(file
, str
)
274 len
= (unsigned)strlen(str
);
275 ret
= gzwrite(file
, str
, len
);
276 return ret
== 0 && len
!= 0 ? -1 : ret
;
282 /* -- see zlib.h -- */
283 int ZEXPORTVA
gzprintf (gzFile file
, const char *format
, ...)
290 /* get internal structure */
293 state
= (gz_statep
)file
;
294 strm
= &(state
->strm
);
296 /* check that we're writing and that there's no error */
297 if (state
->mode
!= GZ_WRITE
|| state
->err
!= Z_OK
)
300 /* make sure we have some buffer space */
301 if (state
->size
== 0 && gz_init(state
) == -1)
304 /* check for seek request */
307 if (gz_zero(state
, state
->skip
) == -1)
311 /* consume whatever's left in the input buffer */
312 if (strm
->avail_in
&& gz_comp(state
, Z_NO_FLUSH
) == -1)
315 /* do the printf() into the input buffer, put length in len */
316 size
= (int)(state
->size
);
317 state
->in
[size
- 1] = 0;
318 va_start(va
, format
);
320 # ifdef HAS_vsprintf_void
321 (void)vsprintf(state
->in
, format
, va
);
323 for (len
= 0; len
< size
; len
++)
324 if (state
->in
[len
] == 0) break;
326 len
= vsprintf(state
->in
, format
, va
);
330 # ifdef HAS_vsnprintf_void
331 (void)vsnprintf(state
->in
, size
, format
, va
);
333 len
= strlen(state
->in
);
335 len
= vsnprintf((char *)(state
->in
), size
, format
, va
);
340 /* check that printf() results fit in buffer */
341 if (len
<= 0 || len
>= (int)size
|| state
->in
[size
- 1] != 0)
344 /* update buffer and position, defer compression until needed */
345 strm
->avail_in
= (unsigned)len
;
346 strm
->next_in
= state
->in
;
353 /* -- see zlib.h -- */
354 int ZEXPORTVA
gzprintf (file
, format
, a1
, a2
, a3
, a4
, a5
, a6
, a7
, a8
, a9
, a10
,
355 a11
, a12
, a13
, a14
, a15
, a16
, a17
, a18
, a19
, a20
)
358 int a1
, a2
, a3
, a4
, a5
, a6
, a7
, a8
, a9
, a10
,
359 a11
, a12
, a13
, a14
, a15
, a16
, a17
, a18
, a19
, a20
;
365 /* get internal structure */
368 state
= (gz_statep
)file
;
369 strm
= &(state
->strm
);
371 /* check that we're writing and that there's no error */
372 if (state
->mode
!= GZ_WRITE
|| state
->err
!= Z_OK
)
375 /* make sure we have some buffer space */
376 if (state
->size
== 0 && gz_init(state
) == -1)
379 /* check for seek request */
382 if (gz_zero(state
, state
->skip
) == -1)
386 /* consume whatever's left in the input buffer */
387 if (strm
->avail_in
&& gz_comp(state
, Z_NO_FLUSH
) == -1)
390 /* do the printf() into the input buffer, put length in len */
391 size
= (int)(state
->size
);
392 state
->in
[size
- 1] = 0;
394 # ifdef HAS_sprintf_void
395 sprintf(state
->in
, format
, a1
, a2
, a3
, a4
, a5
, a6
, a7
, a8
,
396 a9
, a10
, a11
, a12
, a13
, a14
, a15
, a16
, a17
, a18
, a19
, a20
);
397 for (len
= 0; len
< size
; len
++)
398 if (state
->in
[len
] == 0) break;
400 len
= sprintf(state
->in
, format
, a1
, a2
, a3
, a4
, a5
, a6
, a7
, a8
,
401 a9
, a10
, a11
, a12
, a13
, a14
, a15
, a16
, a17
, a18
, a19
, a20
);
404 # ifdef HAS_snprintf_void
405 snprintf(state
->in
, size
, format
, a1
, a2
, a3
, a4
, a5
, a6
, a7
, a8
,
406 a9
, a10
, a11
, a12
, a13
, a14
, a15
, a16
, a17
, a18
, a19
, a20
);
407 len
= strlen(state
->in
);
409 len
= snprintf(state
->in
, size
, format
, a1
, a2
, a3
, a4
, a5
, a6
, a7
, a8
,
410 a9
, a10
, a11
, a12
, a13
, a14
, a15
, a16
, a17
, a18
, a19
, a20
);
414 /* check that printf() results fit in buffer */
415 if (len
<= 0 || len
>= (int)size
|| state
->in
[size
- 1] != 0)
418 /* update buffer and position, defer compression until needed */
419 strm
->avail_in
= (unsigned)len
;
420 strm
->next_in
= state
->in
;
427 /* -- see zlib.h -- */
428 int ZEXPORT
gzflush(file
, flush
)
434 /* get internal structure */
437 state
= (gz_statep
)file
;
439 /* check that we're writing and that there's no error */
440 if (state
->mode
!= GZ_WRITE
|| state
->err
!= Z_OK
)
441 return Z_STREAM_ERROR
;
443 /* check flush parameter */
444 if (flush
< 0 || flush
> Z_FINISH
)
445 return Z_STREAM_ERROR
;
447 /* check for seek request */
450 if (gz_zero(state
, state
->skip
) == -1)
454 /* compress remaining data with requested flush */
455 gz_comp(state
, flush
);
459 /* -- see zlib.h -- */
460 int ZEXPORT
gzsetparams(file
, level
, strategy
)
468 /* get internal structure */
470 return Z_STREAM_ERROR
;
471 state
= (gz_statep
)file
;
472 strm
= &(state
->strm
);
474 /* check that we're writing and that there's no error */
475 if (state
->mode
!= GZ_WRITE
|| state
->err
!= Z_OK
)
476 return Z_STREAM_ERROR
;
478 /* if no change is requested, then do nothing */
479 if (level
== state
->level
&& strategy
== state
->strategy
)
482 /* check for seek request */
485 if (gz_zero(state
, state
->skip
) == -1)
489 /* change compression parameters for subsequent input */
491 /* flush previous input with previous parameters before changing */
492 if (strm
->avail_in
&& gz_comp(state
, Z_PARTIAL_FLUSH
) == -1)
494 deflateParams(strm
, level
, strategy
);
496 state
->level
= level
;
497 state
->strategy
= strategy
;
501 /* -- see zlib.h -- */
502 int ZEXPORT
gzclose_w(file
)
508 /* get internal structure */
510 return Z_STREAM_ERROR
;
511 state
= (gz_statep
)file
;
513 /* check that we're writing */
514 if (state
->mode
!= GZ_WRITE
)
515 return Z_STREAM_ERROR
;
517 /* check for seek request */
520 ret
+= gz_zero(state
, state
->skip
);
523 /* flush, free memory, and close file */
524 ret
+= gz_comp(state
, Z_FINISH
);
525 (void)deflateEnd(&(state
->strm
));
528 gz_error(state
, Z_OK
, NULL
);
530 ret
+= close(state
->fd
);
532 return ret
? Z_ERRNO
: Z_OK
;