Mercurial > hg > sv-dependency-builds
comparison src/zlib-1.2.7/gzlib.c @ 4:e13257ea84a4
Add bzip2, zlib, liblo, portaudio sources
author | Chris Cannam |
---|---|
date | Wed, 20 Mar 2013 13:59:52 +0000 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
3:6c505a35919a | 4:e13257ea84a4 |
---|---|
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 |