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