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