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