diff options
author | unknown <konstantin@mysql.com> | 2004-07-21 17:36:26 -0700 |
---|---|---|
committer | unknown <konstantin@mysql.com> | 2004-07-21 17:36:26 -0700 |
commit | 9fe0a2fa8dbd83359722e077f761a01e37901bb8 (patch) | |
tree | e1c502ab20782af7b4564054ae3c46a321ccbb4e /zlib/gzio.c | |
parent | 2f26571fdcfc4eb701273079ede7fce7afa89e46 (diff) | |
download | mariadb-git-9fe0a2fa8dbd83359722e077f761a01e37901bb8.tar.gz |
First step of implementation of WL#1518 "make bundled zlib
usable for unix builds": zlib 1.2.1 imported
BitKeeper/deleted/.del-Make_vms.com~95dd9cc7505c3153:
Delete: zlib/Make_vms.com
BitKeeper/deleted/.del-Makefile.riscos~f85c6493d3e51733:
Delete: zlib/Makefile.riscos
BitKeeper/deleted/.del-Makefile.pup~b0e9ed99224cc5f4:
Delete: zlib/amiga/Makefile.pup
BitKeeper/deleted/.del-Makefile.sas~be103e936c85b66a:
Delete: zlib/amiga/Makefile.sas
BitKeeper/deleted/.del-README.contrib~2924ba28ef1f9fab:
Delete: zlib/contrib/README.contrib
BitKeeper/deleted/.del-gvmat32.asm~edf721a2de30e964:
Delete: zlib/contrib/asm386/gvmat32.asm
BitKeeper/deleted/.del-visual-basic.txt~859fcbcb668ffbb3:
Delete: zlib/contrib/visual-basic.txt
BitKeeper/deleted/.del-gvmat32c.c~2e97d7d65dd59113:
Delete: zlib/contrib/asm386/gvmat32c.c
BitKeeper/deleted/.del-mkgvmt32.bat~5a92cf0febe3dc81:
Delete: zlib/contrib/asm386/mkgvmt32.bat
BitKeeper/deleted/.del-zlibvc.def~67961fa7815b9267:
Delete: zlib/contrib/asm386/zlibvc.def
BitKeeper/deleted/.del-zlibvc.dsp~a3323c77bcd12995:
Delete: zlib/contrib/asm386/zlibvc.dsp
BitKeeper/deleted/.del-match.s~51b8fef5136642ed:
Delete: zlib/contrib/asm586/match.s
BitKeeper/deleted/.del-readme.586~cb1bb7136b0803bb:
Delete: zlib/contrib/asm586/readme.586
BitKeeper/deleted/.del-zlibvc.dsw~e3dca9d8f342e64e:
Delete: zlib/contrib/asm386/zlibvc.dsw
BitKeeper/deleted/.del-match.s~e4bbe1fa486d1c6c:
Delete: zlib/contrib/asm686/match.s
BitKeeper/deleted/.del-readme.686~98a220c13809fce5:
Delete: zlib/contrib/asm686/readme.686
BitKeeper/deleted/.del-zlib.mak~70f7c5f6947fd807:
Delete: zlib/contrib/delphi/zlib.mak
BitKeeper/deleted/.del-d_zlib.bpr~cefb1beee520d6e8:
Delete: zlib/contrib/delphi2/d_zlib.bpr
BitKeeper/deleted/.del-d_zlib.cpp~62dff1931881afa6:
Delete: zlib/contrib/delphi2/d_zlib.cpp
BitKeeper/deleted/.del-zlibdef.pas~780244c8d12b6c53:
Delete: zlib/contrib/delphi/zlibdef.pas
BitKeeper/deleted/.del-readme.txt~8222e54ca00f2729:
Delete: zlib/contrib/delphi2/readme.txt
BitKeeper/deleted/.del-zlib.bpg~fbd9308275ad8e3:
Delete: zlib/contrib/delphi2/zlib.bpg
BitKeeper/deleted/.del-zlib.bpr~fe8bf5d1c4a2ce5a:
Delete: zlib/contrib/delphi2/zlib.bpr
BitKeeper/deleted/.del-zlib.cpp~bb0c3df062410f5c:
Delete: zlib/contrib/delphi2/zlib.cpp
BitKeeper/deleted/.del-zlib.pas~1d5285e2449b50a3:
Delete: zlib/contrib/delphi2/zlib.pas
BitKeeper/deleted/.del-zlib32.bpr~c2a9f0aa47a1d9ad:
Delete: zlib/contrib/delphi2/zlib32.bpr
BitKeeper/deleted/.del-test.cpp~4480297b204dc360:
Delete: zlib/contrib/iostream/test.cpp
BitKeeper/deleted/.del-zfstream.cpp~943ecbd558e86dde:
Delete: zlib/contrib/iostream/zfstream.cpp
BitKeeper/deleted/.del-zlib32.cpp~bbb4a200d2fe6497:
Delete: zlib/contrib/delphi2/zlib32.cpp
BitKeeper/deleted/.del-ChangeLogUnzip~a3ae0ba899cadd:
Delete: zlib/contrib/minizip/ChangeLogUnzip
BitKeeper/deleted/.del-zfstream.h~71ee057bdc6366ac:
Delete: zlib/contrib/iostream/zfstream.h
BitKeeper/deleted/.del-zstream.h~a6f6be5634962c81:
Delete: zlib/contrib/iostream2/zstream.h
BitKeeper/deleted/.del-zstream_test.cpp~e471b51e7fb553ec:
Delete: zlib/contrib/iostream2/zstream_test.cpp
BitKeeper/deleted/.del-miniunz.c~9da181975b3a48:
Delete: zlib/contrib/minizip/miniunz.c
BitKeeper/deleted/.del-minizip.c~4a49a0addb97272b:
Delete: zlib/contrib/minizip/minizip.c
BitKeeper/deleted/.del-readme.txt~174eb00680149f6b:
Delete: zlib/contrib/minizip/readme.txt
BitKeeper/deleted/.del-unzip.c~662c5ba4edbb3a19:
Delete: zlib/contrib/minizip/unzip.c
BitKeeper/deleted/.del-unzip.def~8a0ad6f745ee5cd4:
Delete: zlib/contrib/minizip/unzip.def
BitKeeper/deleted/.del-unzip.h~d5e800088a368c32:
Delete: zlib/contrib/minizip/unzip.h
BitKeeper/deleted/.del-zip.c~9750c19a123f3057:
Delete: zlib/contrib/minizip/zip.c
BitKeeper/deleted/.del-zip.def~4ffe888e9fd7b5aa:
Delete: zlib/contrib/minizip/zip.def
BitKeeper/deleted/.del-zip.h~4c72b8fcc492f055:
Delete: zlib/contrib/minizip/zip.h
BitKeeper/deleted/.del-zlibvc.def~dd272b3ed71647ba:
Delete: zlib/contrib/minizip/zlibvc.def
BitKeeper/deleted/.del-zlibvc.dsp~ad83fb048811e2d2:
Delete: zlib/contrib/minizip/zlibvc.dsp
BitKeeper/deleted/.del-zlibvc.dsw~c66b33a2d52f37c5:
Delete: zlib/contrib/minizip/zlibvc.dsw
BitKeeper/deleted/.del-makefile.w32~6507530fa1b017c:
Delete: zlib/contrib/untgz/makefile.w32
BitKeeper/deleted/.del-untgz.c~4e8f1a3a2c145373:
Delete: zlib/contrib/untgz/untgz.c
BitKeeper/deleted/.del-Makefile.os2~8ab058477b24d1ff:
Delete: zlib/os2/Makefile.os2
BitKeeper/deleted/.del-zlib.def~385b56ed82784ff3:
Delete: zlib/os2/zlib.def
BitKeeper/deleted/.del-Makefile.b32~10ffaac6cc41847a:
Delete: zlib/msdos/Makefile.b32
BitKeeper/deleted/.del-Makefile.bor~121b2bc837b6367:
Delete: zlib/msdos/Makefile.bor
BitKeeper/deleted/.del-Makefile.dj2~a069623cad6ce7f4:
Delete: zlib/msdos/Makefile.dj2
BitKeeper/deleted/.del-Makefile.emx~11a9e6c8a719ba60:
Delete: zlib/msdos/Makefile.emx
BitKeeper/deleted/.del-Makefile.msc~ba5ad7709ff22aab:
Delete: zlib/msdos/Makefile.msc
BitKeeper/deleted/.del-Makefile.tc~d1398368648e8836:
Delete: zlib/msdos/Makefile.tc
BitKeeper/deleted/.del-Makefile.w32~921a473e873d94d1:
Delete: zlib/msdos/Makefile.w32
BitKeeper/deleted/.del-Makefile.wat~b2b51cbc2c2bc2f4:
Delete: zlib/msdos/Makefile.wat
BitKeeper/deleted/.del-zlib.def~189fba701e5e4b9c:
Delete: zlib/msdos/zlib.def
BitKeeper/deleted/.del-zlib.rc~e5ce22c7c915ec00:
Delete: zlib/msdos/zlib.rc
BitKeeper/deleted/.del-Makefile.emx~b5fa0633cbe6fe01:
Delete: zlib/nt/Makefile.emx
BitKeeper/deleted/.del-Makefile.gcc~7fcd3dd326341fa0:
Delete: zlib/nt/Makefile.gcc
BitKeeper/deleted/.del-Makefile.nt~9910c98f5da056de:
Delete: zlib/nt/Makefile.nt
BitKeeper/deleted/.del-zlib.dnt~8160c636eb3eeed7:
Delete: zlib/nt/zlib.dnt
BitKeeper/deleted/.del-zlib.dsp~a8abac2fb721276e:
Delete: zlib/zlib.dsp
BitKeeper/deleted/.del-zlib.html~2e74efd497dcd4d0:
Delete: zlib/zlib.html
BitKeeper/deleted/.del-minigzip.c~1f21a5863f457cb0:
Delete: zlib/minigzip.c
BitKeeper/deleted/.del-example.c~5ea43c929ccd2a4f:
Delete: zlib/example.c
BitKeeper/deleted/.del-descrip.mms~51cd5d1792d76b9c:
Delete: zlib/descrip.mms
BitKeeper/deleted/.del-infblock.h~7d4f40c3a1d4cdf8:
Delete: zlib/infblock.h
BitKeeper/deleted/.del-infblock.c~3c866934e0f44c43:
Delete: zlib/infblock.c
BitKeeper/deleted/.del-infutil.c~43d2340436244b52:
Delete: zlib/infutil.c
BitKeeper/deleted/.del-infutil.h~a6bd0dcbbdc187ac:
Delete: zlib/infutil.h
BitKeeper/deleted/.del-infcodes.h~c9f64a612c2cc56a:
Delete: zlib/infcodes.h
BitKeeper/deleted/.del-infcodes.c~7ed73df8a54d6d55:
Delete: zlib/infcodes.c
BitKeeper/deleted/.del-maketree.c~846b8b96ac6872d8:
Delete: zlib/maketree.c
VC++Files/zlib/zlib.dsp:
Modified to suit zlib upgrade.
mysys/my_crc32.c:
Modified to suit zlib upgrade.
zlib/ChangeLog:
zlib 1.2.1 imported
zlib/FAQ:
zlib 1.2.1 imported
zlib/INDEX:
zlib 1.2.1 imported
zlib/README:
zlib 1.2.1 imported
zlib/adler32.c:
zlib 1.2.1 imported
zlib/algorithm.txt:
zlib 1.2.1 imported
zlib/compress.c:
zlib 1.2.1 imported
zlib/crc32.c:
zlib 1.2.1 imported
zlib/deflate.c:
zlib 1.2.1 imported
zlib/deflate.h:
zlib 1.2.1 imported
zlib/gzio.c:
zlib 1.2.1 imported
zlib/inffast.c:
zlib 1.2.1 imported
zlib/inffast.h:
zlib 1.2.1 imported
zlib/inffixed.h:
zlib 1.2.1 imported
zlib/inflate.c:
zlib 1.2.1 imported
zlib/inftrees.c:
zlib 1.2.1 imported
zlib/inftrees.h:
zlib 1.2.1 imported
zlib/trees.c:
zlib 1.2.1 imported
zlib/uncompr.c:
zlib 1.2.1 imported
zlib/zconf.h:
zlib 1.2.1 imported
zlib/zlib.3:
zlib 1.2.1 imported
zlib/zlib.h:
zlib 1.2.1 imported
zlib/zutil.c:
zlib 1.2.1 imported
zlib/zutil.h:
zlib 1.2.1 imported
Diffstat (limited to 'zlib/gzio.c')
-rw-r--r-- | zlib/gzio.c | 526 |
1 files changed, 328 insertions, 198 deletions
diff --git a/zlib/gzio.c b/zlib/gzio.c index 09e0a20b8ce..4afd102b3f3 100644 --- a/zlib/gzio.c +++ b/zlib/gzio.c @@ -1,8 +1,8 @@ /* gzio.c -- IO on .gz files - * Copyright (C) 1995-2002 Jean-loup Gailly. + * Copyright (C) 1995-2003 Jean-loup Gailly. * For conditions of distribution and use, see copyright notice in zlib.h * - * Compile this file with -DNO_DEFLATE to avoid the compression code. + * Compile this file with -DNO_GZCOMPRESS to avoid the compression code. */ /* @(#) $Id$ */ @@ -11,7 +11,13 @@ #include "zutil.h" +#ifdef NO_DEFLATE /* for compatiblity with old definition */ +# define NO_GZCOMPRESS +#endif + +#ifndef NO_DUMMY_DECL struct internal_state {int dummy;}; /* for buggy compilers */ +#endif #ifndef Z_BUFSIZE # ifdef MAXSEG_64K @@ -24,10 +30,20 @@ struct internal_state {int dummy;}; /* for buggy compilers */ # define Z_PRINTF_BUFSIZE 4096 #endif +#ifdef __MVS__ +# pragma map (fdopen , "\174\174FDOPEN") + FILE *fdopen(int, const char *); +#endif + +#ifndef STDC +extern voidp malloc OF((uInt size)); +extern void free OF((voidpf ptr)); +#endif + #define ALLOC(size) malloc(size) #define TRYFREE(p) {if (p) free(p);} -static int gz_magic[2] = {0x1f, 0x8b}; /* gzip magic header */ +static int const gz_magic[2] = {0x1f, 0x8b}; /* gzip magic header */ /* gzip flag byte */ #define ASCII_FLAG 0x01 /* bit 0 set: file probably ascii text */ @@ -49,7 +65,11 @@ typedef struct gz_stream { char *path; /* path name for debugging only */ int transparent; /* 1 if input file is not a .gz file */ char mode; /* 'w' or 'r' */ - long startpos; /* start of compressed data in file (header skipped) */ + z_off_t start; /* start of compressed data in file (header skipped) */ + z_off_t in; /* bytes into deflate or inflate */ + z_off_t out; /* bytes out of deflate or inflate */ + int back; /* one character push-back */ + int last; /* true if push-back is last character */ } gz_stream; @@ -65,7 +85,7 @@ local uLong getLong OF((gz_stream *s)); Opens a gzip (.gz) file for reading or writing. The mode parameter is as in fopen ("rb" or "wb"). The file is given either by file descriptor or path name (if fd == -1). - gz_open return NULL if the file could not be opened or if there was + gz_open returns NULL if the file could not be opened or if there was insufficient memory to allocate the (de)compression state; errno can be checked to distinguish the two cases (if errno is zero, the zlib error is Z_MEM_ERROR). @@ -97,6 +117,9 @@ local gzFile gz_open (path, mode, fd) s->file = NULL; s->z_err = Z_OK; s->z_eof = 0; + s->in = 0; + s->out = 0; + s->back = EOF; s->crc = crc32(0L, Z_NULL, 0); s->msg = NULL; s->transparent = 0; @@ -112,19 +135,21 @@ local gzFile gz_open (path, mode, fd) if (*p == 'r') s->mode = 'r'; if (*p == 'w' || *p == 'a') s->mode = 'w'; if (*p >= '0' && *p <= '9') { - level = *p - '0'; - } else if (*p == 'f') { - strategy = Z_FILTERED; - } else if (*p == 'h') { - strategy = Z_HUFFMAN_ONLY; - } else { - *m++ = *p; /* copy the mode */ - } + level = *p - '0'; + } else if (*p == 'f') { + strategy = Z_FILTERED; + } else if (*p == 'h') { + strategy = Z_HUFFMAN_ONLY; + } else if (*p == 'R') { + strategy = Z_RLE; + } else { + *m++ = *p; /* copy the mode */ + } } while (*p++ && m != fmode + sizeof(fmode)); if (s->mode == '\0') return destroy(s), (gzFile)Z_NULL; - + if (s->mode == 'w') { -#ifdef NO_DEFLATE +#ifdef NO_GZCOMPRESS err = Z_STREAM_ERROR; #else err = deflateInit2(&(s->stream), level, @@ -163,17 +188,17 @@ local gzFile gz_open (path, mode, fd) */ fprintf(s->file, "%c%c%c%c%c%c%c%c%c%c", gz_magic[0], gz_magic[1], Z_DEFLATED, 0 /*flags*/, 0,0,0,0 /*time*/, 0 /*xflags*/, OS_CODE); - s->startpos = 10L; - /* We use 10L instead of ftell(s->file) to because ftell causes an + s->start = 10L; + /* We use 10L instead of ftell(s->file) to because ftell causes an * fflush on some systems. This version of the library doesn't use - * startpos anyway in write mode, so this initialization is not + * start anyway in write mode, so this initialization is not * necessary. */ } else { - check_header(s); /* skip the .gz header */ - s->startpos = (ftell(s->file) - s->stream.avail_in); + check_header(s); /* skip the .gz header */ + s->start = ftell(s->file) - s->stream.avail_in; } - + return (gzFile)s; } @@ -218,11 +243,11 @@ int ZEXPORT gzsetparams (file, level, strategy) /* Make room to allow flushing */ if (s->stream.avail_out == 0) { - s->stream.next_out = s->outbuf; - if (fwrite(s->outbuf, 1, Z_BUFSIZE, s->file) != Z_BUFSIZE) { - s->z_err = Z_ERRNO; - } - s->stream.avail_out = Z_BUFSIZE; + s->stream.next_out = s->outbuf; + if (fwrite(s->outbuf, 1, Z_BUFSIZE, s->file) != Z_BUFSIZE) { + s->z_err = Z_ERRNO; + } + s->stream.avail_out = Z_BUFSIZE; } return deflateParams (&(s->stream), level, strategy); @@ -238,14 +263,14 @@ local int get_byte(s) { if (s->z_eof) return EOF; if (s->stream.avail_in == 0) { - errno = 0; - s->stream.avail_in = fread(s->inbuf, 1, Z_BUFSIZE, s->file); - if (s->stream.avail_in == 0) { - s->z_eof = 1; - if (ferror(s->file)) s->z_err = Z_ERRNO; - return EOF; - } - s->stream.next_in = s->inbuf; + errno = 0; + s->stream.avail_in = fread(s->inbuf, 1, Z_BUFSIZE, s->file); + if (s->stream.avail_in == 0) { + s->z_eof = 1; + if (ferror(s->file)) s->z_err = Z_ERRNO; + return EOF; + } + s->stream.next_in = s->inbuf; } s->stream.avail_in--; return *(s->stream.next_in)++; @@ -268,43 +293,57 @@ local void check_header(s) uInt len; int c; - /* Check the gzip magic header */ - for (len = 0; len < 2; len++) { - c = get_byte(s); - if (c != gz_magic[len]) { - if (len != 0) s->stream.avail_in++, s->stream.next_in--; - if (c != EOF) { - s->stream.avail_in++, s->stream.next_in--; - s->transparent = 1; - } - s->z_err = s->stream.avail_in != 0 ? Z_OK : Z_STREAM_END; - return; - } + /* Assure two bytes in the buffer so we can peek ahead -- handle case + where first byte of header is at the end of the buffer after the last + gzip segment */ + len = s->stream.avail_in; + if (len < 2) { + if (len) s->inbuf[0] = s->stream.next_in[0]; + errno = 0; + len = fread(s->inbuf + len, 1, Z_BUFSIZE >> len, s->file); + if (len == 0 && ferror(s->file)) s->z_err = Z_ERRNO; + s->stream.avail_in += len; + s->stream.next_in = s->inbuf; + if (s->stream.avail_in < 2) { + s->transparent = s->stream.avail_in; + return; + } } + + /* Peek ahead to check the gzip magic header */ + if (s->stream.next_in[0] != gz_magic[0] || + s->stream.next_in[1] != gz_magic[1]) { + s->transparent = 1; + return; + } + s->stream.avail_in -= 2; + s->stream.next_in += 2; + + /* Check the rest of the gzip header */ method = get_byte(s); flags = get_byte(s); if (method != Z_DEFLATED || (flags & RESERVED) != 0) { - s->z_err = Z_DATA_ERROR; - return; + s->z_err = Z_DATA_ERROR; + return; } /* Discard time, xflags and OS code: */ for (len = 0; len < 6; len++) (void)get_byte(s); if ((flags & EXTRA_FIELD) != 0) { /* skip the extra field */ - len = (uInt)get_byte(s); - len += ((uInt)get_byte(s))<<8; - /* len is garbage if EOF but the loop below will quit anyway */ - while (len-- != 0 && get_byte(s) != EOF) ; + len = (uInt)get_byte(s); + len += ((uInt)get_byte(s))<<8; + /* len is garbage if EOF but the loop below will quit anyway */ + while (len-- != 0 && get_byte(s) != EOF) ; } if ((flags & ORIG_NAME) != 0) { /* skip the original file name */ - while ((c = get_byte(s)) != 0 && c != EOF) ; + while ((c = get_byte(s)) != 0 && c != EOF) ; } if ((flags & COMMENT) != 0) { /* skip the .gz file comment */ - while ((c = get_byte(s)) != 0 && c != EOF) ; + while ((c = get_byte(s)) != 0 && c != EOF) ; } if ((flags & HEAD_CRC) != 0) { /* skip the header crc */ - for (len = 0; len < 2; len++) (void)get_byte(s); + for (len = 0; len < 2; len++) (void)get_byte(s); } s->z_err = s->z_eof ? Z_DATA_ERROR : Z_OK; } @@ -323,21 +362,21 @@ local int destroy (s) TRYFREE(s->msg); if (s->stream.state != NULL) { - if (s->mode == 'w') { -#ifdef NO_DEFLATE - err = Z_STREAM_ERROR; + if (s->mode == 'w') { +#ifdef NO_GZCOMPRESS + err = Z_STREAM_ERROR; #else - err = deflateEnd(&(s->stream)); + err = deflateEnd(&(s->stream)); #endif - } else if (s->mode == 'r') { - err = inflateEnd(&(s->stream)); - } + } else if (s->mode == 'r') { + err = inflateEnd(&(s->stream)); + } } if (s->file != NULL && fclose(s->file)) { #ifdef ESPIPE - if (errno != ESPIPE) /* fclose is broken for pipes in HP/UX */ + if (errno != ESPIPE) /* fclose is broken for pipes in HP/UX */ #endif - err = Z_ERRNO; + err = Z_ERRNO; } if (s->z_err < 0) err = s->z_err; @@ -370,71 +409,82 @@ int ZEXPORT gzread (file, buf, len) s->stream.next_out = (Bytef*)buf; s->stream.avail_out = len; + if (s->stream.avail_out && s->back != EOF) { + *next_out++ = s->back; + s->stream.next_out++; + s->stream.avail_out--; + s->back = EOF; + s->out++; + if (s->last) { + s->z_err = Z_STREAM_END; + return 1; + } + } + while (s->stream.avail_out != 0) { - if (s->transparent) { - /* Copy first the lookahead bytes: */ - uInt n = s->stream.avail_in; - if (n > s->stream.avail_out) n = s->stream.avail_out; - if (n > 0) { - zmemcpy(s->stream.next_out, s->stream.next_in, n); - next_out += n; - s->stream.next_out = next_out; - s->stream.next_in += n; - s->stream.avail_out -= n; - s->stream.avail_in -= n; - } - if (s->stream.avail_out > 0) { - s->stream.avail_out -= fread(next_out, 1, s->stream.avail_out, - s->file); - } - len -= s->stream.avail_out; - s->stream.total_in += (uLong)len; - s->stream.total_out += (uLong)len; + if (s->transparent) { + /* Copy first the lookahead bytes: */ + uInt n = s->stream.avail_in; + if (n > s->stream.avail_out) n = s->stream.avail_out; + if (n > 0) { + zmemcpy(s->stream.next_out, s->stream.next_in, n); + next_out += n; + s->stream.next_out = next_out; + s->stream.next_in += n; + s->stream.avail_out -= n; + s->stream.avail_in -= n; + } + if (s->stream.avail_out > 0) { + s->stream.avail_out -= fread(next_out, 1, s->stream.avail_out, + s->file); + } + len -= s->stream.avail_out; + s->in += len; + s->out += len; if (len == 0) s->z_eof = 1; - return (int)len; - } + return (int)len; + } if (s->stream.avail_in == 0 && !s->z_eof) { errno = 0; s->stream.avail_in = fread(s->inbuf, 1, Z_BUFSIZE, s->file); if (s->stream.avail_in == 0) { s->z_eof = 1; - if (ferror(s->file)) { - s->z_err = Z_ERRNO; - break; - } + if (ferror(s->file)) { + s->z_err = Z_ERRNO; + break; + } } s->stream.next_in = s->inbuf; } + s->in += s->stream.avail_in; + s->out += s->stream.avail_out; s->z_err = inflate(&(s->stream), Z_NO_FLUSH); - - if (s->z_err == Z_STREAM_END) { - /* Check CRC and original size */ - s->crc = crc32(s->crc, start, (uInt)(s->stream.next_out - start)); - start = s->stream.next_out; - - if (getLong(s) != s->crc) { - s->z_err = Z_DATA_ERROR; - } else { - (void)getLong(s); - /* The uncompressed length returned by above getlong() may - * be different from s->stream.total_out) in case of - * concatenated .gz files. Check for such files: - */ - check_header(s); - if (s->z_err == Z_OK) { - uLong total_in = s->stream.total_in; - uLong total_out = s->stream.total_out; - - inflateReset(&(s->stream)); - s->stream.total_in = total_in; - s->stream.total_out = total_out; - s->crc = crc32(0L, Z_NULL, 0); - } - } - } - if (s->z_err != Z_OK || s->z_eof) break; + s->in -= s->stream.avail_in; + s->out -= s->stream.avail_out; + + if (s->z_err == Z_STREAM_END) { + /* Check CRC and original size */ + s->crc = crc32(s->crc, start, (uInt)(s->stream.next_out - start)); + start = s->stream.next_out; + + if (getLong(s) != s->crc) { + s->z_err = Z_DATA_ERROR; + } else { + (void)getLong(s); + /* The uncompressed length returned by above getlong() may be + * different from s->out in case of concatenated .gz files. + * Check for such files: + */ + check_header(s); + if (s->z_err == Z_OK) { + inflateReset(&(s->stream)); + s->crc = crc32(0L, Z_NULL, 0); + } + } + } + if (s->z_err != Z_OK || s->z_eof) break; } s->crc = crc32(s->crc, start, (uInt)(s->stream.next_out - start)); @@ -456,6 +506,25 @@ int ZEXPORT gzgetc(file) /* =========================================================================== + Push one byte back onto the stream. +*/ +int ZEXPORT gzungetc(c, file) + int c; + gzFile file; +{ + gz_stream *s = (gz_stream*)file; + + if (s == NULL || s->mode != 'r' || c == EOF || s->back != EOF) return EOF; + s->back = c; + s->out--; + s->last = (s->z_err == Z_STREAM_END); + if (s->last) s->z_err = Z_OK; + s->z_eof = 0; + return c; +} + + +/* =========================================================================== Reads bytes from the compressed file until len-1 characters are read, or a newline character is read and transferred to buf, or an end-of-file condition is encountered. The string is then terminated @@ -478,14 +547,14 @@ char * ZEXPORT gzgets(file, buf, len) } -#ifndef NO_DEFLATE +#ifndef NO_GZCOMPRESS /* =========================================================================== Writes the given number of uncompressed bytes into the compressed file. gzwrite returns the number of bytes actually written (0 in case of error). */ int ZEXPORT gzwrite (file, buf, len) gzFile file; - const voidp buf; + voidpc buf; unsigned len; { gz_stream *s = (gz_stream*)file; @@ -506,7 +575,11 @@ int ZEXPORT gzwrite (file, buf, len) } s->stream.avail_out = Z_BUFSIZE; } + s->in += s->stream.avail_in; + s->out += s->stream.avail_out; s->z_err = deflate(&(s->stream), Z_NO_FLUSH); + s->in -= s->stream.avail_in; + s->out -= s->stream.avail_out; if (s->z_err != Z_OK) break; } s->crc = crc32(s->crc, (const Bytef *)buf, len); @@ -514,6 +587,7 @@ int ZEXPORT gzwrite (file, buf, len) return (int)(len - s->stream.avail_in); } + /* =========================================================================== Converts, formats, and writes the args to the compressed file under control of the format string, as in fprintf. gzprintf returns the number of @@ -528,40 +602,67 @@ int ZEXPORTVA gzprintf (gzFile file, const char *format, /* args */ ...) va_list va; int len; + buf[sizeof(buf) - 1] = 0; va_start(va, format); -#ifdef HAS_vsnprintf - (void)vsnprintf(buf, sizeof(buf), format, va); -#else +#ifdef NO_vsnprintf +# ifdef HAS_vsprintf_void (void)vsprintf(buf, format, va); -#endif va_end(va); - len = strlen(buf); /* some *sprintf don't return the nb of bytes written */ - if (len <= 0) return 0; - + for (len = 0; len < sizeof(buf); len++) + if (buf[len] == 0) break; +# else + len = vsprintf(buf, format, va); + va_end(va); +# endif +#else +# ifdef HAS_vsnprintf_void + (void)vsnprintf(buf, sizeof(buf), format, va); + va_end(va); + len = strlen(buf); +# else + len = vsnprintf(buf, sizeof(buf), format, va); + va_end(va); +# endif +#endif + if (len <= 0 || len >= (int)sizeof(buf) || buf[sizeof(buf) - 1] != 0) + return 0; return gzwrite(file, buf, (unsigned)len); } #else /* not ANSI C */ int ZEXPORTVA gzprintf (file, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, - a11, a12, a13, a14, a15, a16, a17, a18, a19, a20) + a11, a12, a13, a14, a15, a16, a17, a18, a19, a20) gzFile file; const char *format; int a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, - a11, a12, a13, a14, a15, a16, a17, a18, a19, a20; + a11, a12, a13, a14, a15, a16, a17, a18, a19, a20; { char buf[Z_PRINTF_BUFSIZE]; int len; -#ifdef HAS_snprintf - snprintf(buf, sizeof(buf), format, a1, a2, a3, a4, a5, a6, a7, a8, - a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20); -#else + buf[sizeof(buf) - 1] = 0; +#ifdef NO_snprintf +# ifdef HAS_sprintf_void sprintf(buf, format, a1, a2, a3, a4, a5, a6, a7, a8, - a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20); + a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20); + for (len = 0; len < sizeof(buf); len++) + if (buf[len] == 0) break; +# else + len = sprintf(buf, format, a1, a2, a3, a4, a5, a6, a7, a8, + a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20); +# endif +#else +# ifdef HAS_snprintf_void + snprintf(buf, sizeof(buf), format, a1, a2, a3, a4, a5, a6, a7, a8, + a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20); + len = strlen(buf); +# else + len = snprintf(buf, sizeof(buf), format, a1, a2, a3, a4, a5, a6, a7, a8, + a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20); +# endif #endif - len = strlen(buf); /* old sprintf doesn't return the nb of bytes written */ - if (len <= 0) return 0; - + if (len <= 0 || len >= sizeof(buf) || buf[sizeof(buf) - 1] != 0) + return 0; return gzwrite(file, buf, len); } #endif @@ -621,16 +722,18 @@ local int do_flush (file, flush) s->stream.avail_out = Z_BUFSIZE; } if (done) break; + s->out += s->stream.avail_out; s->z_err = deflate(&(s->stream), flush); + s->out -= s->stream.avail_out; - /* Ignore the second of two consecutive flushes: */ - if (len == 0 && s->z_err == Z_BUF_ERROR) s->z_err = Z_OK; + /* Ignore the second of two consecutive flushes: */ + if (len == 0 && s->z_err == Z_BUF_ERROR) s->z_err = Z_OK; /* deflate has finished flushing only when it hasn't used up - * all the available space in the output buffer: + * all the available space in the output buffer: */ done = (s->stream.avail_out != 0 || s->z_err == Z_STREAM_END); - + if (s->z_err != Z_OK && s->z_err != Z_STREAM_END) break; } return s->z_err == Z_STREAM_END ? Z_OK : s->z_err; @@ -647,7 +750,7 @@ int ZEXPORT gzflush (file, flush) fflush(s->file); return s->z_err == Z_STREAM_END ? Z_OK : s->z_err; } -#endif /* NO_DEFLATE */ +#endif /* NO_GZCOMPRESS */ /* =========================================================================== Sets the starting position for the next gzread or gzwrite on the given @@ -665,99 +768,105 @@ z_off_t ZEXPORT gzseek (file, offset, whence) gz_stream *s = (gz_stream*)file; if (s == NULL || whence == SEEK_END || - s->z_err == Z_ERRNO || s->z_err == Z_DATA_ERROR) { - return -1L; + s->z_err == Z_ERRNO || s->z_err == Z_DATA_ERROR) { + return -1L; } - + if (s->mode == 'w') { -#ifdef NO_DEFLATE - return -1L; +#ifdef NO_GZCOMPRESS + return -1L; #else - if (whence == SEEK_SET) { - offset -= s->stream.total_in; - } - if (offset < 0) return -1L; - - /* At this point, offset is the number of zero bytes to write. */ - if (s->inbuf == Z_NULL) { - s->inbuf = (Byte*)ALLOC(Z_BUFSIZE); /* for seeking */ - zmemzero(s->inbuf, Z_BUFSIZE); - } - while (offset > 0) { - uInt size = Z_BUFSIZE; - if (offset < Z_BUFSIZE) size = (uInt)offset; - - size = gzwrite(file, s->inbuf, size); - if (size == 0) return -1L; - - offset -= size; - } - return (z_off_t)s->stream.total_in; + if (whence == SEEK_SET) { + offset -= s->in; + } + if (offset < 0) return -1L; + + /* At this point, offset is the number of zero bytes to write. */ + if (s->inbuf == Z_NULL) { + s->inbuf = (Byte*)ALLOC(Z_BUFSIZE); /* for seeking */ + if (s->inbuf == Z_NULL) return -1L; + zmemzero(s->inbuf, Z_BUFSIZE); + } + while (offset > 0) { + uInt size = Z_BUFSIZE; + if (offset < Z_BUFSIZE) size = (uInt)offset; + + size = gzwrite(file, s->inbuf, size); + if (size == 0) return -1L; + + offset -= size; + } + return s->in; #endif } /* Rest of function is for reading only */ /* compute absolute position */ if (whence == SEEK_CUR) { - offset += s->stream.total_out; + offset += s->out; } if (offset < 0) return -1L; if (s->transparent) { - /* map to fseek */ - s->stream.avail_in = 0; - s->stream.next_in = s->inbuf; + /* map to fseek */ + s->back = EOF; + s->stream.avail_in = 0; + s->stream.next_in = s->inbuf; if (fseek(s->file, offset, SEEK_SET) < 0) return -1L; - s->stream.total_in = s->stream.total_out = (uLong)offset; - return offset; + s->in = s->out = offset; + return offset; } /* For a negative seek, rewind and use positive seek */ - if ((uLong)offset >= s->stream.total_out) { - offset -= s->stream.total_out; + if (offset >= s->out) { + offset -= s->out; } else if (gzrewind(file) < 0) { - return -1L; + return -1L; } /* offset is now the number of bytes to skip. */ if (offset != 0 && s->outbuf == Z_NULL) { - s->outbuf = (Byte*)ALLOC(Z_BUFSIZE); + s->outbuf = (Byte*)ALLOC(Z_BUFSIZE); + if (s->outbuf == Z_NULL) return -1L; + } + if (offset && s->back != EOF) { + s->back = EOF; + s->out++; + offset--; + if (s->last) s->z_err = Z_STREAM_END; } while (offset > 0) { - int size = Z_BUFSIZE; - if (offset < Z_BUFSIZE) size = (int)offset; + int size = Z_BUFSIZE; + if (offset < Z_BUFSIZE) size = (int)offset; - size = gzread(file, s->outbuf, (uInt)size); - if (size <= 0) return -1L; - offset -= size; + size = gzread(file, s->outbuf, (uInt)size); + if (size <= 0) return -1L; + offset -= size; } - return (z_off_t)s->stream.total_out; + return s->out; } /* =========================================================================== - Rewinds input file. + Rewinds input file. */ int ZEXPORT gzrewind (file) gzFile file; { gz_stream *s = (gz_stream*)file; - + if (s == NULL || s->mode != 'r') return -1; s->z_err = Z_OK; s->z_eof = 0; + s->back = EOF; s->stream.avail_in = 0; s->stream.next_in = s->inbuf; s->crc = crc32(0L, Z_NULL, 0); - - if (s->startpos == 0) { /* not a compressed file */ - rewind(s->file); - return 0; - } - - (void) inflateReset(&s->stream); - return fseek(s->file, s->startpos, SEEK_SET); + if (!s->transparent) (void)inflateReset(&s->stream); + s->in = 0; + s->out = 0; + return fseek(s->file, s->start, SEEK_SET); } /* =========================================================================== @@ -779,8 +888,14 @@ int ZEXPORT gzeof (file) gzFile file; { gz_stream *s = (gz_stream*)file; - - return (s == NULL || s->mode != 'r') ? 0 : s->z_eof; + + /* With concatenated compressed files that can have embedded + * crc trailers, z_eof is no longer the only/best indicator of EOF + * on a gz_stream. Handle end-of-stream error explicitly here. + */ + if (s == NULL || s->mode != 'r') return 0; + if (s->z_eof) return 1; + return s->z_err == Z_STREAM_END; } /* =========================================================================== @@ -828,14 +943,14 @@ int ZEXPORT gzclose (file) if (s == NULL) return Z_STREAM_ERROR; if (s->mode == 'w') { -#ifdef NO_DEFLATE - return Z_STREAM_ERROR; +#ifdef NO_GZCOMPRESS + return Z_STREAM_ERROR; #else err = do_flush (file, Z_FINISH); if (err != Z_OK) return destroy((gz_stream*)file); putLong (s->file, s->crc); - putLong (s->file, s->stream.total_in); + putLong (s->file, (uLong)(s->in & 0xffffffff)); #endif } return destroy((gz_stream*)file); @@ -848,7 +963,7 @@ int ZEXPORT gzclose (file) errnum is set to Z_ERRNO and the application may consult errno to get the exact error code. */ -const char* ZEXPORT gzerror (file, errnum) +const char * ZEXPORT gzerror (file, errnum) gzFile file; int *errnum; { @@ -862,14 +977,29 @@ const char* ZEXPORT gzerror (file, errnum) *errnum = s->z_err; if (*errnum == Z_OK) return (const char*)""; - m = (char*)(*errnum == Z_ERRNO ? zstrerror(errno) : s->stream.msg); + m = (char*)(*errnum == Z_ERRNO ? zstrerror(errno) : s->stream.msg); if (m == NULL || *m == '\0') m = (char*)ERR_MSG(s->z_err); TRYFREE(s->msg); s->msg = (char*)ALLOC(strlen(s->path) + strlen(m) + 3); + if (s->msg == Z_NULL) return (const char*)ERR_MSG(Z_MEM_ERROR); strcpy(s->msg, s->path); strcat(s->msg, ": "); strcat(s->msg, m); return (const char*)s->msg; } + +/* =========================================================================== + Clear the error and end-of-file flags, and do the same for the real file. +*/ +void ZEXPORT gzclearerr (file) + gzFile file; +{ + gz_stream *s = (gz_stream*)file; + + if (s == NULL) return; + if (s->z_err != Z_STREAM_END) s->z_err = Z_OK; + s->z_eof = 0; + clearerr(s->file); +} |