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