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