gzwrite.c revision 1.2.16.2 1 /* gzwrite.c -- zlib functions for writing gzip files
2 * Copyright (C) 2004, 2005, 2010, 2011, 2012, 2013, 2016 Mark Adler
3 * For conditions of distribution and use, see copyright notice in zlib.h
4 */
5
6 #include "gzguts.h"
7
8 /* Local functions */
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));
13
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
16 success. */
17 local int gz_init(state)
18 gz_statep state;
19 {
20 int ret;
21 z_streamp strm = &(state->strm);
22
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");
27 return -1;
28 }
29
30 /* only need output buffer and deflate state if compressing */
31 if (!state->direct) {
32 /* allocate output buffer */
33 state->out = (unsigned char *)malloc(state->want);
34 if (state->out == NULL) {
35 free(state->in);
36 gz_error(state, Z_MEM_ERROR, "out of memory");
37 return -1;
38 }
39
40 /* allocate deflate memory, set up for gzip compression */
41 strm->zalloc = Z_NULL;
42 strm->zfree = Z_NULL;
43 strm->opaque = Z_NULL;
44 ret = deflateInit2(strm, state->level, Z_DEFLATED,
45 MAX_WBITS + 16, DEF_MEM_LEVEL, state->strategy);
46 if (ret != Z_OK) {
47 free(state->out);
48 free(state->in);
49 gz_error(state, Z_MEM_ERROR, "out of memory");
50 return -1;
51 }
52 strm->next_in = NULL;
53 }
54
55 /* mark state as initialized */
56 state->size = state->want;
57
58 /* initialize write buffer if compressing */
59 if (!state->direct) {
60 strm->avail_out = state->size;
61 strm->next_out = state->out;
62 state->x.next = strm->next_out;
63 }
64 return 0;
65 }
66
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)
74 gz_statep state;
75 int flush;
76 {
77 int ret;
78 ssize_t writ;
79 size_t put;
80 unsigned have, max = ((unsigned)-1 >> 2) + 1;
81 z_streamp strm = &(state->strm);
82
83 /* allocate memory if this is the first time through */
84 if (state->size == 0 && gz_init(state) == -1)
85 return -1;
86
87 /* write directly if requested */
88 if (state->direct) {
89 while (strm->avail_in) {
90 put = strm->avail_in > max ? max : strm->avail_in;
91 writ = write(state->fd, strm->next_in, put);
92 if (writ < 0) {
93 gz_error(state, Z_ERRNO, zstrerror());
94 return -1;
95 }
96 strm->avail_in -= (unsigned)writ;
97 strm->next_in += writ;
98 }
99 return 0;
100 }
101
102 /* run deflate() on provided input until it produces no more output */
103 ret = Z_OK;
104 do {
105 /* write out current buffer contents if full, or if flushing, but if
106 doing Z_FINISH then don't write until we get to Z_STREAM_END */
107 if (strm->avail_out == 0 || (flush != Z_NO_FLUSH &&
108 (flush != Z_FINISH || ret == Z_STREAM_END))) {
109 while (strm->next_out > state->x.next) {
110 put = strm->next_out - state->x.next > (int)max ? max :
111 (unsigned)(strm->next_out - state->x.next);
112 writ = write(state->fd, state->x.next, put);
113 if (writ < 0) {
114 gz_error(state, Z_ERRNO, zstrerror());
115 return -1;
116 }
117 state->x.next += writ;
118 }
119 if (strm->avail_out == 0) {
120 strm->avail_out = state->size;
121 strm->next_out = state->out;
122 state->x.next = state->out;
123 }
124 }
125
126 /* compress */
127 have = strm->avail_out;
128 ret = deflate(strm, flush);
129 if (ret == Z_STREAM_ERROR) {
130 gz_error(state, Z_STREAM_ERROR,
131 "internal error: deflate stream corrupt");
132 return -1;
133 }
134 have -= strm->avail_out;
135 } while (have);
136
137 /* if that completed a deflate stream, allow another to start */
138 if (flush == Z_FINISH)
139 deflateReset(strm);
140
141 /* all done, no errors */
142 return 0;
143 }
144
145 /* Compress len zeros to output. Return -1 on a write error or memory
146 allocation failure by gz_comp(), or 0 on success. */
147 local int gz_zero(state, len)
148 gz_statep state;
149 z_off64_t len;
150 {
151 int first;
152 unsigned n;
153 z_streamp strm = &(state->strm);
154
155 /* consume whatever's left in the input buffer */
156 if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1)
157 return -1;
158
159 /* compress len zeros (len guaranteed > 0) */
160 first = 1;
161 while (len) {
162 n = GT_OFF(state->size) || (z_off64_t)state->size > len ?
163 (unsigned)len : state->size;
164 if (first) {
165 memset(state->in, 0, n);
166 first = 0;
167 }
168 strm->avail_in = n;
169 strm->next_in = state->in;
170 state->x.pos += n;
171 if (gz_comp(state, Z_NO_FLUSH) == -1)
172 return -1;
173 len -= n;
174 }
175 return 0;
176 }
177
178 /* Write len bytes from buf to file. Return the number of bytes written. If
179 the returned value is less than len, then there was an error. */
180 local z_size_t gz_write(state, buf, len)
181 gz_statep state;
182 voidpc buf;
183 z_size_t len;
184 {
185 z_size_t put = len;
186
187 /* if len is zero, avoid unnecessary operations */
188 if (len == 0)
189 return 0;
190
191 /* allocate memory if this is the first time through */
192 if (state->size == 0 && gz_init(state) == -1)
193 return 0;
194
195 /* check for seek request */
196 if (state->seek) {
197 state->seek = 0;
198 if (gz_zero(state, state->skip) == -1)
199 return 0;
200 }
201
202 /* for small len, copy to input buffer, otherwise compress directly */
203 if (len < state->size) {
204 /* copy to input buffer, compress when full */
205 do {
206 unsigned have, copy;
207
208 if (state->strm.avail_in == 0)
209 state->strm.next_in = state->in;
210 have = (unsigned)((state->strm.next_in + state->strm.avail_in) -
211 state->in);
212 copy = state->size - have;
213 if (copy > len)
214 copy = len;
215 memcpy(state->in + have, buf, copy);
216 state->strm.avail_in += copy;
217 state->x.pos += copy;
218 buf = (const char *)buf + copy;
219 len -= copy;
220 if (len && gz_comp(state, Z_NO_FLUSH) == -1)
221 return 0;
222 } while (len);
223 }
224 else {
225 /* consume whatever's left in the input buffer */
226 if (state->strm.avail_in && gz_comp(state, Z_NO_FLUSH) == -1)
227 return 0;
228
229 /* directly compress user buffer to file */
230 state->strm.next_in = __UNCONST(buf);
231 do {
232 unsigned n = (unsigned)-1;
233 if (n > len)
234 n = len;
235 state->strm.avail_in = n;
236 state->x.pos += n;
237 if (gz_comp(state, Z_NO_FLUSH) == -1)
238 return 0;
239 len -= n;
240 } while (len);
241 }
242
243 /* input was all buffered or compressed */
244 return put;
245 }
246
247 /* -- see zlib.h -- */
248 int ZEXPORT gzwrite(file, buf, len)
249 gzFile file;
250 voidpc buf;
251 unsigned len;
252 {
253 gz_statep state;
254
255 /* get internal structure */
256 if (file == NULL)
257 return 0;
258 state = (gz_statep)file;
259
260 /* check that we're writing and that there's no error */
261 if (state->mode != GZ_WRITE || state->err != Z_OK)
262 return 0;
263
264 /* since an int is returned, make sure len fits in one, otherwise return
265 with an error (this avoids a flaw in the interface) */
266 if ((int)len < 0) {
267 gz_error(state, Z_DATA_ERROR, "requested length does not fit in int");
268 return 0;
269 }
270
271 /* write len bytes from buf (the return value will fit in an int) */
272 return (int)gz_write(state, buf, len);
273 }
274
275 /* -- see zlib.h -- */
276 z_size_t ZEXPORT gzfwrite(buf, size, nitems, file)
277 voidpc buf;
278 z_size_t size;
279 z_size_t nitems;
280 gzFile file;
281 {
282 z_size_t len;
283 gz_statep state;
284
285 /* get internal structure */
286 if (file == NULL)
287 return 0;
288 state = (gz_statep)file;
289
290 /* check that we're writing and that there's no error */
291 if (state->mode != GZ_WRITE || state->err != Z_OK)
292 return 0;
293
294 /* compute bytes to read -- error on overflow */
295 len = nitems * size;
296 if (size && len / size != nitems) {
297 gz_error(state, Z_STREAM_ERROR, "request does not fit in a size_t");
298 return 0;
299 }
300
301 /* write len bytes to buf, return the number of full items written */
302 return len ? gz_write(state, buf, len) / size : 0;
303 }
304
305 /* -- see zlib.h -- */
306 int ZEXPORT gzputc(file, c)
307 gzFile file;
308 int c;
309 {
310 unsigned have;
311 unsigned char buf[1];
312 gz_statep state;
313 z_streamp strm;
314
315 /* get internal structure */
316 if (file == NULL)
317 return -1;
318 state = (gz_statep)file;
319 strm = &(state->strm);
320
321 /* check that we're writing and that there's no error */
322 if (state->mode != GZ_WRITE || state->err != Z_OK)
323 return -1;
324
325 /* check for seek request */
326 if (state->seek) {
327 state->seek = 0;
328 if (gz_zero(state, state->skip) == -1)
329 return -1;
330 }
331
332 /* try writing to input buffer for speed (state->size == 0 if buffer not
333 initialized) */
334 if (state->size) {
335 if (strm->avail_in == 0)
336 strm->next_in = state->in;
337 have = (unsigned)((strm->next_in + strm->avail_in) - state->in);
338 if (have < state->size) {
339 state->in[have] = (unsigned char)c;
340 strm->avail_in++;
341 state->x.pos++;
342 return c & 0xff;
343 }
344 }
345
346 /* no room in buffer or not initialized, use gz_write() */
347 buf[0] = (unsigned char)c;
348 if (gz_write(state, buf, 1) != 1)
349 return -1;
350 return c & 0xff;
351 }
352
353 /* -- see zlib.h -- */
354 int ZEXPORT gzputs(file, str)
355 gzFile file;
356 const char *str;
357 {
358 int ret;
359 z_size_t len;
360 gz_statep state;
361
362 /* get internal structure */
363 if (file == NULL)
364 return -1;
365 state = (gz_statep)file;
366
367 /* check that we're writing and that there's no error */
368 if (state->mode != GZ_WRITE || state->err != Z_OK)
369 return -1;
370
371 /* write string */
372 len = strlen(str);
373 ret = gz_write(state, str, len);
374 return ret == 0 && len != 0 ? -1 : ret;
375 }
376
377 #if defined(STDC) || defined(Z_HAVE_STDARG_H)
378 #include <stdarg.h>
379
380 /* -- see zlib.h -- */
381 int ZEXPORTVA gzvprintf(gzFile file, const char *format, va_list va)
382 {
383 int len;
384 unsigned left;
385 char *next;
386 gz_statep state;
387 z_streamp strm;
388
389 /* get internal structure */
390 if (file == NULL)
391 return Z_STREAM_ERROR;
392 state = (gz_statep)file;
393 strm = &(state->strm);
394
395 /* check that we're writing and that there's no error */
396 if (state->mode != GZ_WRITE || state->err != Z_OK)
397 return Z_STREAM_ERROR;
398
399 /* make sure we have some buffer space */
400 if (state->size == 0 && gz_init(state) == -1)
401 return state->err;
402
403 /* check for seek request */
404 if (state->seek) {
405 state->seek = 0;
406 if (gz_zero(state, state->skip) == -1)
407 return state->err;
408 }
409
410 /* do the printf() into the input buffer, put length in len -- the input
411 buffer is double-sized just for this function, so there is guaranteed to
412 be state->size bytes available after the current contents */
413 if (strm->avail_in == 0)
414 strm->next_in = state->in;
415 next = (char *)(state->in + (strm->next_in - state->in) + strm->avail_in);
416 next[state->size - 1] = 0;
417 #ifdef NO_vsnprintf
418 # ifdef HAS_vsprintf_void
419 (void)vsprintf(next, format, va);
420 for (len = 0; len < state->size; len++)
421 if (next[len] == 0) break;
422 # else
423 len = vsprintf(next, format, va);
424 # endif
425 #else
426 # ifdef HAS_vsnprintf_void
427 (void)vsnprintf(next, state->size, format, va);
428 len = strlen(next);
429 # else
430 len = vsnprintf(next, state->size, format, va);
431 # endif
432 #endif
433
434 /* check that printf() results fit in buffer */
435 if (len == 0 || (unsigned)len >= state->size || next[state->size - 1] != 0)
436 return 0;
437
438 /* update buffer and position, compress first half if past that */
439 strm->avail_in += (unsigned)len;
440 state->x.pos += len;
441 if (strm->avail_in >= state->size) {
442 left = strm->avail_in - state->size;
443 strm->avail_in = state->size;
444 if (gz_comp(state, Z_NO_FLUSH) == -1)
445 return state->err;
446 memcpy(state->in, state->in + state->size, left);
447 strm->next_in = state->in;
448 strm->avail_in = left;
449 }
450 return len;
451 }
452
453 int ZEXPORTVA gzprintf(gzFile file, const char *format, ...)
454 {
455 va_list va;
456 int ret;
457
458 va_start(va, format);
459 ret = gzvprintf(file, format, va);
460 va_end(va);
461 return ret;
462 }
463
464 #else /* !STDC && !Z_HAVE_STDARG_H */
465
466 /* -- see zlib.h -- */
467 int ZEXPORTVA gzprintf (file, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10,
468 a11, a12, a13, a14, a15, a16, a17, a18, a19, a20)
469 gzFile file;
470 const char *format;
471 int a1, a2, a3, a4, a5, a6, a7, a8, a9, a10,
472 a11, a12, a13, a14, a15, a16, a17, a18, a19, a20;
473 {
474 unsigned len, left;
475 char *next;
476 gz_statep state;
477 z_streamp strm;
478
479 /* get internal structure */
480 if (file == NULL)
481 return Z_STREAM_ERROR;
482 state = (gz_statep)file;
483 strm = &(state->strm);
484
485 /* check that can really pass pointer in ints */
486 if (sizeof(int) != sizeof(void *))
487 return Z_STREAM_ERROR;
488
489 /* check that we're writing and that there's no error */
490 if (state->mode != GZ_WRITE || state->err != Z_OK)
491 return Z_STREAM_ERROR;
492
493 /* make sure we have some buffer space */
494 if (state->size == 0 && gz_init(state) == -1)
495 return state->error;
496
497 /* check for seek request */
498 if (state->seek) {
499 state->seek = 0;
500 if (gz_zero(state, state->skip) == -1)
501 return state->error;
502 }
503
504 /* do the printf() into the input buffer, put length in len -- the input
505 buffer is double-sized just for this function, so there is guaranteed to
506 be state->size bytes available after the current contents */
507 if (strm->avail_in == 0)
508 strm->next_in = state->in;
509 next = (char *)(strm->next_in + strm->avail_in);
510 next[state->size - 1] = 0;
511 #ifdef NO_snprintf
512 # ifdef HAS_sprintf_void
513 sprintf(next, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12,
514 a13, a14, a15, a16, a17, a18, a19, a20);
515 for (len = 0; len < size; len++)
516 if (next[len] == 0)
517 break;
518 # else
519 len = sprintf(next, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11,
520 a12, a13, a14, a15, a16, a17, a18, a19, a20);
521 # endif
522 #else
523 # ifdef HAS_snprintf_void
524 snprintf(next, state->size, format, a1, a2, a3, a4, a5, a6, a7, a8, a9,
525 a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20);
526 len = strlen(next);
527 # else
528 len = snprintf(next, state->size, format, a1, a2, a3, a4, a5, a6, a7, a8,
529 a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20);
530 # endif
531 #endif
532
533 /* check that printf() results fit in buffer */
534 if (len == 0 || len >= state->size || next[state->size - 1] != 0)
535 return 0;
536
537 /* update buffer and position, compress first half if past that */
538 strm->avail_in += len;
539 state->x.pos += len;
540 if (strm->avail_in >= state->size) {
541 left = strm->avail_in - state->size;
542 strm->avail_in = state->size;
543 if (gz_comp(state, Z_NO_FLUSH) == -1)
544 return state->err;
545 memcpy(state->in, state->in + state->size, left);
546 strm->next_in = state->in;
547 strm->avail_in = left;
548 }
549 return (int)len;
550 }
551
552 #endif
553
554 /* -- see zlib.h -- */
555 int ZEXPORT gzflush(file, flush)
556 gzFile file;
557 int flush;
558 {
559 gz_statep state;
560
561 /* get internal structure */
562 if (file == NULL)
563 return Z_STREAM_ERROR;
564 state = (gz_statep)file;
565
566 /* check that we're writing and that there's no error */
567 if (state->mode != GZ_WRITE || state->err != Z_OK)
568 return Z_STREAM_ERROR;
569
570 /* check flush parameter */
571 if (flush < 0 || flush > Z_FINISH)
572 return Z_STREAM_ERROR;
573
574 /* check for seek request */
575 if (state->seek) {
576 state->seek = 0;
577 if (gz_zero(state, state->skip) == -1)
578 return state->err;
579 }
580
581 /* compress remaining data with requested flush */
582 (void)gz_comp(state, flush);
583 return state->err;
584 }
585
586 /* -- see zlib.h -- */
587 int ZEXPORT gzsetparams(file, level, strategy)
588 gzFile file;
589 int level;
590 int strategy;
591 {
592 gz_statep state;
593 z_streamp strm;
594
595 /* get internal structure */
596 if (file == NULL)
597 return Z_STREAM_ERROR;
598 state = (gz_statep)file;
599 strm = &(state->strm);
600
601 /* check that we're writing and that there's no error */
602 if (state->mode != GZ_WRITE || state->err != Z_OK)
603 return Z_STREAM_ERROR;
604
605 /* if no change is requested, then do nothing */
606 if (level == state->level && strategy == state->strategy)
607 return Z_OK;
608
609 /* check for seek request */
610 if (state->seek) {
611 state->seek = 0;
612 if (gz_zero(state, state->skip) == -1)
613 return state->err;
614 }
615
616 /* change compression parameters for subsequent input */
617 if (state->size) {
618 /* flush previous input with previous parameters before changing */
619 if (strm->avail_in && gz_comp(state, Z_BLOCK) == -1)
620 return state->err;
621 deflateParams(strm, level, strategy);
622 }
623 state->level = level;
624 state->strategy = strategy;
625 return Z_OK;
626 }
627
628 /* -- see zlib.h -- */
629 int ZEXPORT gzclose_w(file)
630 gzFile file;
631 {
632 int ret = Z_OK;
633 gz_statep state;
634
635 /* get internal structure */
636 if (file == NULL)
637 return Z_STREAM_ERROR;
638 state = (gz_statep)file;
639
640 /* check that we're writing */
641 if (state->mode != GZ_WRITE)
642 return Z_STREAM_ERROR;
643
644 /* check for seek request */
645 if (state->seek) {
646 state->seek = 0;
647 if (gz_zero(state, state->skip) == -1)
648 ret = state->err;
649 }
650
651 /* flush, free memory, and close file */
652 if (gz_comp(state, Z_FINISH) == -1)
653 ret = state->err;
654 if (state->size) {
655 if (!state->direct) {
656 (void)deflateEnd(&(state->strm));
657 free(state->out);
658 }
659 free(state->in);
660 }
661 gz_error(state, Z_OK, NULL);
662 free(state->path);
663 /*###661 [cc] error: implicit declaration of function 'close' [-Werror=implicit-function-declaration]%%%*/
664 if (close(state->fd) == -1)
665 ret = Z_ERRNO;
666 free(state);
667 return ret;
668 }
669