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