diff options
Diffstat (limited to 'gzio.c')
-rw-r--r-- | gzio.c | 1196 |
1 files changed, 0 insertions, 1196 deletions
@@ -1,1196 +0,0 @@ | |||
1 | /* gzio.c -- IO on .gz files | ||
2 | * Copyright (C) 1995-2010 Jean-loup Gailly. | ||
3 | * For conditions of distribution and use, see copyright notice in zlib.h | ||
4 | * | ||
5 | * Compile this file with -DNO_GZCOMPRESS to avoid the compression code. | ||
6 | */ | ||
7 | |||
8 | /* @(#) $Id$ */ | ||
9 | |||
10 | #ifdef OLD_GZIO | ||
11 | |||
12 | #ifdef _LARGEFILE64_SOURCE | ||
13 | # ifndef _LARGEFILE_SOURCE | ||
14 | # define _LARGEFILE_SOURCE | ||
15 | # endif | ||
16 | # ifdef _FILE_OFFSET_BITS | ||
17 | # undef _FILE_OFFSET_BITS | ||
18 | # endif | ||
19 | #endif | ||
20 | |||
21 | #include "zutil.h" | ||
22 | #include <stdio.h> | ||
23 | |||
24 | #ifdef NO_DEFLATE /* for compatibility with old definition */ | ||
25 | # define NO_GZCOMPRESS | ||
26 | #endif | ||
27 | |||
28 | #ifndef NO_DUMMY_DECL | ||
29 | struct internal_state {int dummy;}; /* for buggy compilers */ | ||
30 | #endif | ||
31 | |||
32 | #ifndef Z_BUFSIZE | ||
33 | # ifdef MAXSEG_64K | ||
34 | # define Z_BUFSIZE 4096 /* minimize memory usage for 16-bit DOS */ | ||
35 | # else | ||
36 | # define Z_BUFSIZE 16384 | ||
37 | # endif | ||
38 | #endif | ||
39 | #ifndef Z_PRINTF_BUFSIZE | ||
40 | # define Z_PRINTF_BUFSIZE 4096 | ||
41 | #endif | ||
42 | |||
43 | #if defined UNDER_CE && defined NO_ERRNO_H | ||
44 | # include <windows.h> | ||
45 | |||
46 | /* Map the Windows error number in ERROR to a locale-dependent error | ||
47 | message string and return a pointer to it. Typically, the values | ||
48 | for ERROR come from GetLastError. | ||
49 | |||
50 | The string pointed to shall not be modified by the application, | ||
51 | but may be overwritten by a subsequent call to strwinerror | ||
52 | |||
53 | The strwinerror function does not change the current setting | ||
54 | of GetLastError. */ | ||
55 | |||
56 | local char *strwinerror (error) | ||
57 | DWORD error; | ||
58 | { | ||
59 | static char buf[1024]; | ||
60 | |||
61 | wchar_t *msgbuf; | ||
62 | DWORD lasterr = GetLastError(); | ||
63 | DWORD chars = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | ||
64 | | FORMAT_MESSAGE_ALLOCATE_BUFFER, | ||
65 | NULL, | ||
66 | error, | ||
67 | 0, /* Default language */ | ||
68 | (LPVOID)&msgbuf, | ||
69 | 0, | ||
70 | NULL); | ||
71 | if (chars != 0) { | ||
72 | /* If there is an \r\n appended, zap it. */ | ||
73 | if (chars >= 2 | ||
74 | && msgbuf[chars - 2] == '\r' && msgbuf[chars - 1] == '\n') { | ||
75 | chars -= 2; | ||
76 | msgbuf[chars] = 0; | ||
77 | } | ||
78 | |||
79 | if (chars > sizeof (buf) - 1) { | ||
80 | chars = sizeof (buf) - 1; | ||
81 | msgbuf[chars] = 0; | ||
82 | } | ||
83 | |||
84 | wcstombs(buf, msgbuf, chars + 1); | ||
85 | LocalFree(msgbuf); | ||
86 | } | ||
87 | else { | ||
88 | sprintf(buf, "unknown win32 error (%ld)", error); | ||
89 | } | ||
90 | |||
91 | SetLastError(lasterr); | ||
92 | return buf; | ||
93 | } | ||
94 | |||
95 | #endif /* UNDER_CE && NO_ERRNO_H */ | ||
96 | |||
97 | #ifdef __MVS__ | ||
98 | #pragma map (fdopen , "\174\174FDOPEN") | ||
99 | FILE *fdopen(int, const char *); | ||
100 | #endif | ||
101 | |||
102 | #ifndef STDC | ||
103 | extern voidp malloc OF((uInt size)); | ||
104 | extern void free OF((voidpf ptr)); | ||
105 | #endif | ||
106 | |||
107 | #ifdef NO_FSEEKO | ||
108 | # define FSEEK fseek | ||
109 | # define FTELL ftell | ||
110 | #else | ||
111 | # define FSEEK fseeko | ||
112 | # define FTELL ftello | ||
113 | #endif | ||
114 | |||
115 | #define ALLOC(size) malloc(size) | ||
116 | #define TRYFREE(p) {if (p) free(p);} | ||
117 | |||
118 | static int const gz_magic[2] = {0x1f, 0x8b}; /* gzip magic header */ | ||
119 | |||
120 | /* gzip flag byte */ | ||
121 | #define ASCII_FLAG 0x01 /* bit 0 set: file probably ascii text */ | ||
122 | #define HEAD_CRC 0x02 /* bit 1 set: header CRC present */ | ||
123 | #define EXTRA_FIELD 0x04 /* bit 2 set: extra field present */ | ||
124 | #define ORIG_NAME 0x08 /* bit 3 set: original file name present */ | ||
125 | #define COMMENT 0x10 /* bit 4 set: file comment present */ | ||
126 | #define RESERVED 0xE0 /* bits 5..7: reserved */ | ||
127 | |||
128 | typedef struct gz_stream { | ||
129 | z_stream stream; | ||
130 | int z_err; /* error code for last stream operation */ | ||
131 | int z_eof; /* set if end of input file */ | ||
132 | FILE *file; /* .gz file */ | ||
133 | Byte *inbuf; /* input buffer */ | ||
134 | Byte *outbuf; /* output buffer */ | ||
135 | uLong crc; /* crc32 of uncompressed data */ | ||
136 | char *msg; /* error message */ | ||
137 | char *path; /* path name for debugging only */ | ||
138 | int transparent; /* 1 if input file is not a .gz file */ | ||
139 | char mode; /* 'w' or 'r' */ | ||
140 | z_off64_t start; /* start of compressed data in file */ | ||
141 | z_off64_t in; /* bytes into deflate or inflate */ | ||
142 | z_off64_t out; /* bytes out of deflate or inflate */ | ||
143 | int back; /* one character push-back */ | ||
144 | int last; /* true if push-back is last character */ | ||
145 | } gz_stream; | ||
146 | |||
147 | |||
148 | local gzFile gz_open OF((const char *, const char *, int, int)); | ||
149 | local z_off64_t gz_seek OF((gzFile, z_off64_t, int, int)); | ||
150 | local int do_flush OF((gzFile, int)); | ||
151 | local int get_byte OF((gz_stream *)); | ||
152 | local void check_header OF((gz_stream *)); | ||
153 | local int destroy OF((gz_stream *)); | ||
154 | local void putLong OF((FILE *, uLong)); | ||
155 | local uLong getLong OF((gz_stream *)); | ||
156 | |||
157 | /* =========================================================================== | ||
158 | Opens a gzip (.gz) file for reading or writing. The mode parameter | ||
159 | is as in fopen ("rb" or "wb"). The file is given either by file descriptor | ||
160 | or path name (if fd == -1). | ||
161 | gz_open returns NULL if the file could not be opened or if there was | ||
162 | insufficient memory to allocate the (de)compression state; errno | ||
163 | can be checked to distinguish the two cases (if errno is zero, the | ||
164 | zlib error is Z_MEM_ERROR). | ||
165 | */ | ||
166 | local gzFile gz_open (path, mode, fd, use64) | ||
167 | const char *path; | ||
168 | const char *mode; | ||
169 | int fd; | ||
170 | int use64; | ||
171 | { | ||
172 | int err; | ||
173 | int level = Z_DEFAULT_COMPRESSION; /* compression level */ | ||
174 | int strategy = Z_DEFAULT_STRATEGY; /* compression strategy */ | ||
175 | char *p = (char*)mode; | ||
176 | gz_stream *s; | ||
177 | char fmode[80]; /* copy of mode, without the compression level */ | ||
178 | char *m = fmode; | ||
179 | |||
180 | if (!path || !mode) return Z_NULL; | ||
181 | |||
182 | s = (gz_stream *)ALLOC(sizeof(gz_stream)); | ||
183 | if (!s) return Z_NULL; | ||
184 | |||
185 | s->stream.zalloc = (alloc_func)0; | ||
186 | s->stream.zfree = (free_func)0; | ||
187 | s->stream.opaque = (voidpf)0; | ||
188 | s->stream.next_in = s->inbuf = Z_NULL; | ||
189 | s->stream.next_out = s->outbuf = Z_NULL; | ||
190 | s->stream.avail_in = s->stream.avail_out = 0; | ||
191 | s->stream.state = Z_NULL; | ||
192 | s->file = NULL; | ||
193 | s->z_err = Z_OK; | ||
194 | s->z_eof = 0; | ||
195 | s->in = 0; | ||
196 | s->out = 0; | ||
197 | s->back = EOF; | ||
198 | s->crc = crc32(0L, Z_NULL, 0); | ||
199 | s->msg = NULL; | ||
200 | s->transparent = 0; | ||
201 | |||
202 | s->path = (char*)ALLOC(strlen(path)+1); | ||
203 | if (s->path == NULL) { | ||
204 | return destroy(s), (gzFile)Z_NULL; | ||
205 | } | ||
206 | strcpy(s->path, path); /* do this early for debugging */ | ||
207 | |||
208 | s->mode = '\0'; | ||
209 | do { | ||
210 | if (*p == 'r') s->mode = 'r'; | ||
211 | if (*p == 'w' || *p == 'a') s->mode = 'w'; | ||
212 | if (*p >= '0' && *p <= '9') { | ||
213 | level = *p - '0'; | ||
214 | } else if (*p == 'f') { | ||
215 | strategy = Z_FILTERED; | ||
216 | } else if (*p == 'h') { | ||
217 | strategy = Z_HUFFMAN_ONLY; | ||
218 | } else if (*p == 'R') { | ||
219 | strategy = Z_RLE; | ||
220 | } else { | ||
221 | *m++ = *p; /* copy the mode */ | ||
222 | } | ||
223 | } while (*p++ && m != fmode + sizeof(fmode)); | ||
224 | if (s->mode == '\0') return destroy(s), (gzFile)Z_NULL; | ||
225 | |||
226 | if (s->mode == 'w') { | ||
227 | #ifdef NO_GZCOMPRESS | ||
228 | err = Z_STREAM_ERROR; | ||
229 | #else | ||
230 | err = deflateInit2(&(s->stream), level, | ||
231 | Z_DEFLATED, -MAX_WBITS, DEF_MEM_LEVEL, strategy); | ||
232 | /* windowBits is passed < 0 to suppress zlib header */ | ||
233 | |||
234 | s->stream.next_out = s->outbuf = (Byte*)ALLOC(Z_BUFSIZE); | ||
235 | #endif | ||
236 | if (err != Z_OK || s->outbuf == Z_NULL) { | ||
237 | return destroy(s), (gzFile)Z_NULL; | ||
238 | } | ||
239 | } else { | ||
240 | s->stream.next_in = s->inbuf = (Byte*)ALLOC(Z_BUFSIZE); | ||
241 | |||
242 | err = inflateInit2(&(s->stream), -MAX_WBITS); | ||
243 | /* windowBits is passed < 0 to tell that there is no zlib header */ | ||
244 | if (err != Z_OK || s->inbuf == Z_NULL) { | ||
245 | return destroy(s), (gzFile)Z_NULL; | ||
246 | } | ||
247 | } | ||
248 | s->stream.avail_out = Z_BUFSIZE; | ||
249 | |||
250 | zseterrno(0); | ||
251 | s->file = fd == -1 ? | ||
252 | (use64 ? F_OPEN64(path, fmode) : F_OPEN(path, fmode)) : | ||
253 | (FILE*)fdopen(fd, fmode); | ||
254 | |||
255 | if (s->file == NULL) { | ||
256 | return destroy(s), (gzFile)Z_NULL; | ||
257 | } | ||
258 | if (s->mode == 'w') { | ||
259 | /* Write a very simple .gz header: | ||
260 | */ | ||
261 | fprintf(s->file, "%c%c%c%c%c%c%c%c%c%c", gz_magic[0], gz_magic[1], | ||
262 | Z_DEFLATED, 0 /*flags*/, 0,0,0,0 /*time*/, level == 9 ? 2 : | ||
263 | (strategy >= Z_HUFFMAN_ONLY || | ||
264 | (level != Z_DEFAULT_COMPRESSION && level < 2) ? | ||
265 | 4 : 0) /*xflags*/, OS_CODE); | ||
266 | s->start = 10L; | ||
267 | /* We use 10L instead of ftell(s->file) to because ftell causes an | ||
268 | * fflush on some systems. This version of the library doesn't use | ||
269 | * start anyway in write mode, so this initialization is not | ||
270 | * necessary. | ||
271 | */ | ||
272 | } else { | ||
273 | check_header(s); /* skip the .gz header */ | ||
274 | s->start = FTELL(s->file) - s->stream.avail_in; | ||
275 | } | ||
276 | |||
277 | return (gzFile)s; | ||
278 | } | ||
279 | |||
280 | /* =========================================================================== | ||
281 | Opens a gzip (.gz) file for reading or writing. | ||
282 | */ | ||
283 | gzFile ZEXPORT gzopen (path, mode) | ||
284 | const char *path; | ||
285 | const char *mode; | ||
286 | { | ||
287 | return gz_open (path, mode, -1, 0); | ||
288 | } | ||
289 | |||
290 | /* =========================================================================== | ||
291 | Opens a gzip (.gz) file for reading or writing for 64-bit offsets | ||
292 | */ | ||
293 | gzFile ZEXPORT gzopen64 (path, mode) | ||
294 | const char *path; | ||
295 | const char *mode; | ||
296 | { | ||
297 | return gz_open (path, mode, -1, 1); | ||
298 | } | ||
299 | |||
300 | /* =========================================================================== | ||
301 | Associate a gzFile with the file descriptor fd. fd is not dup'ed here | ||
302 | to mimic the behavio(u)r of fdopen. | ||
303 | */ | ||
304 | gzFile ZEXPORT gzdopen (fd, mode) | ||
305 | int fd; | ||
306 | const char *mode; | ||
307 | { | ||
308 | char name[46]; /* allow for up to 128-bit integers */ | ||
309 | |||
310 | if (fd == -1) return (gzFile)Z_NULL; | ||
311 | sprintf(name, "<fd:%d>", fd); /* for debugging */ | ||
312 | |||
313 | return gz_open (name, mode, fd, 0); | ||
314 | } | ||
315 | |||
316 | /* =========================================================================== | ||
317 | * Update the compression level and strategy | ||
318 | */ | ||
319 | int ZEXPORT gzsetparams (file, level, strategy) | ||
320 | gzFile file; | ||
321 | int level; | ||
322 | int strategy; | ||
323 | { | ||
324 | gz_stream *s = (gz_stream*)file; | ||
325 | |||
326 | if (s == NULL || s->mode != 'w') return Z_STREAM_ERROR; | ||
327 | |||
328 | /* Make room to allow flushing */ | ||
329 | if (s->stream.avail_out == 0) { | ||
330 | |||
331 | s->stream.next_out = s->outbuf; | ||
332 | if (fwrite(s->outbuf, 1, Z_BUFSIZE, s->file) != Z_BUFSIZE) { | ||
333 | s->z_err = Z_ERRNO; | ||
334 | } | ||
335 | s->stream.avail_out = Z_BUFSIZE; | ||
336 | } | ||
337 | |||
338 | return deflateParams (&(s->stream), level, strategy); | ||
339 | } | ||
340 | |||
341 | /* =========================================================================== | ||
342 | Read a byte from a gz_stream; update next_in and avail_in. Return EOF | ||
343 | for end of file. | ||
344 | IN assertion: the stream s has been successfully opened for reading. | ||
345 | */ | ||
346 | local int get_byte(s) | ||
347 | gz_stream *s; | ||
348 | { | ||
349 | if (s->z_eof) return EOF; | ||
350 | if (s->stream.avail_in == 0) { | ||
351 | zseterrno(0); | ||
352 | s->stream.avail_in = (uInt)fread(s->inbuf, 1, Z_BUFSIZE, s->file); | ||
353 | if (s->stream.avail_in == 0) { | ||
354 | s->z_eof = 1; | ||
355 | if (ferror(s->file)) s->z_err = Z_ERRNO; | ||
356 | return EOF; | ||
357 | } | ||
358 | s->stream.next_in = s->inbuf; | ||
359 | } | ||
360 | s->stream.avail_in--; | ||
361 | return *(s->stream.next_in)++; | ||
362 | } | ||
363 | |||
364 | /* =========================================================================== | ||
365 | Check the gzip header of a gz_stream opened for reading. Set the stream | ||
366 | mode to transparent if the gzip magic header is not present; set s->err | ||
367 | to Z_DATA_ERROR if the magic header is present but the rest of the header | ||
368 | is incorrect. | ||
369 | IN assertion: the stream s has already been created successfully; | ||
370 | s->stream.avail_in is zero for the first time, but may be non-zero | ||
371 | for concatenated .gz files. | ||
372 | */ | ||
373 | local void check_header(s) | ||
374 | gz_stream *s; | ||
375 | { | ||
376 | int method; /* method byte */ | ||
377 | int flags; /* flags byte */ | ||
378 | uInt len; | ||
379 | int c; | ||
380 | |||
381 | /* Assure two bytes in the buffer so we can peek ahead -- handle case | ||
382 | where first byte of header is at the end of the buffer after the last | ||
383 | gzip segment */ | ||
384 | len = s->stream.avail_in; | ||
385 | if (len < 2) { | ||
386 | if (len) s->inbuf[0] = s->stream.next_in[0]; | ||
387 | zseterrno(0); | ||
388 | len = (uInt)fread(s->inbuf + len, 1, Z_BUFSIZE >> len, s->file); | ||
389 | if (len == 0) s->z_eof = 1; | ||
390 | if (len == 0 && ferror(s->file)) s->z_err = Z_ERRNO; | ||
391 | s->stream.avail_in += len; | ||
392 | s->stream.next_in = s->inbuf; | ||
393 | if (s->stream.avail_in < 2) { | ||
394 | s->transparent = s->stream.avail_in; | ||
395 | return; | ||
396 | } | ||
397 | } | ||
398 | |||
399 | /* Peek ahead to check the gzip magic header */ | ||
400 | if (s->stream.next_in[0] != gz_magic[0] || | ||
401 | s->stream.next_in[1] != gz_magic[1]) { | ||
402 | s->transparent = 1; | ||
403 | return; | ||
404 | } | ||
405 | s->stream.avail_in -= 2; | ||
406 | s->stream.next_in += 2; | ||
407 | |||
408 | /* Check the rest of the gzip header */ | ||
409 | method = get_byte(s); | ||
410 | flags = get_byte(s); | ||
411 | if (method != Z_DEFLATED || (flags & RESERVED) != 0) { | ||
412 | s->z_err = Z_DATA_ERROR; | ||
413 | return; | ||
414 | } | ||
415 | |||
416 | /* Discard time, xflags and OS code: */ | ||
417 | for (len = 0; len < 6; len++) (void)get_byte(s); | ||
418 | |||
419 | if ((flags & EXTRA_FIELD) != 0) { /* skip the extra field */ | ||
420 | len = (uInt)get_byte(s); | ||
421 | len += ((uInt)get_byte(s))<<8; | ||
422 | /* len is garbage if EOF but the loop below will quit anyway */ | ||
423 | while (len-- != 0 && get_byte(s) != EOF) ; | ||
424 | } | ||
425 | if ((flags & ORIG_NAME) != 0) { /* skip the original file name */ | ||
426 | while ((c = get_byte(s)) != 0 && c != EOF) ; | ||
427 | } | ||
428 | if ((flags & COMMENT) != 0) { /* skip the .gz file comment */ | ||
429 | while ((c = get_byte(s)) != 0 && c != EOF) ; | ||
430 | } | ||
431 | if ((flags & HEAD_CRC) != 0) { /* skip the header crc */ | ||
432 | for (len = 0; len < 2; len++) (void)get_byte(s); | ||
433 | } | ||
434 | s->z_err = s->z_eof ? Z_DATA_ERROR : Z_OK; | ||
435 | } | ||
436 | |||
437 | /* =========================================================================== | ||
438 | * Cleanup then free the given gz_stream. Return a zlib error code. | ||
439 | Try freeing in the reverse order of allocations. | ||
440 | */ | ||
441 | local int destroy (s) | ||
442 | gz_stream *s; | ||
443 | { | ||
444 | int err = Z_OK; | ||
445 | |||
446 | if (!s) return Z_STREAM_ERROR; | ||
447 | |||
448 | TRYFREE(s->msg); | ||
449 | |||
450 | if (s->stream.state != NULL) { | ||
451 | if (s->mode == 'w') { | ||
452 | #ifdef NO_GZCOMPRESS | ||
453 | err = Z_STREAM_ERROR; | ||
454 | #else | ||
455 | err = deflateEnd(&(s->stream)); | ||
456 | #endif | ||
457 | } else if (s->mode == 'r') { | ||
458 | err = inflateEnd(&(s->stream)); | ||
459 | } | ||
460 | } | ||
461 | if (s->file != NULL && fclose(s->file)) { | ||
462 | #ifdef ESPIPE | ||
463 | if (zerrno() != ESPIPE) /* fclose is broken for pipes in HP/UX */ | ||
464 | #endif | ||
465 | err = Z_ERRNO; | ||
466 | } | ||
467 | if (s->z_err < 0) err = s->z_err; | ||
468 | |||
469 | TRYFREE(s->inbuf); | ||
470 | TRYFREE(s->outbuf); | ||
471 | TRYFREE(s->path); | ||
472 | TRYFREE(s); | ||
473 | return err; | ||
474 | } | ||
475 | |||
476 | /* =========================================================================== | ||
477 | Reads the given number of uncompressed bytes from the compressed file. | ||
478 | gzread returns the number of bytes actually read (0 for end of file). | ||
479 | */ | ||
480 | int ZEXPORT gzread (file, buf, len) | ||
481 | gzFile file; | ||
482 | voidp buf; | ||
483 | unsigned len; | ||
484 | { | ||
485 | gz_stream *s = (gz_stream*)file; | ||
486 | Bytef *start = (Bytef*)buf; /* starting point for crc computation */ | ||
487 | Byte *next_out; /* == stream.next_out but not forced far (for MSDOS) */ | ||
488 | |||
489 | if (s == NULL || s->mode != 'r') return Z_STREAM_ERROR; | ||
490 | |||
491 | if (s->z_err == Z_DATA_ERROR || s->z_err == Z_ERRNO) return -1; | ||
492 | if (s->z_err == Z_STREAM_END) return 0; /* EOF */ | ||
493 | |||
494 | next_out = (Byte*)buf; | ||
495 | s->stream.next_out = (Bytef*)buf; | ||
496 | s->stream.avail_out = len; | ||
497 | |||
498 | if (s->stream.avail_out && s->back != EOF) { | ||
499 | *next_out++ = s->back; | ||
500 | s->stream.next_out++; | ||
501 | s->stream.avail_out--; | ||
502 | s->back = EOF; | ||
503 | s->out++; | ||
504 | start++; | ||
505 | if (s->last) { | ||
506 | s->z_err = Z_STREAM_END; | ||
507 | return 1; | ||
508 | } | ||
509 | } | ||
510 | |||
511 | while (s->stream.avail_out != 0) { | ||
512 | |||
513 | if (s->transparent) { | ||
514 | /* Copy first the lookahead bytes: */ | ||
515 | uInt n = s->stream.avail_in; | ||
516 | if (n > s->stream.avail_out) n = s->stream.avail_out; | ||
517 | if (n > 0) { | ||
518 | zmemcpy(s->stream.next_out, s->stream.next_in, n); | ||
519 | next_out += n; | ||
520 | s->stream.next_out = next_out; | ||
521 | s->stream.next_in += n; | ||
522 | s->stream.avail_out -= n; | ||
523 | s->stream.avail_in -= n; | ||
524 | } | ||
525 | if (s->stream.avail_out > 0 && !feof(s->file)) { | ||
526 | s->stream.avail_out -= | ||
527 | (uInt)fread(next_out, 1, s->stream.avail_out, s->file); | ||
528 | } | ||
529 | len -= s->stream.avail_out; | ||
530 | s->in += len; | ||
531 | s->out += len; | ||
532 | if (len == 0 && feof(s->file)) s->z_eof = 1; | ||
533 | return (int)len; | ||
534 | } | ||
535 | if (s->stream.avail_in == 0 && !s->z_eof) { | ||
536 | |||
537 | zseterrno(0); | ||
538 | s->stream.avail_in = (uInt)fread(s->inbuf, 1, Z_BUFSIZE, s->file); | ||
539 | if (s->stream.avail_in == 0) { | ||
540 | s->z_eof = 1; | ||
541 | if (ferror(s->file)) { | ||
542 | s->z_err = Z_ERRNO; | ||
543 | break; | ||
544 | } | ||
545 | } | ||
546 | s->stream.next_in = s->inbuf; | ||
547 | } | ||
548 | s->in += s->stream.avail_in; | ||
549 | s->out += s->stream.avail_out; | ||
550 | s->z_err = inflate(&(s->stream), Z_NO_FLUSH); | ||
551 | s->in -= s->stream.avail_in; | ||
552 | s->out -= s->stream.avail_out; | ||
553 | |||
554 | if (s->z_err == Z_STREAM_END) { | ||
555 | /* Check CRC and original size */ | ||
556 | s->crc = crc32(s->crc, start, (uInt)(s->stream.next_out - start)); | ||
557 | start = s->stream.next_out; | ||
558 | |||
559 | if (getLong(s) != s->crc) { | ||
560 | s->z_err = Z_DATA_ERROR; | ||
561 | } else { | ||
562 | (void)getLong(s); | ||
563 | /* The uncompressed length returned by above getlong() may be | ||
564 | * different from s->out in case of concatenated .gz files. | ||
565 | * Check for such files: | ||
566 | */ | ||
567 | check_header(s); | ||
568 | if (s->z_err == Z_OK) { | ||
569 | inflateReset(&(s->stream)); | ||
570 | s->crc = crc32(0L, Z_NULL, 0); | ||
571 | } | ||
572 | } | ||
573 | } | ||
574 | if (s->z_err != Z_OK || s->z_eof) break; | ||
575 | } | ||
576 | s->crc = crc32(s->crc, start, (uInt)(s->stream.next_out - start)); | ||
577 | |||
578 | if (len == s->stream.avail_out && | ||
579 | (s->z_err == Z_DATA_ERROR || s->z_err == Z_ERRNO)) | ||
580 | return -1; | ||
581 | return (int)(len - s->stream.avail_out); | ||
582 | } | ||
583 | |||
584 | |||
585 | /* =========================================================================== | ||
586 | Reads one byte from the compressed file. gzgetc returns this byte | ||
587 | or -1 in case of end of file or error. | ||
588 | */ | ||
589 | int ZEXPORT gzgetc(file) | ||
590 | gzFile file; | ||
591 | { | ||
592 | unsigned char c; | ||
593 | |||
594 | return gzread(file, &c, 1) == 1 ? c : -1; | ||
595 | } | ||
596 | |||
597 | |||
598 | /* =========================================================================== | ||
599 | Push one byte back onto the stream. | ||
600 | */ | ||
601 | int ZEXPORT gzungetc(c, file) | ||
602 | int c; | ||
603 | gzFile file; | ||
604 | { | ||
605 | gz_stream *s = (gz_stream*)file; | ||
606 | |||
607 | if (s == NULL || s->mode != 'r' || c == EOF || s->back != EOF) return EOF; | ||
608 | s->back = c; | ||
609 | s->out--; | ||
610 | s->last = (s->z_err == Z_STREAM_END); | ||
611 | if (s->last) s->z_err = Z_OK; | ||
612 | s->z_eof = 0; | ||
613 | return c; | ||
614 | } | ||
615 | |||
616 | |||
617 | /* =========================================================================== | ||
618 | Reads bytes from the compressed file until len-1 characters are | ||
619 | read, or a newline character is read and transferred to buf, or an | ||
620 | end-of-file condition is encountered. The string is then terminated | ||
621 | with a null character. | ||
622 | gzgets returns buf, or Z_NULL in case of error. | ||
623 | |||
624 | The current implementation is not optimized at all. | ||
625 | */ | ||
626 | char * ZEXPORT gzgets(file, buf, len) | ||
627 | gzFile file; | ||
628 | char *buf; | ||
629 | int len; | ||
630 | { | ||
631 | char *b = buf; | ||
632 | if (buf == Z_NULL || len <= 0) return Z_NULL; | ||
633 | |||
634 | while (--len > 0 && gzread(file, buf, 1) == 1 && *buf++ != '\n') ; | ||
635 | *buf = '\0'; | ||
636 | return b == buf && len > 0 ? Z_NULL : b; | ||
637 | } | ||
638 | |||
639 | |||
640 | #ifndef NO_GZCOMPRESS | ||
641 | /* =========================================================================== | ||
642 | Writes the given number of uncompressed bytes into the compressed file. | ||
643 | gzwrite returns the number of bytes actually written (0 in case of error). | ||
644 | */ | ||
645 | int ZEXPORT gzwrite (file, buf, len) | ||
646 | gzFile file; | ||
647 | voidpc buf; | ||
648 | unsigned len; | ||
649 | { | ||
650 | gz_stream *s = (gz_stream*)file; | ||
651 | |||
652 | if (s == NULL || s->mode != 'w') return Z_STREAM_ERROR; | ||
653 | |||
654 | s->stream.next_in = (Bytef*)buf; | ||
655 | s->stream.avail_in = len; | ||
656 | |||
657 | while (s->stream.avail_in != 0) { | ||
658 | |||
659 | if (s->stream.avail_out == 0) { | ||
660 | |||
661 | s->stream.next_out = s->outbuf; | ||
662 | if (fwrite(s->outbuf, 1, Z_BUFSIZE, s->file) != Z_BUFSIZE) { | ||
663 | s->z_err = Z_ERRNO; | ||
664 | break; | ||
665 | } | ||
666 | s->stream.avail_out = Z_BUFSIZE; | ||
667 | } | ||
668 | s->in += s->stream.avail_in; | ||
669 | s->out += s->stream.avail_out; | ||
670 | s->z_err = deflate(&(s->stream), Z_NO_FLUSH); | ||
671 | s->in -= s->stream.avail_in; | ||
672 | s->out -= s->stream.avail_out; | ||
673 | if (s->z_err != Z_OK) break; | ||
674 | } | ||
675 | s->crc = crc32(s->crc, (const Bytef *)buf, len); | ||
676 | |||
677 | return (int)(len - s->stream.avail_in); | ||
678 | } | ||
679 | |||
680 | |||
681 | /* =========================================================================== | ||
682 | Converts, formats, and writes the args to the compressed file under | ||
683 | control of the format string, as in fprintf. gzprintf returns the number of | ||
684 | uncompressed bytes actually written (0 in case of error). | ||
685 | */ | ||
686 | #ifdef STDC | ||
687 | #include <stdarg.h> | ||
688 | |||
689 | int ZEXPORTVA gzprintf (gzFile file, const char *format, /* args */ ...) | ||
690 | { | ||
691 | char buf[Z_PRINTF_BUFSIZE]; | ||
692 | va_list va; | ||
693 | int len; | ||
694 | |||
695 | buf[sizeof(buf) - 1] = 0; | ||
696 | va_start(va, format); | ||
697 | #ifdef NO_vsnprintf | ||
698 | # ifdef HAS_vsprintf_void | ||
699 | (void)vsprintf(buf, format, va); | ||
700 | va_end(va); | ||
701 | for (len = 0; len < sizeof(buf); len++) | ||
702 | if (buf[len] == 0) break; | ||
703 | # else | ||
704 | len = vsprintf(buf, format, va); | ||
705 | va_end(va); | ||
706 | # endif | ||
707 | #else | ||
708 | # ifdef HAS_vsnprintf_void | ||
709 | (void)vsnprintf(buf, sizeof(buf), format, va); | ||
710 | va_end(va); | ||
711 | len = strlen(buf); | ||
712 | # else | ||
713 | len = vsnprintf(buf, sizeof(buf), format, va); | ||
714 | va_end(va); | ||
715 | # endif | ||
716 | #endif | ||
717 | if (len <= 0 || len >= (int)sizeof(buf) || buf[sizeof(buf) - 1] != 0) | ||
718 | return 0; | ||
719 | return gzwrite(file, buf, (unsigned)len); | ||
720 | } | ||
721 | #else /* not ANSI C */ | ||
722 | |||
723 | int ZEXPORTVA gzprintf (file, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, | ||
724 | a11, a12, a13, a14, a15, a16, a17, a18, a19, a20) | ||
725 | gzFile file; | ||
726 | const char *format; | ||
727 | int a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, | ||
728 | a11, a12, a13, a14, a15, a16, a17, a18, a19, a20; | ||
729 | { | ||
730 | char buf[Z_PRINTF_BUFSIZE]; | ||
731 | int len; | ||
732 | |||
733 | buf[sizeof(buf) - 1] = 0; | ||
734 | #ifdef NO_snprintf | ||
735 | # ifdef HAS_sprintf_void | ||
736 | sprintf(buf, format, a1, a2, a3, a4, a5, a6, a7, a8, | ||
737 | a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20); | ||
738 | for (len = 0; len < sizeof(buf); len++) | ||
739 | if (buf[len] == 0) break; | ||
740 | # else | ||
741 | len = sprintf(buf, format, a1, a2, a3, a4, a5, a6, a7, a8, | ||
742 | a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20); | ||
743 | # endif | ||
744 | #else | ||
745 | # ifdef HAS_snprintf_void | ||
746 | snprintf(buf, sizeof(buf), format, a1, a2, a3, a4, a5, a6, a7, a8, | ||
747 | a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20); | ||
748 | len = strlen(buf); | ||
749 | # else | ||
750 | len = snprintf(buf, sizeof(buf), format, a1, a2, a3, a4, a5, a6, a7, a8, | ||
751 | a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20); | ||
752 | # endif | ||
753 | #endif | ||
754 | if (len <= 0 || len >= sizeof(buf) || buf[sizeof(buf) - 1] != 0) | ||
755 | return 0; | ||
756 | return gzwrite(file, buf, len); | ||
757 | } | ||
758 | #endif | ||
759 | |||
760 | /* =========================================================================== | ||
761 | Writes c, converted to an unsigned char, into the compressed file. | ||
762 | gzputc returns the value that was written, or -1 in case of error. | ||
763 | */ | ||
764 | int ZEXPORT gzputc(file, c) | ||
765 | gzFile file; | ||
766 | int c; | ||
767 | { | ||
768 | unsigned char cc = (unsigned char) c; /* required for big endian systems */ | ||
769 | |||
770 | return gzwrite(file, &cc, 1) == 1 ? (int)cc : -1; | ||
771 | } | ||
772 | |||
773 | |||
774 | /* =========================================================================== | ||
775 | Writes the given null-terminated string to the compressed file, excluding | ||
776 | the terminating null character. | ||
777 | gzputs returns the number of characters written, or -1 in case of error. | ||
778 | */ | ||
779 | int ZEXPORT gzputs(file, s) | ||
780 | gzFile file; | ||
781 | const char *s; | ||
782 | { | ||
783 | return gzwrite(file, (char*)s, (unsigned)strlen(s)); | ||
784 | } | ||
785 | |||
786 | |||
787 | /* =========================================================================== | ||
788 | Flushes all pending output into the compressed file. The parameter | ||
789 | flush is as in the deflate() function. | ||
790 | */ | ||
791 | local int do_flush (file, flush) | ||
792 | gzFile file; | ||
793 | int flush; | ||
794 | { | ||
795 | uInt len; | ||
796 | int done = 0; | ||
797 | gz_stream *s = (gz_stream*)file; | ||
798 | |||
799 | if (s == NULL || s->mode != 'w') return Z_STREAM_ERROR; | ||
800 | |||
801 | s->stream.avail_in = 0; /* should be zero already anyway */ | ||
802 | |||
803 | for (;;) { | ||
804 | len = Z_BUFSIZE - s->stream.avail_out; | ||
805 | |||
806 | if (len != 0) { | ||
807 | if ((uInt)fwrite(s->outbuf, 1, len, s->file) != len) { | ||
808 | s->z_err = Z_ERRNO; | ||
809 | return Z_ERRNO; | ||
810 | } | ||
811 | s->stream.next_out = s->outbuf; | ||
812 | s->stream.avail_out = Z_BUFSIZE; | ||
813 | } | ||
814 | if (done) break; | ||
815 | s->out += s->stream.avail_out; | ||
816 | s->z_err = deflate(&(s->stream), flush); | ||
817 | s->out -= s->stream.avail_out; | ||
818 | |||
819 | /* Ignore the second of two consecutive flushes: */ | ||
820 | if (len == 0 && s->z_err == Z_BUF_ERROR) s->z_err = Z_OK; | ||
821 | |||
822 | /* deflate has finished flushing only when it hasn't used up | ||
823 | * all the available space in the output buffer: | ||
824 | */ | ||
825 | done = (s->stream.avail_out != 0 || s->z_err == Z_STREAM_END); | ||
826 | |||
827 | if (s->z_err != Z_OK && s->z_err != Z_STREAM_END) break; | ||
828 | } | ||
829 | return s->z_err == Z_STREAM_END ? Z_OK : s->z_err; | ||
830 | } | ||
831 | |||
832 | int ZEXPORT gzflush (file, flush) | ||
833 | gzFile file; | ||
834 | int flush; | ||
835 | { | ||
836 | gz_stream *s = (gz_stream*)file; | ||
837 | int err = do_flush (file, flush); | ||
838 | |||
839 | if (err) return err; | ||
840 | fflush(s->file); | ||
841 | return s->z_err == Z_STREAM_END ? Z_OK : s->z_err; | ||
842 | } | ||
843 | #endif /* NO_GZCOMPRESS */ | ||
844 | |||
845 | /* =========================================================================== | ||
846 | Sets the starting position for the next gzread or gzwrite on the given | ||
847 | compressed file. The offset represents a number of bytes in the | ||
848 | gzseek returns the resulting offset location as measured in bytes from | ||
849 | the beginning of the uncompressed stream, or -1 in case of error. | ||
850 | SEEK_END is not implemented, returns error. | ||
851 | In this version of the library, gzseek can be extremely slow. | ||
852 | */ | ||
853 | local z_off64_t gz_seek (file, offset, whence, use64) | ||
854 | gzFile file; | ||
855 | z_off64_t offset; | ||
856 | int whence; | ||
857 | int use64; | ||
858 | { | ||
859 | gz_stream *s = (gz_stream*)file; | ||
860 | |||
861 | if (s == NULL || whence == SEEK_END || | ||
862 | s->z_err == Z_ERRNO || s->z_err == Z_DATA_ERROR) { | ||
863 | return -1L; | ||
864 | } | ||
865 | |||
866 | if (s->mode == 'w') { | ||
867 | #ifdef NO_GZCOMPRESS | ||
868 | return -1L; | ||
869 | #else | ||
870 | if (whence == SEEK_SET) { | ||
871 | offset -= s->in; | ||
872 | } | ||
873 | if (offset < 0) return -1L; | ||
874 | |||
875 | /* At this point, offset is the number of zero bytes to write. */ | ||
876 | if (s->inbuf == Z_NULL) { | ||
877 | s->inbuf = (Byte*)ALLOC(Z_BUFSIZE); /* for seeking */ | ||
878 | if (s->inbuf == Z_NULL) return -1L; | ||
879 | zmemzero(s->inbuf, Z_BUFSIZE); | ||
880 | } | ||
881 | while (offset > 0) { | ||
882 | uInt size = Z_BUFSIZE; | ||
883 | if (offset < Z_BUFSIZE) size = (uInt)offset; | ||
884 | |||
885 | size = gzwrite(file, s->inbuf, size); | ||
886 | if (size == 0) return -1L; | ||
887 | |||
888 | offset -= size; | ||
889 | } | ||
890 | return s->in; | ||
891 | #endif | ||
892 | } | ||
893 | /* Rest of function is for reading only */ | ||
894 | |||
895 | /* compute absolute position */ | ||
896 | if (whence == SEEK_CUR) { | ||
897 | offset += s->out; | ||
898 | } | ||
899 | if (offset < 0) return -1L; | ||
900 | |||
901 | if (s->transparent) { | ||
902 | /* map to fseek */ | ||
903 | s->back = EOF; | ||
904 | s->stream.avail_in = 0; | ||
905 | s->stream.next_in = s->inbuf; | ||
906 | #ifdef _LARGEFILE64_SOURCE | ||
907 | if ((use64 ? fseeko64(s->file, offset, SEEK_SET) : | ||
908 | FSEEK(s->file, offset, SEEK_SET)) < 0) | ||
909 | return -1L; | ||
910 | #else | ||
911 | if (FSEEK(s->file, offset, SEEK_SET) < 0) return -1L; | ||
912 | #endif | ||
913 | |||
914 | s->in = s->out = offset; | ||
915 | return offset; | ||
916 | } | ||
917 | |||
918 | /* For a negative seek, rewind and use positive seek */ | ||
919 | if (offset >= s->out) { | ||
920 | offset -= s->out; | ||
921 | } else if (gzrewind(file) < 0) { | ||
922 | return -1L; | ||
923 | } | ||
924 | /* offset is now the number of bytes to skip. */ | ||
925 | |||
926 | if (offset != 0 && s->outbuf == Z_NULL) { | ||
927 | s->outbuf = (Byte*)ALLOC(Z_BUFSIZE); | ||
928 | if (s->outbuf == Z_NULL) return -1L; | ||
929 | } | ||
930 | if (offset && s->back != EOF) { | ||
931 | s->back = EOF; | ||
932 | s->out++; | ||
933 | offset--; | ||
934 | if (s->last) s->z_err = Z_STREAM_END; | ||
935 | } | ||
936 | while (offset > 0) { | ||
937 | int size = Z_BUFSIZE; | ||
938 | if (offset < Z_BUFSIZE) size = (int)offset; | ||
939 | |||
940 | size = gzread(file, s->outbuf, (uInt)size); | ||
941 | if (size <= 0) return -1L; | ||
942 | offset -= size; | ||
943 | } | ||
944 | return s->out; | ||
945 | } | ||
946 | |||
947 | /* =========================================================================== | ||
948 | Define external functions gzseek() and gzseek64() using local gz_seek(). | ||
949 | */ | ||
950 | z_off_t ZEXPORT gzseek (file, offset, whence) | ||
951 | gzFile file; | ||
952 | z_off_t offset; | ||
953 | int whence; | ||
954 | { | ||
955 | return (z_off_t)gz_seek(file, offset, whence, 0); | ||
956 | } | ||
957 | |||
958 | z_off64_t ZEXPORT gzseek64 (file, offset, whence) | ||
959 | gzFile file; | ||
960 | z_off64_t offset; | ||
961 | int whence; | ||
962 | { | ||
963 | #ifdef _LARGEFILE64_SOURCE | ||
964 | return gz_seek(file, offset, whence, 1); | ||
965 | #else | ||
966 | return gz_seek(file, offset, whence, 0); | ||
967 | #endif | ||
968 | } | ||
969 | |||
970 | /* =========================================================================== | ||
971 | Rewinds input file. | ||
972 | */ | ||
973 | int ZEXPORT gzrewind (file) | ||
974 | gzFile file; | ||
975 | { | ||
976 | gz_stream *s = (gz_stream*)file; | ||
977 | |||
978 | if (s == NULL || s->mode != 'r') return -1; | ||
979 | |||
980 | s->z_err = Z_OK; | ||
981 | s->z_eof = 0; | ||
982 | s->back = EOF; | ||
983 | s->stream.avail_in = 0; | ||
984 | s->stream.next_in = s->inbuf; | ||
985 | s->crc = crc32(0L, Z_NULL, 0); | ||
986 | if (!s->transparent) (void)inflateReset(&s->stream); | ||
987 | s->in = 0; | ||
988 | s->out = 0; | ||
989 | return FSEEK(s->file, s->start, SEEK_SET); | ||
990 | } | ||
991 | |||
992 | /* =========================================================================== | ||
993 | Returns the starting position for the next gzread or gzwrite on the | ||
994 | given compressed file. This position represents a number of bytes in the | ||
995 | uncompressed data stream. | ||
996 | */ | ||
997 | z_off_t ZEXPORT gztell (file) | ||
998 | gzFile file; | ||
999 | { | ||
1000 | return gzseek(file, 0L, SEEK_CUR); | ||
1001 | } | ||
1002 | |||
1003 | /* =========================================================================== | ||
1004 | 64-bit version | ||
1005 | */ | ||
1006 | z_off64_t ZEXPORT gztell64 (file) | ||
1007 | gzFile file; | ||
1008 | { | ||
1009 | return gzseek64(file, 0L, SEEK_CUR); | ||
1010 | } | ||
1011 | |||
1012 | /* =========================================================================== | ||
1013 | Returns 1 when EOF has previously been detected reading the given | ||
1014 | input stream, otherwise zero. | ||
1015 | */ | ||
1016 | int ZEXPORT gzeof (file) | ||
1017 | gzFile file; | ||
1018 | { | ||
1019 | gz_stream *s = (gz_stream*)file; | ||
1020 | |||
1021 | /* With concatenated compressed files that can have embedded | ||
1022 | * crc trailers, z_eof is no longer the only/best indicator of EOF | ||
1023 | * on a gz_stream. Handle end-of-stream error explicitly here. | ||
1024 | */ | ||
1025 | if (s == NULL || s->mode != 'r') return 0; | ||
1026 | if (s->z_eof) return 1; | ||
1027 | return s->z_err == Z_STREAM_END; | ||
1028 | } | ||
1029 | |||
1030 | /* =========================================================================== | ||
1031 | Returns 1 if reading and doing so transparently, otherwise zero. | ||
1032 | */ | ||
1033 | int ZEXPORT gzdirect (file) | ||
1034 | gzFile file; | ||
1035 | { | ||
1036 | gz_stream *s = (gz_stream*)file; | ||
1037 | |||
1038 | if (s == NULL || s->mode != 'r') return 0; | ||
1039 | return s->transparent; | ||
1040 | } | ||
1041 | |||
1042 | /* =========================================================================== | ||
1043 | Outputs a long in LSB order to the given file | ||
1044 | */ | ||
1045 | local void putLong (file, x) | ||
1046 | FILE *file; | ||
1047 | uLong x; | ||
1048 | { | ||
1049 | int n; | ||
1050 | for (n = 0; n < 4; n++) { | ||
1051 | fputc((int)(x & 0xff), file); | ||
1052 | x >>= 8; | ||
1053 | } | ||
1054 | } | ||
1055 | |||
1056 | /* =========================================================================== | ||
1057 | Reads a long in LSB order from the given gz_stream. Sets z_err in case | ||
1058 | of error. | ||
1059 | */ | ||
1060 | local uLong getLong (s) | ||
1061 | gz_stream *s; | ||
1062 | { | ||
1063 | uLong x = (uLong)get_byte(s); | ||
1064 | int c; | ||
1065 | |||
1066 | x += ((uLong)get_byte(s))<<8; | ||
1067 | x += ((uLong)get_byte(s))<<16; | ||
1068 | c = get_byte(s); | ||
1069 | if (c == EOF) s->z_err = Z_DATA_ERROR; | ||
1070 | x += ((uLong)c)<<24; | ||
1071 | return x; | ||
1072 | } | ||
1073 | |||
1074 | /* =========================================================================== | ||
1075 | Flushes all pending output if necessary, closes the compressed file | ||
1076 | and deallocates all the (de)compression state. | ||
1077 | */ | ||
1078 | int ZEXPORT gzclose (file) | ||
1079 | gzFile file; | ||
1080 | { | ||
1081 | gz_stream *s = (gz_stream*)file; | ||
1082 | |||
1083 | if (s == NULL) return Z_STREAM_ERROR; | ||
1084 | |||
1085 | if (s->mode == 'w') { | ||
1086 | #ifdef NO_GZCOMPRESS | ||
1087 | return Z_STREAM_ERROR; | ||
1088 | #else | ||
1089 | if (do_flush (file, Z_FINISH) != Z_OK) | ||
1090 | return destroy((gz_stream*)file); | ||
1091 | |||
1092 | putLong (s->file, s->crc); | ||
1093 | putLong (s->file, (uLong)(s->in & 0xffffffff)); | ||
1094 | #endif | ||
1095 | } | ||
1096 | return destroy((gz_stream*)file); | ||
1097 | } | ||
1098 | |||
1099 | #if defined UNDER_CE && defined NO_ERRNO_H | ||
1100 | # define zstrerror(errnum) strwinerror((DWORD)errnum) | ||
1101 | #else | ||
1102 | # if defined (STDC) | ||
1103 | # define zstrerror(errnum) strerror(errnum) | ||
1104 | # else | ||
1105 | # define zstrerror(errnum) "" | ||
1106 | # endif | ||
1107 | #endif | ||
1108 | |||
1109 | /* =========================================================================== | ||
1110 | Returns the error message for the last error which occurred on the | ||
1111 | given compressed file. errnum is set to zlib error number. If an | ||
1112 | error occurred in the file system and not in the compression library, | ||
1113 | errnum is set to Z_ERRNO and the application may consult errno | ||
1114 | to get the exact error code. | ||
1115 | */ | ||
1116 | const char * ZEXPORT gzerror (file, errnum) | ||
1117 | gzFile file; | ||
1118 | int *errnum; | ||
1119 | { | ||
1120 | char *m; | ||
1121 | gz_stream *s = (gz_stream*)file; | ||
1122 | |||
1123 | if (s == NULL) { | ||
1124 | *errnum = Z_STREAM_ERROR; | ||
1125 | return (const char*)ERR_MSG(Z_STREAM_ERROR); | ||
1126 | } | ||
1127 | *errnum = s->z_err; | ||
1128 | if (*errnum == Z_OK) return (const char*)""; | ||
1129 | |||
1130 | m = (char*)(*errnum == Z_ERRNO ? zstrerror(zerrno()) : s->stream.msg); | ||
1131 | |||
1132 | if (m == NULL || *m == '\0') m = (char*)ERR_MSG(s->z_err); | ||
1133 | |||
1134 | TRYFREE(s->msg); | ||
1135 | s->msg = (char*)ALLOC(strlen(s->path) + strlen(m) + 3); | ||
1136 | if (s->msg == Z_NULL) return (const char*)ERR_MSG(Z_MEM_ERROR); | ||
1137 | strcpy(s->msg, s->path); | ||
1138 | strcat(s->msg, ": "); | ||
1139 | strcat(s->msg, m); | ||
1140 | return (const char*)s->msg; | ||
1141 | } | ||
1142 | |||
1143 | /* =========================================================================== | ||
1144 | Clear the error and end-of-file flags, and do the same for the real file. | ||
1145 | */ | ||
1146 | void ZEXPORT gzclearerr (file) | ||
1147 | gzFile file; | ||
1148 | { | ||
1149 | gz_stream *s = (gz_stream*)file; | ||
1150 | |||
1151 | if (s == NULL) return; | ||
1152 | if (s->z_err != Z_STREAM_END) s->z_err = Z_OK; | ||
1153 | s->z_eof = 0; | ||
1154 | clearerr(s->file); | ||
1155 | } | ||
1156 | |||
1157 | /* new functions in gzlib, but only partially implemented here */ | ||
1158 | |||
1159 | int ZEXPORT gzbuffer (file, size) | ||
1160 | gzFile file; | ||
1161 | unsigned size; | ||
1162 | { | ||
1163 | return -1; | ||
1164 | } | ||
1165 | |||
1166 | z_off_t ZEXPORT gzoffset (file) | ||
1167 | gzFile file; | ||
1168 | { | ||
1169 | return -1; | ||
1170 | } | ||
1171 | |||
1172 | z_off64_t ZEXPORT gzoffset64 (file) | ||
1173 | gzFile file; | ||
1174 | { | ||
1175 | return -1; | ||
1176 | } | ||
1177 | |||
1178 | int ZEXPORT gzclose_r (file) | ||
1179 | gzFile file; | ||
1180 | { | ||
1181 | return gzclose(file); | ||
1182 | } | ||
1183 | |||
1184 | int ZEXPORT gzclose_w (file) | ||
1185 | gzFile file; | ||
1186 | { | ||
1187 | return gzclose(file); | ||
1188 | } | ||
1189 | |||
1190 | int gzio_old = 1; | ||
1191 | |||
1192 | #else /* !OLD_GZIO */ | ||
1193 | |||
1194 | int gzio_old = 0; | ||
1195 | |||
1196 | #endif /* OLD_GZIO */ | ||