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