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