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