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