merge remote-tracking branch 'notaz/master'
[pcsx_rearmed.git] / deps / zlib / gzlib.c
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 */
19 z_off_t ZEXPORT gzoffset(gzFile file);
20 int ZEXPORT gzbuffer(gzFile file, unsigned size);
21
22 /* Local functions */
23 local void gz_reset OF((gz_statep));
24 local 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. */
37 char 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 */
79 local 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. */
94 local 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 -- */
268 gzFile ZEXPORT gzopen(const char *path, const char *mode)
269 {
270    return gz_open(path, -1, mode);
271 }
272
273 /* -- see zlib.h -- */
274 gzFile ZEXPORT gzopen64(const char *path, const char *mode)
275 {
276    return gz_open(path, -1, mode);
277 }
278
279 /* -- see zlib.h -- */
280 gzFile 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
299 gzFile 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 -- */
306 int 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 -- */
329 int 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 -- */
351 z_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 -- */
425 z_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 -- */
434 z_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 -- */
450 z_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 -- */
459 z_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 -- */
481 z_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 -- */
488 int 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 -- */
504 const 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 -- */
523 void 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. */
548 void 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 */
592 unsigned 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