]>
git.saurik.com Git - wxWidgets.git/blob - src/zlib/gzio.c
1 /* gzio.c -- IO on .gz files
2 * Copyright (C) 1995-1998 Jean-loup Gailly.
3 * For conditions of distribution and use, see copyright notice in zlib.h
5 * Compile this file with -DNO_DEFLATE to avoid the compression code.
14 struct internal_state
{int dummy
;}; /* for buggy compilers */
18 # define Z_BUFSIZE 4096 /* minimize memory usage for 16-bit DOS */
20 # define Z_BUFSIZE 16384
23 #ifndef Z_PRINTF_BUFSIZE
24 # define Z_PRINTF_BUFSIZE 4096
27 #define ALLOC(size) malloc(size)
28 #define TRYFREE(p) {if (p) free(p);}
30 static int gz_magic
[2] = {0x1f, 0x8b}; /* gzip magic header */
33 #define ASCII_FLAG 0x01 /* bit 0 set: file probably ascii text */
34 #define HEAD_CRC 0x02 /* bit 1 set: header CRC present */
35 #define EXTRA_FIELD 0x04 /* bit 2 set: extra field present */
36 #define ORIG_NAME 0x08 /* bit 3 set: original file name present */
37 #define COMMENT 0x10 /* bit 4 set: file comment present */
38 #define RESERVED 0xE0 /* bits 5..7: reserved */
40 typedef struct gz_stream
{
42 int z_err
; /* error code for last stream operation */
43 int z_eof
; /* set if end of input file */
44 FILE *file
; /* .gz file */
45 Byte
*inbuf
; /* input buffer */
46 Byte
*outbuf
; /* output buffer */
47 uLong crc
; /* crc32 of uncompressed data */
48 char *msg
; /* error message */
49 char *path
; /* path name for debugging only */
50 int transparent
; /* 1 if input file is not a .gz file */
51 char mode
; /* 'w' or 'r' */
52 long startpos
; /* start of compressed data in file (header skipped) */
56 local gzFile gz_open
OF((const char *path
, const char *mode
, int fd
));
57 local
int do_flush
OF((gzFile file
, int flush
));
58 local
int get_byte
OF((gz_stream
*s
));
59 local
void check_header
OF((gz_stream
*s
));
60 local
int destroy
OF((gz_stream
*s
));
61 local
void putLong
OF((FILE *file
, uLong x
));
62 local uLong getLong
OF((gz_stream
*s
));
64 /* ===========================================================================
65 Opens a gzip (.gz) file for reading or writing. The mode parameter
66 is as in fopen ("rb" or "wb"). The file is given either by file descriptor
67 or path name (if fd == -1).
68 gz_open return NULL if the file could not be opened or if there was
69 insufficient memory to allocate the (de)compression state; errno
70 can be checked to distinguish the two cases (if errno is zero, the
71 zlib error is Z_MEM_ERROR).
73 #if defined(__VISAGECPP__) /* Visualage can't handle this antiquated interface */
74 local gzFile
gz_open (const char* path
, const char* mode
, int fd
)
76 local gzFile
gz_open (path
, mode
, fd
)
83 int level
= Z_DEFAULT_COMPRESSION
; /* compression level */
84 int strategy
= Z_DEFAULT_STRATEGY
; /* compression strategy */
85 char *p
= (char*)mode
;
87 char fmode
[80]; /* copy of mode, without the compression level */
90 if (!path
|| !mode
) return Z_NULL
;
92 s
= (gz_stream
*)ALLOC(sizeof(gz_stream
));
93 if (!s
) return Z_NULL
;
95 s
->stream
.zalloc
= (alloc_func
)0;
96 s
->stream
.zfree
= (free_func
)0;
97 s
->stream
.opaque
= (voidpf
)0;
98 s
->stream
.next_in
= s
->inbuf
= Z_NULL
;
99 s
->stream
.next_out
= s
->outbuf
= Z_NULL
;
100 s
->stream
.avail_in
= s
->stream
.avail_out
= 0;
104 s
->crc
= crc32(0L, Z_NULL
, 0);
108 s
->path
= (char*)ALLOC(strlen(path
)+1);
109 if (s
->path
== NULL
) {
110 return destroy(s
), (gzFile
)Z_NULL
;
112 strcpy(s
->path
, path
); /* do this early for debugging */
116 if (*p
== 'r') s
->mode
= 'r';
117 if (*p
== 'w' || *p
== 'a') s
->mode
= 'w';
118 if (*p
>= '0' && *p
<= '9') {
120 } else if (*p
== 'f') {
121 strategy
= Z_FILTERED
;
122 } else if (*p
== 'h') {
123 strategy
= Z_HUFFMAN_ONLY
;
125 *m
++ = *p
; /* copy the mode */
127 } while (*p
++ && m
!= fmode
+ sizeof(fmode
));
128 if (s
->mode
== '\0') return destroy(s
), (gzFile
)Z_NULL
;
130 if (s
->mode
== 'w') {
132 err
= Z_STREAM_ERROR
;
134 err
= deflateInit2(&(s
->stream
), level
,
135 Z_DEFLATED
, -MAX_WBITS
, DEF_MEM_LEVEL
, strategy
);
136 /* windowBits is passed < 0 to suppress zlib header */
138 s
->stream
.next_out
= s
->outbuf
= (Byte
*)ALLOC(Z_BUFSIZE
);
140 if (err
!= Z_OK
|| s
->outbuf
== Z_NULL
) {
141 return destroy(s
), (gzFile
)Z_NULL
;
144 s
->stream
.next_in
= s
->inbuf
= (Byte
*)ALLOC(Z_BUFSIZE
);
146 err
= inflateInit2(&(s
->stream
), -MAX_WBITS
);
147 /* windowBits is passed < 0 to tell that there is no zlib header.
148 * Note that in this case inflate *requires* an extra "dummy" byte
149 * after the compressed stream in order to complete decompression and
150 * return Z_STREAM_END. Here the gzip CRC32 ensures that 4 bytes are
151 * present after the compressed stream.
153 if (err
!= Z_OK
|| s
->inbuf
== Z_NULL
) {
154 return destroy(s
), (gzFile
)Z_NULL
;
157 s
->stream
.avail_out
= Z_BUFSIZE
;
160 s
->file
= fd
< 0 ? F_OPEN(path
, fmode
) : (FILE*)fdopen(fd
, fmode
);
162 if (s
->file
== NULL
) {
163 return destroy(s
), (gzFile
)Z_NULL
;
165 if (s
->mode
== 'w') {
166 /* Write a very simple .gz header:
168 fprintf(s
->file
, "%c%c%c%c%c%c%c%c%c%c", gz_magic
[0], gz_magic
[1],
169 Z_DEFLATED
, 0 /*flags*/, 0,0,0,0 /*time*/, 0 /*xflags*/, OS_CODE
);
171 /* We use 10L instead of ftell(s->file) to because ftell causes an
172 * fflush on some systems. This version of the library doesn't use
173 * startpos anyway in write mode, so this initialization is not
177 check_header(s
); /* skip the .gz header */
178 s
->startpos
= (ftell(s
->file
) - s
->stream
.avail_in
);
184 /* ===========================================================================
185 Opens a gzip (.gz) file for reading or writing.
187 #if defined(__VISAGECPP__) /* Visualage can't handle this antiquated interface */
188 gzFile ZEXPORT
gzopen (const char* path
, const char* mode
)
190 gzFile ZEXPORT
gzopen (path
, mode
)
195 return gz_open (path
, mode
, -1);
198 /* ===========================================================================
199 Associate a gzFile with the file descriptor fd. fd is not dup'ed here
200 to mimic the behavio(u)r of fdopen.
202 #if defined(__VISAGECPP__) /* Visualage can't handle this antiquated interface */
203 gzFile ZEXPORT
gzdopen (int fd
, const char* mode
)
205 gzFile ZEXPORT
gzdopen (fd
, mode
)
212 if (fd
< 0) return (gzFile
)Z_NULL
;
213 sprintf(name
, "<fd:%d>", fd
); /* for debugging */
215 return gz_open (name
, mode
, fd
);
218 /* ===========================================================================
219 * Update the compression level and strategy
221 #if defined(__VISAGECPP__) /* Visualage can't handle this antiquated interface */
222 int ZEXPORT
gzsetparams (gzFile file
, int level
, int strategy
)
224 int ZEXPORT
gzsetparams (file
, level
, strategy
)
230 gz_stream
*s
= (gz_stream
*)file
;
232 if (s
== NULL
|| s
->mode
!= 'w') return Z_STREAM_ERROR
;
234 /* Make room to allow flushing */
235 if (s
->stream
.avail_out
== 0) {
237 s
->stream
.next_out
= s
->outbuf
;
238 if (fwrite(s
->outbuf
, 1, Z_BUFSIZE
, s
->file
) != Z_BUFSIZE
) {
241 s
->stream
.avail_out
= Z_BUFSIZE
;
244 return deflateParams (&(s
->stream
), level
, strategy
);
247 /* ===========================================================================
248 Read a byte from a gz_stream; update next_in and avail_in. Return EOF
250 IN assertion: the stream s has been sucessfully opened for reading.
252 #if defined(__VISAGECPP__) /* Visualage can't handle this antiquated interface */
253 local
int get_byte(gz_stream
* s
)
255 local
int get_byte(s
)
259 if (s
->z_eof
) return EOF
;
260 if (s
->stream
.avail_in
== 0) {
262 s
->stream
.avail_in
= fread(s
->inbuf
, 1, Z_BUFSIZE
, s
->file
);
263 if (s
->stream
.avail_in
== 0) {
265 if (ferror(s
->file
)) s
->z_err
= Z_ERRNO
;
268 s
->stream
.next_in
= s
->inbuf
;
270 s
->stream
.avail_in
--;
271 return *(s
->stream
.next_in
)++;
274 /* ===========================================================================
275 Check the gzip header of a gz_stream opened for reading. Set the stream
276 mode to transparent if the gzip magic header is not present; set s->err
277 to Z_DATA_ERROR if the magic header is present but the rest of the header
279 IN assertion: the stream s has already been created sucessfully;
280 s->stream.avail_in is zero for the first time, but may be non-zero
281 for concatenated .gz files.
283 #if defined(__VISAGECPP__) /* Visualage can't handle this antiquated interface */
284 local
void check_header(gz_stream
* s
)
286 local
void check_header(s
)
290 int method
; /* method byte */
291 int flags
; /* flags byte */
295 /* Check the gzip magic header */
296 for (len
= 0; len
< 2; len
++) {
298 if (c
!= gz_magic
[len
]) {
299 if (len
!= 0) s
->stream
.avail_in
++, s
->stream
.next_in
--;
301 s
->stream
.avail_in
++, s
->stream
.next_in
--;
304 s
->z_err
= s
->stream
.avail_in
!= 0 ? Z_OK
: Z_STREAM_END
;
308 method
= get_byte(s
);
310 if (method
!= Z_DEFLATED
|| (flags
& RESERVED
) != 0) {
311 s
->z_err
= Z_DATA_ERROR
;
315 /* Discard time, xflags and OS code: */
316 for (len
= 0; len
< 6; len
++) (void)get_byte(s
);
318 if ((flags
& EXTRA_FIELD
) != 0) { /* skip the extra field */
319 len
= (uInt
)get_byte(s
);
320 len
+= ((uInt
)get_byte(s
))<<8;
321 /* len is garbage if EOF but the loop below will quit anyway */
322 while (len
-- != 0 && get_byte(s
) != EOF
) ;
324 if ((flags
& ORIG_NAME
) != 0) { /* skip the original file name */
325 while ((c
= get_byte(s
)) != 0 && c
!= EOF
) ;
327 if ((flags
& COMMENT
) != 0) { /* skip the .gz file comment */
328 while ((c
= get_byte(s
)) != 0 && c
!= EOF
) ;
330 if ((flags
& HEAD_CRC
) != 0) { /* skip the header crc */
331 for (len
= 0; len
< 2; len
++) (void)get_byte(s
);
333 s
->z_err
= s
->z_eof
? Z_DATA_ERROR
: Z_OK
;
336 /* ===========================================================================
337 * Cleanup then free the given gz_stream. Return a zlib error code.
338 Try freeing in the reverse order of allocations.
340 #if defined(__VISAGECPP__) /* Visualage can't handle this antiquated interface */
341 local
int destroy (gz_stream
* s
)
343 local
int destroy (s
)
349 if (!s
) return Z_STREAM_ERROR
;
353 if (s
->stream
.state
!= NULL
) {
354 if (s
->mode
== 'w') {
356 err
= Z_STREAM_ERROR
;
358 err
= deflateEnd(&(s
->stream
));
360 } else if (s
->mode
== 'r') {
361 err
= inflateEnd(&(s
->stream
));
364 if (s
->file
!= NULL
&& fclose(s
->file
)) {
366 if (errno
!= ESPIPE
) /* fclose is broken for pipes in HP/UX */
370 if (s
->z_err
< 0) err
= s
->z_err
;
379 /* ===========================================================================
380 Reads the given number of uncompressed bytes from the compressed file.
381 gzread returns the number of bytes actually read (0 for end of file).
383 #if defined(__VISAGECPP__) /* Visualage can't handle this antiquated interface */
384 int ZEXPORT
gzread (gzFile file
, voidp buf
, unsigned len
)
386 int ZEXPORT
gzread (file
, buf
, len
)
392 gz_stream
*s
= (gz_stream
*)file
;
393 Bytef
*start
= (Bytef
*)buf
; /* starting point for crc computation */
394 Byte
*next_out
; /* == stream.next_out but not forced far (for MSDOS) */
396 if (s
== NULL
|| s
->mode
!= 'r') return Z_STREAM_ERROR
;
398 if (s
->z_err
== Z_DATA_ERROR
|| s
->z_err
== Z_ERRNO
) return -1;
399 if (s
->z_err
== Z_STREAM_END
) return 0; /* EOF */
401 next_out
= (Byte
*)buf
;
402 s
->stream
.next_out
= (Bytef
*)buf
;
403 s
->stream
.avail_out
= len
;
405 while (s
->stream
.avail_out
!= 0) {
407 if (s
->transparent
) {
408 /* Copy first the lookahead bytes: */
409 uInt n
= s
->stream
.avail_in
;
410 if (n
> s
->stream
.avail_out
) n
= s
->stream
.avail_out
;
412 zmemcpy(s
->stream
.next_out
, s
->stream
.next_in
, n
);
414 s
->stream
.next_out
= next_out
;
415 s
->stream
.next_in
+= n
;
416 s
->stream
.avail_out
-= n
;
417 s
->stream
.avail_in
-= n
;
419 if (s
->stream
.avail_out
> 0) {
420 s
->stream
.avail_out
-= fread(next_out
, 1, s
->stream
.avail_out
,
423 len
-= s
->stream
.avail_out
;
424 s
->stream
.total_in
+= (uLong
)len
;
425 s
->stream
.total_out
+= (uLong
)len
;
426 if (len
== 0) s
->z_eof
= 1;
429 if (s
->stream
.avail_in
== 0 && !s
->z_eof
) {
432 s
->stream
.avail_in
= fread(s
->inbuf
, 1, Z_BUFSIZE
, s
->file
);
433 if (s
->stream
.avail_in
== 0) {
435 if (ferror(s
->file
)) {
440 s
->stream
.next_in
= s
->inbuf
;
442 s
->z_err
= inflate(&(s
->stream
), Z_NO_FLUSH
);
444 if (s
->z_err
== Z_STREAM_END
) {
445 /* Check CRC and original size */
446 s
->crc
= crc32(s
->crc
, start
, (uInt
)(s
->stream
.next_out
- start
));
447 start
= s
->stream
.next_out
;
449 if (getLong(s
) != s
->crc
|| getLong(s
) != s
->stream
.total_out
) {
450 s
->z_err
= Z_DATA_ERROR
;
452 /* Check for concatenated .gz files: */
454 if (s
->z_err
== Z_OK
) {
455 uLong total_in
= s
->stream
.total_in
;
456 uLong total_out
= s
->stream
.total_out
;
458 inflateReset(&(s
->stream
));
459 s
->stream
.total_in
= total_in
;
460 s
->stream
.total_out
= total_out
;
461 s
->crc
= crc32(0L, Z_NULL
, 0);
465 if (s
->z_err
!= Z_OK
|| s
->z_eof
) break;
467 s
->crc
= crc32(s
->crc
, start
, (uInt
)(s
->stream
.next_out
- start
));
469 return (int)(len
- s
->stream
.avail_out
);
473 /* ===========================================================================
474 Reads one byte from the compressed file. gzgetc returns this byte
475 or -1 in case of end of file or error.
477 #if defined(__VISAGECPP__) /* Visualage can't handle this antiquated interface */
478 int ZEXPORT
gzgetc(gzFile file
)
480 int ZEXPORT
gzgetc(file
)
486 return gzread(file
, &c
, 1) == 1 ? c
: -1;
490 /* ===========================================================================
491 Reads bytes from the compressed file until len-1 characters are
492 read, or a newline character is read and transferred to buf, or an
493 end-of-file condition is encountered. The string is then terminated
494 with a null character.
495 gzgets returns buf, or Z_NULL in case of error.
497 The current implementation is not optimized at all.
499 #if defined(__VISAGECPP__) /* Visualage can't handle this antiquated interface */
500 char* ZEXPORT
gzgets(gzFile file
, char* buf
, int len
)
502 char * ZEXPORT
gzgets(file
, buf
, len
)
509 if (buf
== Z_NULL
|| len
<= 0) return Z_NULL
;
511 while (--len
> 0 && gzread(file
, buf
, 1) == 1 && *buf
++ != '\n') ;
513 return b
== buf
&& len
> 0 ? Z_NULL
: b
;
518 /* ===========================================================================
519 Writes the given number of uncompressed bytes into the compressed file.
520 gzwrite returns the number of bytes actually written (0 in case of error).
522 #if defined(__VISAGECPP__) /* Visualage can't handle this antiquated interface */
523 int ZEXPORT
gzwrite (gzFile file
, const voidp buf
, unsigned len
)
525 int ZEXPORT
gzwrite (file
, buf
, len
)
531 gz_stream
*s
= (gz_stream
*)file
;
533 if (s
== NULL
|| s
->mode
!= 'w') return Z_STREAM_ERROR
;
535 s
->stream
.next_in
= (Bytef
*)buf
;
536 s
->stream
.avail_in
= len
;
538 while (s
->stream
.avail_in
!= 0) {
540 if (s
->stream
.avail_out
== 0) {
542 s
->stream
.next_out
= s
->outbuf
;
543 if (fwrite(s
->outbuf
, 1, Z_BUFSIZE
, s
->file
) != Z_BUFSIZE
) {
547 s
->stream
.avail_out
= Z_BUFSIZE
;
549 s
->z_err
= deflate(&(s
->stream
), Z_NO_FLUSH
);
550 if (s
->z_err
!= Z_OK
) break;
552 s
->crc
= crc32(s
->crc
, (const Bytef
*)buf
, len
);
554 return (int)(len
- s
->stream
.avail_in
);
557 /* ===========================================================================
558 Converts, formats, and writes the args to the compressed file under
559 control of the format string, as in fprintf. gzprintf returns the number of
560 uncompressed bytes actually written (0 in case of error).
565 int ZEXPORTVA
gzprintf (gzFile file
, const char *format
, /* args */ ...)
567 char buf
[Z_PRINTF_BUFSIZE
];
571 va_start(va
, format
);
573 (void)vsnprintf(buf
, sizeof(buf
), format
, va
);
575 (void)vsprintf(buf
, format
, va
);
578 len
= strlen(buf
); /* some *sprintf don't return the nb of bytes written */
579 if (len
<= 0) return 0;
581 return gzwrite(file
, buf
, (unsigned)len
);
583 #else /* not ANSI C */
585 #if defined(__VISAGECPP__) /* Visualage can't handle this antiquated interface */
586 int ZEXPORTVA
gzprintf (gzFile file
const char* format
, int a1
, int a2
, int a3
, int a4
,
587 int a5
, int a6
, int a7
, int a8
, int a9
, int a10
, int a11
, int a12
588 int a13
, int a14
, int a15
, int a16
, int a17
, int a18
, int a19
, int a20
)
590 int ZEXPORTVA
gzprintf (file
, format
, a1
, a2
, a3
, a4
, a5
, a6
, a7
, a8
, a9
, a10
,
591 a11
, a12
, a13
, a14
, a15
, a16
, a17
, a18
, a19
, a20
)
594 int a1
, a2
, a3
, a4
, a5
, a6
, a7
, a8
, a9
, a10
,
595 a11
, a12
, a13
, a14
, a15
, a16
, a17
, a18
, a19
, a20
;
598 char buf
[Z_PRINTF_BUFSIZE
];
602 snprintf(buf
, sizeof(buf
), format
, a1
, a2
, a3
, a4
, a5
, a6
, a7
, a8
,
603 a9
, a10
, a11
, a12
, a13
, a14
, a15
, a16
, a17
, a18
, a19
, a20
);
605 sprintf(buf
, format
, a1
, a2
, a3
, a4
, a5
, a6
, a7
, a8
,
606 a9
, a10
, a11
, a12
, a13
, a14
, a15
, a16
, a17
, a18
, a19
, a20
);
608 len
= strlen(buf
); /* old sprintf doesn't return the nb of bytes written */
609 if (len
<= 0) return 0;
611 return gzwrite(file
, buf
, len
);
615 /* ===========================================================================
616 Writes c, converted to an unsigned char, into the compressed file.
617 gzputc returns the value that was written, or -1 in case of error.
619 #if defined(__VISAGECPP__) /* Visualage can't handle this antiquated interface */
620 int ZEXPORT
gzputc(gzFile file
, int c
)
622 int ZEXPORT
gzputc(file
, c
)
627 unsigned char cc
= (unsigned char) c
; /* required for big endian systems */
629 return gzwrite(file
, &cc
, 1) == 1 ? (int)cc
: -1;
633 /* ===========================================================================
634 Writes the given null-terminated string to the compressed file, excluding
635 the terminating null character.
636 gzputs returns the number of characters written, or -1 in case of error.
638 #if defined(__VISAGECPP__) /* Visualage can't handle this antiquated interface */
639 int ZEXPORT
gzputs(gzFile file
, const char* s
)
641 int ZEXPORT
gzputs(file
, s
)
646 return gzwrite(file
, (char*)s
, (unsigned)strlen(s
));
650 /* ===========================================================================
651 Flushes all pending output into the compressed file. The parameter
652 flush is as in the deflate() function.
654 #if defined(__VISAGECPP__) /* Visualage can't handle this antiquated interface */
655 local
int do_flush (gzFile file
, int flush
)
657 local
int do_flush (file
, flush
)
664 gz_stream
*s
= (gz_stream
*)file
;
666 if (s
== NULL
|| s
->mode
!= 'w') return Z_STREAM_ERROR
;
668 s
->stream
.avail_in
= 0; /* should be zero already anyway */
671 len
= Z_BUFSIZE
- s
->stream
.avail_out
;
674 if ((uInt
)fwrite(s
->outbuf
, 1, len
, s
->file
) != len
) {
678 s
->stream
.next_out
= s
->outbuf
;
679 s
->stream
.avail_out
= Z_BUFSIZE
;
682 s
->z_err
= deflate(&(s
->stream
), flush
);
684 /* Ignore the second of two consecutive flushes: */
685 if (len
== 0 && s
->z_err
== Z_BUF_ERROR
) s
->z_err
= Z_OK
;
687 /* deflate has finished flushing only when it hasn't used up
688 * all the available space in the output buffer:
690 done
= (s
->stream
.avail_out
!= 0 || s
->z_err
== Z_STREAM_END
);
692 if (s
->z_err
!= Z_OK
&& s
->z_err
!= Z_STREAM_END
) break;
694 return s
->z_err
== Z_STREAM_END
? Z_OK
: s
->z_err
;
697 #if defined(__VISAGECPP__) /* Visualage can't handle this antiquated interface */
698 int ZEXPORT
gzflush (gzFile file
, int flush
)
700 int ZEXPORT
gzflush (file
, flush
)
705 gz_stream
*s
= (gz_stream
*)file
;
706 int err
= do_flush (file
, flush
);
710 return s
->z_err
== Z_STREAM_END
? Z_OK
: s
->z_err
;
712 #endif /* NO_DEFLATE */
714 /* ===========================================================================
715 Sets the starting position for the next gzread or gzwrite on the given
716 compressed file. The offset represents a number of bytes in the
717 gzseek returns the resulting offset location as measured in bytes from
718 the beginning of the uncompressed stream, or -1 in case of error.
719 SEEK_END is not implemented, returns error.
720 In this version of the library, gzseek can be extremely slow.
722 #if defined(__VISAGECPP__) /* Visualage can't handle this antiquated interface */
723 z_off_t ZEXPORT
gzseek (gzFile file
, z_off_t offset
, int whence
)
725 z_off_t ZEXPORT
gzseek (file
, offset
, whence
)
731 gz_stream
*s
= (gz_stream
*)file
;
733 if (s
== NULL
|| whence
== SEEK_END
||
734 s
->z_err
== Z_ERRNO
|| s
->z_err
== Z_DATA_ERROR
) {
738 if (s
->mode
== 'w') {
742 if (whence
== SEEK_SET
) {
743 offset
-= s
->stream
.total_out
;
745 if (offset
< 0) return -1L;
747 /* At this point, offset is the number of zero bytes to write. */
748 if (s
->inbuf
== Z_NULL
) {
749 s
->inbuf
= (Byte
*)ALLOC(Z_BUFSIZE
); /* for seeking */
750 zmemzero(s
->inbuf
, Z_BUFSIZE
);
753 uInt size
= Z_BUFSIZE
;
754 if (offset
< Z_BUFSIZE
) size
= (uInt
)offset
;
756 size
= gzwrite(file
, s
->inbuf
, size
);
757 if (size
== 0) return -1L;
761 return (z_off_t
)s
->stream
.total_in
;
764 /* Rest of function is for reading only */
766 /* compute absolute position */
767 if (whence
== SEEK_CUR
) {
768 offset
+= s
->stream
.total_out
;
770 if (offset
< 0) return -1L;
772 if (s
->transparent
) {
774 s
->stream
.avail_in
= 0;
775 s
->stream
.next_in
= s
->inbuf
;
776 if (fseek(s
->file
, offset
, SEEK_SET
) < 0) return -1L;
778 s
->stream
.total_in
= s
->stream
.total_out
= (uLong
)offset
;
782 /* For a negative seek, rewind and use positive seek */
783 if ((uLong
)offset
>= s
->stream
.total_out
) {
784 offset
-= s
->stream
.total_out
;
785 } else if (gzrewind(file
) < 0) {
788 /* offset is now the number of bytes to skip. */
790 if (offset
!= 0 && s
->outbuf
== Z_NULL
) {
791 s
->outbuf
= (Byte
*)ALLOC(Z_BUFSIZE
);
794 int size
= Z_BUFSIZE
;
795 if (offset
< Z_BUFSIZE
) size
= (int)offset
;
797 size
= gzread(file
, s
->outbuf
, (uInt
)size
);
798 if (size
<= 0) return -1L;
801 return (z_off_t
)s
->stream
.total_out
;
804 /* ===========================================================================
807 #if defined(__VISAGECPP__) /* Visualage can't handle this antiquated interface */
808 int ZEXPORT
gzrewind (gzFile file
)
810 int ZEXPORT
gzrewind (file
)
814 gz_stream
*s
= (gz_stream
*)file
;
816 if (s
== NULL
|| s
->mode
!= 'r') return -1;
820 s
->stream
.avail_in
= 0;
821 s
->stream
.next_in
= s
->inbuf
;
823 if (s
->startpos
== 0) { /* not a compressed file */
828 (void) inflateReset(&s
->stream
);
829 return fseek(s
->file
, s
->startpos
, SEEK_SET
);
832 /* ===========================================================================
833 Returns the starting position for the next gzread or gzwrite on the
834 given compressed file. This position represents a number of bytes in the
835 uncompressed data stream.
837 #if defined(__VISAGECPP__) /* Visualage can't handle this antiquated interface */
838 z_off_t ZEXPORT
gztell (gzFile file
)
840 z_off_t ZEXPORT
gztell (file
)
844 return gzseek(file
, 0L, SEEK_CUR
);
847 /* ===========================================================================
848 Returns 1 when EOF has previously been detected reading the given
849 input stream, otherwise zero.
851 #if defined(__VISAGECPP__) /* Visualage can't handle this antiquated interface */
852 int ZEXPORT
gzeof (gzFile file
)
854 int ZEXPORT
gzeof (file
)
858 gz_stream
*s
= (gz_stream
*)file
;
860 return (s
== NULL
|| s
->mode
!= 'r') ? 0 : s
->z_eof
;
863 /* ===========================================================================
864 Outputs a long in LSB order to the given file
866 #if defined(__VISAGECPP__) /* Visualage can't handle this antiquated interface */
867 local
void putLong (FILE* file
, uLong x
)
869 local
void putLong (file
, x
)
875 for (n
= 0; n
< 4; n
++) {
876 fputc((int)(x
& 0xff), file
);
881 /* ===========================================================================
882 Reads a long in LSB order from the given gz_stream. Sets
884 #if defined(__VISAGECPP__) /* Visualage can't handle this antiquated interface */
885 local uLong
getLong (gz_stream
* s
)
887 local uLong
getLong (s
)
891 uLong x
= (uLong
)get_byte(s
);
894 x
+= ((uLong
)get_byte(s
))<<8;
895 x
+= ((uLong
)get_byte(s
))<<16;
897 if (c
== EOF
) s
->z_err
= Z_DATA_ERROR
;
902 /* ===========================================================================
903 Flushes all pending output if necessary, closes the compressed file
904 and deallocates all the (de)compression state.
906 #if defined(__VISAGECPP__) /* Visualage can't handle this antiquated interface */
907 int ZEXPORT
gzclose (gzFile file
)
909 int ZEXPORT
gzclose (file
)
914 gz_stream
*s
= (gz_stream
*)file
;
916 if (s
== NULL
) return Z_STREAM_ERROR
;
918 if (s
->mode
== 'w') {
920 return Z_STREAM_ERROR
;
922 err
= do_flush (file
, Z_FINISH
);
923 if (err
!= Z_OK
) return destroy((gz_stream
*)file
);
925 putLong (s
->file
, s
->crc
);
926 putLong (s
->file
, s
->stream
.total_in
);
929 return destroy((gz_stream
*)file
);
932 /* ===========================================================================
933 Returns the error message for the last error which occured on the
934 given compressed file. errnum is set to zlib error number. If an
935 error occured in the file system and not in the compression library,
936 errnum is set to Z_ERRNO and the application may consult errno
937 to get the exact error code.
939 #if defined(__VISAGECPP__) /* Visualage can't handle this antiquated interface */
940 const char* ZEXPORT
gzerror (gzFile file
, int* errnum
)
942 const char* ZEXPORT
gzerror (file
, errnum
)
948 gz_stream
*s
= (gz_stream
*)file
;
951 *errnum
= Z_STREAM_ERROR
;
952 return (const char*)ERR_MSG(Z_STREAM_ERROR
);
955 if (*errnum
== Z_OK
) return (const char*)"";
957 m
= (char*)(*errnum
== Z_ERRNO
? zstrerror(errno
) : s
->stream
.msg
);
959 if (m
== NULL
|| *m
== '\0') m
= (char*)ERR_MSG(s
->z_err
);
962 s
->msg
= (char*)ALLOC(strlen(s
->path
) + strlen(m
) + 3);
963 strcpy(s
->msg
, s
->path
);
964 strcat(s
->msg
, ": ");
966 return (const char*)s
->msg
;