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