git subrepo pull (merge) --force deps/libchdr
[pcsx_rearmed.git] / deps / libchdr / deps / zstd-1.5.6 / zlibWrapper / gzlib.c
CommitLineData
648db22b 1/* gzlib.c contains minimal changes required to be compiled with zlibWrapper:
2 * - gz_statep was converted to union to work with -Wstrict-aliasing=1 */
3
b24e7fce 4/* gzlib.c -- zlib functions common to reading and writing gzip files
648db22b 5 * Copyright (C) 2004-2017 Mark Adler
6 * For conditions of distribution and use, see https://www.zlib.net/zlib_license.html
b24e7fce 7 */
8
9#include "gzguts.h"
10
648db22b 11#if defined(_WIN32) && !defined(__BORLANDC__) && !defined(__MINGW32__)
b24e7fce 12# define LSEEK _lseeki64
13#else
14#if defined(_LARGEFILE64_SOURCE) && _LFS64_LARGEFILE-0
15# define LSEEK lseek64
16#else
17# define LSEEK lseek
18#endif
19#endif
20
21/* Local functions */
648db22b 22local void gz_reset _Z_OF((gz_statep));
23local gzFile gz_open _Z_OF((const void *, int, const char *));
b24e7fce 24
25#if defined UNDER_CE
26
27/* Map the Windows error number in ERROR to a locale-dependent error message
28 string and return a pointer to it. Typically, the values for ERROR come
29 from GetLastError.
30
31 The string pointed to shall not be modified by the application, but may be
32 overwritten by a subsequent call to gz_strwinerror
33
34 The gz_strwinerror function does not change the current setting of
35 GetLastError. */
f535537f 36char ZLIB_INTERNAL *gz_strwinerror(DWORD error) {
b24e7fce 37 static char buf[1024];
38
39 wchar_t *msgbuf;
40 DWORD lasterr = GetLastError();
41 DWORD chars = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM
42 | FORMAT_MESSAGE_ALLOCATE_BUFFER,
43 NULL,
44 error,
45 0, /* Default language */
46 (LPVOID)&msgbuf,
47 0,
48 NULL);
49 if (chars != 0) {
50 /* If there is an \r\n appended, zap it. */
51 if (chars >= 2
52 && msgbuf[chars - 2] == '\r' && msgbuf[chars - 1] == '\n') {
53 chars -= 2;
54 msgbuf[chars] = 0;
55 }
56
57 if (chars > sizeof (buf) - 1) {
58 chars = sizeof (buf) - 1;
59 msgbuf[chars] = 0;
60 }
61
62 wcstombs(buf, msgbuf, chars + 1);
63 LocalFree(msgbuf);
64 }
65 else {
66 sprintf(buf, "unknown win32 error (%ld)", error);
67 }
68
69 SetLastError(lasterr);
70 return buf;
71}
72
73#endif /* UNDER_CE */
74
75/* Reset gzip file state */
f535537f 76local void gz_reset(gz_statep state) {
648db22b 77 state.state->x.have = 0; /* no output data available */
78 if (state.state->mode == GZ_READ) { /* for reading ... */
79 state.state->eof = 0; /* not at end of file */
80 state.state->past = 0; /* have not read past end yet */
81 state.state->how = LOOK; /* look for gzip header */
b24e7fce 82 }
648db22b 83 state.state->seek = 0; /* no seek request pending */
b24e7fce 84 gz_error(state, Z_OK, NULL); /* clear error */
648db22b 85 state.state->x.pos = 0; /* no uncompressed data yet */
86 state.state->strm.avail_in = 0; /* no input data yet */
b24e7fce 87}
88
89/* Open a gzip file either by name or file descriptor. */
f535537f 90local gzFile gz_open(const void *path, int fd, const char *mode) {
b24e7fce 91 gz_statep state;
92 z_size_t len;
93 int oflag;
94#ifdef O_CLOEXEC
95 int cloexec = 0;
96#endif
97#ifdef O_EXCL
98 int exclusive = 0;
99#endif
100
101 /* check input */
102 if (path == NULL)
103 return NULL;
104
105 /* allocate gzFile structure to return */
648db22b 106 state.state = (gz_state*)malloc(sizeof(gz_state));
107 if (state.state == NULL)
b24e7fce 108 return NULL;
648db22b 109 state.state->size = 0; /* no buffers allocated yet */
110 state.state->want = GZBUFSIZE; /* requested buffer size */
111 state.state->msg = NULL; /* no error message yet */
b24e7fce 112
113 /* interpret mode */
648db22b 114 state.state->mode = GZ_NONE;
115 state.state->level = Z_DEFAULT_COMPRESSION;
116 state.state->strategy = Z_DEFAULT_STRATEGY;
117 state.state->direct = 0;
b24e7fce 118 while (*mode) {
119 if (*mode >= '0' && *mode <= '9')
648db22b 120 state.state->level = *mode - '0';
b24e7fce 121 else
122 switch (*mode) {
123 case 'r':
648db22b 124 state.state->mode = GZ_READ;
b24e7fce 125 break;
126#ifndef NO_GZCOMPRESS
127 case 'w':
648db22b 128 state.state->mode = GZ_WRITE;
b24e7fce 129 break;
130 case 'a':
648db22b 131 state.state->mode = GZ_APPEND;
b24e7fce 132 break;
133#endif
134 case '+': /* can't read and write at the same time */
648db22b 135 free(state.state);
b24e7fce 136 return NULL;
137 case 'b': /* ignore -- will request binary anyway */
138 break;
139#ifdef O_CLOEXEC
140 case 'e':
141 cloexec = 1;
142 break;
143#endif
144#ifdef O_EXCL
145 case 'x':
146 exclusive = 1;
147 break;
148#endif
149 case 'f':
648db22b 150 state.state->strategy = Z_FILTERED;
b24e7fce 151 break;
152 case 'h':
648db22b 153 state.state->strategy = Z_HUFFMAN_ONLY;
b24e7fce 154 break;
155 case 'R':
648db22b 156 state.state->strategy = Z_RLE;
b24e7fce 157 break;
158 case 'F':
648db22b 159 state.state->strategy = Z_FIXED;
b24e7fce 160 break;
161 case 'T':
648db22b 162 state.state->direct = 1;
b24e7fce 163 break;
164 default: /* could consider as an error, but just ignore */
165 ;
166 }
167 mode++;
168 }
169
170 /* must provide an "r", "w", or "a" */
648db22b 171 if (state.state->mode == GZ_NONE) {
172 free(state.state);
b24e7fce 173 return NULL;
174 }
175
176 /* can't force transparent read */
648db22b 177 if (state.state->mode == GZ_READ) {
178 if (state.state->direct) {
179 free(state.state);
b24e7fce 180 return NULL;
181 }
648db22b 182 state.state->direct = 1; /* for empty file */
b24e7fce 183 }
184
185 /* save the path name for error messages */
186#ifdef WIDECHAR
187 if (fd == -2) {
188 len = wcstombs(NULL, path, 0);
189 if (len == (z_size_t)-1)
190 len = 0;
191 }
192 else
193#endif
194 len = strlen((const char *)path);
648db22b 195 state.state->path = (char *)malloc(len + 1);
196 if (state.state->path == NULL) {
197 free(state.state);
b24e7fce 198 return NULL;
199 }
200#ifdef WIDECHAR
201 if (fd == -2)
202 if (len)
648db22b 203 wcstombs(state.state->path, path, len + 1);
b24e7fce 204 else
648db22b 205 *(state.state->path) = 0;
b24e7fce 206 else
207#endif
208#if !defined(NO_snprintf) && !defined(NO_vsnprintf)
648db22b 209 (void)snprintf(state.state->path, len + 1, "%s", (const char *)path);
b24e7fce 210#else
648db22b 211 strcpy(state.state->path, (const char*)path);
b24e7fce 212#endif
213
214 /* compute the flags for open() */
215 oflag =
216#ifdef O_LARGEFILE
217 O_LARGEFILE |
218#endif
219#ifdef O_BINARY
220 O_BINARY |
221#endif
222#ifdef O_CLOEXEC
223 (cloexec ? O_CLOEXEC : 0) |
224#endif
648db22b 225 (state.state->mode == GZ_READ ?
b24e7fce 226 O_RDONLY :
227 (O_WRONLY | O_CREAT |
228#ifdef O_EXCL
229 (exclusive ? O_EXCL : 0) |
230#endif
648db22b 231 (state.state->mode == GZ_WRITE ?
b24e7fce 232 O_TRUNC :
233 O_APPEND)));
234
235 /* open the file with the appropriate flags (or just use fd) */
648db22b 236 state.state->fd = fd > -1 ? fd : (
b24e7fce 237#ifdef WIDECHAR
238 fd == -2 ? _wopen(path, oflag, 0666) :
239#endif
240 open((const char *)path, oflag, 0666));
648db22b 241 if (state.state->fd == -1) {
242 free(state.state->path);
243 free(state.state);
b24e7fce 244 return NULL;
245 }
648db22b 246 if (state.state->mode == GZ_APPEND) {
247 LSEEK(state.state->fd, 0, SEEK_END); /* so gzoffset() is correct */
248 state.state->mode = GZ_WRITE; /* simplify later checks */
b24e7fce 249 }
250
251 /* save the current position for rewinding (only if reading) */
648db22b 252 if (state.state->mode == GZ_READ) {
253 state.state->start = LSEEK(state.state->fd, 0, SEEK_CUR);
254 if (state.state->start == -1) state.state->start = 0;
b24e7fce 255 }
256
257 /* initialize stream */
258 gz_reset(state);
259
260 /* return stream */
648db22b 261 return state.file;
b24e7fce 262}
263
264/* -- see zlib.h -- */
f535537f 265gzFile ZEXPORT gzopen(const char *path, const char *mode) {
b24e7fce 266 return gz_open(path, -1, mode);
267}
268
269/* -- see zlib.h -- */
f535537f 270gzFile ZEXPORT gzopen64(const char *path, const char *mode) {
b24e7fce 271 return gz_open(path, -1, mode);
272}
273
274/* -- see zlib.h -- */
f535537f 275gzFile ZEXPORT gzdopen(int fd, const char *mode) {
b24e7fce 276 char *path; /* identifier for error messages */
277 gzFile gz;
278
279 if (fd == -1 || (path = (char *)malloc(7 + 3 * sizeof(int))) == NULL)
280 return NULL;
281#if !defined(NO_snprintf) && !defined(NO_vsnprintf)
282 (void)snprintf(path, 7 + 3 * sizeof(int), "<fd:%d>", fd);
283#else
284 sprintf(path, "<fd:%d>", fd); /* for debugging */
285#endif
286 gz = gz_open(path, fd, mode);
287 free(path);
288 return gz;
289}
290
291/* -- see zlib.h -- */
292#ifdef WIDECHAR
f535537f 293gzFile ZEXPORT gzopen_w(const wchar_t *path, const char *mode) {
b24e7fce 294 return gz_open(path, -2, mode);
295}
296#endif
297
298/* -- see zlib.h -- */
f535537f 299int ZEXPORT gzbuffer(gzFile file, unsigned size) {
b24e7fce 300 gz_statep state;
301
302 /* get internal structure and check integrity */
303 if (file == NULL)
304 return -1;
648db22b 305 state.file = file;
306 if (state.state->mode != GZ_READ && state.state->mode != GZ_WRITE)
b24e7fce 307 return -1;
308
309 /* make sure we haven't already allocated memory */
648db22b 310 if (state.state->size != 0)
b24e7fce 311 return -1;
312
313 /* check and set requested size */
314 if ((size << 1) < size)
315 return -1; /* need to be able to double it */
316 if (size < 2)
317 size = 2; /* need two bytes to check magic header */
648db22b 318 state.state->want = size;
b24e7fce 319 return 0;
320}
321
322/* -- see zlib.h -- */
f535537f 323int ZEXPORT gzrewind(gzFile file) {
b24e7fce 324 gz_statep state;
325
326 /* get internal structure */
327 if (file == NULL)
328 return -1;
648db22b 329 state.file = file;
b24e7fce 330
331 /* check that we're reading and that there's no error */
648db22b 332 if (state.state->mode != GZ_READ ||
333 (state.state->err != Z_OK && state.state->err != Z_BUF_ERROR))
b24e7fce 334 return -1;
335
336 /* back up and start over */
648db22b 337 if (LSEEK(state.state->fd, state.state->start, SEEK_SET) == -1)
b24e7fce 338 return -1;
339 gz_reset(state);
340 return 0;
341}
342
343/* -- see zlib.h -- */
f535537f 344z_off64_t ZEXPORT gzseek64(gzFile file, z_off64_t offset, int whence) {
b24e7fce 345 unsigned n;
346 z_off64_t ret;
347 gz_statep state;
348
349 /* get internal structure and check integrity */
350 if (file == NULL)
351 return -1;
648db22b 352 state.file = file;
353 if (state.state->mode != GZ_READ && state.state->mode != GZ_WRITE)
b24e7fce 354 return -1;
355
356 /* check that there's no error */
648db22b 357 if (state.state->err != Z_OK && state.state->err != Z_BUF_ERROR)
b24e7fce 358 return -1;
359
360 /* can only seek from start or relative to current position */
361 if (whence != SEEK_SET && whence != SEEK_CUR)
362 return -1;
363
364 /* normalize offset to a SEEK_CUR specification */
365 if (whence == SEEK_SET)
648db22b 366 offset -= state.state->x.pos;
367 else if (state.state->seek)
368 offset += state.state->skip;
369 state.state->seek = 0;
b24e7fce 370
371 /* if within raw area while reading, just go there */
648db22b 372 if (state.state->mode == GZ_READ && state.state->how == COPY &&
373 state.state->x.pos + offset >= 0) {
374 ret = LSEEK(state.state->fd, offset - state.state->x.have, SEEK_CUR);
b24e7fce 375 if (ret == -1)
376 return -1;
648db22b 377 state.state->x.have = 0;
378 state.state->eof = 0;
379 state.state->past = 0;
380 state.state->seek = 0;
b24e7fce 381 gz_error(state, Z_OK, NULL);
648db22b 382 state.state->strm.avail_in = 0;
383 state.state->x.pos += offset;
384 return state.state->x.pos;
b24e7fce 385 }
386
387 /* calculate skip amount, rewinding if needed for back seek when reading */
388 if (offset < 0) {
648db22b 389 if (state.state->mode != GZ_READ) /* writing -- can't go backwards */
b24e7fce 390 return -1;
648db22b 391 offset += state.state->x.pos;
b24e7fce 392 if (offset < 0) /* before start of file! */
393 return -1;
394 if (gzrewind(file) == -1) /* rewind, then skip to offset */
395 return -1;
396 }
397
398 /* if reading, skip what's in output buffer (one less gzgetc() check) */
648db22b 399 if (state.state->mode == GZ_READ) {
400 n = GT_OFF(state.state->x.have) || (z_off64_t)state.state->x.have > offset ?
401 (unsigned)offset : state.state->x.have;
402 state.state->x.have -= n;
403 state.state->x.next += n;
404 state.state->x.pos += n;
b24e7fce 405 offset -= n;
406 }
407
408 /* request skip (if not zero) */
409 if (offset) {
648db22b 410 state.state->seek = 1;
411 state.state->skip = offset;
b24e7fce 412 }
648db22b 413 return state.state->x.pos + offset;
b24e7fce 414}
415
416/* -- see zlib.h -- */
f535537f 417z_off_t ZEXPORT gzseek(gzFile file, z_off_t offset, int whence) {
b24e7fce 418 z_off64_t ret;
419
420 ret = gzseek64(file, (z_off64_t)offset, whence);
421 return ret == (z_off_t)ret ? (z_off_t)ret : -1;
422}
423
424/* -- see zlib.h -- */
f535537f 425z_off64_t ZEXPORT gztell64(gzFile file) {
b24e7fce 426 gz_statep state;
427
428 /* get internal structure and check integrity */
429 if (file == NULL)
430 return -1;
648db22b 431 state.file = file;
432 if (state.state->mode != GZ_READ && state.state->mode != GZ_WRITE)
b24e7fce 433 return -1;
434
435 /* return position */
648db22b 436 return state.state->x.pos + (state.state->seek ? state.state->skip : 0);
b24e7fce 437}
438
439/* -- see zlib.h -- */
f535537f 440z_off_t ZEXPORT gztell(gzFile file) {
b24e7fce 441 z_off64_t ret;
442
443 ret = gztell64(file);
444 return ret == (z_off_t)ret ? (z_off_t)ret : -1;
445}
446
447/* -- see zlib.h -- */
f535537f 448z_off64_t ZEXPORT gzoffset64(gzFile file) {
b24e7fce 449 z_off64_t offset;
450 gz_statep state;
451
452 /* get internal structure and check integrity */
453 if (file == NULL)
454 return -1;
648db22b 455 state.file = file;
456 if (state.state->mode != GZ_READ && state.state->mode != GZ_WRITE)
b24e7fce 457 return -1;
458
459 /* compute and return effective offset in file */
648db22b 460 offset = LSEEK(state.state->fd, 0, SEEK_CUR);
b24e7fce 461 if (offset == -1)
462 return -1;
648db22b 463 if (state.state->mode == GZ_READ) /* reading */
464 offset -= state.state->strm.avail_in; /* don't count buffered input */
b24e7fce 465 return offset;
466}
467
468/* -- see zlib.h -- */
f535537f 469z_off_t ZEXPORT gzoffset(gzFile file) {
b24e7fce 470 z_off64_t ret;
471
472 ret = gzoffset64(file);
473 return ret == (z_off_t)ret ? (z_off_t)ret : -1;
474}
475
476/* -- see zlib.h -- */
f535537f 477int ZEXPORT gzeof(gzFile file) {
b24e7fce 478 gz_statep state;
479
480 /* get internal structure and check integrity */
481 if (file == NULL)
482 return 0;
648db22b 483 state.file = file;
484 if (state.state->mode != GZ_READ && state.state->mode != GZ_WRITE)
b24e7fce 485 return 0;
486
487 /* return end-of-file state */
648db22b 488 return state.state->mode == GZ_READ ? state.state->past : 0;
b24e7fce 489}
490
491/* -- see zlib.h -- */
f535537f 492const char * ZEXPORT gzerror(gzFile file, int *errnum) {
b24e7fce 493 gz_statep state;
494
495 /* get internal structure and check integrity */
496 if (file == NULL)
497 return NULL;
648db22b 498 state.file = file;
499 if (state.state->mode != GZ_READ && state.state->mode != GZ_WRITE)
b24e7fce 500 return NULL;
501
502 /* return error information */
503 if (errnum != NULL)
648db22b 504 *errnum = state.state->err;
505 return state.state->err == Z_MEM_ERROR ? "out of memory" :
506 (state.state->msg == NULL ? "" : state.state->msg);
b24e7fce 507}
508
509/* -- see zlib.h -- */
f535537f 510void ZEXPORT gzclearerr(gzFile file) {
b24e7fce 511 gz_statep state;
512
513 /* get internal structure and check integrity */
514 if (file == NULL)
515 return;
648db22b 516 state.file = file;
517 if (state.state->mode != GZ_READ && state.state->mode != GZ_WRITE)
b24e7fce 518 return;
519
520 /* clear error and end-of-file */
648db22b 521 if (state.state->mode == GZ_READ) {
522 state.state->eof = 0;
523 state.state->past = 0;
b24e7fce 524 }
525 gz_error(state, Z_OK, NULL);
526}
527
648db22b 528/* Create an error message in allocated memory and set state.state->err and
529 state.state->msg accordingly. Free any previous error message already there. Do
b24e7fce 530 not try to free or allocate space if the error is Z_MEM_ERROR (out of
531 memory). Simply save the error message as a static string. If there is an
532 allocation failure constructing the error message, then convert the error to
533 out of memory. */
f535537f 534void ZLIB_INTERNAL gz_error(gz_statep state, int err, const char *msg) {
b24e7fce 535 /* free previously allocated message and clear */
648db22b 536 if (state.state->msg != NULL) {
537 if (state.state->err != Z_MEM_ERROR)
538 free(state.state->msg);
539 state.state->msg = NULL;
b24e7fce 540 }
541
648db22b 542 /* if fatal, set state.state->x.have to 0 so that the gzgetc() macro fails */
b24e7fce 543 if (err != Z_OK && err != Z_BUF_ERROR)
648db22b 544 state.state->x.have = 0;
b24e7fce 545
546 /* set error code, and if no message, then done */
648db22b 547 state.state->err = err;
b24e7fce 548 if (msg == NULL)
549 return;
550
551 /* for an out of memory error, return literal string when requested */
552 if (err == Z_MEM_ERROR)
553 return;
554
555 /* construct error message with path */
648db22b 556 if ((state.state->msg = (char *)malloc(strlen(state.state->path) + strlen(msg) + 3)) ==
b24e7fce 557 NULL) {
648db22b 558 state.state->err = Z_MEM_ERROR;
b24e7fce 559 return;
560 }
561#if !defined(NO_snprintf) && !defined(NO_vsnprintf)
648db22b 562 (void)snprintf(state.state->msg, strlen(state.state->path) + strlen(msg) + 3,
563 "%s%s%s", state.state->path, ": ", msg);
b24e7fce 564#else
648db22b 565 strcpy(state.state->msg, state.state->path);
566 strcat(state.state->msg, ": ");
567 strcat(state.state->msg, msg);
b24e7fce 568#endif
569}
570
571#ifndef INT_MAX
572/* portably return maximum value for an int (when limits.h presumed not
573 available) -- we need to do this to cover cases where 2's complement not
574 used, since C standard permits 1's complement and sign-bit representations,
575 otherwise we could just use ((unsigned)-1) >> 1 */
f535537f 576unsigned ZLIB_INTERNAL gz_intmax() {
b24e7fce 577 unsigned p, q;
578
579 p = 1;
580 do {
581 q = p;
582 p <<= 1;
583 p++;
584 } while (p > q);
585 return q >> 1;
586}
587#endif