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;