diff options
Diffstat (limited to 'gzio.c')
-rw-r--r-- | gzio.c | 347 |
1 files changed, 316 insertions, 31 deletions
@@ -1,9 +1,11 @@ | |||
1 | /* gzio.c -- IO on .gz files | 1 | /* gzio.c -- IO on .gz files |
2 | * Copyright (C) 1995-1996 Jean-loup Gailly. | 2 | * Copyright (C) 1995-1998 Jean-loup Gailly. |
3 | * For conditions of distribution and use, see copyright notice in zlib.h | 3 | * For conditions of distribution and use, see copyright notice in zlib.h |
4 | * | ||
5 | * Compile this file with -DNO_DEFLATE to avoid the compression code. | ||
4 | */ | 6 | */ |
5 | 7 | ||
6 | /* $Id: gzio.c,v 1.14 1996/07/24 13:41:01 me Exp $ */ | 8 | /* @(#) $Id$ */ |
7 | 9 | ||
8 | #include <stdio.h> | 10 | #include <stdio.h> |
9 | 11 | ||
@@ -38,10 +40,12 @@ typedef struct gz_stream { | |||
38 | char *path; /* path name for debugging only */ | 40 | char *path; /* path name for debugging only */ |
39 | int transparent; /* 1 if input file is not a .gz file */ | 41 | int transparent; /* 1 if input file is not a .gz file */ |
40 | char mode; /* 'w' or 'r' */ | 42 | char mode; /* 'w' or 'r' */ |
43 | long startpos; /* start of compressed data in file (header skipped) */ | ||
41 | } gz_stream; | 44 | } gz_stream; |
42 | 45 | ||
43 | 46 | ||
44 | local gzFile gz_open OF((const char *path, const char *mode, int fd)); | 47 | local gzFile gz_open OF((const char *path, const char *mode, int fd)); |
48 | local int do_flush OF((gzFile file, int flush)); | ||
45 | local int get_byte OF((gz_stream *s)); | 49 | local int get_byte OF((gz_stream *s)); |
46 | local void check_header OF((gz_stream *s)); | 50 | local void check_header OF((gz_stream *s)); |
47 | local int destroy OF((gz_stream *s)); | 51 | local int destroy OF((gz_stream *s)); |
@@ -64,6 +68,7 @@ local gzFile gz_open (path, mode, fd) | |||
64 | { | 68 | { |
65 | int err; | 69 | int err; |
66 | int level = Z_DEFAULT_COMPRESSION; /* compression level */ | 70 | int level = Z_DEFAULT_COMPRESSION; /* compression level */ |
71 | int strategy = Z_DEFAULT_STRATEGY; /* compression strategy */ | ||
67 | char *p = (char*)mode; | 72 | char *p = (char*)mode; |
68 | gz_stream *s; | 73 | gz_stream *s; |
69 | char fmode[80]; /* copy of mode, without the compression level */ | 74 | char fmode[80]; /* copy of mode, without the compression level */ |
@@ -99,6 +104,10 @@ local gzFile gz_open (path, mode, fd) | |||
99 | if (*p == 'w' || *p == 'a') s->mode = 'w'; | 104 | if (*p == 'w' || *p == 'a') s->mode = 'w'; |
100 | if (*p >= '0' && *p <= '9') { | 105 | if (*p >= '0' && *p <= '9') { |
101 | level = *p - '0'; | 106 | level = *p - '0'; |
107 | } else if (*p == 'f') { | ||
108 | strategy = Z_FILTERED; | ||
109 | } else if (*p == 'h') { | ||
110 | strategy = Z_HUFFMAN_ONLY; | ||
102 | } else { | 111 | } else { |
103 | *m++ = *p; /* copy the mode */ | 112 | *m++ = *p; /* copy the mode */ |
104 | } | 113 | } |
@@ -106,19 +115,24 @@ local gzFile gz_open (path, mode, fd) | |||
106 | if (s->mode == '\0') return destroy(s), (gzFile)Z_NULL; | 115 | if (s->mode == '\0') return destroy(s), (gzFile)Z_NULL; |
107 | 116 | ||
108 | if (s->mode == 'w') { | 117 | if (s->mode == 'w') { |
118 | #ifdef NO_DEFLATE | ||
119 | err = Z_STREAM_ERROR; | ||
120 | #else | ||
109 | err = deflateInit2(&(s->stream), level, | 121 | err = deflateInit2(&(s->stream), level, |
110 | Z_DEFLATED, -MAX_WBITS, DEF_MEM_LEVEL, 0); | 122 | Z_DEFLATED, -MAX_WBITS, DEF_MEM_LEVEL, strategy); |
111 | /* windowBits is passed < 0 to suppress zlib header */ | 123 | /* windowBits is passed < 0 to suppress zlib header */ |
112 | 124 | ||
113 | s->stream.next_out = s->outbuf = (Byte*)ALLOC(Z_BUFSIZE); | 125 | s->stream.next_out = s->outbuf = (Byte*)ALLOC(Z_BUFSIZE); |
114 | 126 | #endif | |
115 | if (err != Z_OK || s->outbuf == Z_NULL) { | 127 | if (err != Z_OK || s->outbuf == Z_NULL) { |
116 | return destroy(s), (gzFile)Z_NULL; | 128 | return destroy(s), (gzFile)Z_NULL; |
117 | } | 129 | } |
118 | } else { | 130 | } else { |
119 | err = inflateInit2(&(s->stream), -MAX_WBITS); | ||
120 | s->stream.next_in = s->inbuf = (Byte*)ALLOC(Z_BUFSIZE); | 131 | s->stream.next_in = s->inbuf = (Byte*)ALLOC(Z_BUFSIZE); |
121 | 132 | ||
133 | err = inflateInit2(&(s->stream), -MAX_WBITS); | ||
134 | /* windowBits is passed < 0 to tell that there is no zlib header */ | ||
135 | |||
122 | if (err != Z_OK || s->inbuf == Z_NULL) { | 136 | if (err != Z_OK || s->inbuf == Z_NULL) { |
123 | return destroy(s), (gzFile)Z_NULL; | 137 | return destroy(s), (gzFile)Z_NULL; |
124 | } | 138 | } |
@@ -126,7 +140,7 @@ local gzFile gz_open (path, mode, fd) | |||
126 | s->stream.avail_out = Z_BUFSIZE; | 140 | s->stream.avail_out = Z_BUFSIZE; |
127 | 141 | ||
128 | errno = 0; | 142 | errno = 0; |
129 | s->file = fd < 0 ? FOPEN(path, fmode) : (FILE*)fdopen(fd, fmode); | 143 | s->file = fd < 0 ? F_OPEN(path, fmode) : (FILE*)fdopen(fd, fmode); |
130 | 144 | ||
131 | if (s->file == NULL) { | 145 | if (s->file == NULL) { |
132 | return destroy(s), (gzFile)Z_NULL; | 146 | return destroy(s), (gzFile)Z_NULL; |
@@ -136,16 +150,19 @@ local gzFile gz_open (path, mode, fd) | |||
136 | */ | 150 | */ |
137 | fprintf(s->file, "%c%c%c%c%c%c%c%c%c%c", gz_magic[0], gz_magic[1], | 151 | fprintf(s->file, "%c%c%c%c%c%c%c%c%c%c", gz_magic[0], gz_magic[1], |
138 | Z_DEFLATED, 0 /*flags*/, 0,0,0,0 /*time*/, 0 /*xflags*/, OS_CODE); | 152 | Z_DEFLATED, 0 /*flags*/, 0,0,0,0 /*time*/, 0 /*xflags*/, OS_CODE); |
153 | s->startpos = ftell(s->file); | ||
139 | } else { | 154 | } else { |
140 | check_header(s); /* skip the .gz header */ | 155 | check_header(s); /* skip the .gz header */ |
156 | s->startpos = (ftell(s->file) - s->stream.avail_in); | ||
141 | } | 157 | } |
158 | |||
142 | return (gzFile)s; | 159 | return (gzFile)s; |
143 | } | 160 | } |
144 | 161 | ||
145 | /* =========================================================================== | 162 | /* =========================================================================== |
146 | Opens a gzip (.gz) file for reading or writing. | 163 | Opens a gzip (.gz) file for reading or writing. |
147 | */ | 164 | */ |
148 | gzFile gzopen (path, mode) | 165 | gzFile EXPORT gzopen (path, mode) |
149 | const char *path; | 166 | const char *path; |
150 | const char *mode; | 167 | const char *mode; |
151 | { | 168 | { |
@@ -156,7 +173,7 @@ gzFile gzopen (path, mode) | |||
156 | Associate a gzFile with the file descriptor fd. fd is not dup'ed here | 173 | Associate a gzFile with the file descriptor fd. fd is not dup'ed here |
157 | to mimic the behavio(u)r of fdopen. | 174 | to mimic the behavio(u)r of fdopen. |
158 | */ | 175 | */ |
159 | gzFile gzdopen (fd, mode) | 176 | gzFile EXPORT gzdopen (fd, mode) |
160 | int fd; | 177 | int fd; |
161 | const char *mode; | 178 | const char *mode; |
162 | { | 179 | { |
@@ -169,6 +186,31 @@ gzFile gzdopen (fd, mode) | |||
169 | } | 186 | } |
170 | 187 | ||
171 | /* =========================================================================== | 188 | /* =========================================================================== |
189 | * Update the compression level and strategy | ||
190 | */ | ||
191 | int EXPORT gzsetparams (file, level, strategy) | ||
192 | gzFile file; | ||
193 | int level; | ||
194 | int strategy; | ||
195 | { | ||
196 | gz_stream *s = (gz_stream*)file; | ||
197 | |||
198 | if (s == NULL || s->mode != 'w') return Z_STREAM_ERROR; | ||
199 | |||
200 | /* Make room to allow flushing */ | ||
201 | if (s->stream.avail_out == 0) { | ||
202 | |||
203 | s->stream.next_out = s->outbuf; | ||
204 | if (fwrite(s->outbuf, 1, Z_BUFSIZE, s->file) != Z_BUFSIZE) { | ||
205 | s->z_err = Z_ERRNO; | ||
206 | } | ||
207 | s->stream.avail_out = Z_BUFSIZE; | ||
208 | } | ||
209 | |||
210 | return deflateParams (&(s->stream), level, strategy); | ||
211 | } | ||
212 | |||
213 | /* =========================================================================== | ||
172 | Read a byte from a gz_stream; update next_in and avail_in. Return EOF | 214 | Read a byte from a gz_stream; update next_in and avail_in. Return EOF |
173 | for end of file. | 215 | for end of file. |
174 | IN assertion: the stream s has been sucessfully opened for reading. | 216 | IN assertion: the stream s has been sucessfully opened for reading. |
@@ -212,8 +254,11 @@ local void check_header(s) | |||
212 | for (len = 0; len < 2; len++) { | 254 | for (len = 0; len < 2; len++) { |
213 | c = get_byte(s); | 255 | c = get_byte(s); |
214 | if (c != gz_magic[len]) { | 256 | if (c != gz_magic[len]) { |
215 | s->transparent = 1; | 257 | if (len != 0) s->stream.avail_in++, s->stream.next_in--; |
216 | if (c != EOF) s->stream.avail_in++, s->stream.next_in--; | 258 | if (c != EOF) { |
259 | s->stream.avail_in++, s->stream.next_in--; | ||
260 | s->transparent = 1; | ||
261 | } | ||
217 | s->z_err = s->stream.avail_in != 0 ? Z_OK : Z_STREAM_END; | 262 | s->z_err = s->stream.avail_in != 0 ? Z_OK : Z_STREAM_END; |
218 | return; | 263 | return; |
219 | } | 264 | } |
@@ -260,14 +305,21 @@ local int destroy (s) | |||
260 | TRYFREE(s->msg); | 305 | TRYFREE(s->msg); |
261 | 306 | ||
262 | if (s->stream.state != NULL) { | 307 | if (s->stream.state != NULL) { |
263 | if (s->mode == 'w') { | 308 | if (s->mode == 'w') { |
264 | err = deflateEnd(&(s->stream)); | 309 | #ifdef NO_DEFLATE |
265 | } else if (s->mode == 'r') { | 310 | err = Z_STREAM_ERROR; |
266 | err = inflateEnd(&(s->stream)); | 311 | #else |
267 | } | 312 | err = deflateEnd(&(s->stream)); |
313 | #endif | ||
314 | } else if (s->mode == 'r') { | ||
315 | err = inflateEnd(&(s->stream)); | ||
316 | } | ||
268 | } | 317 | } |
269 | if (s->file != NULL && fclose(s->file)) { | 318 | if (s->file != NULL && fclose(s->file)) { |
270 | err = Z_ERRNO; | 319 | #ifdef ESPIPE |
320 | if (errno != ESPIPE) /* fclose is broken for pipes in HP/UX */ | ||
321 | #endif | ||
322 | err = Z_ERRNO; | ||
271 | } | 323 | } |
272 | if (s->z_err < 0) err = s->z_err; | 324 | if (s->z_err < 0) err = s->z_err; |
273 | 325 | ||
@@ -282,13 +334,13 @@ local int destroy (s) | |||
282 | Reads the given number of uncompressed bytes from the compressed file. | 334 | Reads the given number of uncompressed bytes from the compressed file. |
283 | gzread returns the number of bytes actually read (0 for end of file). | 335 | gzread returns the number of bytes actually read (0 for end of file). |
284 | */ | 336 | */ |
285 | int gzread (file, buf, len) | 337 | int EXPORT gzread (file, buf, len) |
286 | gzFile file; | 338 | gzFile file; |
287 | voidp buf; | 339 | voidp buf; |
288 | unsigned len; | 340 | unsigned len; |
289 | { | 341 | { |
290 | gz_stream *s = (gz_stream*)file; | 342 | gz_stream *s = (gz_stream*)file; |
291 | Bytef *start = buf; /* starting point for crc computation */ | 343 | Bytef *start = (Bytef*)buf; /* starting point for crc computation */ |
292 | Byte *next_out; /* == stream.next_out but not forced far (for MSDOS) */ | 344 | Byte *next_out; /* == stream.next_out but not forced far (for MSDOS) */ |
293 | 345 | ||
294 | if (s == NULL || s->mode != 'r') return Z_STREAM_ERROR; | 346 | if (s == NULL || s->mode != 'r') return Z_STREAM_ERROR; |
@@ -296,7 +348,8 @@ int gzread (file, buf, len) | |||
296 | if (s->z_err == Z_DATA_ERROR || s->z_err == Z_ERRNO) return -1; | 348 | if (s->z_err == Z_DATA_ERROR || s->z_err == Z_ERRNO) return -1; |
297 | if (s->z_err == Z_STREAM_END) return 0; /* EOF */ | 349 | if (s->z_err == Z_STREAM_END) return 0; /* EOF */ |
298 | 350 | ||
299 | s->stream.next_out = next_out = buf; | 351 | next_out = (Byte*)buf; |
352 | s->stream.next_out = (Bytef*)buf; | ||
300 | s->stream.avail_out = len; | 353 | s->stream.avail_out = len; |
301 | 354 | ||
302 | while (s->stream.avail_out != 0) { | 355 | while (s->stream.avail_out != 0) { |
@@ -345,7 +398,12 @@ int gzread (file, buf, len) | |||
345 | /* Check for concatenated .gz files: */ | 398 | /* Check for concatenated .gz files: */ |
346 | check_header(s); | 399 | check_header(s); |
347 | if (s->z_err == Z_OK) { | 400 | if (s->z_err == Z_OK) { |
401 | uLong total_in = s->stream.total_in; | ||
402 | uLong total_out = s->stream.total_out; | ||
403 | |||
348 | inflateReset(&(s->stream)); | 404 | inflateReset(&(s->stream)); |
405 | s->stream.total_in = total_in; | ||
406 | s->stream.total_out = total_out; | ||
349 | s->crc = crc32(0L, Z_NULL, 0); | 407 | s->crc = crc32(0L, Z_NULL, 0); |
350 | } | 408 | } |
351 | } | 409 | } |
@@ -357,11 +415,26 @@ int gzread (file, buf, len) | |||
357 | return (int)(len - s->stream.avail_out); | 415 | return (int)(len - s->stream.avail_out); |
358 | } | 416 | } |
359 | 417 | ||
418 | |||
419 | /* =========================================================================== | ||
420 | Reads one byte from the compressed file. gzgetc returns this byte | ||
421 | or -1 in case of end of file or error. | ||
422 | */ | ||
423 | int EXPORT gzgetc(file) | ||
424 | gzFile file; | ||
425 | { | ||
426 | int c; | ||
427 | |||
428 | return gzread(file, &c, 1) == 1 ? c : -1; | ||
429 | } | ||
430 | |||
431 | |||
432 | #ifndef NO_DEFLATE | ||
360 | /* =========================================================================== | 433 | /* =========================================================================== |
361 | Writes the given number of uncompressed bytes into the compressed file. | 434 | Writes the given number of uncompressed bytes into the compressed file. |
362 | gzwrite returns the number of bytes actually written (0 in case of error). | 435 | gzwrite returns the number of bytes actually written (0 in case of error). |
363 | */ | 436 | */ |
364 | int gzwrite (file, buf, len) | 437 | int EXPORT gzwrite (file, buf, len) |
365 | gzFile file; | 438 | gzFile file; |
366 | const voidp buf; | 439 | const voidp buf; |
367 | unsigned len; | 440 | unsigned len; |
@@ -370,7 +443,7 @@ int gzwrite (file, buf, len) | |||
370 | 443 | ||
371 | if (s == NULL || s->mode != 'w') return Z_STREAM_ERROR; | 444 | if (s == NULL || s->mode != 'w') return Z_STREAM_ERROR; |
372 | 445 | ||
373 | s->stream.next_in = buf; | 446 | s->stream.next_in = (Bytef*)buf; |
374 | s->stream.avail_in = len; | 447 | s->stream.avail_in = len; |
375 | 448 | ||
376 | while (s->stream.avail_in != 0) { | 449 | while (s->stream.avail_in != 0) { |
@@ -387,18 +460,79 @@ int gzwrite (file, buf, len) | |||
387 | s->z_err = deflate(&(s->stream), Z_NO_FLUSH); | 460 | s->z_err = deflate(&(s->stream), Z_NO_FLUSH); |
388 | if (s->z_err != Z_OK) break; | 461 | if (s->z_err != Z_OK) break; |
389 | } | 462 | } |
390 | s->crc = crc32(s->crc, buf, len); | 463 | s->crc = crc32(s->crc, (const Bytef *)buf, len); |
391 | 464 | ||
392 | return (int)(len - s->stream.avail_in); | 465 | return (int)(len - s->stream.avail_in); |
393 | } | 466 | } |
394 | 467 | ||
395 | /* =========================================================================== | 468 | /* =========================================================================== |
469 | Converts, formats, and writes the args to the compressed file under | ||
470 | control of the format string, as in fprintf. gzprintf returns the number of | ||
471 | uncompressed bytes actually written (0 in case of error). | ||
472 | */ | ||
473 | #ifdef STDC | ||
474 | #include <stdarg.h> | ||
475 | |||
476 | int EXPORTVA gzprintf (gzFile file, const char *format, /* args */ ...) | ||
477 | { | ||
478 | char buf[Z_BUFSIZE]; | ||
479 | va_list va; | ||
480 | int len; | ||
481 | |||
482 | va_start(va, format); | ||
483 | #ifdef HAS_vsnprintf | ||
484 | len = vsnprintf(buf, sizeof(buf), format, va); | ||
485 | #else | ||
486 | len = vsprintf(buf, format, va); | ||
487 | #endif | ||
488 | va_end(va); | ||
489 | if (len <= 0) return 0; | ||
490 | |||
491 | return gzwrite(file, buf, (unsigned)len); | ||
492 | } | ||
493 | #else /* not ANSI C */ | ||
494 | |||
495 | int EXPORTVA gzprintf (file, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, | ||
496 | a11, a12, a13, a14, a15, a16, a17, a18, a19, a20) | ||
497 | gzFile file; | ||
498 | const char *format; | ||
499 | int a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, | ||
500 | a11, a12, a13, a14, a15, a16, a17, a18, a19, a20; | ||
501 | { | ||
502 | char buf[Z_BUFSIZE]; | ||
503 | int len; | ||
504 | |||
505 | #ifdef HAS_snprintf | ||
506 | snprintf(buf, sizeof(buf), format, a1, a2, a3, a4, a5, a6, a7, a8, | ||
507 | a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20); | ||
508 | #else | ||
509 | sprintf(buf, format, a1, a2, a3, a4, a5, a6, a7, a8, | ||
510 | a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20); | ||
511 | #endif | ||
512 | len = strlen(buf); /* old sprintf doesn't return the nb of bytes written */ | ||
513 | if (len <= 0) return 0; | ||
514 | |||
515 | return gzwrite(file, buf, len); | ||
516 | } | ||
517 | #endif | ||
518 | |||
519 | /* =========================================================================== | ||
520 | Writes c, converted to an unsigned char, into the compressed file. | ||
521 | gzputc returns the value that was written, or -1 in case of error. | ||
522 | */ | ||
523 | int EXPORT gzputc(file, c) | ||
524 | gzFile file; | ||
525 | int c; | ||
526 | { | ||
527 | return gzwrite(file, &c, 1) == 1 ? c : -1; | ||
528 | } | ||
529 | |||
530 | |||
531 | /* =========================================================================== | ||
396 | Flushes all pending output into the compressed file. The parameter | 532 | Flushes all pending output into the compressed file. The parameter |
397 | flush is as in the deflate() function. | 533 | flush is as in the deflate() function. |
398 | gzflush should be called only when strictly necessary because it can | ||
399 | degrade compression. | ||
400 | */ | 534 | */ |
401 | int gzflush (file, flush) | 535 | local int do_flush (file, flush) |
402 | gzFile file; | 536 | gzFile file; |
403 | int flush; | 537 | int flush; |
404 | { | 538 | { |
@@ -424,6 +558,9 @@ int gzflush (file, flush) | |||
424 | if (done) break; | 558 | if (done) break; |
425 | s->z_err = deflate(&(s->stream), flush); | 559 | s->z_err = deflate(&(s->stream), flush); |
426 | 560 | ||
561 | /* Ignore the second of two consecutive flushes: */ | ||
562 | if (len == 0 && s->z_err == Z_BUF_ERROR) s->z_err = Z_OK; | ||
563 | |||
427 | /* deflate has finished flushing only when it hasn't used up | 564 | /* deflate has finished flushing only when it hasn't used up |
428 | * all the available space in the output buffer: | 565 | * all the available space in the output buffer: |
429 | */ | 566 | */ |
@@ -431,9 +568,154 @@ int gzflush (file, flush) | |||
431 | 568 | ||
432 | if (s->z_err != Z_OK && s->z_err != Z_STREAM_END) break; | 569 | if (s->z_err != Z_OK && s->z_err != Z_STREAM_END) break; |
433 | } | 570 | } |
571 | return s->z_err == Z_STREAM_END ? Z_OK : s->z_err; | ||
572 | } | ||
573 | |||
574 | int EXPORT gzflush (file, flush) | ||
575 | gzFile file; | ||
576 | int flush; | ||
577 | { | ||
578 | gz_stream *s = (gz_stream*)file; | ||
579 | int err = do_flush (file, flush); | ||
580 | |||
581 | if (err) return err; | ||
434 | fflush(s->file); | 582 | fflush(s->file); |
435 | return s->z_err == Z_STREAM_END ? Z_OK : s->z_err; | 583 | return s->z_err == Z_STREAM_END ? Z_OK : s->z_err; |
436 | } | 584 | } |
585 | #endif /* NO_DEFLATE */ | ||
586 | |||
587 | /* =========================================================================== | ||
588 | Sets the starting position for the next gzread or gzwrite on the given | ||
589 | compressed file. The offset represents a number of bytes in the | ||
590 | gzseek returns the resulting offset location as measured in bytes from | ||
591 | the beginning of the uncompressed stream, or -1 in case of error. | ||
592 | SEEK_END is not implemented, returns error. | ||
593 | In this version of the library, gzseek can be extremely slow. | ||
594 | */ | ||
595 | z_off_t EXPORT gzseek (file, offset, whence) | ||
596 | gzFile file; | ||
597 | z_off_t offset; | ||
598 | int whence; | ||
599 | { | ||
600 | gz_stream *s = (gz_stream*)file; | ||
601 | |||
602 | if (s == NULL || whence == SEEK_END || s->z_err == Z_ERRNO) return -1L; | ||
603 | |||
604 | s->z_err = Z_OK; | ||
605 | s->z_eof = 0; | ||
606 | |||
607 | if (s->mode == 'w') { | ||
608 | #ifdef NO_DEFLATE | ||
609 | return -1L; | ||
610 | #else | ||
611 | if (whence == SEEK_SET) { | ||
612 | offset -= s->stream.total_out; | ||
613 | } | ||
614 | if (offset < 0) return -1L; | ||
615 | |||
616 | /* At this point, offset is the number of zero bytes to write. */ | ||
617 | if (s->inbuf == Z_NULL) { | ||
618 | s->inbuf = (Byte*)ALLOC(Z_BUFSIZE); /* for seeking */ | ||
619 | zmemzero(s->inbuf, Z_BUFSIZE); | ||
620 | } | ||
621 | while (offset > 0) { | ||
622 | uInt size = Z_BUFSIZE; | ||
623 | if (offset < Z_BUFSIZE) size = (uInt)offset; | ||
624 | |||
625 | size = gzwrite(file, s->inbuf, size); | ||
626 | if (size == 0) return -1L; | ||
627 | |||
628 | offset -= size; | ||
629 | } | ||
630 | return s->stream.total_in; | ||
631 | #endif | ||
632 | } | ||
633 | /* Rest of function is for reading only */ | ||
634 | |||
635 | if (s->z_err == Z_DATA_ERROR) return -1L; | ||
636 | |||
637 | /* compute absolute position */ | ||
638 | if (whence == SEEK_CUR) { | ||
639 | offset += s->stream.total_out; | ||
640 | } | ||
641 | if (offset < 0) return -1L; | ||
642 | |||
643 | if (s->transparent) { | ||
644 | /* map to fseek */ | ||
645 | s->stream.avail_in = 0; | ||
646 | s->stream.next_in = s->inbuf; | ||
647 | if (fseek(s->file, offset, SEEK_SET) < 0) return -1L; | ||
648 | return offset; | ||
649 | } | ||
650 | |||
651 | /* For a negative seek, rewind and use positive seek */ | ||
652 | if ((uLong)offset >= s->stream.total_out) { | ||
653 | offset -= s->stream.total_out; | ||
654 | } else if (gzrewind(file) < 0) { | ||
655 | return -1L; | ||
656 | } | ||
657 | /* offset is now the number of bytes to skip. */ | ||
658 | |||
659 | if (offset != 0 && s->outbuf == Z_NULL) { | ||
660 | s->outbuf = (Byte*)ALLOC(Z_BUFSIZE); | ||
661 | } | ||
662 | while (offset > 0) { | ||
663 | int size = Z_BUFSIZE; | ||
664 | if (offset < Z_BUFSIZE) size = (int)offset; | ||
665 | |||
666 | size = gzread(file, s->outbuf, (uInt)size); | ||
667 | if (size <= 0) return -1L; | ||
668 | offset -= size; | ||
669 | } | ||
670 | return s->stream.total_out; | ||
671 | } | ||
672 | |||
673 | /* =========================================================================== | ||
674 | Rewinds input file. | ||
675 | */ | ||
676 | int EXPORT gzrewind (file) | ||
677 | gzFile file; | ||
678 | { | ||
679 | gz_stream *s = (gz_stream*)file; | ||
680 | |||
681 | if (s == NULL || s->mode != 'r') return -1; | ||
682 | |||
683 | s->z_err = Z_OK; | ||
684 | s->z_eof = 0; | ||
685 | s->stream.avail_in = 0; | ||
686 | s->stream.next_in = s->inbuf; | ||
687 | |||
688 | if (s->startpos == 0) { /* not a compressed file */ | ||
689 | rewind(s->file); | ||
690 | return 0; | ||
691 | } | ||
692 | |||
693 | (void) inflateReset(&s->stream); | ||
694 | return fseek(s->file, s->startpos, SEEK_SET); | ||
695 | } | ||
696 | |||
697 | /* =========================================================================== | ||
698 | Returns the starting position for the next gzread or gzwrite on the | ||
699 | given compressed file. This position represents a number of bytes in the | ||
700 | uncompressed data stream. | ||
701 | */ | ||
702 | z_off_t EXPORT gztell (file) | ||
703 | gzFile file; | ||
704 | { | ||
705 | return gzseek(file, 0L, SEEK_CUR); | ||
706 | } | ||
707 | |||
708 | /* =========================================================================== | ||
709 | Returns 1 when EOF has previously been detected reading the given | ||
710 | input stream, otherwise zero. | ||
711 | */ | ||
712 | int EXPORT gzeof (file) | ||
713 | gzFile file; | ||
714 | { | ||
715 | gz_stream *s = (gz_stream*)file; | ||
716 | |||
717 | return (s == NULL || s->mode != 'r') ? 0 : s->z_eof; | ||
718 | } | ||
437 | 719 | ||
438 | /* =========================================================================== | 720 | /* =========================================================================== |
439 | Outputs a long in LSB order to the given file | 721 | Outputs a long in LSB order to the given file |
@@ -470,7 +752,7 @@ local uLong getLong (s) | |||
470 | Flushes all pending output if necessary, closes the compressed file | 752 | Flushes all pending output if necessary, closes the compressed file |
471 | and deallocates all the (de)compression state. | 753 | and deallocates all the (de)compression state. |
472 | */ | 754 | */ |
473 | int gzclose (file) | 755 | int EXPORT gzclose (file) |
474 | gzFile file; | 756 | gzFile file; |
475 | { | 757 | { |
476 | int err; | 758 | int err; |
@@ -479,14 +761,17 @@ int gzclose (file) | |||
479 | if (s == NULL) return Z_STREAM_ERROR; | 761 | if (s == NULL) return Z_STREAM_ERROR; |
480 | 762 | ||
481 | if (s->mode == 'w') { | 763 | if (s->mode == 'w') { |
482 | err = gzflush (file, Z_FINISH); | 764 | #ifdef NO_DEFLATE |
483 | if (err != Z_OK) return destroy(file); | 765 | return Z_STREAM_ERROR; |
766 | #else | ||
767 | err = do_flush (file, Z_FINISH); | ||
768 | if (err != Z_OK) return destroy((gz_stream*)file); | ||
484 | 769 | ||
485 | putLong (s->file, s->crc); | 770 | putLong (s->file, s->crc); |
486 | putLong (s->file, s->stream.total_in); | 771 | putLong (s->file, s->stream.total_in); |
487 | 772 | #endif | |
488 | } | 773 | } |
489 | return destroy(file); | 774 | return destroy((gz_stream*)file); |
490 | } | 775 | } |
491 | 776 | ||
492 | /* =========================================================================== | 777 | /* =========================================================================== |
@@ -496,7 +781,7 @@ int gzclose (file) | |||
496 | errnum is set to Z_ERRNO and the application may consult errno | 781 | errnum is set to Z_ERRNO and the application may consult errno |
497 | to get the exact error code. | 782 | to get the exact error code. |
498 | */ | 783 | */ |
499 | const char* gzerror (file, errnum) | 784 | const char* EXPORT gzerror (file, errnum) |
500 | gzFile file; | 785 | gzFile file; |
501 | int *errnum; | 786 | int *errnum; |
502 | { | 787 | { |