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 gzoffset(gzFile file);
20 int gzbuffer(gzFile file, unsigned size);
21
22 /* Local functions */
23 static void gz_reset OF((gz_statep));
24 static 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. */
gz_strwinerror(error)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 */
gz_reset(gz_statep state)79 static 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. */
gz_open(const void * path,int fd,const char * mode)94 static 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
gzopen(const char * path,const char * mode)267 gzFile gzopen(const char *path, const char *mode)
268 {
269 return gz_open(path, -1, mode);
270 }
271
gzopen64(const char * path,const char * mode)272 gzFile gzopen64(const char *path, const char *mode)
273 {
274 return gz_open(path, -1, mode);
275 }
276
gzdopen(int fd,const char * mode)277 gzFile gzdopen(int fd, const char *mode)
278 {
279 char *path; /* identifier for error messages */
280 gzFile gz;
281
282 if (fd == -1 || (path = (char *)malloc(7 + 3 * sizeof(int))) == NULL)
283 return NULL;
284 #if !defined(NO_snprintf) && !defined(NO_vsnprintf)
285 snprintf(path, 7 + 3 * sizeof(int), "<fd:%d>", fd); /* for debugging */
286 #else
287 sprintf(path, "<fd:%d>", fd); /* for debugging */
288 #endif
289 gz = gz_open(path, fd, mode);
290 free(path);
291 return gz;
292 }
293
294 #ifdef _WIN32
gzopen_w(const wchar_t * path,const char * mode)295 gzFile gzopen_w(const wchar_t *path, const char *mode)
296 {
297 return gz_open(path, -2, mode);
298 }
299 #endif
300
gzbuffer(gzFile file,unsigned size)301 int gzbuffer(gzFile file, unsigned size)
302 {
303 gz_statep state;
304
305 /* get internal structure and check integrity */
306 if (file == NULL)
307 return -1;
308 state = (gz_statep)file;
309 if (state->mode != GZ_READ && state->mode != GZ_WRITE)
310 return -1;
311
312 /* make sure we haven't already allocated memory */
313 if (state->size != 0)
314 return -1;
315
316 /* check and set requested size */
317 if (size < 2)
318 size = 2; /* need two bytes to check magic header */
319 state->want = size;
320 return 0;
321 }
322
gzrewind(gzFile file)323 int gzrewind(gzFile file)
324 {
325 gz_statep state;
326
327 /* get internal structure */
328 if (file == NULL)
329 return -1;
330 state = (gz_statep)file;
331
332 /* check that we're reading and that there's no error */
333 if (state->mode != GZ_READ ||
334 (state->err != Z_OK && state->err != Z_BUF_ERROR))
335 return -1;
336
337 /* back up and start over */
338 if (LSEEK(state->fd, state->start, SEEK_SET) == -1)
339 return -1;
340 gz_reset(state);
341 return 0;
342 }
343
gzseek64(gzFile file,z_off64_t offset,int whence)344 z_off64_t gzseek64(gzFile file, z_off64_t offset, int whence)
345 {
346 unsigned n;
347 z_off64_t ret;
348 gz_statep state;
349
350 /* get internal structure and check integrity */
351 if (file == NULL)
352 return -1;
353 state = (gz_statep)file;
354 if (state->mode != GZ_READ && state->mode != GZ_WRITE)
355 return -1;
356
357 /* check that there's no error */
358 if (state->err != Z_OK && state->err != Z_BUF_ERROR)
359 return -1;
360
361 /* can only seek from start or relative to current position */
362 if (whence != SEEK_SET && whence != SEEK_CUR)
363 return -1;
364
365 /* normalize offset to a SEEK_CUR specification */
366 if (whence == SEEK_SET)
367 offset -= state->x.pos;
368 else if (state->seek)
369 offset += state->skip;
370 state->seek = 0;
371
372 /* if within raw area while reading, just go there */
373 if (state->mode == GZ_READ && state->how == MODE_COPY &&
374 state->x.pos + offset >= 0) {
375 ret = LSEEK(state->fd, offset - state->x.have, SEEK_CUR);
376 if (ret == -1)
377 return -1;
378 state->x.have = 0;
379 state->eof = 0;
380 state->past = 0;
381 state->seek = 0;
382 gz_error(state, Z_OK, NULL);
383 state->strm.avail_in = 0;
384 state->x.pos += offset;
385 return state->x.pos;
386 }
387
388 /* calculate skip amount, rewinding if needed for back seek when reading */
389 if (offset < 0) {
390 if (state->mode != GZ_READ) /* writing -- can't go backwards */
391 return -1;
392 offset += state->x.pos;
393 if (offset < 0) /* before start of file! */
394 return -1;
395 if (gzrewind(file) == -1) /* rewind, then skip to offset */
396 return -1;
397 }
398
399 /* if reading, skip what's in output buffer (one less gzgetc() check) */
400 if (state->mode == GZ_READ) {
401 n = GT_OFF(state->x.have) || (z_off64_t)state->x.have > offset ?
402 (unsigned)offset : state->x.have;
403 state->x.have -= n;
404 state->x.next += n;
405 state->x.pos += n;
406 offset -= n;
407 }
408
409 /* request skip (if not zero) */
410 if (offset) {
411 state->seek = 1;
412 state->skip = offset;
413 }
414 return state->x.pos + offset;
415 }
416
gzseek(gzFile file,z_off_t offset,int whence)417 z_off_t gzseek(gzFile file, z_off_t offset, int whence)
418 {
419 z_off64_t ret;
420
421 ret = gzseek64(file, (z_off64_t)offset, whence);
422 return ret == (z_off_t)ret ? (z_off_t)ret : -1;
423 }
424
gztell64(gzFile file)425 z_off64_t gztell64(gzFile file)
426 {
427 gz_statep state;
428
429 /* get internal structure and check integrity */
430 if (file == NULL)
431 return -1;
432 state = (gz_statep)file;
433 if (state->mode != GZ_READ && state->mode != GZ_WRITE)
434 return -1;
435
436 /* return position */
437 return state->x.pos + (state->seek ? state->skip : 0);
438 }
439
gztell(gzFile file)440 z_off_t gztell(gzFile file)
441 {
442 z_off64_t ret;
443
444 ret = gztell64(file);
445 return ret == (z_off_t)ret ? (z_off_t)ret : -1;
446 }
447
gzoffset64(gzFile file)448 z_off64_t gzoffset64(gzFile file)
449 {
450 z_off64_t offset;
451 gz_statep state;
452
453 /* get internal structure and check integrity */
454 if (file == NULL)
455 return -1;
456 state = (gz_statep)file;
457 if (state->mode != GZ_READ && state->mode != GZ_WRITE)
458 return -1;
459
460 /* compute and return effective offset in file */
461 offset = LSEEK(state->fd, 0, SEEK_CUR);
462 if (offset == -1)
463 return -1;
464 if (state->mode == GZ_READ) /* reading */
465 offset -= state->strm.avail_in; /* don't count buffered input */
466 return offset;
467 }
468
gzoffset(gzFile file)469 z_off_t gzoffset(gzFile file)
470 {
471 z_off64_t ret = gzoffset64(file);
472 return ret == (z_off_t)ret ? (z_off_t)ret : -1;
473 }
474
gzeof(gzFile file)475 int gzeof(gzFile file)
476 {
477 gz_statep state;
478
479 /* get internal structure and check integrity */
480 if (file == NULL)
481 return 0;
482 state = (gz_statep)file;
483 if (state->mode != GZ_READ && state->mode != GZ_WRITE)
484 return 0;
485
486 /* return end-of-file state */
487 return state->mode == GZ_READ ? state->past : 0;
488 }
489
gzerror(gzFile file,int * errnum)490 const char * gzerror(gzFile file, int *errnum)
491 {
492 gz_statep state;
493
494 /* get internal structure and check integrity */
495 if (file == NULL)
496 return NULL;
497 state = (gz_statep)file;
498 if (state->mode != GZ_READ && state->mode != GZ_WRITE)
499 return NULL;
500
501 /* return error information */
502 if (errnum != NULL)
503 *errnum = state->err;
504 return state->err == Z_MEM_ERROR ? "out of memory" :
505 (state->msg == NULL ? "" : state->msg);
506 }
507
gzclearerr(gzFile file)508 void gzclearerr(gzFile file)
509 {
510 gz_statep state;
511
512 /* get internal structure and check integrity */
513 if (file == NULL)
514 return;
515 state = (gz_statep)file;
516 if (state->mode != GZ_READ && state->mode != GZ_WRITE)
517 return;
518
519 /* clear error and end-of-file */
520 if (state->mode == GZ_READ) {
521 state->eof = 0;
522 state->past = 0;
523 }
524 gz_error(state, Z_OK, NULL);
525 }
526
527 /* Create an error message in allocated memory and set state->err and
528 state->msg accordingly. Free any previous error message already there. Do
529 not try to free or allocate space if the error is Z_MEM_ERROR (out of
530 memory). Simply save the error message as a static string. If there is an
531 allocation failure constructing the error message, then convert the error to
532 out of memory. */
gz_error(gz_statep state,int err,const char * msg)533 void ZLIB_INTERNAL gz_error(gz_statep state, int err, const char *msg)
534 {
535 /* free previously allocated message and clear */
536 if (state->msg != NULL) {
537 if (state->err != Z_MEM_ERROR)
538 free(state->msg);
539 state->msg = NULL;
540 }
541
542 /* if fatal, set state->x.have to 0 so that the gzgetc() macro fails */
543 if (err != Z_OK && err != Z_BUF_ERROR)
544 state->x.have = 0;
545
546 /* set error code, and if no message, then done */
547 state->err = err;
548 if (msg == NULL)
549 return;
550
551 /* for an out of memory error, return literal string when requested */
552 if (err == Z_MEM_ERROR)
553 return;
554
555 /* construct error message with path */
556 if ((state->msg = (char *)malloc(strlen(state->path) + strlen(msg) + 3)) ==
557 NULL) {
558 state->err = Z_MEM_ERROR;
559 return;
560 }
561 #if !defined(NO_snprintf) && !defined(NO_vsnprintf)
562 snprintf(state->msg, strlen(state->path) + strlen(msg) + 3,
563 "%s%s%s", state->path, ": ", msg);
564 #else
565 strlcpy(state->msg, state->path, sizeof(state->msg));
566 strlcat(state->msg, ": ", sizeof(state->msg));
567 strlcat(state->msg, msg, sizeof(state->msg));
568 #endif
569 return;
570 }
571
572 #ifndef INT_MAX
573 /* portably return maximum value for an int (when limits.h presumed not
574 available) -- we need to do this to cover cases where 2's complement not
575 used, since C standard permits 1's complement and sign-bit representations,
576 otherwise we could just use ((unsigned)-1) >> 1 */
gz_intmax()577 unsigned ZLIB_INTERNAL gz_intmax()
578 {
579 unsigned p, q;
580
581 p = 1;
582 do {
583 q = p;
584 p <<= 1;
585 p++;
586 } while (p > q);
587 return q >> 1;
588 }
589 #endif
590