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