aboutsummaryrefslogtreecommitdiff
path: root/gzwrite.c
diff options
context:
space:
mode:
authorMark Adler <madler@alumni.caltech.edu>2011-09-09 23:26:49 -0700
committerMark Adler <madler@alumni.caltech.edu>2011-09-09 23:26:49 -0700
commitd004b047838a7e803818b4973a2e39e0ff8c1fa2 (patch)
tree9e8c804f78d73152c70d4ff24c6a7531a0d46782 /gzwrite.c
parentf6194ef39af5864f792412460c354cc339dde7d1 (diff)
downloadzlib-d004b047838a7e803818b4973a2e39e0ff8c1fa2.tar.gz
zlib-d004b047838a7e803818b4973a2e39e0ff8c1fa2.tar.bz2
zlib-d004b047838a7e803818b4973a2e39e0ff8c1fa2.zip
zlib 1.2.3.5v1.2.3.5
Diffstat (limited to 'gzwrite.c')
-rw-r--r--gzwrite.c529
1 files changed, 529 insertions, 0 deletions
diff --git a/gzwrite.c b/gzwrite.c
new file mode 100644
index 0000000..65a13c3
--- /dev/null
+++ b/gzwrite.c
@@ -0,0 +1,529 @@
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
4 */
5
6#ifndef OLD_GZIO
7
8#include "gzguts.h"
9
10/* Local functions */
11local int gz_init OF((gz_statep));
12local int gz_comp OF((gz_statep, int));
13local int gz_zero OF((gz_statep, z_off_t));
14
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. */
17local int gz_init(state)
18 gz_statep state;
19{
20 int ret;
21 z_streamp strm = &(state->strm);
22
23 /* check version of zlib -- need 1.2.1 or later for gzip deflate() */
24#ifdef ZLIB_VERNUM
25 if (ZLIB_VERNUM < 0x1210)
26#endif
27 {
28 gz_error(state, Z_VERSION_ERROR, "need zlib 1.2.1 or later");
29 return -1;
30 }
31
32 /* allocate input and output buffers */
33 state->in = malloc(state->want);
34 state->out = malloc(state->want);
35 if (state->in == NULL || state->out == NULL) {
36 if (state->out != NULL)
37 free(state->out);
38 if (state->in != NULL)
39 free(state->in);
40 gz_error(state, Z_MEM_ERROR, "out of memory");
41 return -1;
42 }
43
44 /* allocate deflate memory, set up for gzip compression */
45 strm->zalloc = Z_NULL;
46 strm->zfree = Z_NULL;
47 strm->opaque = Z_NULL;
48 ret = deflateInit2(strm, state->level, Z_DEFLATED,
49 15 + 16, 8, state->strategy);
50 if (ret != Z_OK) {
51 free(state->in);
52 gz_error(state, Z_MEM_ERROR, "out of memory");
53 return -1;
54 }
55
56 /* mark state as initialized */
57 state->size = state->want;
58
59 /* initialize write buffer */
60 strm->avail_out = state->size;
61 strm->next_out = state->out;
62 state->next = strm->next_out;
63 return 0;
64}
65
66/* Compress whatever is at avail_in and next_in and write to the output file.
67 Return -1 if there is an error writing to the output file, otherwise 0.
68 flush is assumed to be a valid deflate() flush value. If flush is Z_FINISH,
69 then the deflate() state is reset to start a new gzip stream. */
70local int gz_comp(state, flush)
71 gz_statep state;
72 int flush;
73{
74 int ret;
75 unsigned have;
76 z_streamp strm = &(state->strm);
77
78 /* allocate memory if this is the first time through */
79 if (state->size == 0 && gz_init(state) == -1)
80 return -1;
81
82 /* run deflate() on provided input until it produces no more output */
83 ret = Z_OK;
84 do {
85 /* write out current buffer contents if full, or if flushing, but if
86 doing Z_FINISH then don't write until we get to Z_STREAM_END */
87 if (strm->avail_out == 0 || (flush != Z_NO_FLUSH &&
88 (flush != Z_FINISH || ret == Z_STREAM_END))) {
89 have = strm->next_out - state->next;
90 if (have && write(state->fd, state->next, have) != have) {
91 gz_error(state, Z_ERRNO, zstrerror());
92 return -1;
93 }
94 if (strm->avail_out == 0) {
95 strm->avail_out = state->size;
96 strm->next_out = state->out;
97 }
98 state->next = strm->next_out;
99 }
100
101 /* compress */
102 have = strm->avail_out;
103 ret = deflate(strm, flush);
104 if (ret == Z_STREAM_ERROR) {
105 gz_error(state, Z_STREAM_ERROR,
106 "internal error: deflate stream corrupt");
107 return -1;
108 }
109 have -= strm->avail_out;
110 } while (have);
111
112 /* if that completed a deflate stream, allow another to start */
113 if (flush == Z_FINISH)
114 deflateReset(strm);
115
116 /* all done, no errors */
117 return 0;
118}
119
120/* Compress len zeros to output. Return -1 on error, 0 on success. */
121local int gz_zero(state, len)
122 gz_statep state;
123 z_off_t len;
124{
125 int first;
126 unsigned n;
127 z_streamp strm = &(state->strm);
128
129 /* consume whatever's left in the input buffer */
130 if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1)
131 return -1;
132
133 /* compress len zeros */
134 first = 1;
135 while (len) {
136 n = len < state->size ? (unsigned)len : state->size;
137 if (first) {
138 memset(state->in, 0, n);
139 first = 0;
140 }
141 strm->avail_in = n;
142 strm->next_in = state->in;
143 state->pos += n;
144 if (gz_comp(state, Z_NO_FLUSH) == -1)
145 return -1;
146 len -= n;
147 }
148 return 0;
149}
150
151/* -- see zlib.h -- */
152int ZEXPORT gzwrite(file, buf, len)
153 gzFile file;
154 voidpc buf;
155 unsigned len;
156{
157 unsigned put = len;
158 unsigned n;
159 gz_statep state;
160 z_streamp strm;
161
162 /* get internal structure */
163 if (file == NULL)
164 return -1;
165 state = (gz_statep)file;
166 strm = &(state->strm);
167
168 /* check that we're writing and that there's no error */
169 if (state->mode != GZ_WRITE || state->err != Z_OK)
170 return -1;
171
172 /* allocate memory if this is the first time through */
173 if (state->size == 0 && gz_init(state) == -1)
174 return -1;
175
176 /* check for seek request */
177 if (state->seek) {
178 state->seek = 0;
179 if (gz_zero(state, state->skip) == -1)
180 return -1;
181 }
182
183 /* for small len, copy to input buffer, otherwise compress directly */
184 if (len < state->size) {
185 /* copy to input buffer, compress when full */
186 while (len) {
187 if (strm->avail_in == 0)
188 strm->next_in = state->in;
189 n = state->size - strm->avail_in;
190 if (n > len)
191 n = len;
192 memcpy(strm->next_in + strm->avail_in, buf, n);
193 strm->avail_in += n;
194 state->pos += n;
195 buf += n;
196 len -= n;
197 if (len && gz_comp(state, Z_NO_FLUSH) == -1)
198 return -1;
199 }
200 }
201 else {
202 /* consume whatever's left in the input buffer */
203 if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1)
204 return -1;
205
206 /* directly compress user buffer to file */
207 strm->avail_in = len;
208 strm->next_in = (voidp)buf;
209 state->pos += len;
210 if (gz_comp(state, Z_NO_FLUSH) == -1)
211 return -1;
212 }
213
214 /* input was all buffered or compressed */
215 return (int)put;
216}
217
218/* -- see zlib.h -- */
219int ZEXPORT gzputc(file, c)
220 gzFile file;
221 int c;
222{
223 unsigned char buf[1];
224 gz_statep state;
225 z_streamp strm;
226
227 /* get internal structure */
228 if (file == NULL)
229 return -1;
230 state = (gz_statep)file;
231 strm = &(state->strm);
232
233 /* check that we're writing and that there's no error */
234 if (state->mode != GZ_WRITE || state->err != Z_OK)
235 return -1;
236
237 /* check for seek request */
238 if (state->seek) {
239 state->seek = 0;
240 if (gz_zero(state, state->skip) == -1)
241 return -1;
242 }
243
244 /* try writing to input buffer for speed (state->size == 0 if buffer not
245 initialized) */
246 if (strm->avail_in < state->size) {
247 if (strm->avail_in == 0)
248 strm->next_in = state->in;
249 strm->next_in[strm->avail_in++] = c;
250 state->pos++;
251 return c;
252 }
253
254 /* no room in buffer or not initialized, use gz_write() */
255 buf[0] = c;
256 if (gzwrite(file, buf, 1) != 1)
257 return -1;
258 return c;
259}
260
261/* -- see zlib.h -- */
262int ZEXPORT gzputs(file, str)
263 gzFile file;
264 const char *str;
265{
266 /* write string */
267 return gzwrite(file, str, strlen(str));
268}
269
270#ifdef STDC
271#include <stdarg.h>
272
273/* -- see zlib.h -- */
274int ZEXPORTVA gzprintf (gzFile file, const char *format, ...)
275{
276 int size, len;
277 gz_statep state;
278 z_streamp strm;
279 va_list va;
280
281 /* get internal structure */
282 if (file == NULL)
283 return -1;
284 state = (gz_statep)file;
285 strm = &(state->strm);
286
287 /* check that we're writing and that there's no error */
288 if (state->mode != GZ_WRITE || state->err != Z_OK)
289 return 0;
290
291 /* make sure we have some buffer space */
292 if (state->size == 0 && gz_init(state) == -1)
293 return 0;
294
295 /* check for seek request */
296 if (state->seek) {
297 state->seek = 0;
298 if (gz_zero(state, state->skip) == -1)
299 return 0;
300 }
301
302 /* consume whatever's left in the input buffer */
303 if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1)
304 return 0;
305
306 /* do the printf() into the input buffer, put length in len */
307 size = (int)(state->size);
308 state->in[size - 1] = 0;
309 va_start(va, format);
310#ifdef NO_vsnprintf
311# ifdef HAS_vsprintf_void
312 (void)vsprintf(state->in, format, va);
313 va_end(va);
314 for (len = 0; len < state->in; len++)
315 if (state->in[len] == 0) break;
316# else
317 len = vsprintf(state->in, format, va);
318 va_end(va);
319# endif
320#else
321# ifdef HAS_vsnprintf_void
322 (void)vsnprintf(state->in, size, format, va);
323 va_end(va);
324 len = strlen(state->in);
325# else
326 len = vsnprintf((char *)(state->in), size, format, va);
327 va_end(va);
328# endif
329#endif
330
331 /* check that printf() results fit in buffer */
332 if (len <= 0 || len >= (int)size || state->in[size - 1] != 0)
333 return 0;
334
335 /* write out result of printf() */
336 strm->avail_in = (unsigned)len;
337 strm->next_in = state->in;
338 state->pos += len;
339 if (gz_comp(state, Z_NO_FLUSH) == -1)
340 return 0;
341 return len;
342}
343
344#else /* !STDC */
345
346/* -- see zlib.h -- */
347int ZEXPORTVA gzprintf (file, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10,
348 a11, a12, a13, a14, a15, a16, a17, a18, a19, a20)
349 gzFile file;
350 const char *format;
351 int a1, a2, a3, a4, a5, a6, a7, a8, a9, a10,
352 a11, a12, a13, a14, a15, a16, a17, a18, a19, a20;
353{
354 int size, len;
355 gz_statep state;
356 z_streamp strm;
357
358 /* get internal structure */
359 if (file == NULL)
360 return -1;
361 state = (gz_statep)file;
362 strm = &(state->strm);
363
364 /* check that we're writing and that there's no error */
365 if (state->mode != GZ_WRITE || state->err != Z_OK)
366 return 0;
367
368 /* make sure we have some buffer space */
369 if (state->size == 0 && gz_init(state) == -1)
370 return 0;
371
372 /* check for seek request */
373 if (state->seek) {
374 state->seek = 0;
375 if (gz_zero(state, state->skip) == -1)
376 return 0;
377 }
378
379 /* consume whatever's left in the input buffer */
380 if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1)
381 return 0;
382
383 /* do the printf() into the input buffer, put length in len */
384 size = (int)(state->size);
385 state->in[size - 1] = 0;
386#ifdef NO_snprintf
387# ifdef HAS_sprintf_void
388 sprintf(state->in, format, a1, a2, a3, a4, a5, a6, a7, a8,
389 a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20);
390 for (len = 0; len < size; len++)
391 if (state->in[len] == 0) break;
392# else
393 len = 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# endif
396#else
397# ifdef HAS_snprintf_void
398 snprintf(state->in, size, format, a1, a2, a3, a4, a5, a6, a7, a8,
399 a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20);
400 len = strlen(state->in);
401# else
402 len = snprintf(state->in, size, format, a1, a2, a3, a4, a5, a6, a7, a8,
403 a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20);
404# endif
405#endif
406
407 /* check that printf() results fit in buffer */
408 if (len <= 0 || len >= (int)size || state->in[size - 1] != 0)
409 return 0;
410
411 /* write out result of printf() */
412 strm->avail_in = (unsigned)len;
413 strm->next_in = state->in;
414 state->pos += len;
415 if (gz_comp(state, Z_NO_FLUSH) == -1)
416 return 0;
417 return len;
418}
419
420#endif
421
422/* -- see zlib.h -- */
423int ZEXPORT gzflush(file, flush)
424 gzFile file;
425 int flush;
426{
427 gz_statep state;
428
429 /* get internal structure */
430 if (file == NULL)
431 return -1;
432 state = (gz_statep)file;
433
434 /* check that we're writing and that there's no error */
435 if (state->mode != GZ_WRITE|| state->err != Z_OK)
436
437 /* check flush parameter */
438 if (flush < 0 || flush > Z_FINISH)
439 return Z_STREAM_ERROR;
440
441 /* check for seek request */
442 if (state->seek) {
443 state->seek = 0;
444 if (gz_zero(state, state->skip) == -1)
445 return -1;
446 }
447
448 /* compress remaining data with requested flush */
449 gz_comp(state, flush);
450 return state->err;
451}
452
453/* -- see zlib.h -- */
454int ZEXPORT gzsetparams(file, level, strategy)
455 gzFile file;
456 int level;
457 int strategy;
458{
459 gz_statep state;
460 z_streamp strm;
461
462 /* get internal structure */
463 if (file == NULL)
464 return Z_STREAM_ERROR;
465 state = (gz_statep)file;
466 strm = &(state->strm);
467
468 /* check that we're writing and that there's no error */
469 if (state->mode != GZ_WRITE || state->err != Z_OK)
470 return Z_STREAM_ERROR;
471
472 /* if no change is requested, then do nothing */
473 if (level == state->level && strategy == state->strategy)
474 return Z_OK;
475
476 /* check for seek request */
477 if (state->seek) {
478 state->seek = 0;
479 if (gz_zero(state, state->skip) == -1)
480 return -1;
481 }
482
483 /* change compression parameters for subsequent input */
484 if (state->size) {
485 /* flush previous input with previous parameters before changing */
486 if (strm->avail_in && gz_comp(state, Z_PARTIAL_FLUSH) == -1)
487 return state->err;
488 deflateParams(strm, level, strategy);
489 }
490 state->level = level;
491 state->strategy = strategy;
492 return Z_OK;
493}
494
495/* -- see zlib.h -- */
496int ZEXPORT gzclose_w(file)
497 gzFile file;
498{
499 int ret;
500 gz_statep state;
501
502 /* get internal structure */
503 if (file == NULL)
504 return Z_STREAM_ERROR;
505 state = (gz_statep)file;
506
507 /* check that we're writing */
508 if (state->mode != GZ_WRITE)
509 return Z_STREAM_ERROR;
510
511 /* check for seek request */
512 if (state->seek) {
513 state->seek = 0;
514 if (gz_zero(state, state->skip) == -1)
515 return -1;
516 }
517
518 /* flush, free memory, and close file */
519 ret = gz_comp(state, Z_FINISH);
520 deflateEnd(&(state->strm));
521 free(state->out);
522 free(state->in);
523 ret += close(state->fd);
524 gz_error(state, Z_OK, NULL);
525 free(state);
526 return ret ? Z_ERRNO : Z_OK;
527}
528
529#endif /* !OLD_GZIO */