obligatory forgotten android fixup
[pcsx_rearmed.git] / deps / libchdr / deps / zstd-1.5.6 / zlibWrapper / gzlib.c
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
4 /* gzlib.c -- zlib functions common to reading and 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 "gzguts.h"
10
11 #if defined(_WIN32) && !defined(__BORLANDC__) && !defined(__MINGW32__)
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 */
22 local void gz_reset _Z_OF((gz_statep));
23 local gzFile gz_open _Z_OF((const void *, int, const char *));
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. */
36 char ZLIB_INTERNAL *gz_strwinerror(DWORD error) {
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 */
76 local void gz_reset(gz_statep state) {
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 */
82     }
83     state.state->seek = 0;                /* no seek request pending */
84     gz_error(state, Z_OK, NULL);    /* clear error */
85     state.state->x.pos = 0;               /* no uncompressed data yet */
86     state.state->strm.avail_in = 0;       /* no input data yet */
87 }
88
89 /* Open a gzip file either by name or file descriptor. */
90 local gzFile gz_open(const void *path, int fd, const char *mode) {
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 */
106     state.state = (gz_state*)malloc(sizeof(gz_state));
107     if (state.state == NULL)
108         return NULL;
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 */
112
113     /* interpret mode */
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;
118     while (*mode) {
119         if (*mode >= '0' && *mode <= '9')
120             state.state->level = *mode - '0';
121         else
122             switch (*mode) {
123             case 'r':
124                 state.state->mode = GZ_READ;
125                 break;
126 #ifndef NO_GZCOMPRESS
127             case 'w':
128                 state.state->mode = GZ_WRITE;
129                 break;
130             case 'a':
131                 state.state->mode = GZ_APPEND;
132                 break;
133 #endif
134             case '+':       /* can't read and write at the same time */
135                 free(state.state);
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':
150                 state.state->strategy = Z_FILTERED;
151                 break;
152             case 'h':
153                 state.state->strategy = Z_HUFFMAN_ONLY;
154                 break;
155             case 'R':
156                 state.state->strategy = Z_RLE;
157                 break;
158             case 'F':
159                 state.state->strategy = Z_FIXED;
160                 break;
161             case 'T':
162                 state.state->direct = 1;
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" */
171     if (state.state->mode == GZ_NONE) {
172         free(state.state);
173         return NULL;
174     }
175
176     /* can't force transparent read */
177     if (state.state->mode == GZ_READ) {
178         if (state.state->direct) {
179             free(state.state);
180             return NULL;
181         }
182         state.state->direct = 1;      /* for empty file */
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);
195     state.state->path = (char *)malloc(len + 1);
196     if (state.state->path == NULL) {
197         free(state.state);
198         return NULL;
199     }
200 #ifdef WIDECHAR
201     if (fd == -2)
202         if (len)
203             wcstombs(state.state->path, path, len + 1);
204         else
205             *(state.state->path) = 0;
206     else
207 #endif
208 #if !defined(NO_snprintf) && !defined(NO_vsnprintf)
209         (void)snprintf(state.state->path, len + 1, "%s", (const char *)path);
210 #else
211         strcpy(state.state->path, (const char*)path);
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
225         (state.state->mode == GZ_READ ?
226          O_RDONLY :
227          (O_WRONLY | O_CREAT |
228 #ifdef O_EXCL
229           (exclusive ? O_EXCL : 0) |
230 #endif
231           (state.state->mode == GZ_WRITE ?
232            O_TRUNC :
233            O_APPEND)));
234
235     /* open the file with the appropriate flags (or just use fd) */
236     state.state->fd = fd > -1 ? fd : (
237 #ifdef WIDECHAR
238         fd == -2 ? _wopen(path, oflag, 0666) :
239 #endif
240         open((const char *)path, oflag, 0666));
241     if (state.state->fd == -1) {
242         free(state.state->path);
243         free(state.state);
244         return NULL;
245     }
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 */
249     }
250
251     /* save the current position for rewinding (only if reading) */
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;
255     }
256
257     /* initialize stream */
258     gz_reset(state);
259
260     /* return stream */
261     return state.file;
262 }
263
264 /* -- see zlib.h -- */
265 gzFile ZEXPORT gzopen(const char *path, const char *mode) {
266     return gz_open(path, -1, mode);
267 }
268
269 /* -- see zlib.h -- */
270 gzFile ZEXPORT gzopen64(const char *path, const char *mode) {
271     return gz_open(path, -1, mode);
272 }
273
274 /* -- see zlib.h -- */
275 gzFile ZEXPORT gzdopen(int fd, const char *mode) {
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
293 gzFile ZEXPORT gzopen_w(const wchar_t *path, const char *mode) {
294     return gz_open(path, -2, mode);
295 }
296 #endif
297
298 /* -- see zlib.h -- */
299 int ZEXPORT gzbuffer(gzFile file, unsigned size) {
300     gz_statep state;
301
302     /* get internal structure and check integrity */
303     if (file == NULL)
304         return -1;
305     state.file = file;
306     if (state.state->mode != GZ_READ && state.state->mode != GZ_WRITE)
307         return -1;
308
309     /* make sure we haven't already allocated memory */
310     if (state.state->size != 0)
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 */
318     state.state->want = size;
319     return 0;
320 }
321
322 /* -- see zlib.h -- */
323 int ZEXPORT gzrewind(gzFile file) {
324     gz_statep state;
325
326     /* get internal structure */
327     if (file == NULL)
328         return -1;
329     state.file = file;
330
331     /* check that we're reading and that there's no error */
332     if (state.state->mode != GZ_READ ||
333             (state.state->err != Z_OK && state.state->err != Z_BUF_ERROR))
334         return -1;
335
336     /* back up and start over */
337     if (LSEEK(state.state->fd, state.state->start, SEEK_SET) == -1)
338         return -1;
339     gz_reset(state);
340     return 0;
341 }
342
343 /* -- see zlib.h -- */
344 z_off64_t ZEXPORT gzseek64(gzFile file, z_off64_t offset, int whence) {
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;
352     state.file = file;
353     if (state.state->mode != GZ_READ && state.state->mode != GZ_WRITE)
354         return -1;
355
356     /* check that there's no error */
357     if (state.state->err != Z_OK && state.state->err != Z_BUF_ERROR)
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)
366         offset -= state.state->x.pos;
367     else if (state.state->seek)
368         offset += state.state->skip;
369     state.state->seek = 0;
370
371     /* if within raw area while reading, just go there */
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);
375         if (ret == -1)
376             return -1;
377         state.state->x.have = 0;
378         state.state->eof = 0;
379         state.state->past = 0;
380         state.state->seek = 0;
381         gz_error(state, Z_OK, NULL);
382         state.state->strm.avail_in = 0;
383         state.state->x.pos += offset;
384         return state.state->x.pos;
385     }
386
387     /* calculate skip amount, rewinding if needed for back seek when reading */
388     if (offset < 0) {
389         if (state.state->mode != GZ_READ)         /* writing -- can't go backwards */
390             return -1;
391         offset += state.state->x.pos;
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) */
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;
405         offset -= n;
406     }
407
408     /* request skip (if not zero) */
409     if (offset) {
410         state.state->seek = 1;
411         state.state->skip = offset;
412     }
413     return state.state->x.pos + offset;
414 }
415
416 /* -- see zlib.h -- */
417 z_off_t ZEXPORT gzseek(gzFile file, z_off_t offset, int whence) {
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 -- */
425 z_off64_t ZEXPORT gztell64(gzFile file) {
426     gz_statep state;
427
428     /* get internal structure and check integrity */
429     if (file == NULL)
430         return -1;
431     state.file = file;
432     if (state.state->mode != GZ_READ && state.state->mode != GZ_WRITE)
433         return -1;
434
435     /* return position */
436     return state.state->x.pos + (state.state->seek ? state.state->skip : 0);
437 }
438
439 /* -- see zlib.h -- */
440 z_off_t ZEXPORT gztell(gzFile file) {
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 -- */
448 z_off64_t ZEXPORT gzoffset64(gzFile file) {
449     z_off64_t offset;
450     gz_statep state;
451
452     /* get internal structure and check integrity */
453     if (file == NULL)
454         return -1;
455     state.file = file;
456     if (state.state->mode != GZ_READ && state.state->mode != GZ_WRITE)
457         return -1;
458
459     /* compute and return effective offset in file */
460     offset = LSEEK(state.state->fd, 0, SEEK_CUR);
461     if (offset == -1)
462         return -1;
463     if (state.state->mode == GZ_READ)             /* reading */
464         offset -= state.state->strm.avail_in;     /* don't count buffered input */
465     return offset;
466 }
467
468 /* -- see zlib.h -- */
469 z_off_t ZEXPORT gzoffset(gzFile file) {
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 -- */
477 int ZEXPORT gzeof(gzFile file) {
478     gz_statep state;
479
480     /* get internal structure and check integrity */
481     if (file == NULL)
482         return 0;
483     state.file = file;
484     if (state.state->mode != GZ_READ && state.state->mode != GZ_WRITE)
485         return 0;
486
487     /* return end-of-file state */
488     return state.state->mode == GZ_READ ? state.state->past : 0;
489 }
490
491 /* -- see zlib.h -- */
492 const char * ZEXPORT gzerror(gzFile file, int *errnum) {
493     gz_statep state;
494
495     /* get internal structure and check integrity */
496     if (file == NULL)
497         return NULL;
498     state.file = file;
499     if (state.state->mode != GZ_READ && state.state->mode != GZ_WRITE)
500         return NULL;
501
502     /* return error information */
503     if (errnum != NULL)
504         *errnum = state.state->err;
505     return state.state->err == Z_MEM_ERROR ? "out of memory" :
506                                        (state.state->msg == NULL ? "" : state.state->msg);
507 }
508
509 /* -- see zlib.h -- */
510 void ZEXPORT gzclearerr(gzFile file) {
511     gz_statep state;
512
513     /* get internal structure and check integrity */
514     if (file == NULL)
515         return;
516     state.file = file;
517     if (state.state->mode != GZ_READ && state.state->mode != GZ_WRITE)
518         return;
519
520     /* clear error and end-of-file */
521     if (state.state->mode == GZ_READ) {
522         state.state->eof = 0;
523         state.state->past = 0;
524     }
525     gz_error(state, Z_OK, NULL);
526 }
527
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
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. */
534 void ZLIB_INTERNAL gz_error(gz_statep state, int err, const char *msg) {
535     /* free previously allocated message and clear */
536     if (state.state->msg != NULL) {
537         if (state.state->err != Z_MEM_ERROR)
538             free(state.state->msg);
539         state.state->msg = NULL;
540     }
541
542     /* if fatal, set state.state->x.have to 0 so that the gzgetc() macro fails */
543     if (err != Z_OK && err != Z_BUF_ERROR)
544         state.state->x.have = 0;
545
546     /* set error code, and if no message, then done */
547     state.state->err = err;
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 */
556     if ((state.state->msg = (char *)malloc(strlen(state.state->path) + strlen(msg) + 3)) ==
557             NULL) {
558         state.state->err = Z_MEM_ERROR;
559         return;
560     }
561 #if !defined(NO_snprintf) && !defined(NO_vsnprintf)
562     (void)snprintf(state.state->msg, strlen(state.state->path) + strlen(msg) + 3,
563                    "%s%s%s", state.state->path, ": ", msg);
564 #else
565     strcpy(state.state->msg, state.state->path);
566     strcat(state.state->msg, ": ");
567     strcat(state.state->msg, msg);
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 */
576 unsigned ZLIB_INTERNAL gz_intmax() {
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