Updated internal Zlib to latest version (1.2.5).

git-svn-id: svn://svn.code.sf.net/p/stella/code/trunk@2067 8b62c5a3-ac7e-4cc8-8f21-d9a121418aba
This commit is contained in:
stephena 2010-07-10 20:53:22 +00:00
parent 3e7662c478
commit 113d7af8c2
30 changed files with 3672 additions and 2136 deletions

View File

@ -1,154 +0,0 @@
# Makefile for zlib
# Copyright (C) 1995-2005 Jean-loup Gailly.
# For conditions of distribution and use, see copyright notice in zlib.h
# To compile and test, type:
# ./configure; make test
# The call of configure is optional if you don't have special requirements
# If you wish to build zlib as a shared library, use: ./configure -s
# To use the asm code, type:
# cp contrib/asm?86/match.S ./match.S
# make LOC=-DASMV OBJA=match.o
# To install /usr/local/lib/libz.* and /usr/local/include/zlib.h, type:
# make install
# To install in $HOME instead of /usr/local, use:
# make install prefix=$HOME
CC=g++
CFLAGS=-O2 -pipe
#CFLAGS=-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7
#CFLAGS=-g -DDEBUG
#CFLAGS=-O3 -Wall -Wwrite-strings -Wpointer-arith -Wconversion \
# -Wstrict-prototypes -Wmissing-prototypes
LDFLAGS=libz.a
LDSHARED=$(CC)
CPP=$(CC) -E
LIBS=libz.a
SHAREDLIB=libz.so
SHAREDLIBV=libz.so.1.2.3
SHAREDLIBM=libz.so.1
AR=ar rc
RANLIB=ranlib
TAR=tar
SHELL=/bin/sh
EXE=
prefix = /usr/local
exec_prefix = ${prefix}
libdir = ${exec_prefix}/lib
includedir = ${prefix}/include
mandir = ${prefix}/share/man
man3dir = ${mandir}/man3
OBJS = adler32.o compress.o crc32.o gzio.o uncompr.o deflate.o trees.o \
zutil.o inflate.o infback.o inftrees.o inffast.o
OBJA =
# to use the asm code: make OBJA=match.o
TEST_OBJS = example.o
all: example$(EXE)
check: test
test: all
@LD_LIBRARY_PATH=.:$(LD_LIBRARY_PATH) ; export LD_LIBRARY_PATH; \
echo hello world | ./minigzip | ./minigzip -d || \
echo ' *** minigzip test FAILED ***' ; \
if ./example; then \
echo ' *** zlib test OK ***'; \
else \
echo ' *** zlib test FAILED ***'; \
fi
libz.a: $(OBJS) $(OBJA)
$(AR) $@ $(OBJS) $(OBJA)
-@ ($(RANLIB) $@ || true) >/dev/null 2>&1
match.o: match.S
$(CPP) match.S > _match.s
$(CC) -c _match.s
mv _match.o match.o
rm -f _match.s
$(SHAREDLIBV): $(OBJS)
$(LDSHARED) -o $@ $(OBJS)
rm -f $(SHAREDLIB) $(SHAREDLIBM)
ln -s $@ $(SHAREDLIB)
ln -s $@ $(SHAREDLIBM)
example$(EXE): example.o $(LIBS)
$(CC) $(CFLAGS) -o $@ example.o $(LDFLAGS)
minigzip$(EXE): minigzip.o $(LIBS)
$(CC) $(CFLAGS) -o $@ minigzip.o $(LDFLAGS)
install: $(LIBS)
-@if [ ! -d $(exec_prefix) ]; then mkdir -p $(exec_prefix); fi
-@if [ ! -d $(includedir) ]; then mkdir -p $(includedir); fi
-@if [ ! -d $(libdir) ]; then mkdir -p $(libdir); fi
-@if [ ! -d $(man3dir) ]; then mkdir -p $(man3dir); fi
cp zlib.h zconf.h $(includedir)
chmod 644 $(includedir)/zlib.h $(includedir)/zconf.h
cp $(LIBS) $(libdir)
cd $(libdir); chmod 755 $(LIBS)
-@(cd $(libdir); $(RANLIB) libz.a || true) >/dev/null 2>&1
cd $(libdir); if test -f $(SHAREDLIBV); then \
rm -f $(SHAREDLIB) $(SHAREDLIBM); \
ln -s $(SHAREDLIBV) $(SHAREDLIB); \
ln -s $(SHAREDLIBV) $(SHAREDLIBM); \
(ldconfig || true) >/dev/null 2>&1; \
fi
cp zlib.3 $(man3dir)
chmod 644 $(man3dir)/zlib.3
# The ranlib in install is needed on NeXTSTEP which checks file times
# ldconfig is for Linux
uninstall:
cd $(includedir); \
cd $(libdir); rm -f libz.a; \
if test -f $(SHAREDLIBV); then \
rm -f $(SHAREDLIBV) $(SHAREDLIB) $(SHAREDLIBM); \
fi
cd $(man3dir); rm -f zlib.3
mostlyclean: clean
clean:
rm -f *.o *~ example$(EXE) minigzip$(EXE) \
libz.* foo.gz so_locations \
_match.s maketree contrib/infback9/*.o
maintainer-clean: distclean
distclean: clean
cp -p Makefile.in Makefile
cp -p zconf.in.h zconf.h
rm -f .DS_Store
tags:
etags *.[ch]
depend:
makedepend -- $(CFLAGS) -- *.[ch]
# DO NOT DELETE THIS LINE -- make depend depends on it.
adler32.o: zlib.h zconf.h
compress.o: zlib.h zconf.h
crc32.o: crc32.h zlib.h zconf.h
deflate.o: deflate.h zutil.h zlib.h zconf.h
example.o: zlib.h zconf.h
gzio.o: zutil.h zlib.h zconf.h
inffast.o: zutil.h zlib.h zconf.h inftrees.h inflate.h inffast.h
inflate.o: zutil.h zlib.h zconf.h inftrees.h inflate.h inffast.h
infback.o: zutil.h zlib.h zconf.h inftrees.h inflate.h inffast.h
inftrees.o: zutil.h zlib.h zconf.h inftrees.h
minigzip.o: zlib.h zconf.h
trees.o: deflate.h zutil.h zlib.h zconf.h trees.h
uncompr.o: zlib.h zconf.h
zutil.o: zutil.h zlib.h zconf.h

View File

@ -1,11 +1,10 @@
ZLIB DATA COMPRESSION LIBRARY ZLIB DATA COMPRESSION LIBRARY
zlib 1.2.3 is a general purpose data compression library. All the code is zlib 1.2.5 is a general purpose data compression library. All the code is
thread safe. The data format used by the zlib library is described by RFCs thread safe. The data format used by the zlib library is described by RFCs
(Request for Comments) 1950 to 1952 in the files (Request for Comments) 1950 to 1952 in the files
http://www.ietf.org/rfc/rfc1950.txt (zlib format), rfc1951.txt (deflate format) http://www.ietf.org/rfc/rfc1950.txt (zlib format), rfc1951.txt (deflate format)
and rfc1952.txt (gzip format). These documents are also available in other and rfc1952.txt (gzip format).
formats from ftp://ftp.uu.net/graphics/png/documents/zlib/zdoc-index.html
All functions of the compression library are documented in the file zlib.h All functions of the compression library are documented in the file zlib.h
(volunteer to write man pages welcome, contact zlib@gzip.org). A usage example (volunteer to write man pages welcome, contact zlib@gzip.org). A usage example
@ -15,42 +14,39 @@ compression library itself is composed of all source files except example.c and
minigzip.c. minigzip.c.
To compile all files and run the test program, follow the instructions given at To compile all files and run the test program, follow the instructions given at
the top of Makefile. In short "make test; make install" should work for most the top of Makefile.in. In short "./configure; make test", and if that goes
machines. For Unix: "./configure; make test; make install". For MSDOS, use one well, "make install" should work for most flavors of Unix. For Windows, use one
of the special makefiles such as Makefile.msc. For VMS, use make_vms.com. of the special makefiles in win32/ or contrib/vstudio/ . For VMS, use
make_vms.com.
Questions about zlib should be sent to <zlib@gzip.org>, or to Gilles Vollant Questions about zlib should be sent to <zlib@gzip.org>, or to Gilles Vollant
<info@winimage.com> for the Windows DLL version. The zlib home page is <info@winimage.com> for the Windows DLL version. The zlib home page is
http://www.zlib.org or http://www.gzip.org/zlib/ Before reporting a problem, http://zlib.net/ . Before reporting a problem, please check this site to
please check this site to verify that you have the latest version of zlib; verify that you have the latest version of zlib; otherwise get the latest
otherwise get the latest version and check whether the problem still exists or version and check whether the problem still exists or not.
not.
PLEASE read the zlib FAQ http://www.gzip.org/zlib/zlib_faq.html before asking PLEASE read the zlib FAQ http://zlib.net/zlib_faq.html before asking for help.
for help.
Mark Nelson <markn@ieee.org> wrote an article about zlib for the Jan. 1997 Mark Nelson <markn@ieee.org> wrote an article about zlib for the Jan. 1997
issue of Dr. Dobb's Journal; a copy of the article is available in issue of Dr. Dobb's Journal; a copy of the article is available at
http://dogma.net/markn/articles/zlibtool/zlibtool.htm http://marknelson.us/1997/01/01/zlib-engine/ .
The changes made in version 1.2.3 are documented in the file ChangeLog. The changes made in version 1.2.5 are documented in the file ChangeLog.
Unsupported third party contributions are provided in directory "contrib". Unsupported third party contributions are provided in directory contrib/ .
A Java implementation of zlib is available in the Java Development Kit zlib is available in Java using the java.util.zip package, documented at
http://java.sun.com/j2se/1.4.2/docs/api/java/util/zip/package-summary.html http://java.sun.com/developer/technicalArticles/Programming/compression/ .
See the zlib home page http://www.zlib.org for details.
A Perl interface to zlib written by Paul Marquess <pmqs@cpan.org> is in the A Perl interface to zlib written by Paul Marquess <pmqs@cpan.org> is available
CPAN (Comprehensive Perl Archive Network) sites at CPAN (Comprehensive Perl Archive Network) sites, including
http://www.cpan.org/modules/by-module/Compress/ http://search.cpan.org/~pmqs/IO-Compress-Zlib/ .
A Python interface to zlib written by A.M. Kuchling <amk@amk.ca> is A Python interface to zlib written by A.M. Kuchling <amk@amk.ca> is
available in Python 1.5 and later versions, see available in Python 1.5 and later versions, see
http://www.python.org/doc/lib/module-zlib.html http://www.python.org/doc/lib/module-zlib.html .
A zlib binding for TCL written by Andreas Kupries <a.kupries@westend.com> is zlib is built into tcl: http://wiki.tcl.tk/4610 .
availlable at http://www.oche.de/~akupries/soft/trf/trf_zip.html
An experimental package to read and write files in .zip format, written on top An experimental package to read and write files in .zip format, written on top
of zlib by Gilles Vollant <info@winimage.com>, is available in the of zlib by Gilles Vollant <info@winimage.com>, is available in the
@ -74,25 +70,21 @@ Notes for some targets:
- zlib doesn't work on HP-UX 9.05 with some versions of /bin/cc. It works with - zlib doesn't work on HP-UX 9.05 with some versions of /bin/cc. It works with
other compilers. Use "make test" to check your compiler. other compilers. Use "make test" to check your compiler.
- gzdopen is not supported on RISCOS, BEOS and by some Mac compilers. - gzdopen is not supported on RISCOS or BEOS.
- For PalmOs, see http://palmzlib.sourceforge.net/ - For PalmOs, see http://palmzlib.sourceforge.net/
- When building a shared, i.e. dynamic library on Mac OS X, the library must be
installed before testing (do "make install" before "make test"), since the
library location is specified in the library.
Acknowledgments: Acknowledgments:
The deflate format used by zlib was defined by Phil Katz. The deflate The deflate format used by zlib was defined by Phil Katz. The deflate and
and zlib specifications were written by L. Peter Deutsch. Thanks to all the zlib specifications were written by L. Peter Deutsch. Thanks to all the
people who reported problems and suggested various improvements in zlib; people who reported problems and suggested various improvements in zlib; they
they are too numerous to cite here. are too numerous to cite here.
Copyright notice: Copyright notice:
(C) 1995-2004 Jean-loup Gailly and Mark Adler (C) 1995-2010 Jean-loup Gailly and Mark Adler
This software is provided 'as-is', without any express or implied This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages warranty. In no event will the authors be held liable for any damages
@ -113,13 +105,11 @@ Copyright notice:
Jean-loup Gailly Mark Adler Jean-loup Gailly Mark Adler
jloup@gzip.org madler@alumni.caltech.edu jloup@gzip.org madler@alumni.caltech.edu
If you use the zlib library in a product, we would appreciate *not* If you use the zlib library in a product, we would appreciate *not* receiving
receiving lengthy legal documents to sign. The sources are provided lengthy legal documents to sign. The sources are provided for free but without
for free but without warranty of any kind. The library has been warranty of any kind. The library has been entirely written by Jean-loup
entirely written by Jean-loup Gailly and Mark Adler; it does not Gailly and Mark Adler; it does not include third-party code.
include third-party code.
If you redistribute modified sources, we would appreciate that you include If you redistribute modified sources, we would appreciate that you include in
in the file ChangeLog history information documenting your changes. Please the file ChangeLog history information documenting your changes. Please read
read the FAQ for more information on the distribution of modified source the FAQ for more information on the distribution of modified source versions.
versions.

View File

@ -1,12 +1,15 @@
/* adler32.c -- compute the Adler-32 checksum of a data stream /* adler32.c -- compute the Adler-32 checksum of a data stream
* Copyright (C) 1995-2004 Mark Adler * Copyright (C) 1995-2007 Mark Adler
* For conditions of distribution and use, see copyright notice in zlib.h * For conditions of distribution and use, see copyright notice in zlib.h
*/ */
/* @(#) $Id$ */ /* @(#) $Id$ */
#define ZLIB_INTERNAL #include "zutil.h"
#include "zlib.h"
#define local static
local uLong adler32_combine_(uLong adler1, uLong adler2, z_off64_t len2);
#define BASE 65521UL /* largest prime smaller than 65536 */ #define BASE 65521UL /* largest prime smaller than 65536 */
#define NMAX 5552 #define NMAX 5552
@ -122,7 +125,7 @@ uLong ZEXPORT adler32(uLong adler, const Bytef *buf, uInt len)
} }
/* ========================================================================= */ /* ========================================================================= */
uLong ZEXPORT adler32_combine(uLong adler1, uLong adler2, z_off_t len2) local uLong adler32_combine_(uLong adler1, uLong adler2, z_off64_t len2)
{ {
unsigned long sum1; unsigned long sum1;
unsigned long sum2; unsigned long sum2;
@ -135,9 +138,20 @@ uLong ZEXPORT adler32_combine(uLong adler1, uLong adler2, z_off_t len2)
MOD(sum2); MOD(sum2);
sum1 += (adler2 & 0xffff) + BASE - 1; sum1 += (adler2 & 0xffff) + BASE - 1;
sum2 += ((adler1 >> 16) & 0xffff) + ((adler2 >> 16) & 0xffff) + BASE - rem; sum2 += ((adler1 >> 16) & 0xffff) + ((adler2 >> 16) & 0xffff) + BASE - rem;
if (sum1 > BASE) sum1 -= BASE; if (sum1 >= BASE) sum1 -= BASE;
if (sum1 > BASE) sum1 -= BASE; if (sum1 >= BASE) sum1 -= BASE;
if (sum2 > (BASE << 1)) sum2 -= (BASE << 1); if (sum2 >= (BASE << 1)) sum2 -= (BASE << 1);
if (sum2 > BASE) sum2 -= BASE; if (sum2 >= BASE) sum2 -= BASE;
return sum1 | (sum2 << 16); return sum1 | (sum2 << 16);
} }
/* ========================================================================= */
uLong ZEXPORT adler32_combine(uLong adler1, uLong adler2, z_off_t len2)
{
return adler32_combine_(adler1, adler2, len2);
}
uLong ZEXPORT adler32_combine64(uLong adler1, uLong adler2, z_off_t len2)
{
return adler32_combine_(adler1, adler2, len2);
}

View File

@ -1,5 +1,5 @@
/* compress.c -- compress a memory buffer /* compress.c -- compress a memory buffer
* Copyright (C) 1995-2003 Jean-loup Gailly. * Copyright (C) 1995-2005 Jean-loup Gailly.
* For conditions of distribution and use, see copyright notice in zlib.h * For conditions of distribution and use, see copyright notice in zlib.h
*/ */
@ -19,8 +19,9 @@
memory, Z_BUF_ERROR if there was not enough room in the output buffer, memory, Z_BUF_ERROR if there was not enough room in the output buffer,
Z_STREAM_ERROR if the level parameter is invalid. Z_STREAM_ERROR if the level parameter is invalid.
*/ */
int ZEXPORT compress2 (Bytef *dest, uLongf *destLen, const Bytef *source, int ZEXPORT compress2 (Bytef *dest, uLongf *destLen,
uLong sourceLen, int level) const Bytef *source, uLong sourceLen,
int level)
{ {
z_stream stream; z_stream stream;
int err; int err;
@ -67,5 +68,6 @@ int ZEXPORT compress (Bytef *dest, uLongf *destLen,
*/ */
uLong ZEXPORT compressBound (uLong sourceLen) uLong ZEXPORT compressBound (uLong sourceLen)
{ {
return sourceLen + (sourceLen >> 12) + (sourceLen >> 14) + 11; return sourceLen + (sourceLen >> 12) + (sourceLen >> 14) +
(sourceLen >> 25) + 13;
} }

View File

@ -1,5 +1,5 @@
/* crc32.c -- compute the CRC-32 of a data stream /* crc32.c -- compute the CRC-32 of a data stream
* Copyright (C) 1995-2005 Mark Adler * Copyright (C) 1995-2006, 2010 Mark Adler
* For conditions of distribution and use, see copyright notice in zlib.h * For conditions of distribution and use, see copyright notice in zlib.h
* *
* Thanks to Rodney Brown <rbrown64@csc.com.au> for his contribution of faster * Thanks to Rodney Brown <rbrown64@csc.com.au> for his contribution of faster
@ -53,7 +53,7 @@
/* Definitions for doing the crc four data bytes at a time. */ /* Definitions for doing the crc four data bytes at a time. */
#ifdef BYFOUR #ifdef BYFOUR
# define REV(w) (((w)>>24)+(((w)>>8)&0xff00)+ \ # define REV(w) ((((w)>>24)&0xff)+(((w)>>8)&0xff00)+ \
(((w)&0xff00)<<8)+(((w)&0xff)<<24)) (((w)&0xff00)<<8)+(((w)&0xff)<<24))
local unsigned long crc32_little OF((unsigned long, local unsigned long crc32_little OF((unsigned long,
const unsigned char FAR *, unsigned)); const unsigned char FAR *, unsigned));
@ -68,6 +68,8 @@
local unsigned long gf2_matrix_times OF((unsigned long *mat, local unsigned long gf2_matrix_times OF((unsigned long *mat,
unsigned long vec)); unsigned long vec));
local void gf2_matrix_square OF((unsigned long *square, unsigned long *mat)); local void gf2_matrix_square OF((unsigned long *square, unsigned long *mat));
local uLong crc32_combine_(uLong crc1, uLong crc2, z_off64_t len2);
#ifdef DYNAMIC_CRC_TABLE #ifdef DYNAMIC_CRC_TABLE
@ -180,7 +182,9 @@ local void make_crc_table()
} }
#ifdef MAKECRCH #ifdef MAKECRCH
local void write_table(FILE *out, const unsigned long FAR *table) local void write_table(out, table)
FILE *out;
const unsigned long FAR *table;
{ {
int n; int n;
@ -214,7 +218,7 @@ const unsigned long FAR * ZEXPORT get_crc_table()
#define DO8 DO1; DO1; DO1; DO1; DO1; DO1; DO1; DO1 #define DO8 DO1; DO1; DO1; DO1; DO1; DO1; DO1; DO1
/* ========================================================================= */ /* ========================================================================= */
unsigned long ZEXPORT crc32(unsigned long crc, const unsigned char FAR *buf, unsigned len) uLong ZEXPORT crc32 (uLong crc, const Bytef *buf, uInt len)
{ {
if (buf == Z_NULL) return 0UL; if (buf == Z_NULL) return 0UL;
@ -254,7 +258,8 @@ unsigned long ZEXPORT crc32(unsigned long crc, const unsigned char FAR *buf, uns
#define DOLIT32 DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4 #define DOLIT32 DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4
/* ========================================================================= */ /* ========================================================================= */
local unsigned long crc32_little(unsigned long crc, const unsigned char FAR *buf, unsigned len) local unsigned long crc32_little(unsigned long crc,
const unsigned char FAR *buf, unsigned len)
{ {
register u4 c; register u4 c;
register const u4 FAR *buf4; register const u4 FAR *buf4;
@ -291,7 +296,8 @@ local unsigned long crc32_little(unsigned long crc, const unsigned char FAR *buf
#define DOBIG32 DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4 #define DOBIG32 DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4
/* ========================================================================= */ /* ========================================================================= */
local unsigned long crc32_big(unsigned long crc, const unsigned char FAR *buf, unsigned len) local unsigned long crc32_big(unsigned long crc,
const unsigned char FAR *buf, unsigned len)
{ {
register u4 c; register u4 c;
register const u4 FAR *buf4; register const u4 FAR *buf4;
@ -352,19 +358,19 @@ local void gf2_matrix_square(unsigned long *square, unsigned long *mat)
} }
/* ========================================================================= */ /* ========================================================================= */
uLong ZEXPORT crc32_combine(uLong crc1, uLong crc2, z_off_t len2) local uLong crc32_combine_(uLong crc1, uLong crc2, z_off64_t len2)
{ {
int n; int n;
unsigned long row; unsigned long row;
unsigned long even[GF2_DIM]; /* even-power-of-two zeros operator */ unsigned long even[GF2_DIM]; /* even-power-of-two zeros operator */
unsigned long odd[GF2_DIM]; /* odd-power-of-two zeros operator */ unsigned long odd[GF2_DIM]; /* odd-power-of-two zeros operator */
/* degenerate case */ /* degenerate case (also disallow negative lengths) */
if (len2 == 0) if (len2 <= 0)
return crc1; return crc1;
/* put operator for one zero bit in odd */ /* put operator for one zero bit in odd */
odd[0] = 0xedb88320L; /* CRC-32 polynomial */ odd[0] = 0xedb88320UL; /* CRC-32 polynomial */
row = 1; row = 1;
for (n = 1; n < GF2_DIM; n++) { for (n = 1; n < GF2_DIM; n++) {
odd[n] = row; odd[n] = row;
@ -403,3 +409,14 @@ uLong ZEXPORT crc32_combine(uLong crc1, uLong crc2, z_off_t len2)
crc1 ^= crc2; crc1 ^= crc2;
return crc1; return crc1;
} }
/* ========================================================================= */
uLong ZEXPORT crc32_combine(uLong crc1, uLong crc2, z_off_t len2)
{
return crc32_combine_(crc1, crc2, len2);
}
uLong ZEXPORT crc32_combine64(uLong crc1, uLong crc2, z_off_t len2)
{
return crc32_combine_(crc1, crc2, len2);
}

View File

@ -1,5 +1,5 @@
/* deflate.c -- compress data using the deflation algorithm /* deflate.c -- compress data using the deflation algorithm
* Copyright (C) 1995-2005 Jean-loup Gailly. * Copyright (C) 1995-2010 Jean-loup Gailly and Mark Adler
* For conditions of distribution and use, see copyright notice in zlib.h * For conditions of distribution and use, see copyright notice in zlib.h
*/ */
@ -52,7 +52,7 @@
#include "deflate.h" #include "deflate.h"
const char deflate_copyright[] = const char deflate_copyright[] =
" deflate 1.2.3 Copyright 1995-2005 Jean-loup Gailly "; " deflate 1.2.5 Copyright 1995-2010 Jean-loup Gailly and Mark Adler ";
/* /*
If you use the zlib library in a product, an acknowledgment is welcome If you use the zlib library in a product, an acknowledgment is welcome
in the documentation of your product. If for some reason you cannot in the documentation of your product. If for some reason you cannot
@ -79,19 +79,18 @@ local block_state deflate_fast OF((deflate_state *s, int flush));
#ifndef FASTEST #ifndef FASTEST
local block_state deflate_slow OF((deflate_state *s, int flush)); local block_state deflate_slow OF((deflate_state *s, int flush));
#endif #endif
local block_state deflate_rle OF((deflate_state *s, int flush));
local block_state deflate_huff OF((deflate_state *s, int flush));
local void lm_init OF((deflate_state *s)); local void lm_init OF((deflate_state *s));
local void putShortMSB OF((deflate_state *s, uInt b)); local void putShortMSB OF((deflate_state *s, uInt b));
local void flush_pending OF((z_streamp strm)); local void flush_pending OF((z_streamp strm));
local int read_buf OF((z_streamp strm, Bytef *buf, unsigned size)); local int read_buf OF((z_streamp strm, Bytef *buf, unsigned size));
#ifndef FASTEST
#ifdef ASMV #ifdef ASMV
void match_init OF((void)); /* asm code initialization */ void match_init OF((void)); /* asm code initialization */
uInt longest_match OF((deflate_state *s, IPos cur_match)); uInt longest_match OF((deflate_state *s, IPos cur_match));
#else #else
local uInt longest_match OF((deflate_state *s, IPos cur_match)); local uInt longest_match OF((deflate_state *s, IPos cur_match));
#endif #endif
#endif
local uInt longest_match_fast OF((deflate_state *s, IPos cur_match));
#ifdef DEBUG #ifdef DEBUG
local void check_match OF((deflate_state *s, IPos start, IPos match, local void check_match OF((deflate_state *s, IPos start, IPos match,
@ -110,11 +109,6 @@ local void check_match OF((deflate_state *s, IPos start, IPos match,
#endif #endif
/* Matches of length 3 are discarded if their distance exceeds TOO_FAR */ /* Matches of length 3 are discarded if their distance exceeds TOO_FAR */
#define MIN_LOOKAHEAD (MAX_MATCH+MIN_MATCH+1)
/* Minimum amount of lookahead, except at the end of the input file.
* See deflate.c for comments about the MIN_MATCH+1.
*/
/* Values for max_lazy_match, good_match and max_chain_length, depending on /* Values for max_lazy_match, good_match and max_chain_length, depending on
* the desired pack level (0..9). The values given below have been tuned to * the desired pack level (0..9). The values given below have been tuned to
* exclude worst case performance for pathological files. Better values may be * exclude worst case performance for pathological files. Better values may be
@ -201,7 +195,8 @@ struct static_tree_desc_s {int dummy;}; /* for buggy compilers */
zmemzero((Bytef *)s->head, (unsigned)(s->hash_size-1)*sizeof(*s->head)); zmemzero((Bytef *)s->head, (unsigned)(s->hash_size-1)*sizeof(*s->head));
/* ========================================================================= */ /* ========================================================================= */
int ZEXPORT deflateInit_(z_streamp strm, int level, const char *version, int stream_size) int ZEXPORT deflateInit_(z_streamp strm, int level,
const char *version, int stream_size)
{ {
return deflateInit2_(strm, level, Z_DEFLATED, MAX_WBITS, DEF_MEM_LEVEL, return deflateInit2_(strm, level, Z_DEFLATED, MAX_WBITS, DEF_MEM_LEVEL,
Z_DEFAULT_STRATEGY, version, stream_size); Z_DEFAULT_STRATEGY, version, stream_size);
@ -209,8 +204,10 @@ int ZEXPORT deflateInit_(z_streamp strm, int level, const char *version, int str
} }
/* ========================================================================= */ /* ========================================================================= */
int ZEXPORT deflateInit2_(z_streamp strm, int level, int method, int windowBits, int ZEXPORT deflateInit2_(z_streamp strm, int level, int method,
int memLevel, int strategy, const char *version, int stream_size) int windowBits, int memLevel,
int strategy, const char *version,
int stream_size)
{ {
deflate_state *s; deflate_state *s;
int wrap = 1; int wrap = 1;
@ -276,6 +273,8 @@ int ZEXPORT deflateInit2_(z_streamp strm, int level, int method, int windowBits,
s->prev = (Posf *) ZALLOC(strm, s->w_size, sizeof(Pos)); s->prev = (Posf *) ZALLOC(strm, s->w_size, sizeof(Pos));
s->head = (Posf *) ZALLOC(strm, s->hash_size, sizeof(Pos)); s->head = (Posf *) ZALLOC(strm, s->hash_size, sizeof(Pos));
s->high_water = 0; /* nothing written to s->window yet */
s->lit_bufsize = 1 << (memLevel + 6); /* 16K elements by default */ s->lit_bufsize = 1 << (memLevel + 6); /* 16K elements by default */
overlay = (ushf *) ZALLOC(strm, s->lit_bufsize, sizeof(ush)+2); overlay = (ushf *) ZALLOC(strm, s->lit_bufsize, sizeof(ush)+2);
@ -300,7 +299,9 @@ int ZEXPORT deflateInit2_(z_streamp strm, int level, int method, int windowBits,
} }
/* ========================================================================= */ /* ========================================================================= */
int ZEXPORT deflateSetDictionary (z_streamp strm, const Bytef *dictionary, uInt dictLength) int ZEXPORT deflateSetDictionary (z_streamp strm,
const Bytef *dictionary,
uInt dictLength)
{ {
deflate_state *s; deflate_state *s;
uInt length = dictLength; uInt length = dictLength;
@ -317,8 +318,8 @@ int ZEXPORT deflateSetDictionary (z_streamp strm, const Bytef *dictionary, uInt
strm->adler = adler32(strm->adler, dictionary, dictLength); strm->adler = adler32(strm->adler, dictionary, dictLength);
if (length < MIN_MATCH) return Z_OK; if (length < MIN_MATCH) return Z_OK;
if (length > MAX_DIST(s)) { if (length > s->w_size) {
length = MAX_DIST(s); length = s->w_size;
dictionary += dictLength - length; /* use the tail of the dictionary */ dictionary += dictLength - length; /* use the tail of the dictionary */
} }
zmemcpy(s->window, dictionary, length); zmemcpy(s->window, dictionary, length);
@ -411,9 +412,10 @@ int ZEXPORT deflateParams(z_streamp strm, int level, int strategy)
} }
func = configuration_table[s->level].func; func = configuration_table[s->level].func;
if (func != configuration_table[level].func && strm->total_in != 0) { if ((strategy != s->strategy || func != configuration_table[level].func) &&
strm->total_in != 0) {
/* Flush the last buffer: */ /* Flush the last buffer: */
err = deflate(strm, Z_PARTIAL_FLUSH); err = deflate(strm, Z_BLOCK);
} }
if (s->level != level) { if (s->level != level) {
s->level = level; s->level = level;
@ -453,31 +455,64 @@ int ZEXPORT deflateTune(z_streamp strm, int good_length, int max_lazy,
* resulting from using fixed blocks instead of stored blocks, which deflate * resulting from using fixed blocks instead of stored blocks, which deflate
* can emit on compressed data for some combinations of the parameters. * can emit on compressed data for some combinations of the parameters.
* *
* This function could be more sophisticated to provide closer upper bounds * This function could be more sophisticated to provide closer upper bounds for
* for every combination of windowBits and memLevel, as well as wrap. * every combination of windowBits and memLevel. But even the conservative
* But even the conservative upper bound of about 14% expansion does not * upper bound of about 14% expansion does not seem onerous for output buffer
* seem onerous for output buffer allocation. * allocation.
*/ */
uLong ZEXPORT deflateBound(z_streamp strm, uLong sourceLen) uLong ZEXPORT deflateBound(z_streamp strm, uLong sourceLen)
{ {
deflate_state *s; deflate_state *s;
uLong destLen; uLong complen, wraplen;
Bytef *str;
/* conservative upper bound */ /* conservative upper bound for compressed data */
destLen = sourceLen + complen = sourceLen +
((sourceLen + 7) >> 3) + ((sourceLen + 63) >> 6) + 11; ((sourceLen + 7) >> 3) + ((sourceLen + 63) >> 6) + 5;
/* if can't get parameters, return conservative bound */ /* if can't get parameters, return conservative bound plus zlib wrapper */
if (strm == Z_NULL || strm->state == Z_NULL) if (strm == Z_NULL || strm->state == Z_NULL)
return destLen; return complen + 6;
/* compute wrapper length */
s = strm->state;
switch (s->wrap) {
case 0: /* raw deflate */
wraplen = 0;
break;
case 1: /* zlib wrapper */
wraplen = 6 + (s->strstart ? 4 : 0);
break;
case 2: /* gzip wrapper */
wraplen = 18;
if (s->gzhead != Z_NULL) { /* user-supplied gzip header */
if (s->gzhead->extra != Z_NULL)
wraplen += 2 + s->gzhead->extra_len;
str = s->gzhead->name;
if (str != Z_NULL)
do {
wraplen++;
} while (*str++);
str = s->gzhead->comment;
if (str != Z_NULL)
do {
wraplen++;
} while (*str++);
if (s->gzhead->hcrc)
wraplen += 2;
}
break;
default: /* for compiler happiness */
wraplen = 6;
}
/* if not default parameters, return conservative bound */ /* if not default parameters, return conservative bound */
s = strm->state;
if (s->w_bits != 15 || s->hash_bits != 8 + 7) if (s->w_bits != 15 || s->hash_bits != 8 + 7)
return destLen; return complen + wraplen;
/* default settings: return tight bound for that case */ /* default settings: return tight bound for that case */
return compressBound(sourceLen); return sourceLen + (sourceLen >> 12) + (sourceLen >> 14) +
(sourceLen >> 25) + 13 - 6 + wraplen;
} }
/* ========================================================================= /* =========================================================================
@ -522,7 +557,7 @@ int ZEXPORT deflate (z_streamp strm, int flush)
deflate_state *s; deflate_state *s;
if (strm == Z_NULL || strm->state == Z_NULL || if (strm == Z_NULL || strm->state == Z_NULL ||
flush > Z_FINISH || flush < 0) { flush > Z_BLOCK || flush < 0) {
return Z_STREAM_ERROR; return Z_STREAM_ERROR;
} }
s = strm->state; s = strm->state;
@ -546,7 +581,7 @@ int ZEXPORT deflate (z_streamp strm, int flush)
put_byte(s, 31); put_byte(s, 31);
put_byte(s, 139); put_byte(s, 139);
put_byte(s, 8); put_byte(s, 8);
if (s->gzhead == NULL) { if (s->gzhead == Z_NULL) {
put_byte(s, 0); put_byte(s, 0);
put_byte(s, 0); put_byte(s, 0);
put_byte(s, 0); put_byte(s, 0);
@ -573,7 +608,7 @@ int ZEXPORT deflate (z_streamp strm, int flush)
(s->strategy >= Z_HUFFMAN_ONLY || s->level < 2 ? (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2 ?
4 : 0)); 4 : 0));
put_byte(s, s->gzhead->os & 0xff); put_byte(s, s->gzhead->os & 0xff);
if (s->gzhead->extra != NULL) { if (s->gzhead->extra != Z_NULL) {
put_byte(s, s->gzhead->extra_len & 0xff); put_byte(s, s->gzhead->extra_len & 0xff);
put_byte(s, (s->gzhead->extra_len >> 8) & 0xff); put_byte(s, (s->gzhead->extra_len >> 8) & 0xff);
} }
@ -615,7 +650,7 @@ int ZEXPORT deflate (z_streamp strm, int flush)
} }
#ifdef GZIP #ifdef GZIP
if (s->status == EXTRA_STATE) { if (s->status == EXTRA_STATE) {
if (s->gzhead->extra != NULL) { if (s->gzhead->extra != Z_NULL) {
uInt beg = s->pending; /* start of bytes to update crc */ uInt beg = s->pending; /* start of bytes to update crc */
while (s->gzindex < (s->gzhead->extra_len & 0xffff)) { while (s->gzindex < (s->gzhead->extra_len & 0xffff)) {
@ -643,7 +678,7 @@ int ZEXPORT deflate (z_streamp strm, int flush)
s->status = NAME_STATE; s->status = NAME_STATE;
} }
if (s->status == NAME_STATE) { if (s->status == NAME_STATE) {
if (s->gzhead->name != NULL) { if (s->gzhead->name != Z_NULL) {
uInt beg = s->pending; /* start of bytes to update crc */ uInt beg = s->pending; /* start of bytes to update crc */
int val; int val;
@ -674,7 +709,7 @@ int ZEXPORT deflate (z_streamp strm, int flush)
s->status = COMMENT_STATE; s->status = COMMENT_STATE;
} }
if (s->status == COMMENT_STATE) { if (s->status == COMMENT_STATE) {
if (s->gzhead->comment != NULL) { if (s->gzhead->comment != Z_NULL) {
uInt beg = s->pending; /* start of bytes to update crc */ uInt beg = s->pending; /* start of bytes to update crc */
int val; int val;
@ -752,7 +787,9 @@ int ZEXPORT deflate (z_streamp strm, int flush)
(flush != Z_NO_FLUSH && s->status != FINISH_STATE)) { (flush != Z_NO_FLUSH && s->status != FINISH_STATE)) {
block_state bstate; block_state bstate;
bstate = (*(configuration_table[s->level].func))(s, flush); bstate = s->strategy == Z_HUFFMAN_ONLY ? deflate_huff(s, flush) :
(s->strategy == Z_RLE ? deflate_rle(s, flush) :
(*(configuration_table[s->level].func))(s, flush));
if (bstate == finish_started || bstate == finish_done) { if (bstate == finish_started || bstate == finish_done) {
s->status = FINISH_STATE; s->status = FINISH_STATE;
@ -773,13 +810,17 @@ int ZEXPORT deflate (z_streamp strm, int flush)
if (bstate == block_done) { if (bstate == block_done) {
if (flush == Z_PARTIAL_FLUSH) { if (flush == Z_PARTIAL_FLUSH) {
_tr_align(s); _tr_align(s);
} else { /* FULL_FLUSH or SYNC_FLUSH */ } else if (flush != Z_BLOCK) { /* FULL_FLUSH or SYNC_FLUSH */
_tr_stored_block(s, (char*)0, 0L, 0); _tr_stored_block(s, (char*)0, 0L, 0);
/* For a full flush, this empty block will be recognized /* For a full flush, this empty block will be recognized
* as a special marker by inflate_sync(). * as a special marker by inflate_sync().
*/ */
if (flush == Z_FULL_FLUSH) { if (flush == Z_FULL_FLUSH) {
CLEAR_HASH(s); /* forget history */ CLEAR_HASH(s); /* forget history */
if (s->lookahead == 0) {
s->strstart = 0;
s->block_start = 0L;
}
} }
} }
flush_pending(strm); flush_pending(strm);
@ -982,7 +1023,8 @@ local void lm_init (deflate_state *s)
/* For 80x86 and 680x0, an optimized version will be provided in match.asm or /* For 80x86 and 680x0, an optimized version will be provided in match.asm or
* match.S. The code will be functionally equivalent. * match.S. The code will be functionally equivalent.
*/ */
local uInt longest_match(deflate_state *s, IPos cur_match) local uInt longest_match(deflate_state *s,
IPos cur_match) /* current match */
{ {
unsigned chain_length = s->max_chain_length;/* max hash chain length */ unsigned chain_length = s->max_chain_length;/* max hash chain length */
register Bytef *scan = s->window + s->strstart; /* current string */ register Bytef *scan = s->window + s->strstart; /* current string */
@ -1123,12 +1165,14 @@ local uInt longest_match(deflate_state *s, IPos cur_match)
return s->lookahead; return s->lookahead;
} }
#endif /* ASMV */ #endif /* ASMV */
#endif /* FASTEST */
#else /* FASTEST */
/* --------------------------------------------------------------------------- /* ---------------------------------------------------------------------------
* Optimized version for level == 1 or strategy == Z_RLE only * Optimized version for FASTEST only
*/ */
local uInt longest_match_fast(deflate_state *s, IPos cur_match) local uInt longest_match(deflate_state *s,
IPos cur_match) /* current match */
{ {
register Bytef *scan = s->window + s->strstart; /* current string */ register Bytef *scan = s->window + s->strstart; /* current string */
register Bytef *match; /* matched string */ register Bytef *match; /* matched string */
@ -1179,11 +1223,16 @@ local uInt longest_match_fast(deflate_state *s, IPos cur_match)
return (uInt)len <= s->lookahead ? (uInt)len : s->lookahead; return (uInt)len <= s->lookahead ? (uInt)len : s->lookahead;
} }
#endif /* FASTEST */
#ifdef DEBUG #ifdef DEBUG
/* =========================================================================== /* ===========================================================================
* Check that the match at match_start is indeed a match. * Check that the match at match_start is indeed a match.
*/ */
local void check_match(deflate_state *s, IPos start, IPos match, int length) local void check_match(s, start, match, length)
deflate_state *s;
IPos start, match;
int length;
{ {
/* check that the match is indeed a match */ /* check that the match is indeed a match */
if (zmemcmp(s->window + match, if (zmemcmp(s->window + match,
@ -1253,7 +1302,6 @@ local void fill_window(deflate_state *s)
later. (Using level 0 permanently is not an optimal usage of later. (Using level 0 permanently is not an optimal usage of
zlib, so we don't care about this pathological case.) zlib, so we don't care about this pathological case.)
*/ */
/* %%% avoid this when Z_RLE */
n = s->hash_size; n = s->hash_size;
p = &s->head[n]; p = &s->head[n];
do { do {
@ -1305,27 +1353,61 @@ local void fill_window(deflate_state *s)
*/ */
} while (s->lookahead < MIN_LOOKAHEAD && s->strm->avail_in != 0); } while (s->lookahead < MIN_LOOKAHEAD && s->strm->avail_in != 0);
/* If the WIN_INIT bytes after the end of the current data have never been
* written, then zero those bytes in order to avoid memory check reports of
* the use of uninitialized (or uninitialised as Julian writes) bytes by
* the longest match routines. Update the high water mark for the next
* time through here. WIN_INIT is set to MAX_MATCH since the longest match
* routines allow scanning to strstart + MAX_MATCH, ignoring lookahead.
*/
if (s->high_water < s->window_size) {
ulg curr = s->strstart + (ulg)(s->lookahead);
ulg init;
if (s->high_water < curr) {
/* Previous high water mark below current data -- zero WIN_INIT
* bytes or up to end of window, whichever is less.
*/
init = s->window_size - curr;
if (init > WIN_INIT)
init = WIN_INIT;
zmemzero(s->window + curr, (unsigned)init);
s->high_water = curr + init;
}
else if (s->high_water < (ulg)curr + WIN_INIT) {
/* High water mark at or above current data, but below current data
* plus WIN_INIT -- zero out to current data plus WIN_INIT, or up
* to end of window, whichever is less.
*/
init = (ulg)curr + WIN_INIT - s->high_water;
if (init > s->window_size - s->high_water)
init = s->window_size - s->high_water;
zmemzero(s->window + s->high_water, (unsigned)init);
s->high_water += init;
}
}
} }
/* =========================================================================== /* ===========================================================================
* Flush the current block, with given end-of-file flag. * Flush the current block, with given end-of-file flag.
* IN assertion: strstart is set to the end of the current match. * IN assertion: strstart is set to the end of the current match.
*/ */
#define FLUSH_BLOCK_ONLY(s, eof) { \ #define FLUSH_BLOCK_ONLY(s, last) { \
_tr_flush_block(s, (s->block_start >= 0L ? \ _tr_flush_block(s, (s->block_start >= 0L ? \
(charf *)&s->window[(unsigned)s->block_start] : \ (charf *)&s->window[(unsigned)s->block_start] : \
(charf *)Z_NULL), \ (charf *)Z_NULL), \
(ulg)((long)s->strstart - s->block_start), \ (ulg)((long)s->strstart - s->block_start), \
(eof)); \ (last)); \
s->block_start = s->strstart; \ s->block_start = s->strstart; \
flush_pending(s->strm); \ flush_pending(s->strm); \
Tracev((stderr,"[FLUSH]")); \ Tracev((stderr,"[FLUSH]")); \
} }
/* Same but force premature exit if necessary. */ /* Same but force premature exit if necessary. */
#define FLUSH_BLOCK(s, eof) { \ #define FLUSH_BLOCK(s, last) { \
FLUSH_BLOCK_ONLY(s, eof); \ FLUSH_BLOCK_ONLY(s, last); \
if (s->strm->avail_out == 0) return (eof) ? finish_started : need_more; \ if (s->strm->avail_out == 0) return (last) ? finish_started : need_more; \
} }
/* =========================================================================== /* ===========================================================================
@ -1395,7 +1477,7 @@ local block_state deflate_stored(deflate_state *s, int flush)
*/ */
local block_state deflate_fast(deflate_state *s, int flush) local block_state deflate_fast(deflate_state *s, int flush)
{ {
IPos hash_head = NIL; /* head of the hash chain */ IPos hash_head; /* head of the hash chain */
int bflush; /* set if current block must be flushed */ int bflush; /* set if current block must be flushed */
for (;;) { for (;;) {
@ -1415,6 +1497,7 @@ local block_state deflate_fast(deflate_state *s, int flush)
/* Insert the string window[strstart .. strstart+2] in the /* Insert the string window[strstart .. strstart+2] in the
* dictionary, and set hash_head to the head of the hash chain: * dictionary, and set hash_head to the head of the hash chain:
*/ */
hash_head = NIL;
if (s->lookahead >= MIN_MATCH) { if (s->lookahead >= MIN_MATCH) {
INSERT_STRING(s, s->strstart, hash_head); INSERT_STRING(s, s->strstart, hash_head);
} }
@ -1427,19 +1510,8 @@ local block_state deflate_fast(deflate_state *s, int flush)
* of window index 0 (in particular we have to avoid a match * of window index 0 (in particular we have to avoid a match
* of the string with itself at the start of the input file). * of the string with itself at the start of the input file).
*/ */
#ifdef FASTEST
if ((s->strategy != Z_HUFFMAN_ONLY && s->strategy != Z_RLE) ||
(s->strategy == Z_RLE && s->strstart - hash_head == 1)) {
s->match_length = longest_match_fast (s, hash_head);
}
#else
if (s->strategy != Z_HUFFMAN_ONLY && s->strategy != Z_RLE) {
s->match_length = longest_match (s, hash_head); s->match_length = longest_match (s, hash_head);
} else if (s->strategy == Z_RLE && s->strstart - hash_head == 1) { /* longest_match() sets match_start */
s->match_length = longest_match_fast (s, hash_head);
}
#endif
/* longest_match() or longest_match_fast() sets match_start */
} }
if (s->match_length >= MIN_MATCH) { if (s->match_length >= MIN_MATCH) {
check_match(s, s->strstart, s->match_start, s->match_length); check_match(s, s->strstart, s->match_start, s->match_length);
@ -1499,7 +1571,7 @@ local block_state deflate_fast(deflate_state *s, int flush)
*/ */
local block_state deflate_slow(deflate_state *s, int flush) local block_state deflate_slow(deflate_state *s, int flush)
{ {
IPos hash_head = NIL; /* head of hash chain */ IPos hash_head; /* head of hash chain */
int bflush; /* set if current block must be flushed */ int bflush; /* set if current block must be flushed */
/* Process the input block. */ /* Process the input block. */
@ -1520,6 +1592,7 @@ local block_state deflate_slow(deflate_state *s, int flush)
/* Insert the string window[strstart .. strstart+2] in the /* Insert the string window[strstart .. strstart+2] in the
* dictionary, and set hash_head to the head of the hash chain: * dictionary, and set hash_head to the head of the hash chain:
*/ */
hash_head = NIL;
if (s->lookahead >= MIN_MATCH) { if (s->lookahead >= MIN_MATCH) {
INSERT_STRING(s, s->strstart, hash_head); INSERT_STRING(s, s->strstart, hash_head);
} }
@ -1535,12 +1608,8 @@ local block_state deflate_slow(deflate_state *s, int flush)
* of window index 0 (in particular we have to avoid a match * of window index 0 (in particular we have to avoid a match
* of the string with itself at the start of the input file). * of the string with itself at the start of the input file).
*/ */
if (s->strategy != Z_HUFFMAN_ONLY && s->strategy != Z_RLE) {
s->match_length = longest_match (s, hash_head); s->match_length = longest_match (s, hash_head);
} else if (s->strategy == Z_RLE && s->strstart - hash_head == 1) { /* longest_match() sets match_start */
s->match_length = longest_match_fast (s, hash_head);
}
/* longest_match() or longest_match_fast() sets match_start */
if (s->match_length <= 5 && (s->strategy == Z_FILTERED if (s->match_length <= 5 && (s->strategy == Z_FILTERED
#if TOO_FAR <= 32767 #if TOO_FAR <= 32767
@ -1618,7 +1687,6 @@ local block_state deflate_slow(deflate_state *s, int flush)
} }
#endif /* FASTEST */ #endif /* FASTEST */
#if 0
/* =========================================================================== /* ===========================================================================
* For Z_RLE, simply look for runs of bytes, generate matches only of distance * For Z_RLE, simply look for runs of bytes, generate matches only of distance
* one. Do not maintain a hash table. (It will be regenerated if this run of * one. Do not maintain a hash table. (It will be regenerated if this run of
@ -1627,10 +1695,8 @@ local block_state deflate_slow(deflate_state *s, int flush)
local block_state deflate_rle(deflate_state *s, int flush) local block_state deflate_rle(deflate_state *s, int flush)
{ {
int bflush; /* set if current block must be flushed */ int bflush; /* set if current block must be flushed */
uInt run; /* length of run */
uInt max; /* maximum length of run */
uInt prev; /* byte at distance one to match */ uInt prev; /* byte at distance one to match */
Bytef *scan; /* scan for end of run */ Bytef *scan, *strend; /* scan goes up to strend for length of run */
for (;;) { for (;;) {
/* Make sure that we always have enough lookahead, except /* Make sure that we always have enough lookahead, except
@ -1646,23 +1712,33 @@ local block_state deflate_rle(deflate_state *s, int flush)
} }
/* See how many times the previous byte repeats */ /* See how many times the previous byte repeats */
run = 0; s->match_length = 0;
if (s->strstart > 0) { /* if there is a previous byte, that is */ if (s->lookahead >= MIN_MATCH && s->strstart > 0) {
max = s->lookahead < MAX_MATCH ? s->lookahead : MAX_MATCH;
scan = s->window + s->strstart - 1; scan = s->window + s->strstart - 1;
prev = *scan++; prev = *scan;
if (prev == *++scan && prev == *++scan && prev == *++scan) {
strend = s->window + s->strstart + MAX_MATCH;
do { do {
if (*scan++ != prev) } while (prev == *++scan && prev == *++scan &&
break; prev == *++scan && prev == *++scan &&
} while (++run < max); prev == *++scan && prev == *++scan &&
prev == *++scan && prev == *++scan &&
scan < strend);
s->match_length = MAX_MATCH - (int)(strend - scan);
if (s->match_length > s->lookahead)
s->match_length = s->lookahead;
}
} }
/* Emit match if have run of MIN_MATCH or longer, else emit literal */ /* Emit match if have run of MIN_MATCH or longer, else emit literal */
if (run >= MIN_MATCH) { if (s->match_length >= MIN_MATCH) {
check_match(s, s->strstart, s->strstart - 1, run); check_match(s, s->strstart, s->strstart - 1, s->match_length);
_tr_tally_dist(s, 1, run - MIN_MATCH, bflush);
s->lookahead -= run; _tr_tally_dist(s, 1, s->match_length - MIN_MATCH, bflush);
s->strstart += run;
s->lookahead -= s->match_length;
s->strstart += s->match_length;
s->match_length = 0;
} else { } else {
/* No match, output a literal byte */ /* No match, output a literal byte */
Tracevv((stderr,"%c", s->window[s->strstart])); Tracevv((stderr,"%c", s->window[s->strstart]));
@ -1675,4 +1751,34 @@ local block_state deflate_rle(deflate_state *s, int flush)
FLUSH_BLOCK(s, flush == Z_FINISH); FLUSH_BLOCK(s, flush == Z_FINISH);
return flush == Z_FINISH ? finish_done : block_done; return flush == Z_FINISH ? finish_done : block_done;
} }
#endif
/* ===========================================================================
* For Z_HUFFMAN_ONLY, do not look for matches. Do not maintain a hash table.
* (It will be regenerated if this run of deflate switches away from Huffman.)
*/
local block_state deflate_huff(deflate_state *s, int flush)
{
int bflush; /* set if current block must be flushed */
for (;;) {
/* Make sure that we have a literal to write. */
if (s->lookahead == 0) {
fill_window(s);
if (s->lookahead == 0) {
if (flush == Z_NO_FLUSH)
return need_more;
break; /* flush the current block */
}
}
/* Output a literal byte */
s->match_length = 0;
Tracevv((stderr,"%c", s->window[s->strstart]));
_tr_tally_lit (s, s->window[s->strstart], bflush);
s->lookahead--;
s->strstart++;
if (bflush) FLUSH_BLOCK(s, 0);
}
FLUSH_BLOCK(s, flush == Z_FINISH);
return flush == Z_FINISH ? finish_done : block_done;
}

View File

@ -1,5 +1,5 @@
/* deflate.h -- internal compression state /* deflate.h -- internal compression state
* Copyright (C) 1995-2004 Jean-loup Gailly * Copyright (C) 1995-2010 Jean-loup Gailly
* For conditions of distribution and use, see copyright notice in zlib.h * For conditions of distribution and use, see copyright notice in zlib.h
*/ */
@ -260,6 +260,13 @@ typedef struct internal_state {
* are always zero. * are always zero.
*/ */
ulg high_water;
/* High water mark offset in window for initialized bytes -- bytes above
* this are set to zero in order to avoid memory check warnings when
* longest match routines access bytes past the input. This is then
* updated to the new high water mark.
*/
} FAR deflate_state; } FAR deflate_state;
/* Output a byte on the stream. /* Output a byte on the stream.
@ -278,14 +285,18 @@ typedef struct internal_state {
* distances are limited to MAX_DIST instead of WSIZE. * distances are limited to MAX_DIST instead of WSIZE.
*/ */
#define WIN_INIT MAX_MATCH
/* Number of bytes after end of data in window to initialize in order to avoid
memory checker errors from longest match routines */
/* in trees.c */ /* in trees.c */
void _tr_init OF((deflate_state *s)); void ZLIB_INTERNAL _tr_init OF((deflate_state *s));
int _tr_tally OF((deflate_state *s, unsigned dist, unsigned lc)); int ZLIB_INTERNAL _tr_tally OF((deflate_state *s, unsigned dist, unsigned lc));
void _tr_flush_block OF((deflate_state *s, charf *buf, ulg stored_len, void ZLIB_INTERNAL _tr_flush_block OF((deflate_state *s, charf *buf,
int eof)); ulg stored_len, int last));
void _tr_align OF((deflate_state *s)); void ZLIB_INTERNAL _tr_align OF((deflate_state *s));
void _tr_stored_block OF((deflate_state *s, charf *buf, ulg stored_len, void ZLIB_INTERNAL _tr_stored_block OF((deflate_state *s, charf *buf,
int eof)); ulg stored_len, int last));
#define d_code(dist) \ #define d_code(dist) \
((dist) < 256 ? _dist_code[dist] : _dist_code[256+((dist)>>7)]) ((dist) < 256 ? _dist_code[dist] : _dist_code[256+((dist)>>7)])
@ -298,11 +309,11 @@ void _tr_stored_block OF((deflate_state *s, charf *buf, ulg stored_len,
/* Inline versions of _tr_tally for speed: */ /* Inline versions of _tr_tally for speed: */
#if defined(GEN_TREES_H) || !defined(STDC) #if defined(GEN_TREES_H) || !defined(STDC)
extern uch _length_code[]; extern uch ZLIB_INTERNAL _length_code[];
extern uch _dist_code[]; extern uch ZLIB_INTERNAL _dist_code[];
#else #else
extern const uch _length_code[]; extern const uch ZLIB_INTERNAL _length_code[];
extern const uch _dist_code[]; extern const uch ZLIB_INTERNAL _dist_code[];
#endif #endif
# define _tr_tally_lit(s, c, flush) \ # define _tr_tally_lit(s, c, flush) \

View File

@ -1,12 +1,12 @@
/* example.c -- usage example of the zlib compression library /* example.c -- usage example of the zlib compression library
* Copyright (C) 1995-2004 Jean-loup Gailly. * Copyright (C) 1995-2006 Jean-loup Gailly.
* For conditions of distribution and use, see copyright notice in zlib.h * For conditions of distribution and use, see copyright notice in zlib.h
*/ */
/* @(#) $Id$ */ /* @(#) $Id$ */
#include <stdio.h>
#include "zlib.h" #include "zlib.h"
#include <stdio.h>
#ifdef STDC #ifdef STDC
# include <string.h> # include <string.h>
@ -56,7 +56,8 @@ int main OF((int argc, char *argv[]));
/* =========================================================================== /* ===========================================================================
* Test compress() and uncompress() * Test compress() and uncompress()
*/ */
void test_compress(Byte *compr, uLong comprLen, Byte *uncompr, uLong uncomprLen) void test_compress(Byte *compr, uLong comprLen,
Byte *uncompr, uLong uncomprLen)
{ {
int err; int err;
uLong len = (uLong)strlen(hello)+1; uLong len = (uLong)strlen(hello)+1;
@ -236,7 +237,8 @@ void test_inflate(Byte *compr, uLong comprLen, Byte *uncompr, uLong uncomprLen)
/* =========================================================================== /* ===========================================================================
* Test deflate() with large buffers and dynamic change of compression level * Test deflate() with large buffers and dynamic change of compression level
*/ */
void test_large_deflate(Byte *compr, uLong comprLen, Byte *uncompr, uLong uncomprLen) void test_large_deflate(Byte *compr, uLong comprLen,
Byte *uncompr, uLong uncomprLen)
{ {
z_stream c_stream; /* compression stream */ z_stream c_stream; /* compression stream */
int err; int err;
@ -289,7 +291,8 @@ void test_large_deflate(Byte *compr, uLong comprLen, Byte *uncompr, uLong uncomp
/* =========================================================================== /* ===========================================================================
* Test inflate() with large buffers * Test inflate() with large buffers
*/ */
void test_large_inflate(Byte *compr, uLong comprLen, Byte *uncompr, uLong uncomprLen) void test_large_inflate(Byte *compr, uLong comprLen,
Byte *uncompr, uLong uncomprLen)
{ {
int err; int err;
z_stream d_stream; /* decompression stream */ z_stream d_stream; /* decompression stream */
@ -441,7 +444,8 @@ void test_dict_deflate(Byte *compr, uLong comprLen)
/* =========================================================================== /* ===========================================================================
* Test inflate() with a preset dictionary * Test inflate() with a preset dictionary
*/ */
void test_dict_inflate(Byte *compr, uLong comprLen, Byte *uncompr, uLong uncomprLen) void test_dict_inflate(Byte *compr, uLong comprLen,
Byte *uncompr, uLong uncomprLen)
{ {
int err; int err;
z_stream d_stream; /* decompression stream */ z_stream d_stream; /* decompression stream */

24
src/zlib/gzclose.c Normal file
View File

@ -0,0 +1,24 @@
/* gzclose.c -- zlib gzclose() function
* Copyright (C) 2004, 2010 Mark Adler
* For conditions of distribution and use, see copyright notice in zlib.h
*/
#include "gzguts.h"
/* gzclose() is in a separate file so that it is linked in only if it is used.
That way the other gzclose functions can be used instead to avoid linking in
unneeded compression or decompression routines. */
int ZEXPORT gzclose(gzFile file)
{
#ifndef NO_GZCOMPRESS
gz_statep state;
if (file == NULL)
return Z_STREAM_ERROR;
state = (gz_statep)file;
return state->mode == GZ_READ ? gzclose_r(file) : gzclose_w(file);
#else
return gzclose_r(file);
#endif
}

132
src/zlib/gzguts.h Normal file
View File

@ -0,0 +1,132 @@
/* gzguts.h -- zlib internal header definitions for gz* operations
* Copyright (C) 2004, 2005, 2010 Mark Adler
* For conditions of distribution and use, see copyright notice in zlib.h
*/
#ifdef _LARGEFILE64_SOURCE
# ifndef _LARGEFILE_SOURCE
# define _LARGEFILE_SOURCE 1
# endif
# ifdef _FILE_OFFSET_BITS
# undef _FILE_OFFSET_BITS
# endif
#endif
#if ((__GNUC__-0) * 10 + __GNUC_MINOR__-0 >= 33) && !defined(NO_VIZ)
# define ZLIB_INTERNAL __attribute__((visibility ("hidden")))
#else
# define ZLIB_INTERNAL
#endif
#include <stdio.h>
#include "zlib.h"
#ifdef STDC
# include <string.h>
# include <stdlib.h>
# include <limits.h>
#endif
#include <fcntl.h>
#ifdef NO_DEFLATE /* for compatibility with old definition */
# define NO_GZCOMPRESS
#endif
#ifdef _MSC_VER
# include <io.h>
# define vsnprintf _vsnprintf
#endif
#ifndef local
# define local static
#endif
/* compile with -Dlocal if your debugger can't find static symbols */
/* gz* functions always use library allocation functions */
#ifndef STDC
extern voidp malloc OF((uInt size));
extern void free OF((voidpf ptr));
#endif
/* get errno and strerror definition */
#if defined UNDER_CE
# include <windows.h>
# define zstrerror() gz_strwinerror((DWORD)GetLastError())
#else
# ifdef STDC
# include <errno.h>
# define zstrerror() strerror(errno)
# else
# define zstrerror() "stdio error (consult errno)"
# endif
#endif
/* provide prototypes for these when building zlib without LFS */
#if !defined(_LARGEFILE64_SOURCE) || _LFS64_LARGEFILE-0 == 0
ZEXTERN gzFile ZEXPORT gzopen64 OF((const char *, const char *));
ZEXTERN z_off64_t ZEXPORT gzseek64 OF((gzFile, z_off64_t, int));
ZEXTERN z_off64_t ZEXPORT gztell64 OF((gzFile));
ZEXTERN z_off64_t ZEXPORT gzoffset64 OF((gzFile));
#endif
/* default i/o buffer size -- double this for output when reading */
#define GZBUFSIZE 8192
/* gzip modes, also provide a little integrity check on the passed structure */
#define GZ_NONE 0
#define GZ_READ 7247
#define GZ_WRITE 31153
#define GZ_APPEND 1 /* mode set to GZ_WRITE after the file is opened */
/* values for gz_state how */
#define LOOK 0 /* look for a gzip header */
#define COPY 1 /* copy input directly */
#define GZIP 2 /* decompress a gzip stream */
/* internal gzip file state data structure */
typedef struct {
/* used for both reading and writing */
int mode; /* see gzip modes above */
int fd; /* file descriptor */
char *path; /* path or fd for error messages */
z_off64_t pos; /* current position in uncompressed data */
unsigned size; /* buffer size, zero if not allocated yet */
unsigned want; /* requested buffer size, default is GZBUFSIZE */
unsigned char *in; /* input buffer */
unsigned char *out; /* output buffer (double-sized when reading) */
unsigned char *next; /* next output data to deliver or write */
/* just for reading */
unsigned have; /* amount of output data unused at next */
int eof; /* true if end of input file reached */
z_off64_t start; /* where the gzip data started, for rewinding */
z_off64_t raw; /* where the raw data started, for seeking */
int how; /* 0: get header, 1: copy, 2: decompress */
int direct; /* true if last read direct, false if gzip */
/* just for writing */
int level; /* compression level */
int strategy; /* compression strategy */
/* seek request */
z_off64_t skip; /* amount to skip (already rewound if backwards) */
int seek; /* true if seek request pending */
/* error information */
int err; /* error code */
char *msg; /* error message */
/* zlib inflate or deflate stream */
z_stream strm; /* stream structure in-place (not a pointer) */
} gz_state;
typedef gz_state FAR *gz_statep;
/* shared functions */
void ZLIB_INTERNAL gz_error OF((gz_statep, int, const char *));
#if defined UNDER_CE
char ZLIB_INTERNAL *gz_strwinerror OF((DWORD error));
#endif
/* GT_OFF(x), where x is an unsigned value, is true if x > maximum z_off64_t
value -- needed when comparing unsigned to z_off64_t, which is signed
(possible z_off64_t types off_t, off64_t, and long are all signed) */
#ifdef INT_MAX
# define GT_OFF(x) (sizeof(int) == sizeof(z_off64_t) && (x) > INT_MAX)
#else
unsigned ZLIB_INTERNAL gz_intmax OF((void));
# define GT_OFF(x) (sizeof(int) == sizeof(z_off64_t) && (x) > gz_intmax())
#endif

View File

@ -1,976 +0,0 @@
/* gzio.c -- IO on .gz files
* Copyright (C) 1995-2005 Jean-loup Gailly.
* For conditions of distribution and use, see copyright notice in zlib.h
*
* Compile this file with -DNO_GZCOMPRESS to avoid the compression code.
*/
/* @(#) $Id$ */
#include <stdio.h>
#include "zutil.h"
#ifdef NO_DEFLATE /* for compatibility 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
# define Z_BUFSIZE 4096 /* minimize memory usage for 16-bit DOS */
# else
# define Z_BUFSIZE 16384
# endif
#endif
#ifndef Z_PRINTF_BUFSIZE
# 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 const gz_magic[2] = {0x1f, 0x8b}; /* gzip magic header */
/* gzip flag byte */
#define ASCII_FLAG 0x01 /* bit 0 set: file probably ascii text */
#define HEAD_CRC 0x02 /* bit 1 set: header CRC present */
#define EXTRA_FIELD 0x04 /* bit 2 set: extra field present */
#define ORIG_NAME 0x08 /* bit 3 set: original file name present */
#define COMMENT 0x10 /* bit 4 set: file comment present */
#define RESERVED 0xE0 /* bits 5..7: reserved */
typedef struct gz_stream {
z_stream stream;
int z_err; /* error code for last stream operation */
int z_eof; /* set if end of input file */
FILE *file; /* .gz file */
Byte *inbuf; /* input buffer */
Byte *outbuf; /* output buffer */
uLong crc; /* crc32 of uncompressed data */
char *msg; /* error message */
char *path; /* path name for debugging only */
int transparent; /* 1 if input file is not a .gz file */
char mode; /* 'w' or 'r' */
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;
local gzFile gz_open OF((const char *path, const char *mode, int fd));
local int do_flush OF((gzFile file, int flush));
local int get_byte OF((gz_stream *s));
local void check_header OF((gz_stream *s));
local int destroy OF((gz_stream *s));
local void putLong OF((FILE *file, uLong x));
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 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).
*/
local gzFile gz_open (const char *path, const char *mode, int fd)
{
int err;
int level = Z_DEFAULT_COMPRESSION; /* compression level */
int strategy = Z_DEFAULT_STRATEGY; /* compression strategy */
char *p = (char*)mode;
gz_stream *s;
char fmode[80]; /* copy of mode, without the compression level */
char *m = fmode;
if (!path || !mode) return Z_NULL;
s = (gz_stream *)ALLOC(sizeof(gz_stream));
if (!s) return Z_NULL;
s->stream.zalloc = (alloc_func)0;
s->stream.zfree = (free_func)0;
s->stream.opaque = (voidpf)0;
s->stream.next_in = s->inbuf = Z_NULL;
s->stream.next_out = s->outbuf = Z_NULL;
s->stream.avail_in = s->stream.avail_out = 0;
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;
s->path = (char*)ALLOC(strlen(path)+1);
if (s->path == NULL) {
return destroy(s), (gzFile)Z_NULL;
}
strcpy(s->path, path); /* do this early for debugging */
s->mode = '\0';
do {
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 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_GZCOMPRESS
err = Z_STREAM_ERROR;
#else
err = deflateInit2(&(s->stream), level,
Z_DEFLATED, -MAX_WBITS, DEF_MEM_LEVEL, strategy);
/* windowBits is passed < 0 to suppress zlib header */
s->stream.next_out = s->outbuf = (Byte*)ALLOC(Z_BUFSIZE);
#endif
if (err != Z_OK || s->outbuf == Z_NULL) {
return destroy(s), (gzFile)Z_NULL;
}
} else {
s->stream.next_in = s->inbuf = (Byte*)ALLOC(Z_BUFSIZE);
err = inflateInit2(&(s->stream), -MAX_WBITS);
/* windowBits is passed < 0 to tell that there is no zlib header.
* Note that in this case inflate *requires* an extra "dummy" byte
* after the compressed stream in order to complete decompression and
* return Z_STREAM_END. Here the gzip CRC32 ensures that 4 bytes are
* present after the compressed stream.
*/
if (err != Z_OK || s->inbuf == Z_NULL) {
return destroy(s), (gzFile)Z_NULL;
}
}
s->stream.avail_out = Z_BUFSIZE;
errno = 0;
s->file = fd < 0 ? F_OPEN(path, fmode) : (FILE*)fdopen(fd, fmode);
if (s->file == NULL) {
return destroy(s), (gzFile)Z_NULL;
}
if (s->mode == 'w') {
/* Write a very simple .gz header:
*/
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->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
* start anyway in write mode, so this initialization is not
* necessary.
*/
} else {
check_header(s); /* skip the .gz header */
s->start = ftell(s->file) - s->stream.avail_in;
}
return (gzFile)s;
}
/* ===========================================================================
Opens a gzip (.gz) file for reading or writing.
*/
gzFile ZEXPORT gzopen (const char *path, const char *mode)
{
return gz_open (path, mode, -1);
}
/* ===========================================================================
Associate a gzFile with the file descriptor fd. fd is not dup'ed here
to mimic the behavio(u)r of fdopen.
*/
gzFile ZEXPORT gzdopen (int fd, const char *mode)
{
char name[46]; /* allow for up to 128-bit integers */
if (fd < 0) return (gzFile)Z_NULL;
sprintf(name, "<fd:%d>", fd); /* for debugging */
return gz_open (name, mode, fd);
}
/* ===========================================================================
* Update the compression level and strategy
*/
int ZEXPORT gzsetparams (gzFile file, int level, int strategy)
{
gz_stream *s = (gz_stream*)file;
if (s == NULL || s->mode != 'w') return Z_STREAM_ERROR;
/* 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;
}
return deflateParams (&(s->stream), level, strategy);
}
/* ===========================================================================
Read a byte from a gz_stream; update next_in and avail_in. Return EOF
for end of file.
IN assertion: the stream s has been sucessfully opened for reading.
*/
local int get_byte(gz_stream *s)
{
if (s->z_eof) return EOF;
if (s->stream.avail_in == 0) {
errno = 0;
s->stream.avail_in = (uInt)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)++;
}
/* ===========================================================================
Check the gzip header of a gz_stream opened for reading. Set the stream
mode to transparent if the gzip magic header is not present; set s->err
to Z_DATA_ERROR if the magic header is present but the rest of the header
is incorrect.
IN assertion: the stream s has already been created sucessfully;
s->stream.avail_in is zero for the first time, but may be non-zero
for concatenated .gz files.
*/
local void check_header(gz_stream *s)
{
int method; /* method byte */
int flags; /* flags byte */
uInt len;
int c;
/* 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 = (uInt)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;
}
/* 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) ;
}
if ((flags & ORIG_NAME) != 0) { /* skip the original file name */
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) ;
}
if ((flags & HEAD_CRC) != 0) { /* skip the header crc */
for (len = 0; len < 2; len++) (void)get_byte(s);
}
s->z_err = s->z_eof ? Z_DATA_ERROR : Z_OK;
}
/* ===========================================================================
* Cleanup then free the given gz_stream. Return a zlib error code.
Try freeing in the reverse order of allocations.
*/
local int destroy (gz_stream *s)
{
int err = Z_OK;
if (!s) return Z_STREAM_ERROR;
TRYFREE(s->msg);
if (s->stream.state != NULL) {
if (s->mode == 'w') {
#ifdef NO_GZCOMPRESS
err = Z_STREAM_ERROR;
#else
err = deflateEnd(&(s->stream));
#endif
} 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 */
#endif
err = Z_ERRNO;
}
if (s->z_err < 0) err = s->z_err;
TRYFREE(s->inbuf);
TRYFREE(s->outbuf);
TRYFREE(s->path);
TRYFREE(s);
return err;
}
/* ===========================================================================
Reads the given number of uncompressed bytes from the compressed file.
gzread returns the number of bytes actually read (0 for end of file).
*/
int ZEXPORT gzread (gzFile file, voidp buf, unsigned len)
{
gz_stream *s = (gz_stream*)file;
Bytef *start = (Bytef*)buf; /* starting point for crc computation */
Byte *next_out; /* == stream.next_out but not forced far (for MSDOS) */
if (s == NULL || s->mode != 'r') return Z_STREAM_ERROR;
if (s->z_err == Z_DATA_ERROR || s->z_err == Z_ERRNO) return -1;
if (s->z_err == Z_STREAM_END) return 0; /* EOF */
next_out = (Byte*)buf;
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++;
start++;
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 -=
(uInt)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;
}
if (s->stream.avail_in == 0 && !s->z_eof) {
errno = 0;
s->stream.avail_in = (uInt)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;
}
}
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);
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));
if (len == s->stream.avail_out &&
(s->z_err == Z_DATA_ERROR || s->z_err == Z_ERRNO))
return -1;
return (int)(len - s->stream.avail_out);
}
/* ===========================================================================
Reads one byte from the compressed file. gzgetc returns this byte
or -1 in case of end of file or error.
*/
int ZEXPORT gzgetc(gzFile file)
{
unsigned char c;
return gzread(file, &c, 1) == 1 ? c : -1;
}
/* ===========================================================================
Push one byte back onto the stream.
*/
int ZEXPORT gzungetc(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
with a null character.
gzgets returns buf, or Z_NULL in case of error.
The current implementation is not optimized at all.
*/
char * ZEXPORT gzgets(gzFile file, char *buf, int len)
{
char *b = buf;
if (buf == Z_NULL || len <= 0) return Z_NULL;
while (--len > 0 && gzread(file, buf, 1) == 1 && *buf++ != '\n') ;
*buf = '\0';
return b == buf && len > 0 ? Z_NULL : b;
}
#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 (gzFile file, voidpc buf, unsigned len)
{
gz_stream *s = (gz_stream*)file;
if (s == NULL || s->mode != 'w') return Z_STREAM_ERROR;
s->stream.next_in = (Bytef*)buf;
s->stream.avail_in = len;
while (s->stream.avail_in != 0) {
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;
break;
}
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);
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
uncompressed bytes actually written (0 in case of error).
*/
#ifdef STDC
#include <stdarg.h>
int ZEXPORTVA gzprintf (gzFile file, const char *format, /* args */ ...)
{
char buf[Z_PRINTF_BUFSIZE];
va_list va;
int len;
buf[sizeof(buf) - 1] = 0;
va_start(va, format);
#ifdef NO_vsnprintf
# ifdef HAS_vsprintf_void
(void)vsprintf(buf, format, va);
va_end(va);
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 (gzFile file, const char *format, int a1, int a2, int a3, int a4,
int a5, int a6, int a7, int a8, int a9, int a10, int a11, int a12,
int a13, int a14, int a15, int a16, int a17, int a18, int a19, int a20)
{
char buf[Z_PRINTF_BUFSIZE];
int len;
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);
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
if (len <= 0 || len >= sizeof(buf) || buf[sizeof(buf) - 1] != 0)
return 0;
return gzwrite(file, buf, len);
}
#endif
/* ===========================================================================
Writes c, converted to an unsigned char, into the compressed file.
gzputc returns the value that was written, or -1 in case of error.
*/
int ZEXPORT gzputc(gzFile file, int c)
{
unsigned char cc = (unsigned char) c; /* required for big endian systems */
return gzwrite(file, &cc, 1) == 1 ? (int)cc : -1;
}
/* ===========================================================================
Writes the given null-terminated string to the compressed file, excluding
the terminating null character.
gzputs returns the number of characters written, or -1 in case of error.
*/
int ZEXPORT gzputs(gzFile file, const char *s)
{
return gzwrite(file, (char*)s, (unsigned)strlen(s));
}
/* ===========================================================================
Flushes all pending output into the compressed file. The parameter
flush is as in the deflate() function.
*/
local int do_flush (gzFile file, int flush)
{
uInt len;
int done = 0;
gz_stream *s = (gz_stream*)file;
if (s == NULL || s->mode != 'w') return Z_STREAM_ERROR;
s->stream.avail_in = 0; /* should be zero already anyway */
for (;;) {
len = Z_BUFSIZE - s->stream.avail_out;
if (len != 0) {
if ((uInt)fwrite(s->outbuf, 1, len, s->file) != len) {
s->z_err = Z_ERRNO;
return Z_ERRNO;
}
s->stream.next_out = s->outbuf;
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;
/* deflate has finished flushing only when it hasn't used up
* 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;
}
int ZEXPORT gzflush (gzFile file, int flush)
{
gz_stream *s = (gz_stream*)file;
int err = do_flush (file, flush);
if (err) return err;
fflush(s->file);
return s->z_err == Z_STREAM_END ? Z_OK : s->z_err;
}
#endif /* NO_GZCOMPRESS */
/* ===========================================================================
Sets the starting position for the next gzread or gzwrite on the given
compressed file. The offset represents a number of bytes in the
gzseek returns the resulting offset location as measured in bytes from
the beginning of the uncompressed stream, or -1 in case of error.
SEEK_END is not implemented, returns error.
In this version of the library, gzseek can be extremely slow.
*/
z_off_t ZEXPORT gzseek (gzFile file, z_off_t offset, int 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;
}
if (s->mode == 'w') {
#ifdef NO_GZCOMPRESS
return -1L;
#else
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->out;
}
if (offset < 0) return -1L;
if (s->transparent) {
/* 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->in = s->out = offset;
return offset;
}
/* For a negative seek, rewind and use positive seek */
if (offset >= s->out) {
offset -= s->out;
} else if (gzrewind(file) < 0) {
return -1L;
}
/* offset is now the number of bytes to skip. */
if (offset != 0 && s->outbuf == Z_NULL) {
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;
size = gzread(file, s->outbuf, (uInt)size);
if (size <= 0) return -1L;
offset -= size;
}
return s->out;
}
/* ===========================================================================
Rewinds input file.
*/
int ZEXPORT gzrewind (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->transparent) (void)inflateReset(&s->stream);
s->in = 0;
s->out = 0;
return fseek(s->file, s->start, SEEK_SET);
}
/* ===========================================================================
Returns the starting position for the next gzread or gzwrite on the
given compressed file. This position represents a number of bytes in the
uncompressed data stream.
*/
z_off_t ZEXPORT gztell (gzFile file)
{
return gzseek(file, 0L, SEEK_CUR);
}
/* ===========================================================================
Returns 1 when EOF has previously been detected reading the given
input stream, otherwise zero.
*/
int ZEXPORT gzeof (gzFile file)
{
gz_stream *s = (gz_stream*)file;
/* 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;
}
/* ===========================================================================
Returns 1 if reading and doing so transparently, otherwise zero.
*/
int ZEXPORT gzdirect (gzFile file)
{
gz_stream *s = (gz_stream*)file;
if (s == NULL || s->mode != 'r') return 0;
return s->transparent;
}
/* ===========================================================================
Outputs a long in LSB order to the given file
*/
local void putLong (FILE *file, uLong x)
{
int n;
for (n = 0; n < 4; n++) {
fputc((int)(x & 0xff), file);
x >>= 8;
}
}
/* ===========================================================================
Reads a long in LSB order from the given gz_stream. Sets z_err in case
of error.
*/
local uLong getLong (gz_stream *s)
{
uLong x = (uLong)get_byte(s);
int c;
x += ((uLong)get_byte(s))<<8;
x += ((uLong)get_byte(s))<<16;
c = get_byte(s);
if (c == EOF) s->z_err = Z_DATA_ERROR;
x += ((uLong)c)<<24;
return x;
}
/* ===========================================================================
Flushes all pending output if necessary, closes the compressed file
and deallocates all the (de)compression state.
*/
int ZEXPORT gzclose (gzFile file)
{
gz_stream *s = (gz_stream*)file;
if (s == NULL) return Z_STREAM_ERROR;
if (s->mode == 'w') {
#ifdef NO_GZCOMPRESS
return Z_STREAM_ERROR;
#else
if (do_flush (file, Z_FINISH) != Z_OK)
return destroy((gz_stream*)file);
putLong (s->file, s->crc);
putLong (s->file, (uLong)(s->in & 0xffffffff));
#endif
}
return destroy((gz_stream*)file);
}
#ifdef STDC
# define zstrerror(errnum) strerror(errnum)
#else
# define zstrerror(errnum) ""
#endif
/* ===========================================================================
Returns the error message for the last error which occurred on the
given compressed file. errnum is set to zlib error number. If an
error occurred in the file system and not in the compression library,
errnum is set to Z_ERRNO and the application may consult errno
to get the exact error code.
*/
const char * ZEXPORT gzerror (gzFile file, int *errnum)
{
char *m;
gz_stream *s = (gz_stream*)file;
if (s == NULL) {
*errnum = Z_STREAM_ERROR;
return (const char*)ERR_MSG(Z_STREAM_ERROR);
}
*errnum = s->z_err;
if (*errnum == Z_OK) return (const char*)"";
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 (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);
}

506
src/zlib/gzlib.c Normal file
View File

@ -0,0 +1,506 @@
/* gzlib.c -- zlib functions common to reading and writing gzip files
* Copyright (C) 2004, 2010 Mark Adler
* For conditions of distribution and use, see copyright notice in zlib.h
*/
#include "gzguts.h"
#if defined(_LARGEFILE64_SOURCE) && _LFS64_LARGEFILE-0
# define LSEEK lseek64
#else
# define LSEEK lseek
#endif
/* Local functions */
local void gz_reset OF((gz_statep));
local gzFile gz_open OF((const char *, int, const char *));
#if defined UNDER_CE
/* Map the Windows error number in ERROR to a locale-dependent error message
string and return a pointer to it. Typically, the values for ERROR come
from GetLastError.
The string pointed to shall not be modified by the application, but may be
overwritten by a subsequent call to gz_strwinerror
The gz_strwinerror function does not change the current setting of
GetLastError. */
char ZLIB_INTERNAL *gz_strwinerror (DWORD error)
{
static char buf[1024];
wchar_t *msgbuf;
DWORD lasterr = GetLastError();
DWORD chars = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM
| FORMAT_MESSAGE_ALLOCATE_BUFFER,
NULL,
error,
0, /* Default language */
(LPVOID)&msgbuf,
0,
NULL);
if (chars != 0) {
/* If there is an \r\n appended, zap it. */
if (chars >= 2
&& msgbuf[chars - 2] == '\r' && msgbuf[chars - 1] == '\n') {
chars -= 2;
msgbuf[chars] = 0;
}
if (chars > sizeof (buf) - 1) {
chars = sizeof (buf) - 1;
msgbuf[chars] = 0;
}
wcstombs(buf, msgbuf, chars + 1);
LocalFree(msgbuf);
}
else {
sprintf(buf, "unknown win32 error (%ld)", error);
}
SetLastError(lasterr);
return buf;
}
#endif /* UNDER_CE */
/* Reset gzip file state */
local void gz_reset(gz_statep state)
{
if (state->mode == GZ_READ) { /* for reading ... */
state->have = 0; /* no output data available */
state->eof = 0; /* not at end of file */
state->how = LOOK; /* look for gzip header */
state->direct = 1; /* default for empty file */
}
state->seek = 0; /* no seek request pending */
gz_error(state, Z_OK, NULL); /* clear error */
state->pos = 0; /* no uncompressed data yet */
state->strm.avail_in = 0; /* no input data yet */
}
/* Open a gzip file either by name or file descriptor. */
local gzFile gz_open(const char *path, int fd, const char *mode)
{
gz_statep state;
/* allocate gzFile structure to return */
state = (gz_statep) malloc(sizeof(gz_state));
if (state == NULL)
return NULL;
state->size = 0; /* no buffers allocated yet */
state->want = GZBUFSIZE; /* requested buffer size */
state->msg = NULL; /* no error message yet */
/* interpret mode */
state->mode = GZ_NONE;
state->level = Z_DEFAULT_COMPRESSION;
state->strategy = Z_DEFAULT_STRATEGY;
while (*mode) {
if (*mode >= '0' && *mode <= '9')
state->level = *mode - '0';
else
switch (*mode) {
case 'r':
state->mode = GZ_READ;
break;
#ifndef NO_GZCOMPRESS
case 'w':
state->mode = GZ_WRITE;
break;
case 'a':
state->mode = GZ_APPEND;
break;
#endif
case '+': /* can't read and write at the same time */
free(state);
return NULL;
case 'b': /* ignore -- will request binary anyway */
break;
case 'f':
state->strategy = Z_FILTERED;
break;
case 'h':
state->strategy = Z_HUFFMAN_ONLY;
break;
case 'R':
state->strategy = Z_RLE;
break;
case 'F':
state->strategy = Z_FIXED;
default: /* could consider as an error, but just ignore */
;
}
mode++;
}
/* must provide an "r", "w", or "a" */
if (state->mode == GZ_NONE) {
free(state);
return NULL;
}
/* save the path name for error messages */
state->path = (char*) malloc(strlen(path) + 1);
if (state->path == NULL) {
free(state);
return NULL;
}
strcpy(state->path, path);
/* open the file with the appropriate mode (or just use fd) */
state->fd = fd != -1 ? fd :
open(path,
#ifdef O_LARGEFILE
O_LARGEFILE |
#endif
#ifdef O_BINARY
O_BINARY |
#endif
(state->mode == GZ_READ ?
O_RDONLY :
(O_WRONLY | O_CREAT | (
state->mode == GZ_WRITE ?
O_TRUNC :
O_APPEND))),
0666);
if (state->fd == -1) {
free(state->path);
free(state);
return NULL;
}
if (state->mode == GZ_APPEND)
state->mode = GZ_WRITE; /* simplify later checks */
/* save the current position for rewinding (only if reading) */
if (state->mode == GZ_READ) {
state->start = LSEEK(state->fd, 0, SEEK_CUR);
if (state->start == -1) state->start = 0;
}
/* initialize stream */
gz_reset(state);
/* return stream */
return (gzFile)state;
}
/* -- see zlib.h -- */
gzFile ZEXPORT gzopen(const char *path, const char *mode)
{
return gz_open(path, -1, mode);
}
/* -- see zlib.h -- */
gzFile ZEXPORT gzopen64(const char *path, const char *mode)
{
return gz_open(path, -1, mode);
}
/* -- see zlib.h -- */
gzFile ZEXPORT gzdopen(int fd, const char *mode)
{
char *path; /* identifier for error messages */
gzFile gz;
if (fd == -1 || (path = (char*) malloc(7 + 3 * sizeof(int))) == NULL)
return NULL;
sprintf(path, "<fd:%d>", fd); /* for debugging */
gz = gz_open(path, fd, mode);
free(path);
return gz;
}
/* -- see zlib.h -- */
int ZEXPORT gzbuffer(gzFile file, unsigned size)
{
gz_statep state;
/* get internal structure and check integrity */
if (file == NULL)
return -1;
state = (gz_statep)file;
if (state->mode != GZ_READ && state->mode != GZ_WRITE)
return -1;
/* make sure we haven't already allocated memory */
if (state->size != 0)
return -1;
/* check and set requested size */
if (size == 0)
return -1;
state->want = size;
return 0;
}
/* -- see zlib.h -- */
int ZEXPORT gzrewind(gzFile file)
{
gz_statep state;
/* get internal structure */
if (file == NULL)
return -1;
state = (gz_statep)file;
/* check that we're reading and that there's no error */
if (state->mode != GZ_READ || state->err != Z_OK)
return -1;
/* back up and start over */
if (LSEEK(state->fd, state->start, SEEK_SET) == -1)
return -1;
gz_reset(state);
return 0;
}
/* -- see zlib.h -- */
z_off64_t ZEXPORT gzseek64(gzFile file, z_off64_t offset, int whence)
{
unsigned n;
z_off64_t ret;
gz_statep state;
/* get internal structure and check integrity */
if (file == NULL)
return -1;
state = (gz_statep)file;
if (state->mode != GZ_READ && state->mode != GZ_WRITE)
return -1;
/* check that there's no error */
if (state->err != Z_OK)
return -1;
/* can only seek from start or relative to current position */
if (whence != SEEK_SET && whence != SEEK_CUR)
return -1;
/* normalize offset to a SEEK_CUR specification */
if (whence == SEEK_SET)
offset -= state->pos;
else if (state->seek)
offset += state->skip;
state->seek = 0;
/* if within raw area while reading, just go there */
if (state->mode == GZ_READ && state->how == COPY &&
state->pos + offset >= state->raw) {
ret = LSEEK(state->fd, offset - state->have, SEEK_CUR);
if (ret == -1)
return -1;
state->have = 0;
state->eof = 0;
state->seek = 0;
gz_error(state, Z_OK, NULL);
state->strm.avail_in = 0;
state->pos += offset;
return state->pos;
}
/* calculate skip amount, rewinding if needed for back seek when reading */
if (offset < 0) {
if (state->mode != GZ_READ) /* writing -- can't go backwards */
return -1;
offset += state->pos;
if (offset < 0) /* before start of file! */
return -1;
if (gzrewind(file) == -1) /* rewind, then skip to offset */
return -1;
}
/* if reading, skip what's in output buffer (one less gzgetc() check) */
if (state->mode == GZ_READ) {
n = GT_OFF(state->have) || (z_off64_t)state->have > offset ?
(unsigned)offset : state->have;
state->have -= n;
state->next += n;
state->pos += n;
offset -= n;
}
/* request skip (if not zero) */
if (offset) {
state->seek = 1;
state->skip = offset;
}
return state->pos + offset;
}
/* -- see zlib.h -- */
z_off_t ZEXPORT gzseek(gzFile file, z_off_t offset, int whence)
{
z_off64_t ret;
ret = gzseek64(file, (z_off64_t)offset, whence);
return ret == (z_off_t)ret ? (z_off_t)ret : -1;
}
/* -- see zlib.h -- */
z_off64_t ZEXPORT gztell64(gzFile file)
{
gz_statep state;
/* get internal structure and check integrity */
if (file == NULL)
return -1;
state = (gz_statep)file;
if (state->mode != GZ_READ && state->mode != GZ_WRITE)
return -1;
/* return position */
return state->pos + (state->seek ? state->skip : 0);
}
/* -- see zlib.h -- */
z_off_t ZEXPORT gztell(gzFile file)
{
z_off64_t ret;
ret = gztell64(file);
return ret == (z_off_t)ret ? (z_off_t)ret : -1;
}
/* -- see zlib.h -- */
z_off64_t ZEXPORT gzoffset64(gzFile file)
{
z_off64_t offset;
gz_statep state;
/* get internal structure and check integrity */
if (file == NULL)
return -1;
state = (gz_statep)file;
if (state->mode != GZ_READ && state->mode != GZ_WRITE)
return -1;
/* compute and return effective offset in file */
offset = LSEEK(state->fd, 0, SEEK_CUR);
if (offset == -1)
return -1;
if (state->mode == GZ_READ) /* reading */
offset -= state->strm.avail_in; /* don't count buffered input */
return offset;
}
/* -- see zlib.h -- */
z_off_t ZEXPORT gzoffset(gzFile file)
{
z_off64_t ret;
ret = gzoffset64(file);
return ret == (z_off_t)ret ? (z_off_t)ret : -1;
}
/* -- see zlib.h -- */
int ZEXPORT gzeof(gzFile file)
{
gz_statep state;
/* get internal structure and check integrity */
if (file == NULL)
return 0;
state = (gz_statep)file;
if (state->mode != GZ_READ && state->mode != GZ_WRITE)
return 0;
/* return end-of-file state */
return state->mode == GZ_READ ?
(state->eof && state->strm.avail_in == 0 && state->have == 0) : 0;
}
/* -- see zlib.h -- */
const char * ZEXPORT gzerror(gzFile file, int *errnum)
{
gz_statep state;
/* get internal structure and check integrity */
if (file == NULL)
return NULL;
state = (gz_statep)file;
if (state->mode != GZ_READ && state->mode != GZ_WRITE)
return NULL;
/* return error information */
if (errnum != NULL)
*errnum = state->err;
return state->msg == NULL ? "" : state->msg;
}
/* -- see zlib.h -- */
void ZEXPORT gzclearerr(gzFile file)
{
gz_statep state;
/* get internal structure and check integrity */
if (file == NULL)
return;
state = (gz_statep)file;
if (state->mode != GZ_READ && state->mode != GZ_WRITE)
return;
/* clear error and end-of-file */
if (state->mode == GZ_READ)
state->eof = 0;
gz_error(state, Z_OK, NULL);
}
/* Create an error message in allocated memory and set state->err and
state->msg accordingly. Free any previous error message already there. Do
not try to free or allocate space if the error is Z_MEM_ERROR (out of
memory). Simply save the error message as a static string. If there is an
allocation failure constructing the error message, then convert the error to
out of memory. */
void ZLIB_INTERNAL gz_error(gz_statep state, int err, const char *msg)
{
/* free previously allocated message and clear */
if (state->msg != NULL) {
if (state->err != Z_MEM_ERROR)
free(state->msg);
state->msg = NULL;
}
/* set error code, and if no message, then done */
state->err = err;
if (msg == NULL)
return;
/* for an out of memory error, save as static string */
if (err == Z_MEM_ERROR) {
state->msg = (char *)msg;
return;
}
/* construct error message with path */
if ((state->msg = (char*) malloc(strlen(state->path) + strlen(msg) + 3)) == NULL) {
state->err = Z_MEM_ERROR;
state->msg = (char *)"out of memory";
return;
}
strcpy(state->msg, state->path);
strcat(state->msg, ": ");
strcat(state->msg, msg);
return;
}
#ifndef INT_MAX
/* portably return maximum value for an int (when limits.h presumed not
available) -- we need to do this to cover cases where 2's complement not
used, since C standard permits 1's complement and sign-bit representations,
otherwise we could just use ((unsigned)-1) >> 1 */
unsigned ZLIB_INTERNAL gz_intmax()
{
unsigned p, q;
p = 1;
do {
q = p;
p <<= 1;
p++;
} while (p > q);
return q >> 1;
}
#endif

631
src/zlib/gzread.c Normal file
View File

@ -0,0 +1,631 @@
/* gzread.c -- zlib functions for reading gzip files
* Copyright (C) 2004, 2005, 2010 Mark Adler
* For conditions of distribution and use, see copyright notice in zlib.h
*/
#include "gzguts.h"
/* Local functions */
local int gz_load OF((gz_statep, unsigned char *, unsigned, unsigned *));
local int gz_avail OF((gz_statep));
local int gz_next4 OF((gz_statep, unsigned long *));
local int gz_head OF((gz_statep));
local int gz_decomp OF((gz_statep));
local int gz_make OF((gz_statep));
local int gz_skip OF((gz_statep, z_off64_t));
/* Use read() to load a buffer -- return -1 on error, otherwise 0. Read from
state->fd, and update state->eof, state->err, and state->msg as appropriate.
This function needs to loop on read(), since read() is not guaranteed to
read the number of bytes requested, depending on the type of descriptor. */
local int gz_load(gz_statep state, unsigned char *buf,
unsigned len, unsigned *have)
{
int ret;
*have = 0;
do {
ret = read(state->fd, buf + *have, len - *have);
if (ret <= 0)
break;
*have += ret;
} while (*have < len);
if (ret < 0) {
gz_error(state, Z_ERRNO, zstrerror());
return -1;
}
if (ret == 0)
state->eof = 1;
return 0;
}
/* Load up input buffer and set eof flag if last data loaded -- return -1 on
error, 0 otherwise. Note that the eof flag is set when the end of the input
file is reached, even though there may be unused data in the buffer. Once
that data has been used, no more attempts will be made to read the file.
gz_avail() assumes that strm->avail_in == 0. */
local int gz_avail(gz_statep state)
{
z_streamp strm = &(state->strm);
if (state->err != Z_OK)
return -1;
if (state->eof == 0) {
if (gz_load(state, state->in, state->size,
(unsigned *)&(strm->avail_in)) == -1)
return -1;
strm->next_in = state->in;
}
return 0;
}
/* Get next byte from input, or -1 if end or error. */
#define NEXT() ((strm->avail_in == 0 && gz_avail(state) == -1) ? -1 : \
(strm->avail_in == 0 ? -1 : \
(strm->avail_in--, *(strm->next_in)++)))
/* Get a four-byte little-endian integer and return 0 on success and the value
in *ret. Otherwise -1 is returned and *ret is not modified. */
local int gz_next4(gz_statep state, unsigned long *ret)
{
int ch;
unsigned long val;
z_streamp strm = &(state->strm);
val = NEXT();
val += (unsigned)NEXT() << 8;
val += (unsigned long)NEXT() << 16;
ch = NEXT();
if (ch == -1)
return -1;
val += (unsigned long)ch << 24;
*ret = val;
return 0;
}
/* Look for gzip header, set up for inflate or copy. state->have must be zero.
If this is the first time in, allocate required memory. state->how will be
left unchanged if there is no more input data available, will be set to COPY
if there is no gzip header and direct copying will be performed, or it will
be set to GZIP for decompression, and the gzip header will be skipped so
that the next available input data is the raw deflate stream. If direct
copying, then leftover input data from the input buffer will be copied to
the output buffer. In that case, all further file reads will be directly to
either the output buffer or a user buffer. If decompressing, the inflate
state and the check value will be initialized. gz_head() will return 0 on
success or -1 on failure. Failures may include read errors or gzip header
errors. */
local int gz_head(gz_statep state)
{
z_streamp strm = &(state->strm);
int flags;
unsigned len;
/* allocate read buffers and inflate memory */
if (state->size == 0) {
/* allocate buffers */
state->in = (unsigned char*) malloc(state->want);
state->out = (unsigned char*) malloc(state->want << 1);
if (state->in == NULL || state->out == NULL) {
if (state->out != NULL)
free(state->out);
if (state->in != NULL)
free(state->in);
gz_error(state, Z_MEM_ERROR, "out of memory");
return -1;
}
state->size = state->want;
/* allocate inflate memory */
state->strm.zalloc = Z_NULL;
state->strm.zfree = Z_NULL;
state->strm.opaque = Z_NULL;
state->strm.avail_in = 0;
state->strm.next_in = Z_NULL;
if (inflateInit2(&(state->strm), -15) != Z_OK) { /* raw inflate */
free(state->out);
free(state->in);
state->size = 0;
gz_error(state, Z_MEM_ERROR, "out of memory");
return -1;
}
}
/* get some data in the input buffer */
if (strm->avail_in == 0) {
if (gz_avail(state) == -1)
return -1;
if (strm->avail_in == 0)
return 0;
}
/* look for the gzip magic header bytes 31 and 139 */
if (strm->next_in[0] == 31) {
strm->avail_in--;
strm->next_in++;
if (strm->avail_in == 0 && gz_avail(state) == -1)
return -1;
if (strm->avail_in && strm->next_in[0] == 139) {
/* we have a gzip header, woo hoo! */
strm->avail_in--;
strm->next_in++;
/* skip rest of header */
if (NEXT() != 8) { /* compression method */
gz_error(state, Z_DATA_ERROR, "unknown compression method");
return -1;
}
flags = NEXT();
if (flags & 0xe0) { /* reserved flag bits */
gz_error(state, Z_DATA_ERROR, "unknown header flags set");
return -1;
}
NEXT(); /* modification time */
NEXT();
NEXT();
NEXT();
NEXT(); /* extra flags */
NEXT(); /* operating system */
if (flags & 4) { /* extra field */
len = (unsigned)NEXT();
len += (unsigned)NEXT() << 8;
while (len--)
if (NEXT() < 0)
break;
}
if (flags & 8) /* file name */
while (NEXT() > 0)
;
if (flags & 16) /* comment */
while (NEXT() > 0)
;
if (flags & 2) { /* header crc */
NEXT();
NEXT();
}
/* an unexpected end of file is not checked for here -- it will be
noticed on the first request for uncompressed data */
/* set up for decompression */
inflateReset(strm);
strm->adler = crc32(0L, Z_NULL, 0);
state->how = GZIP;
state->direct = 0;
return 0;
}
else {
/* not a gzip file -- save first byte (31) and fall to raw i/o */
state->out[0] = 31;
state->have = 1;
}
}
/* doing raw i/o, save start of raw data for seeking, copy any leftover
input to output -- this assumes that the output buffer is larger than
the input buffer, which also assures space for gzungetc() */
state->raw = state->pos;
state->next = state->out;
if (strm->avail_in) {
memcpy(state->next + state->have, strm->next_in, strm->avail_in);
state->have += strm->avail_in;
strm->avail_in = 0;
}
state->how = COPY;
state->direct = 1;
return 0;
}
/* Decompress from input to the provided next_out and avail_out in the state.
If the end of the compressed data is reached, then verify the gzip trailer
check value and length (modulo 2^32). state->have and state->next are set
to point to the just decompressed data, and the crc is updated. If the
trailer is verified, state->how is reset to LOOK to look for the next gzip
stream or raw data, once state->have is depleted. Returns 0 on success, -1
on failure. Failures may include invalid compressed data or a failed gzip
trailer verification. */
local int gz_decomp(gz_statep state)
{
int ret;
unsigned had;
unsigned long crc, len;
z_streamp strm = &(state->strm);
/* fill output buffer up to end of deflate stream */
had = strm->avail_out;
do {
/* get more input for inflate() */
if (strm->avail_in == 0 && gz_avail(state) == -1)
return -1;
if (strm->avail_in == 0) {
gz_error(state, Z_DATA_ERROR, "unexpected end of file");
return -1;
}
/* decompress and handle errors */
ret = inflate(strm, Z_NO_FLUSH);
if (ret == Z_STREAM_ERROR || ret == Z_NEED_DICT) {
gz_error(state, Z_STREAM_ERROR,
"internal error: inflate stream corrupt");
return -1;
}
if (ret == Z_MEM_ERROR) {
gz_error(state, Z_MEM_ERROR, "out of memory");
return -1;
}
if (ret == Z_DATA_ERROR) { /* deflate stream invalid */
gz_error(state, Z_DATA_ERROR,
strm->msg == NULL ? "compressed data error" : strm->msg);
return -1;
}
} while (strm->avail_out && ret != Z_STREAM_END);
/* update available output and crc check value */
state->have = had - strm->avail_out;
state->next = strm->next_out - state->have;
strm->adler = crc32(strm->adler, state->next, state->have);
/* check gzip trailer if at end of deflate stream */
if (ret == Z_STREAM_END) {
if (gz_next4(state, &crc) == -1 || gz_next4(state, &len) == -1) {
gz_error(state, Z_DATA_ERROR, "unexpected end of file");
return -1;
}
if (crc != strm->adler) {
gz_error(state, Z_DATA_ERROR, "incorrect data check");
return -1;
}
if (len != (strm->total_out & 0xffffffffL)) {
gz_error(state, Z_DATA_ERROR, "incorrect length check");
return -1;
}
state->how = LOOK; /* ready for next stream, once have is 0 (leave
state->direct unchanged to remember how) */
}
/* good decompression */
return 0;
}
/* Make data and put in the output buffer. Assumes that state->have == 0.
Data is either copied from the input file or decompressed from the input
file depending on state->how. If state->how is LOOK, then a gzip header is
looked for (and skipped if found) to determine wither to copy or decompress.
Returns -1 on error, otherwise 0. gz_make() will leave state->have as COPY
or GZIP unless the end of the input file has been reached and all data has
been processed. */
local int gz_make(gz_statep state)
{
z_streamp strm = &(state->strm);
if (state->how == LOOK) { /* look for gzip header */
if (gz_head(state) == -1)
return -1;
if (state->have) /* got some data from gz_head() */
return 0;
}
if (state->how == COPY) { /* straight copy */
if (gz_load(state, state->out, state->size << 1, &(state->have)) == -1)
return -1;
state->next = state->out;
}
else if (state->how == GZIP) { /* decompress */
strm->avail_out = state->size << 1;
strm->next_out = state->out;
if (gz_decomp(state) == -1)
return -1;
}
return 0;
}
/* Skip len uncompressed bytes of output. Return -1 on error, 0 on success. */
local int gz_skip(gz_statep state, z_off64_t len)
{
unsigned n;
/* skip over len bytes or reach end-of-file, whichever comes first */
while (len)
/* skip over whatever is in output buffer */
if (state->have) {
n = GT_OFF(state->have) || (z_off64_t)state->have > len ?
(unsigned)len : state->have;
state->have -= n;
state->next += n;
state->pos += n;
len -= n;
}
/* output buffer empty -- return if we're at the end of the input */
else if (state->eof && state->strm.avail_in == 0)
break;
/* need more data to skip -- load up output buffer */
else {
/* get more output, looking for header if required */
if (gz_make(state) == -1)
return -1;
}
return 0;
}
/* -- see zlib.h -- */
int ZEXPORT gzread(gzFile file, voidp buf, unsigned len)
{
unsigned got, n;
gz_statep state;
z_streamp strm;
/* get internal structure */
if (file == NULL)
return -1;
state = (gz_statep)file;
strm = &(state->strm);
/* check that we're reading and that there's no error */
if (state->mode != GZ_READ || state->err != Z_OK)
return -1;
/* since an int is returned, make sure len fits in one, otherwise return
with an error (this avoids the flaw in the interface) */
if ((int)len < 0) {
gz_error(state, Z_BUF_ERROR, "requested length does not fit in int");
return -1;
}
/* if len is zero, avoid unnecessary operations */
if (len == 0)
return 0;
/* process a skip request */
if (state->seek) {
state->seek = 0;
if (gz_skip(state, state->skip) == -1)
return -1;
}
/* get len bytes to buf, or less than len if at the end */
got = 0;
do {
/* first just try copying data from the output buffer */
if (state->have) {
n = state->have > len ? len : state->have;
memcpy(buf, state->next, n);
state->next += n;
state->have -= n;
}
/* output buffer empty -- return if we're at the end of the input */
else if (state->eof && strm->avail_in == 0)
break;
/* need output data -- for small len or new stream load up our output
buffer */
else if (state->how == LOOK || len < (state->size << 1)) {
/* get more output, looking for header if required */
if (gz_make(state) == -1)
return -1;
continue; /* no progress yet -- go back to memcpy() above */
/* the copy above assures that we will leave with space in the
output buffer, allowing at least one gzungetc() to succeed */
}
/* large len -- read directly into user buffer */
else if (state->how == COPY) { /* read directly */
if (gz_load(state, (unsigned char*)buf, len, &n) == -1)
return -1;
}
/* large len -- decompress directly into user buffer */
else { /* state->how == GZIP */
strm->avail_out = len;
strm->next_out = (Bytef*) buf;
if (gz_decomp(state) == -1)
return -1;
n = state->have;
state->have = 0;
}
/* update progress */
len -= n;
buf = (char *)buf + n;
got += n;
state->pos += n;
} while (len);
/* return number of bytes read into user buffer (will fit in int) */
return (int)got;
}
/* -- see zlib.h -- */
int ZEXPORT gzgetc(gzFile file)
{
int ret;
unsigned char buf[1];
gz_statep state;
/* get internal structure */
if (file == NULL)
return -1;
state = (gz_statep)file;
/* check that we're reading and that there's no error */
if (state->mode != GZ_READ || state->err != Z_OK)
return -1;
/* try output buffer (no need to check for skip request) */
if (state->have) {
state->have--;
state->pos++;
return *(state->next)++;
}
/* nothing there -- try gzread() */
ret = gzread(file, buf, 1);
return ret < 1 ? -1 : buf[0];
}
/* -- see zlib.h -- */
int ZEXPORT gzungetc(int c, gzFile file)
{
gz_statep state;
/* get internal structure */
if (file == NULL)
return -1;
state = (gz_statep)file;
/* check that we're reading and that there's no error */
if (state->mode != GZ_READ || state->err != Z_OK)
return -1;
/* process a skip request */
if (state->seek) {
state->seek = 0;
if (gz_skip(state, state->skip) == -1)
return -1;
}
/* can't push EOF */
if (c < 0)
return -1;
/* if output buffer empty, put byte at end (allows more pushing) */
if (state->have == 0) {
state->have = 1;
state->next = state->out + (state->size << 1) - 1;
state->next[0] = c;
state->pos--;
return c;
}
/* if no room, give up (must have already done a gzungetc()) */
if (state->have == (state->size << 1)) {
gz_error(state, Z_BUF_ERROR, "out of room to push characters");
return -1;
}
/* slide output data if needed and insert byte before existing data */
if (state->next == state->out) {
unsigned char *src = state->out + state->have;
unsigned char *dest = state->out + (state->size << 1);
while (src > state->out)
*--dest = *--src;
state->next = dest;
}
state->have++;
state->next--;
state->next[0] = c;
state->pos--;
return c;
}
/* -- see zlib.h -- */
char * ZEXPORT gzgets(gzFile file, char *buf, int len)
{
unsigned left, n;
char *str;
unsigned char *eol;
gz_statep state;
/* check parameters and get internal structure */
if (file == NULL || buf == NULL || len < 1)
return NULL;
state = (gz_statep)file;
/* check that we're reading and that there's no error */
if (state->mode != GZ_READ || state->err != Z_OK)
return NULL;
/* process a skip request */
if (state->seek) {
state->seek = 0;
if (gz_skip(state, state->skip) == -1)
return NULL;
}
/* copy output bytes up to new line or len - 1, whichever comes first --
append a terminating zero to the string (we don't check for a zero in
the contents, let the user worry about that) */
str = buf;
left = (unsigned)len - 1;
if (left) do {
/* assure that something is in the output buffer */
if (state->have == 0) {
if (gz_make(state) == -1)
return NULL; /* error */
if (state->have == 0) { /* end of file */
if (buf == str) /* got bupkus */
return NULL;
break; /* got something -- return it */
}
}
/* look for end-of-line in current output buffer */
n = state->have > left ? left : state->have;
eol = (unsigned char *) memchr(state->next, '\n', n);
if (eol != NULL)
n = (unsigned)(eol - state->next) + 1;
/* copy through end-of-line, or remainder if not found */
memcpy(buf, state->next, n);
state->have -= n;
state->next += n;
state->pos += n;
left -= n;
buf += n;
} while (left && eol == NULL);
/* found end-of-line or out of space -- terminate string and return it */
buf[0] = 0;
return str;
}
/* -- see zlib.h -- */
int ZEXPORT gzdirect(gzFile file)
{
gz_statep state;
/* get internal structure */
if (file == NULL)
return 0;
state = (gz_statep)file;
/* check that we're reading */
if (state->mode != GZ_READ)
return 0;
/* if the state is not known, but we can find out, then do so (this is
mainly for right after a gzopen() or gzdopen()) */
if (state->how == LOOK && state->have == 0)
(void)gz_head(state);
/* return 1 if reading direct, 0 if decompressing a gzip stream */
return state->direct;
}
/* -- see zlib.h -- */
int ZEXPORT gzclose_r(gzFile file)
{
int ret;
gz_statep state;
/* get internal structure */
if (file == NULL)
return Z_STREAM_ERROR;
state = (gz_statep)file;
/* check that we're reading */
if (state->mode != GZ_READ)
return Z_STREAM_ERROR;
/* free memory and close file */
if (state->size) {
inflateEnd(&(state->strm));
free(state->out);
free(state->in);
}
gz_error(state, Z_OK, NULL);
free(state->path);
ret = close(state->fd);
free(state);
return ret ? Z_ERRNO : Z_OK;
}

513
src/zlib/gzwrite.c Normal file
View File

@ -0,0 +1,513 @@
/* gzwrite.c -- zlib functions for writing gzip files
* Copyright (C) 2004, 2005, 2010 Mark Adler
* For conditions of distribution and use, see copyright notice in zlib.h
*/
#include "gzguts.h"
/* Local functions */
local int gz_init OF((gz_statep));
local int gz_comp OF((gz_statep, int));
local int gz_zero OF((gz_statep, z_off64_t));
/* Initialize state for writing a gzip file. Mark initialization by setting
state->size to non-zero. Return -1 on failure or 0 on success. */
local int gz_init(gz_statep state)
{
int ret;
z_streamp strm = &(state->strm);
/* allocate input and output buffers */
state->in = (unsigned char *) malloc(state->want);
state->out = (unsigned char *) malloc(state->want);
if (state->in == NULL || state->out == NULL) {
if (state->out != NULL)
free(state->out);
if (state->in != NULL)
free(state->in);
gz_error(state, Z_MEM_ERROR, "out of memory");
return -1;
}
/* allocate deflate memory, set up for gzip compression */
strm->zalloc = Z_NULL;
strm->zfree = Z_NULL;
strm->opaque = Z_NULL;
ret = deflateInit2(strm, state->level, Z_DEFLATED,
15 + 16, 8, state->strategy);
if (ret != Z_OK) {
free(state->in);
gz_error(state, Z_MEM_ERROR, "out of memory");
return -1;
}
/* mark state as initialized */
state->size = state->want;
/* initialize write buffer */
strm->avail_out = state->size;
strm->next_out = state->out;
state->next = strm->next_out;
return 0;
}
/* Compress whatever is at avail_in and next_in and write to the output file.
Return -1 if there is an error writing to the output file, otherwise 0.
flush is assumed to be a valid deflate() flush value. If flush is Z_FINISH,
then the deflate() state is reset to start a new gzip stream. */
local int gz_comp(gz_statep state, int flush)
{
int ret, got;
unsigned have;
z_streamp strm = &(state->strm);
/* allocate memory if this is the first time through */
if (state->size == 0 && gz_init(state) == -1)
return -1;
/* run deflate() on provided input until it produces no more output */
ret = Z_OK;
do {
/* write out current buffer contents if full, or if flushing, but if
doing Z_FINISH then don't write until we get to Z_STREAM_END */
if (strm->avail_out == 0 || (flush != Z_NO_FLUSH &&
(flush != Z_FINISH || ret == Z_STREAM_END))) {
have = (unsigned)(strm->next_out - state->next);
if (have && ((got = write(state->fd, state->next, have)) < 0 ||
(unsigned)got != have)) {
gz_error(state, Z_ERRNO, zstrerror());
return -1;
}
if (strm->avail_out == 0) {
strm->avail_out = state->size;
strm->next_out = state->out;
}
state->next = strm->next_out;
}
/* compress */
have = strm->avail_out;
ret = deflate(strm, flush);
if (ret == Z_STREAM_ERROR) {
gz_error(state, Z_STREAM_ERROR,
"internal error: deflate stream corrupt");
return -1;
}
have -= strm->avail_out;
} while (have);
/* if that completed a deflate stream, allow another to start */
if (flush == Z_FINISH)
deflateReset(strm);
/* all done, no errors */
return 0;
}
/* Compress len zeros to output. Return -1 on error, 0 on success. */
local int gz_zero(gz_statep state, z_off64_t len)
{
int first;
unsigned n;
z_streamp strm = &(state->strm);
/* consume whatever's left in the input buffer */
if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1)
return -1;
/* compress len zeros (len guaranteed > 0) */
first = 1;
while (len) {
n = GT_OFF(state->size) || (z_off64_t)state->size > len ?
(unsigned)len : state->size;
if (first) {
memset(state->in, 0, n);
first = 0;
}
strm->avail_in = n;
strm->next_in = state->in;
state->pos += n;
if (gz_comp(state, Z_NO_FLUSH) == -1)
return -1;
len -= n;
}
return 0;
}
/* -- see zlib.h -- */
int ZEXPORT gzwrite(gzFile file, voidpc buf, unsigned len)
{
unsigned put = len;
unsigned n;
gz_statep state;
z_streamp strm;
/* get internal structure */
if (file == NULL)
return 0;
state = (gz_statep)file;
strm = &(state->strm);
/* check that we're writing and that there's no error */
if (state->mode != GZ_WRITE || state->err != Z_OK)
return 0;
/* since an int is returned, make sure len fits in one, otherwise return
with an error (this avoids the flaw in the interface) */
if ((int)len < 0) {
gz_error(state, Z_BUF_ERROR, "requested length does not fit in int");
return 0;
}
/* if len is zero, avoid unnecessary operations */
if (len == 0)
return 0;
/* allocate memory if this is the first time through */
if (state->size == 0 && gz_init(state) == -1)
return 0;
/* check for seek request */
if (state->seek) {
state->seek = 0;
if (gz_zero(state, state->skip) == -1)
return 0;
}
/* for small len, copy to input buffer, otherwise compress directly */
if (len < state->size) {
/* copy to input buffer, compress when full */
do {
if (strm->avail_in == 0)
strm->next_in = state->in;
n = state->size - strm->avail_in;
if (n > len)
n = len;
memcpy(strm->next_in + strm->avail_in, buf, n);
strm->avail_in += n;
state->pos += n;
buf = (char *)buf + n;
len -= n;
if (len && gz_comp(state, Z_NO_FLUSH) == -1)
return 0;
} while (len);
}
else {
/* consume whatever's left in the input buffer */
if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1)
return 0;
/* directly compress user buffer to file */
strm->avail_in = len;
strm->next_in = (Bytef*)buf;
state->pos += len;
if (gz_comp(state, Z_NO_FLUSH) == -1)
return 0;
}
/* input was all buffered or compressed (put will fit in int) */
return (int)put;
}
/* -- see zlib.h -- */
int ZEXPORT gzputc(gzFile file, int c)
{
unsigned char buf[1];
gz_statep state;
z_streamp strm;
/* get internal structure */
if (file == NULL)
return -1;
state = (gz_statep)file;
strm = &(state->strm);
/* check that we're writing and that there's no error */
if (state->mode != GZ_WRITE || state->err != Z_OK)
return -1;
/* check for seek request */
if (state->seek) {
state->seek = 0;
if (gz_zero(state, state->skip) == -1)
return -1;
}
/* try writing to input buffer for speed (state->size == 0 if buffer not
initialized) */
if (strm->avail_in < state->size) {
if (strm->avail_in == 0)
strm->next_in = state->in;
strm->next_in[strm->avail_in++] = c;
state->pos++;
return c;
}
/* no room in buffer or not initialized, use gz_write() */
buf[0] = c;
if (gzwrite(file, buf, 1) != 1)
return -1;
return c;
}
/* -- see zlib.h -- */
int ZEXPORT gzputs(gzFile file, const char *str)
{
int ret;
unsigned len;
/* write string */
len = (unsigned)strlen(str);
ret = gzwrite(file, str, len);
return ret == 0 && len != 0 ? -1 : ret;
}
#ifdef STDC
#include <stdarg.h>
/* -- see zlib.h -- */
int ZEXPORTVA gzprintf (gzFile file, const char *format, ...)
{
int size, len;
gz_statep state;
z_streamp strm;
va_list va;
/* get internal structure */
if (file == NULL)
return -1;
state = (gz_statep)file;
strm = &(state->strm);
/* check that we're writing and that there's no error */
if (state->mode != GZ_WRITE || state->err != Z_OK)
return 0;
/* make sure we have some buffer space */
if (state->size == 0 && gz_init(state) == -1)
return 0;
/* check for seek request */
if (state->seek) {
state->seek = 0;
if (gz_zero(state, state->skip) == -1)
return 0;
}
/* consume whatever's left in the input buffer */
if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1)
return 0;
/* do the printf() into the input buffer, put length in len */
size = (int)(state->size);
state->in[size - 1] = 0;
va_start(va, format);
#ifdef NO_vsnprintf
# ifdef HAS_vsprintf_void
(void)vsprintf(state->in, format, va);
va_end(va);
for (len = 0; len < size; len++)
if (state->in[len] == 0) break;
# else
len = vsprintf(state->in, format, va);
va_end(va);
# endif
#else
# ifdef HAS_vsnprintf_void
(void)vsnprintf(state->in, size, format, va);
va_end(va);
len = strlen(state->in);
# else
len = vsnprintf((char *)(state->in), size, format, va);
va_end(va);
# endif
#endif
/* check that printf() results fit in buffer */
if (len <= 0 || len >= (int)size || state->in[size - 1] != 0)
return 0;
/* update buffer and position, defer compression until needed */
strm->avail_in = (unsigned)len;
strm->next_in = state->in;
state->pos += len;
return len;
}
#else /* !STDC */
/* -- see zlib.h -- */
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)
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;
{
int size, len;
gz_statep state;
z_streamp strm;
/* get internal structure */
if (file == NULL)
return -1;
state = (gz_statep)file;
strm = &(state->strm);
/* check that we're writing and that there's no error */
if (state->mode != GZ_WRITE || state->err != Z_OK)
return 0;
/* make sure we have some buffer space */
if (state->size == 0 && gz_init(state) == -1)
return 0;
/* check for seek request */
if (state->seek) {
state->seek = 0;
if (gz_zero(state, state->skip) == -1)
return 0;
}
/* consume whatever's left in the input buffer */
if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1)
return 0;
/* do the printf() into the input buffer, put length in len */
size = (int)(state->size);
state->in[size - 1] = 0;
#ifdef NO_snprintf
# ifdef HAS_sprintf_void
sprintf(state->in, format, a1, a2, a3, a4, a5, a6, a7, a8,
a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20);
for (len = 0; len < size; len++)
if (state->in[len] == 0) break;
# else
len = sprintf(state->in, 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(state->in, size, format, a1, a2, a3, a4, a5, a6, a7, a8,
a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20);
len = strlen(state->in);
# else
len = snprintf(state->in, size, format, a1, a2, a3, a4, a5, a6, a7, a8,
a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20);
# endif
#endif
/* check that printf() results fit in buffer */
if (len <= 0 || len >= (int)size || state->in[size - 1] != 0)
return 0;
/* update buffer and position, defer compression until needed */
strm->avail_in = (unsigned)len;
strm->next_in = state->in;
state->pos += len;
return len;
}
#endif
/* -- see zlib.h -- */
int ZEXPORT gzflush(gzFile file, int flush)
{
gz_statep state;
/* get internal structure */
if (file == NULL)
return -1;
state = (gz_statep)file;
/* check that we're writing and that there's no error */
if (state->mode != GZ_WRITE || state->err != Z_OK)
return Z_STREAM_ERROR;
/* check flush parameter */
if (flush < 0 || flush > Z_FINISH)
return Z_STREAM_ERROR;
/* check for seek request */
if (state->seek) {
state->seek = 0;
if (gz_zero(state, state->skip) == -1)
return -1;
}
/* compress remaining data with requested flush */
gz_comp(state, flush);
return state->err;
}
/* -- see zlib.h -- */
int ZEXPORT gzsetparams(gzFile file, int level, int strategy)
{
gz_statep state;
z_streamp strm;
/* get internal structure */
if (file == NULL)
return Z_STREAM_ERROR;
state = (gz_statep)file;
strm = &(state->strm);
/* check that we're writing and that there's no error */
if (state->mode != GZ_WRITE || state->err != Z_OK)
return Z_STREAM_ERROR;
/* if no change is requested, then do nothing */
if (level == state->level && strategy == state->strategy)
return Z_OK;
/* check for seek request */
if (state->seek) {
state->seek = 0;
if (gz_zero(state, state->skip) == -1)
return -1;
}
/* change compression parameters for subsequent input */
if (state->size) {
/* flush previous input with previous parameters before changing */
if (strm->avail_in && gz_comp(state, Z_PARTIAL_FLUSH) == -1)
return state->err;
deflateParams(strm, level, strategy);
}
state->level = level;
state->strategy = strategy;
return Z_OK;
}
/* -- see zlib.h -- */
int ZEXPORT gzclose_w(gzFile file)
{
int ret = 0;
gz_statep state;
/* get internal structure */
if (file == NULL)
return Z_STREAM_ERROR;
state = (gz_statep)file;
/* check that we're writing */
if (state->mode != GZ_WRITE)
return Z_STREAM_ERROR;
/* check for seek request */
if (state->seek) {
state->seek = 0;
ret += gz_zero(state, state->skip);
}
/* flush, free memory, and close file */
ret += gz_comp(state, Z_FINISH);
(void)deflateEnd(&(state->strm));
free(state->out);
free(state->in);
gz_error(state, Z_OK, NULL);
free(state->path);
ret += close(state->fd);
free(state);
return ret ? Z_ERRNO : Z_OK;
}

View File

@ -1,5 +1,5 @@
/* infback.c -- inflate using a call-back interface /* infback.c -- inflate using a call-back interface
* Copyright (C) 1995-2005 Mark Adler * Copyright (C) 1995-2009 Mark Adler
* For conditions of distribution and use, see copyright notice in zlib.h * For conditions of distribution and use, see copyright notice in zlib.h
*/ */
@ -25,8 +25,10 @@ local void fixedtables OF((struct inflate_state FAR *state));
windowBits is in the range 8..15, and window is a user-supplied windowBits is in the range 8..15, and window is a user-supplied
window and output buffer that is 2**windowBits bytes. window and output buffer that is 2**windowBits bytes.
*/ */
int ZEXPORT inflateBackInit_(z_streamp strm, int windowBits, unsigned char FAR *window, int ZEXPORT inflateBackInit_(z_streamp strm, int windowBits,
const char *version, int stream_size) unsigned char FAR *window,
const char *version,
int stream_size)
{ {
struct inflate_state FAR *state; struct inflate_state FAR *state;
@ -51,7 +53,7 @@ int ZEXPORT inflateBackInit_(z_streamp strm, int windowBits, unsigned char FAR *
state->wbits = windowBits; state->wbits = windowBits;
state->wsize = 1U << windowBits; state->wsize = 1U << windowBits;
state->window = window; state->window = window;
state->write = 0; state->wnext = 0;
state->whave = 0; state->whave = 0;
return Z_OK; return Z_OK;
} }
@ -244,7 +246,7 @@ int ZEXPORT inflateBack(z_streamp strm, in_func in, void FAR *in_desc,
unsigned bits; /* bits in bit buffer */ unsigned bits; /* bits in bit buffer */
unsigned copy; /* number of stored or match bytes to copy */ unsigned copy; /* number of stored or match bytes to copy */
unsigned char FAR *from; /* where to copy match bytes from */ unsigned char FAR *from; /* where to copy match bytes from */
code This; /* current decoding table entry */ code here; /* current decoding table entry */
code last; /* parent table entry */ code last; /* parent table entry */
unsigned len; /* length to copy for repeats, bits to drop */ unsigned len; /* length to copy for repeats, bits to drop */
int ret; /* return code */ int ret; /* return code */
@ -380,19 +382,19 @@ int ZEXPORT inflateBack(z_streamp strm, in_func in, void FAR *in_desc,
state->have = 0; state->have = 0;
while (state->have < state->nlen + state->ndist) { while (state->have < state->nlen + state->ndist) {
for (;;) { for (;;) {
This = state->lencode[BITS(state->lenbits)]; here = state->lencode[BITS(state->lenbits)];
if ((unsigned)(This.bits) <= bits) break; if ((unsigned)(here.bits) <= bits) break;
PULLBYTE(); PULLBYTE();
} }
if (This.val < 16) { if (here.val < 16) {
NEEDBITS(This.bits); NEEDBITS(here.bits);
DROPBITS(This.bits); DROPBITS(here.bits);
state->lens[state->have++] = This.val; state->lens[state->have++] = here.val;
} }
else { else {
if (This.val == 16) { if (here.val == 16) {
NEEDBITS(This.bits + 2); NEEDBITS(here.bits + 2);
DROPBITS(This.bits); DROPBITS(here.bits);
if (state->have == 0) { if (state->have == 0) {
strm->msg = (char *)"invalid bit length repeat"; strm->msg = (char *)"invalid bit length repeat";
state->mode = BAD; state->mode = BAD;
@ -402,16 +404,16 @@ int ZEXPORT inflateBack(z_streamp strm, in_func in, void FAR *in_desc,
copy = 3 + BITS(2); copy = 3 + BITS(2);
DROPBITS(2); DROPBITS(2);
} }
else if (This.val == 17) { else if (here.val == 17) {
NEEDBITS(This.bits + 3); NEEDBITS(here.bits + 3);
DROPBITS(This.bits); DROPBITS(here.bits);
len = 0; len = 0;
copy = 3 + BITS(3); copy = 3 + BITS(3);
DROPBITS(3); DROPBITS(3);
} }
else { else {
NEEDBITS(This.bits + 7); NEEDBITS(here.bits + 7);
DROPBITS(This.bits); DROPBITS(here.bits);
len = 0; len = 0;
copy = 11 + BITS(7); copy = 11 + BITS(7);
DROPBITS(7); DROPBITS(7);
@ -429,7 +431,16 @@ int ZEXPORT inflateBack(z_streamp strm, in_func in, void FAR *in_desc,
/* handle error breaks in while */ /* handle error breaks in while */
if (state->mode == BAD) break; if (state->mode == BAD) break;
/* build code tables */ /* check for end-of-block code (better have one) */
if (state->lens[256] == 0) {
strm->msg = (char *)"invalid code -- missing end-of-block";
state->mode = BAD;
break;
}
/* build code tables -- note: do not change the lenbits or distbits
values here (9 and 6) without reading the comments in inftrees.h
concerning the ENOUGH constants, which depend on those values */
state->next = state->codes; state->next = state->codes;
state->lencode = (code const FAR *)(state->next); state->lencode = (code const FAR *)(state->next);
state->lenbits = 9; state->lenbits = 9;
@ -465,28 +476,28 @@ int ZEXPORT inflateBack(z_streamp strm, in_func in, void FAR *in_desc,
/* get a literal, length, or end-of-block code */ /* get a literal, length, or end-of-block code */
for (;;) { for (;;) {
This = state->lencode[BITS(state->lenbits)]; here = state->lencode[BITS(state->lenbits)];
if ((unsigned)(This.bits) <= bits) break; if ((unsigned)(here.bits) <= bits) break;
PULLBYTE(); PULLBYTE();
} }
if (This.op && (This.op & 0xf0) == 0) { if (here.op && (here.op & 0xf0) == 0) {
last = This; last = here;
for (;;) { for (;;) {
This = state->lencode[last.val + here = state->lencode[last.val +
(BITS(last.bits + last.op) >> last.bits)]; (BITS(last.bits + last.op) >> last.bits)];
if ((unsigned)(last.bits + This.bits) <= bits) break; if ((unsigned)(last.bits + here.bits) <= bits) break;
PULLBYTE(); PULLBYTE();
} }
DROPBITS(last.bits); DROPBITS(last.bits);
} }
DROPBITS(This.bits); DROPBITS(here.bits);
state->length = (unsigned)This.val; state->length = (unsigned)here.val;
/* process literal */ /* process literal */
if (This.op == 0) { if (here.op == 0) {
Tracevv((stderr, This.val >= 0x20 && This.val < 0x7f ? Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ?
"inflate: literal '%c'\n" : "inflate: literal '%c'\n" :
"inflate: literal 0x%02x\n", This.val)); "inflate: literal 0x%02x\n", here.val));
ROOM(); ROOM();
*put++ = (unsigned char)(state->length); *put++ = (unsigned char)(state->length);
left--; left--;
@ -495,21 +506,21 @@ int ZEXPORT inflateBack(z_streamp strm, in_func in, void FAR *in_desc,
} }
/* process end of block */ /* process end of block */
if (This.op & 32) { if (here.op & 32) {
Tracevv((stderr, "inflate: end of block\n")); Tracevv((stderr, "inflate: end of block\n"));
state->mode = TYPE; state->mode = TYPE;
break; break;
} }
/* invalid code */ /* invalid code */
if (This.op & 64) { if (here.op & 64) {
strm->msg = (char *)"invalid literal/length code"; strm->msg = (char *)"invalid literal/length code";
state->mode = BAD; state->mode = BAD;
break; break;
} }
/* length code -- get extra bits, if any */ /* length code -- get extra bits, if any */
state->extra = (unsigned)(This.op) & 15; state->extra = (unsigned)(here.op) & 15;
if (state->extra != 0) { if (state->extra != 0) {
NEEDBITS(state->extra); NEEDBITS(state->extra);
state->length += BITS(state->extra); state->length += BITS(state->extra);
@ -519,30 +530,30 @@ int ZEXPORT inflateBack(z_streamp strm, in_func in, void FAR *in_desc,
/* get distance code */ /* get distance code */
for (;;) { for (;;) {
This = state->distcode[BITS(state->distbits)]; here = state->distcode[BITS(state->distbits)];
if ((unsigned)(This.bits) <= bits) break; if ((unsigned)(here.bits) <= bits) break;
PULLBYTE(); PULLBYTE();
} }
if ((This.op & 0xf0) == 0) { if ((here.op & 0xf0) == 0) {
last = This; last = here;
for (;;) { for (;;) {
This = state->distcode[last.val + here = state->distcode[last.val +
(BITS(last.bits + last.op) >> last.bits)]; (BITS(last.bits + last.op) >> last.bits)];
if ((unsigned)(last.bits + This.bits) <= bits) break; if ((unsigned)(last.bits + here.bits) <= bits) break;
PULLBYTE(); PULLBYTE();
} }
DROPBITS(last.bits); DROPBITS(last.bits);
} }
DROPBITS(This.bits); DROPBITS(here.bits);
if (This.op & 64) { if (here.op & 64) {
strm->msg = (char *)"invalid distance code"; strm->msg = (char *)"invalid distance code";
state->mode = BAD; state->mode = BAD;
break; break;
} }
state->offset = (unsigned)This.val; state->offset = (unsigned)here.val;
/* get distance extra bits, if any */ /* get distance extra bits, if any */
state->extra = (unsigned)(This.op) & 15; state->extra = (unsigned)(here.op) & 15;
if (state->extra != 0) { if (state->extra != 0) {
NEEDBITS(state->extra); NEEDBITS(state->extra);
state->offset += BITS(state->extra); state->offset += BITS(state->extra);

View File

@ -1,5 +1,5 @@
/* inffast.c -- fast decoding /* inffast.c -- fast decoding
* Copyright (C) 1995-2004 Mark Adler * Copyright (C) 1995-2008, 2010 Mark Adler
* For conditions of distribution and use, see copyright notice in zlib.h * For conditions of distribution and use, see copyright notice in zlib.h
*/ */
@ -64,7 +64,10 @@
requires strm->avail_out >= 258 for each loop to avoid checking for requires strm->avail_out >= 258 for each loop to avoid checking for
output space. output space.
*/ */
void inflate_fast(z_streamp strm, unsigned start) void ZLIB_INTERNAL inflate_fast(
z_streamp strm,
unsigned start /* inflate()'s starting value for strm->avail_out */
)
{ {
struct inflate_state FAR *state; struct inflate_state FAR *state;
unsigned char FAR *in; /* local strm->next_in */ unsigned char FAR *in; /* local strm->next_in */
@ -77,7 +80,7 @@ void inflate_fast(z_streamp strm, unsigned start)
#endif #endif
unsigned wsize; /* window size or zero if not using window */ unsigned wsize; /* window size or zero if not using window */
unsigned whave; /* valid bytes in the window */ unsigned whave; /* valid bytes in the window */
unsigned write; /* window write index */ unsigned wnext; /* window write index */
unsigned char FAR *window; /* allocated sliding window, if wsize != 0 */ unsigned char FAR *window; /* allocated sliding window, if wsize != 0 */
unsigned long hold; /* local strm->hold */ unsigned long hold; /* local strm->hold */
unsigned bits; /* local strm->bits */ unsigned bits; /* local strm->bits */
@ -85,7 +88,7 @@ void inflate_fast(z_streamp strm, unsigned start)
code const FAR *dcode; /* local strm->distcode */ code const FAR *dcode; /* local strm->distcode */
unsigned lmask; /* mask for first level of length codes */ unsigned lmask; /* mask for first level of length codes */
unsigned dmask; /* mask for first level of distance codes */ unsigned dmask; /* mask for first level of distance codes */
code This; /* retrieved table entry */ code here; /* retrieved table entry */
unsigned op; /* code bits, operation, extra bits, or */ unsigned op; /* code bits, operation, extra bits, or */
/* window position, window bytes to copy */ /* window position, window bytes to copy */
unsigned len; /* match length, unused bytes */ unsigned len; /* match length, unused bytes */
@ -104,7 +107,7 @@ void inflate_fast(z_streamp strm, unsigned start)
#endif #endif
wsize = state->wsize; wsize = state->wsize;
whave = state->whave; whave = state->whave;
write = state->write; wnext = state->wnext;
window = state->window; window = state->window;
hold = state->hold; hold = state->hold;
bits = state->bits; bits = state->bits;
@ -122,20 +125,20 @@ void inflate_fast(z_streamp strm, unsigned start)
hold += (unsigned long)(PUP(in)) << bits; hold += (unsigned long)(PUP(in)) << bits;
bits += 8; bits += 8;
} }
This = lcode[hold & lmask]; here = lcode[hold & lmask];
dolen: dolen:
op = (unsigned)(This.bits); op = (unsigned)(here.bits);
hold >>= op; hold >>= op;
bits -= op; bits -= op;
op = (unsigned)(This.op); op = (unsigned)(here.op);
if (op == 0) { /* literal */ if (op == 0) { /* literal */
Tracevv((stderr, This.val >= 0x20 && This.val < 0x7f ? Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ?
"inflate: literal '%c'\n" : "inflate: literal '%c'\n" :
"inflate: literal 0x%02x\n", This.val)); "inflate: literal 0x%02x\n", here.val));
PUP(out) = (unsigned char)(This.val); PUP(out) = (unsigned char)(here.val);
} }
else if (op & 16) { /* length base */ else if (op & 16) { /* length base */
len = (unsigned)(This.val); len = (unsigned)(here.val);
op &= 15; /* number of extra bits */ op &= 15; /* number of extra bits */
if (op) { if (op) {
if (bits < op) { if (bits < op) {
@ -153,14 +156,14 @@ void inflate_fast(z_streamp strm, unsigned start)
hold += (unsigned long)(PUP(in)) << bits; hold += (unsigned long)(PUP(in)) << bits;
bits += 8; bits += 8;
} }
This = dcode[hold & dmask]; here = dcode[hold & dmask];
dodist: dodist:
op = (unsigned)(This.bits); op = (unsigned)(here.bits);
hold >>= op; hold >>= op;
bits -= op; bits -= op;
op = (unsigned)(This.op); op = (unsigned)(here.op);
if (op & 16) { /* distance base */ if (op & 16) { /* distance base */
dist = (unsigned)(This.val); dist = (unsigned)(here.val);
op &= 15; /* number of extra bits */ op &= 15; /* number of extra bits */
if (bits < op) { if (bits < op) {
hold += (unsigned long)(PUP(in)) << bits; hold += (unsigned long)(PUP(in)) << bits;
@ -185,12 +188,34 @@ void inflate_fast(z_streamp strm, unsigned start)
if (dist > op) { /* see if copy from window */ if (dist > op) { /* see if copy from window */
op = dist - op; /* distance back in window */ op = dist - op; /* distance back in window */
if (op > whave) { if (op > whave) {
strm->msg = (char *)"invalid distance too far back"; if (state->sane) {
strm->msg =
(char *)"invalid distance too far back";
state->mode = BAD; state->mode = BAD;
break; break;
} }
#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR
if (len <= op - whave) {
do {
PUP(out) = 0;
} while (--len);
continue;
}
len -= op - whave;
do {
PUP(out) = 0;
} while (--op > whave);
if (op == 0) {
from = out - dist;
do {
PUP(out) = PUP(from);
} while (--len);
continue;
}
#endif
}
from = window - OFF; from = window - OFF;
if (write == 0) { /* very common case */ if (wnext == 0) { /* very common case */
from += wsize - op; from += wsize - op;
if (op < len) { /* some from window */ if (op < len) { /* some from window */
len -= op; len -= op;
@ -200,17 +225,17 @@ void inflate_fast(z_streamp strm, unsigned start)
from = out - dist; /* rest from output */ from = out - dist; /* rest from output */
} }
} }
else if (write < op) { /* wrap around window */ else if (wnext < op) { /* wrap around window */
from += wsize + write - op; from += wsize + wnext - op;
op -= write; op -= wnext;
if (op < len) { /* some from end of window */ if (op < len) { /* some from end of window */
len -= op; len -= op;
do { do {
PUP(out) = PUP(from); PUP(out) = PUP(from);
} while (--op); } while (--op);
from = window - OFF; from = window - OFF;
if (write < len) { /* some from start of window */ if (wnext < len) { /* some from start of window */
op = write; op = wnext;
len -= op; len -= op;
do { do {
PUP(out) = PUP(from); PUP(out) = PUP(from);
@ -220,7 +245,7 @@ void inflate_fast(z_streamp strm, unsigned start)
} }
} }
else { /* contiguous in window */ else { /* contiguous in window */
from += write - op; from += wnext - op;
if (op < len) { /* some from window */ if (op < len) { /* some from window */
len -= op; len -= op;
do { do {
@ -257,7 +282,7 @@ void inflate_fast(z_streamp strm, unsigned start)
} }
} }
else if ((op & 64) == 0) { /* 2nd level distance code */ else if ((op & 64) == 0) { /* 2nd level distance code */
This = dcode[This.val + (hold & ((1U << op) - 1))]; here = dcode[here.val + (hold & ((1U << op) - 1))];
goto dodist; goto dodist;
} }
else { else {
@ -267,7 +292,7 @@ void inflate_fast(z_streamp strm, unsigned start)
} }
} }
else if ((op & 64) == 0) { /* 2nd level length code */ else if ((op & 64) == 0) { /* 2nd level length code */
This = lcode[This.val + (hold & ((1U << op) - 1))]; here = lcode[here.val + (hold & ((1U << op) - 1))];
goto dolen; goto dolen;
} }
else if (op & 32) { /* end-of-block */ else if (op & 32) { /* end-of-block */
@ -303,7 +328,7 @@ void inflate_fast(z_streamp strm, unsigned start)
inflate_fast() speedups that turned out slower (on a PowerPC G3 750CXe): inflate_fast() speedups that turned out slower (on a PowerPC G3 750CXe):
- Using bit fields for code structure - Using bit fields for code structure
- Different op definition to avoid & for extra bits (do & for table bits) - Different op definition to avoid & for extra bits (do & for table bits)
- Three separate decoding do-loops for direct, window, and write == 0 - Three separate decoding do-loops for direct, window, and wnext == 0
- Special case for distance > 1 copies to do overlapped load and store copy - Special case for distance > 1 copies to do overlapped load and store copy
- Explicit branch predictions (based on measured branch probabilities) - Explicit branch predictions (based on measured branch probabilities)
- Deferring match copy and interspersed it with decoding subsequent codes - Deferring match copy and interspersed it with decoding subsequent codes

View File

@ -1,5 +1,5 @@
/* inffast.h -- header to use inffast.c /* inffast.h -- header to use inffast.c
* Copyright (C) 1995-2003 Mark Adler * Copyright (C) 1995-2003, 2010 Mark Adler
* For conditions of distribution and use, see copyright notice in zlib.h * For conditions of distribution and use, see copyright notice in zlib.h
*/ */
@ -8,4 +8,4 @@
subject to change. Applications should only use zlib.h. subject to change. Applications should only use zlib.h.
*/ */
void inflate_fast OF((z_streamp strm, unsigned start)); void ZLIB_INTERNAL inflate_fast OF((z_streamp strm, unsigned start));

View File

@ -1,5 +1,5 @@
/* inflate.c -- zlib decompression /* inflate.c -- zlib decompression
* Copyright (C) 1995-2005 Mark Adler * Copyright (C) 1995-2010 Mark Adler
* For conditions of distribution and use, see copyright notice in zlib.h * For conditions of distribution and use, see copyright notice in zlib.h
*/ */
@ -45,7 +45,7 @@
* - Rearrange window copies in inflate_fast() for speed and simplification * - Rearrange window copies in inflate_fast() for speed and simplification
* - Unroll last copy for window match in inflate_fast() * - Unroll last copy for window match in inflate_fast()
* - Use local copies of window variables in inflate_fast() for speed * - Use local copies of window variables in inflate_fast() for speed
* - Pull out common write == 0 case for speed in inflate_fast() * - Pull out common wnext == 0 case for speed in inflate_fast()
* - Make op and len in inflate_fast() unsigned for consistency * - Make op and len in inflate_fast() unsigned for consistency
* - Add FAR to lcode and dcode declarations in inflate_fast() * - Add FAR to lcode and dcode declarations in inflate_fast()
* - Simplified bad distance check in inflate_fast() * - Simplified bad distance check in inflate_fast()
@ -116,29 +116,56 @@ int ZEXPORT inflateReset(z_streamp strm)
state->head = Z_NULL; state->head = Z_NULL;
state->wsize = 0; state->wsize = 0;
state->whave = 0; state->whave = 0;
state->write = 0; state->wnext = 0;
state->hold = 0; state->hold = 0;
state->bits = 0; state->bits = 0;
state->lencode = state->distcode = state->next = state->codes; state->lencode = state->distcode = state->next = state->codes;
state->sane = 1;
state->back = -1;
Tracev((stderr, "inflate: reset\n")); Tracev((stderr, "inflate: reset\n"));
return Z_OK; return Z_OK;
} }
int ZEXPORT inflatePrime(z_streamp strm, int bits, int value) int ZEXPORT inflateReset2(z_streamp strm, int windowBits)
{ {
int wrap;
struct inflate_state FAR *state; struct inflate_state FAR *state;
/* get the state */
if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
state = (struct inflate_state FAR *)strm->state; state = (struct inflate_state FAR *)strm->state;
if (bits > 16 || state->bits + bits > 32) return Z_STREAM_ERROR;
value &= (1L << bits) - 1; /* extract wrap request from windowBits parameter */
state->hold += value << state->bits; if (windowBits < 0) {
state->bits += bits; wrap = 0;
return Z_OK; windowBits = -windowBits;
}
else {
wrap = (windowBits >> 4) + 1;
#ifdef GUNZIP
if (windowBits < 48)
windowBits &= 15;
#endif
}
/* set number of window bits, free window if different */
if (windowBits && (windowBits < 8 || windowBits > 15))
return Z_STREAM_ERROR;
if (state->window != Z_NULL && state->wbits != (unsigned)windowBits) {
ZFREE(strm, state->window);
state->window = Z_NULL;
}
/* update state and reset the rest of it */
state->wrap = wrap;
state->wbits = (unsigned)windowBits;
return inflateReset(strm);
} }
int ZEXPORT inflateInit2_(z_streamp strm, int windowBits, const char *version, int stream_size) int ZEXPORT inflateInit2_(z_streamp strm, int windowBits,
const char *version, int stream_size)
{ {
int ret;
struct inflate_state FAR *state; struct inflate_state FAR *state;
if (version == Z_NULL || version[0] != ZLIB_VERSION[0] || if (version == Z_NULL || version[0] != ZLIB_VERSION[0] ||
@ -156,31 +183,39 @@ int ZEXPORT inflateInit2_(z_streamp strm, int windowBits, const char *version, i
if (state == Z_NULL) return Z_MEM_ERROR; if (state == Z_NULL) return Z_MEM_ERROR;
Tracev((stderr, "inflate: allocated\n")); Tracev((stderr, "inflate: allocated\n"));
strm->state = (struct internal_state FAR *)state; strm->state = (struct internal_state FAR *)state;
if (windowBits < 0) { state->window = Z_NULL;
state->wrap = 0; ret = inflateReset2(strm, windowBits);
windowBits = -windowBits; if (ret != Z_OK) {
}
else {
state->wrap = (windowBits >> 4) + 1;
#ifdef GUNZIP
if (windowBits < 48) windowBits &= 15;
#endif
}
if (windowBits < 8 || windowBits > 15) {
ZFREE(strm, state); ZFREE(strm, state);
strm->state = Z_NULL; strm->state = Z_NULL;
return Z_STREAM_ERROR;
} }
state->wbits = (unsigned)windowBits; return ret;
state->window = Z_NULL;
return inflateReset(strm);
} }
int ZEXPORT inflateInit_(z_streamp strm, const char *version, int stream_size) int ZEXPORT inflateInit_(z_streamp strm,
const char *version, int stream_size)
{ {
return inflateInit2_(strm, DEF_WBITS, version, stream_size); return inflateInit2_(strm, DEF_WBITS, version, stream_size);
} }
int ZEXPORT inflatePrime(z_streamp strm, int bits, int value)
{
struct inflate_state FAR *state;
if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
state = (struct inflate_state FAR *)strm->state;
if (bits < 0) {
state->hold = 0;
state->bits = 0;
return Z_OK;
}
if (bits > 16 || state->bits + bits > 32) return Z_STREAM_ERROR;
value &= (1L << bits) - 1;
state->hold += value << state->bits;
state->bits += bits;
return Z_OK;
}
/* /*
Return state with length and distance decoding tables and index sizes set to Return state with length and distance decoding tables and index sizes set to
fixed code decoding. Normally this returns fixed tables from inffixed.h. fixed code decoding. Normally this returns fixed tables from inffixed.h.
@ -326,7 +361,7 @@ local int updatewindow(z_streamp strm, unsigned out)
/* if window not in use yet, initialize */ /* if window not in use yet, initialize */
if (state->wsize == 0) { if (state->wsize == 0) {
state->wsize = 1U << state->wbits; state->wsize = 1U << state->wbits;
state->write = 0; state->wnext = 0;
state->whave = 0; state->whave = 0;
} }
@ -334,22 +369,22 @@ local int updatewindow(z_streamp strm, unsigned out)
copy = out - strm->avail_out; copy = out - strm->avail_out;
if (copy >= state->wsize) { if (copy >= state->wsize) {
zmemcpy(state->window, strm->next_out - state->wsize, state->wsize); zmemcpy(state->window, strm->next_out - state->wsize, state->wsize);
state->write = 0; state->wnext = 0;
state->whave = state->wsize; state->whave = state->wsize;
} }
else { else {
dist = state->wsize - state->write; dist = state->wsize - state->wnext;
if (dist > copy) dist = copy; if (dist > copy) dist = copy;
zmemcpy(state->window + state->write, strm->next_out - copy, dist); zmemcpy(state->window + state->wnext, strm->next_out - copy, dist);
copy -= dist; copy -= dist;
if (copy) { if (copy) {
zmemcpy(state->window, strm->next_out - copy, copy); zmemcpy(state->window, strm->next_out - copy, copy);
state->write = copy; state->wnext = copy;
state->whave = state->wsize; state->whave = state->wsize;
} }
else { else {
state->write += dist; state->wnext += dist;
if (state->write == state->wsize) state->write = 0; if (state->wnext == state->wsize) state->wnext = 0;
if (state->whave < state->wsize) state->whave += dist; if (state->whave < state->wsize) state->whave += dist;
} }
} }
@ -548,7 +583,7 @@ int ZEXPORT inflate(z_streamp strm, int flush)
unsigned in, out; /* save starting available input and output */ unsigned in, out; /* save starting available input and output */
unsigned copy; /* number of stored or match bytes to copy */ unsigned copy; /* number of stored or match bytes to copy */
unsigned char FAR *from; /* where to copy match bytes from */ unsigned char FAR *from; /* where to copy match bytes from */
code This; /* current decoding table entry */ code here; /* current decoding table entry */
code last; /* parent table entry */ code last; /* parent table entry */
unsigned len; /* length to copy for repeats, bits to drop */ unsigned len; /* length to copy for repeats, bits to drop */
int ret; /* return code */ int ret; /* return code */
@ -603,7 +638,9 @@ int ZEXPORT inflate(z_streamp strm, int flush)
} }
DROPBITS(4); DROPBITS(4);
len = BITS(4) + 8; len = BITS(4) + 8;
if (len > state->wbits) { if (state->wbits == 0)
state->wbits = len;
else if (len > state->wbits) {
strm->msg = (char *)"invalid window size"; strm->msg = (char *)"invalid window size";
state->mode = BAD; state->mode = BAD;
break; break;
@ -755,7 +792,7 @@ int ZEXPORT inflate(z_streamp strm, int flush)
strm->adler = state->check = adler32(0L, Z_NULL, 0); strm->adler = state->check = adler32(0L, Z_NULL, 0);
state->mode = TYPE; state->mode = TYPE;
case TYPE: case TYPE:
if (flush == Z_BLOCK) goto inf_leave; if (flush == Z_BLOCK || flush == Z_TREES) goto inf_leave;
case TYPEDO: case TYPEDO:
if (state->last) { if (state->last) {
BYTEBITS(); BYTEBITS();
@ -775,7 +812,11 @@ int ZEXPORT inflate(z_streamp strm, int flush)
fixedtables(state); fixedtables(state);
Tracev((stderr, "inflate: fixed codes block%s\n", Tracev((stderr, "inflate: fixed codes block%s\n",
state->last ? " (last)" : "")); state->last ? " (last)" : ""));
state->mode = LEN; /* decode codes */ state->mode = LEN_; /* decode codes */
if (flush == Z_TREES) {
DROPBITS(2);
goto inf_leave;
}
break; break;
case 2: /* dynamic block */ case 2: /* dynamic block */
Tracev((stderr, "inflate: dynamic codes block%s\n", Tracev((stderr, "inflate: dynamic codes block%s\n",
@ -800,6 +841,9 @@ int ZEXPORT inflate(z_streamp strm, int flush)
Tracev((stderr, "inflate: stored length %u\n", Tracev((stderr, "inflate: stored length %u\n",
state->length)); state->length));
INITBITS(); INITBITS();
state->mode = COPY_;
if (flush == Z_TREES) goto inf_leave;
case COPY_:
state->mode = COPY; state->mode = COPY;
case COPY: case COPY:
copy = state->length; copy = state->length;
@ -860,19 +904,19 @@ int ZEXPORT inflate(z_streamp strm, int flush)
case CODELENS: case CODELENS:
while (state->have < state->nlen + state->ndist) { while (state->have < state->nlen + state->ndist) {
for (;;) { for (;;) {
This = state->lencode[BITS(state->lenbits)]; here = state->lencode[BITS(state->lenbits)];
if ((unsigned)(This.bits) <= bits) break; if ((unsigned)(here.bits) <= bits) break;
PULLBYTE(); PULLBYTE();
} }
if (This.val < 16) { if (here.val < 16) {
NEEDBITS(This.bits); NEEDBITS(here.bits);
DROPBITS(This.bits); DROPBITS(here.bits);
state->lens[state->have++] = This.val; state->lens[state->have++] = here.val;
} }
else { else {
if (This.val == 16) { if (here.val == 16) {
NEEDBITS(This.bits + 2); NEEDBITS(here.bits + 2);
DROPBITS(This.bits); DROPBITS(here.bits);
if (state->have == 0) { if (state->have == 0) {
strm->msg = (char *)"invalid bit length repeat"; strm->msg = (char *)"invalid bit length repeat";
state->mode = BAD; state->mode = BAD;
@ -882,16 +926,16 @@ int ZEXPORT inflate(z_streamp strm, int flush)
copy = 3 + BITS(2); copy = 3 + BITS(2);
DROPBITS(2); DROPBITS(2);
} }
else if (This.val == 17) { else if (here.val == 17) {
NEEDBITS(This.bits + 3); NEEDBITS(here.bits + 3);
DROPBITS(This.bits); DROPBITS(here.bits);
len = 0; len = 0;
copy = 3 + BITS(3); copy = 3 + BITS(3);
DROPBITS(3); DROPBITS(3);
} }
else { else {
NEEDBITS(This.bits + 7); NEEDBITS(here.bits + 7);
DROPBITS(This.bits); DROPBITS(here.bits);
len = 0; len = 0;
copy = 11 + BITS(7); copy = 11 + BITS(7);
DROPBITS(7); DROPBITS(7);
@ -909,7 +953,16 @@ int ZEXPORT inflate(z_streamp strm, int flush)
/* handle error breaks in while */ /* handle error breaks in while */
if (state->mode == BAD) break; if (state->mode == BAD) break;
/* build code tables */ /* check for end-of-block code (better have one) */
if (state->lens[256] == 0) {
strm->msg = (char *)"invalid code -- missing end-of-block";
state->mode = BAD;
break;
}
/* build code tables -- note: do not change the lenbits or distbits
values here (9 and 6) without reading the comments in inftrees.h
concerning the ENOUGH constants, which depend on those values */
state->next = state->codes; state->next = state->codes;
state->lencode = (code const FAR *)(state->next); state->lencode = (code const FAR *)(state->next);
state->lenbits = 9; state->lenbits = 9;
@ -930,88 +983,102 @@ int ZEXPORT inflate(z_streamp strm, int flush)
break; break;
} }
Tracev((stderr, "inflate: codes ok\n")); Tracev((stderr, "inflate: codes ok\n"));
state->mode = LEN_;
if (flush == Z_TREES) goto inf_leave;
case LEN_:
state->mode = LEN; state->mode = LEN;
case LEN: case LEN:
if (have >= 6 && left >= 258) { if (have >= 6 && left >= 258) {
RESTORE(); RESTORE();
inflate_fast(strm, out); inflate_fast(strm, out);
LOAD(); LOAD();
if (state->mode == TYPE)
state->back = -1;
break; break;
} }
state->back = 0;
for (;;) { for (;;) {
This = state->lencode[BITS(state->lenbits)]; here = state->lencode[BITS(state->lenbits)];
if ((unsigned)(This.bits) <= bits) break; if ((unsigned)(here.bits) <= bits) break;
PULLBYTE(); PULLBYTE();
} }
if (This.op && (This.op & 0xf0) == 0) { if (here.op && (here.op & 0xf0) == 0) {
last = This; last = here;
for (;;) { for (;;) {
This = state->lencode[last.val + here = state->lencode[last.val +
(BITS(last.bits + last.op) >> last.bits)]; (BITS(last.bits + last.op) >> last.bits)];
if ((unsigned)(last.bits + This.bits) <= bits) break; if ((unsigned)(last.bits + here.bits) <= bits) break;
PULLBYTE(); PULLBYTE();
} }
DROPBITS(last.bits); DROPBITS(last.bits);
state->back += last.bits;
} }
DROPBITS(This.bits); DROPBITS(here.bits);
state->length = (unsigned)This.val; state->back += here.bits;
if ((int)(This.op) == 0) { state->length = (unsigned)here.val;
Tracevv((stderr, This.val >= 0x20 && This.val < 0x7f ? if ((int)(here.op) == 0) {
Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ?
"inflate: literal '%c'\n" : "inflate: literal '%c'\n" :
"inflate: literal 0x%02x\n", This.val)); "inflate: literal 0x%02x\n", here.val));
state->mode = LIT; state->mode = LIT;
break; break;
} }
if (This.op & 32) { if (here.op & 32) {
Tracevv((stderr, "inflate: end of block\n")); Tracevv((stderr, "inflate: end of block\n"));
state->back = -1;
state->mode = TYPE; state->mode = TYPE;
break; break;
} }
if (This.op & 64) { if (here.op & 64) {
strm->msg = (char *)"invalid literal/length code"; strm->msg = (char *)"invalid literal/length code";
state->mode = BAD; state->mode = BAD;
break; break;
} }
state->extra = (unsigned)(This.op) & 15; state->extra = (unsigned)(here.op) & 15;
state->mode = LENEXT; state->mode = LENEXT;
case LENEXT: case LENEXT:
if (state->extra) { if (state->extra) {
NEEDBITS(state->extra); NEEDBITS(state->extra);
state->length += BITS(state->extra); state->length += BITS(state->extra);
DROPBITS(state->extra); DROPBITS(state->extra);
state->back += state->extra;
} }
Tracevv((stderr, "inflate: length %u\n", state->length)); Tracevv((stderr, "inflate: length %u\n", state->length));
state->was = state->length;
state->mode = DIST; state->mode = DIST;
case DIST: case DIST:
for (;;) { for (;;) {
This = state->distcode[BITS(state->distbits)]; here = state->distcode[BITS(state->distbits)];
if ((unsigned)(This.bits) <= bits) break; if ((unsigned)(here.bits) <= bits) break;
PULLBYTE(); PULLBYTE();
} }
if ((This.op & 0xf0) == 0) { if ((here.op & 0xf0) == 0) {
last = This; last = here;
for (;;) { for (;;) {
This = state->distcode[last.val + here = state->distcode[last.val +
(BITS(last.bits + last.op) >> last.bits)]; (BITS(last.bits + last.op) >> last.bits)];
if ((unsigned)(last.bits + This.bits) <= bits) break; if ((unsigned)(last.bits + here.bits) <= bits) break;
PULLBYTE(); PULLBYTE();
} }
DROPBITS(last.bits); DROPBITS(last.bits);
state->back += last.bits;
} }
DROPBITS(This.bits); DROPBITS(here.bits);
if (This.op & 64) { state->back += here.bits;
if (here.op & 64) {
strm->msg = (char *)"invalid distance code"; strm->msg = (char *)"invalid distance code";
state->mode = BAD; state->mode = BAD;
break; break;
} }
state->offset = (unsigned)This.val; state->offset = (unsigned)here.val;
state->extra = (unsigned)(This.op) & 15; state->extra = (unsigned)(here.op) & 15;
state->mode = DISTEXT; state->mode = DISTEXT;
case DISTEXT: case DISTEXT:
if (state->extra) { if (state->extra) {
NEEDBITS(state->extra); NEEDBITS(state->extra);
state->offset += BITS(state->extra); state->offset += BITS(state->extra);
DROPBITS(state->extra); DROPBITS(state->extra);
state->back += state->extra;
} }
#ifdef INFLATE_STRICT #ifdef INFLATE_STRICT
if (state->offset > state->dmax) { if (state->offset > state->dmax) {
@ -1020,11 +1087,6 @@ int ZEXPORT inflate(z_streamp strm, int flush)
break; break;
} }
#endif #endif
if (state->offset > state->whave + out - left) {
strm->msg = (char *)"invalid distance too far back";
state->mode = BAD;
break;
}
Tracevv((stderr, "inflate: distance %u\n", state->offset)); Tracevv((stderr, "inflate: distance %u\n", state->offset));
state->mode = MATCH; state->mode = MATCH;
case MATCH: case MATCH:
@ -1032,12 +1094,32 @@ int ZEXPORT inflate(z_streamp strm, int flush)
copy = out - left; copy = out - left;
if (state->offset > copy) { /* copy from window */ if (state->offset > copy) { /* copy from window */
copy = state->offset - copy; copy = state->offset - copy;
if (copy > state->write) { if (copy > state->whave) {
copy -= state->write; if (state->sane) {
strm->msg = (char *)"invalid distance too far back";
state->mode = BAD;
break;
}
#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR
Trace((stderr, "inflate.c too far\n"));
copy -= state->whave;
if (copy > state->length) copy = state->length;
if (copy > left) copy = left;
left -= copy;
state->length -= copy;
do {
*put++ = 0;
} while (--copy);
if (state->length == 0) state->mode = LEN;
break;
#endif
}
if (copy > state->wnext) {
copy -= state->wnext;
from = state->window + (state->wsize - copy); from = state->window + (state->wsize - copy);
} }
else else
from = state->window + (state->write - copy); from = state->window + (state->wnext - copy);
if (copy > state->length) copy = state->length; if (copy > state->length) copy = state->length;
} }
else { /* copy from output */ else { /* copy from output */
@ -1130,7 +1212,8 @@ int ZEXPORT inflate(z_streamp strm, int flush)
strm->adler = state->check = strm->adler = state->check =
UPDATE(state->check, strm->next_out - out, out); UPDATE(state->check, strm->next_out - out, out);
strm->data_type = state->bits + (state->last ? 64 : 0) + strm->data_type = state->bits + (state->last ? 64 : 0) +
(state->mode == TYPE ? 128 : 0); (state->mode == TYPE ? 128 : 0) +
(state->mode == LEN_ || state->mode == COPY_ ? 256 : 0);
if (((in == 0 && out == 0) || flush == Z_FINISH) && ret == Z_OK) if (((in == 0 && out == 0) || flush == Z_FINISH) && ret == Z_OK)
ret = Z_BUF_ERROR; ret = Z_BUF_ERROR;
return ret; return ret;
@ -1149,7 +1232,8 @@ int ZEXPORT inflateEnd(z_streamp strm)
return Z_OK; return Z_OK;
} }
int ZEXPORT inflateSetDictionary(z_streamp strm, const Bytef *dictionary, uInt dictLength) int ZEXPORT inflateSetDictionary(z_streamp strm, const Bytef *dictionary,
uInt dictLength)
{ {
struct inflate_state FAR *state; struct inflate_state FAR *state;
unsigned long id; unsigned long id;
@ -1214,7 +1298,8 @@ int ZEXPORT inflateGetHeader(z_streamp strm, gz_headerp head)
called again with more data and the *have state. *have is initialized to called again with more data and the *have state. *have is initialized to
zero for the first call. zero for the first call.
*/ */
local unsigned syncsearch(unsigned FAR *have, unsigned char FAR *buf, unsigned len) local unsigned syncsearch(unsigned FAR *have, unsigned char FAR *buf,
unsigned len)
{ {
unsigned got; unsigned got;
unsigned next; unsigned next;
@ -1337,3 +1422,29 @@ int ZEXPORT inflateCopy(z_streamp dest, z_streamp source)
dest->state = (struct internal_state FAR *)copy; dest->state = (struct internal_state FAR *)copy;
return Z_OK; return Z_OK;
} }
int ZEXPORT inflateUndermine(z_streamp strm, int subvert)
{
struct inflate_state FAR *state;
if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
state = (struct inflate_state FAR *)strm->state;
state->sane = !subvert;
#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR
return Z_OK;
#else
state->sane = 1;
return Z_DATA_ERROR;
#endif
}
long ZEXPORT inflateMark(z_streamp strm)
{
struct inflate_state FAR *state;
if (strm == Z_NULL || strm->state == Z_NULL) return -1L << 16;
state = (struct inflate_state FAR *)strm->state;
return ((long)(state->back) << 16) +
(state->mode == COPY ? state->length :
(state->mode == MATCH ? state->was - state->length : 0));
}

View File

@ -1,5 +1,5 @@
/* inflate.h -- internal inflate state definition /* inflate.h -- internal inflate state definition
* Copyright (C) 1995-2004 Mark Adler * Copyright (C) 1995-2009 Mark Adler
* For conditions of distribution and use, see copyright notice in zlib.h * For conditions of distribution and use, see copyright notice in zlib.h
*/ */
@ -32,11 +32,13 @@ typedef enum {
TYPE, /* i: waiting for type bits, including last-flag bit */ TYPE, /* i: waiting for type bits, including last-flag bit */
TYPEDO, /* i: same, but skip check to exit inflate on new block */ TYPEDO, /* i: same, but skip check to exit inflate on new block */
STORED, /* i: waiting for stored size (length and complement) */ STORED, /* i: waiting for stored size (length and complement) */
COPY_, /* i/o: same as COPY below, but only first time in */
COPY, /* i/o: waiting for input or output to copy stored block */ COPY, /* i/o: waiting for input or output to copy stored block */
TABLE, /* i: waiting for dynamic block table lengths */ TABLE, /* i: waiting for dynamic block table lengths */
LENLENS, /* i: waiting for code length code lengths */ LENLENS, /* i: waiting for code length code lengths */
CODELENS, /* i: waiting for length/lit and distance code lengths */ CODELENS, /* i: waiting for length/lit and distance code lengths */
LEN, /* i: waiting for length/lit code */ LEN_, /* i: same as LEN below, but only first time in */
LEN, /* i: waiting for length/lit/eob code */
LENEXT, /* i: waiting for length extra bits */ LENEXT, /* i: waiting for length extra bits */
DIST, /* i: waiting for distance code */ DIST, /* i: waiting for distance code */
DISTEXT, /* i: waiting for distance extra bits */ DISTEXT, /* i: waiting for distance extra bits */
@ -53,19 +55,21 @@ typedef enum {
/* /*
State transitions between above modes - State transitions between above modes -
(most modes can go to the BAD or MEM mode -- not shown for clarity) (most modes can go to BAD or MEM on error -- not shown for clarity)
Process header: Process header:
HEAD -> (gzip) or (zlib) HEAD -> (gzip) or (zlib) or (raw)
(gzip) -> FLAGS -> TIME -> OS -> EXLEN -> EXTRA -> NAME (gzip) -> FLAGS -> TIME -> OS -> EXLEN -> EXTRA -> NAME -> COMMENT ->
NAME -> COMMENT -> HCRC -> TYPE HCRC -> TYPE
(zlib) -> DICTID or TYPE (zlib) -> DICTID or TYPE
DICTID -> DICT -> TYPE DICTID -> DICT -> TYPE
(raw) -> TYPEDO
Read deflate blocks: Read deflate blocks:
TYPE -> STORED or TABLE or LEN or CHECK TYPE -> TYPEDO -> STORED or TABLE or LEN_ or CHECK
STORED -> COPY -> TYPE STORED -> COPY_ -> COPY -> TYPE
TABLE -> LENLENS -> CODELENS -> LEN TABLE -> LENLENS -> CODELENS -> LEN_
Read deflate codes: LEN_ -> LEN
Read deflate codes in fixed or dynamic block:
LEN -> LENEXT or LIT or TYPE LEN -> LENEXT or LIT or TYPE
LENEXT -> DIST -> DISTEXT -> MATCH -> LEN LENEXT -> DIST -> DISTEXT -> MATCH -> LEN
LIT -> LEN LIT -> LEN
@ -73,7 +77,7 @@ typedef enum {
CHECK -> LENGTH -> DONE CHECK -> LENGTH -> DONE
*/ */
/* state maintained between inflate() calls. Approximately 7K bytes. */ /* state maintained between inflate() calls. Approximately 10K bytes. */
struct inflate_state { struct inflate_state {
inflate_mode mode; /* current inflate mode */ inflate_mode mode; /* current inflate mode */
int last; /* true if processing last block */ int last; /* true if processing last block */
@ -88,7 +92,7 @@ struct inflate_state {
unsigned wbits; /* log base 2 of requested window size */ unsigned wbits; /* log base 2 of requested window size */
unsigned wsize; /* window size or zero if not using window */ unsigned wsize; /* window size or zero if not using window */
unsigned whave; /* valid bytes in the window */ unsigned whave; /* valid bytes in the window */
unsigned write; /* window write index */ unsigned wnext; /* window write index */
unsigned char FAR *window; /* allocated sliding window, if needed */ unsigned char FAR *window; /* allocated sliding window, if needed */
/* bit accumulator */ /* bit accumulator */
unsigned long hold; /* input bit accumulator */ unsigned long hold; /* input bit accumulator */
@ -112,4 +116,7 @@ struct inflate_state {
unsigned short lens[320]; /* temporary storage for code lengths */ unsigned short lens[320]; /* temporary storage for code lengths */
unsigned short work[288]; /* work area for code table building */ unsigned short work[288]; /* work area for code table building */
code codes[ENOUGH]; /* space for code tables */ code codes[ENOUGH]; /* space for code tables */
int sane; /* if false, allow invalid distance too far */
int back; /* bits back of last unprocessed length/lit */
unsigned was; /* initial length of match */
}; };

View File

@ -1,5 +1,5 @@
/* inftrees.c -- generate Huffman trees for efficient decoding /* inftrees.c -- generate Huffman trees for efficient decoding
* Copyright (C) 1995-2005 Mark Adler * Copyright (C) 1995-2010 Mark Adler
* For conditions of distribution and use, see copyright notice in zlib.h * For conditions of distribution and use, see copyright notice in zlib.h
*/ */
@ -9,7 +9,7 @@
#define MAXBITS 15 #define MAXBITS 15
const char inflate_copyright[] = const char inflate_copyright[] =
" inflate 1.2.3 Copyright 1995-2005 Mark Adler "; " inflate 1.2.5 Copyright 1995-2010 Mark Adler ";
/* /*
If you use the zlib library in a product, an acknowledgment is welcome If you use the zlib library in a product, an acknowledgment is welcome
in the documentation of your product. If for some reason you cannot in the documentation of your product. If for some reason you cannot
@ -29,8 +29,9 @@ const char inflate_copyright[] =
table index bits. It will differ if the request is greater than the table index bits. It will differ if the request is greater than the
longest code or if it is less than the shortest code. longest code or if it is less than the shortest code.
*/ */
int inflate_table(codetype type, unsigned short FAR *lens, unsigned codes, int ZLIB_INTERNAL inflate_table(codetype type, unsigned short FAR *lens,
code FAR * FAR *table, unsigned FAR *bits, unsigned short FAR *work) unsigned codes, code FAR * FAR *table,
unsigned FAR *bits, unsigned short FAR *work)
{ {
unsigned len; /* a code's length in bits */ unsigned len; /* a code's length in bits */
unsigned sym; /* index of code symbols */ unsigned sym; /* index of code symbols */
@ -45,7 +46,7 @@ int inflate_table(codetype type, unsigned short FAR *lens, unsigned codes,
unsigned fill; /* index for replicating entries */ unsigned fill; /* index for replicating entries */
unsigned low; /* low bits for current root entry */ unsigned low; /* low bits for current root entry */
unsigned mask; /* mask for low root bits */ unsigned mask; /* mask for low root bits */
code This; /* table entry for duplication */ code here; /* table entry for duplication */
code FAR *next; /* next available space in table */ code FAR *next; /* next available space in table */
const unsigned short FAR *base; /* base value table to use */ const unsigned short FAR *base; /* base value table to use */
const unsigned short FAR *extra; /* extra bits table to use */ const unsigned short FAR *extra; /* extra bits table to use */
@ -57,7 +58,7 @@ int inflate_table(codetype type, unsigned short FAR *lens, unsigned codes,
35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0}; 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0};
static const unsigned short lext[31] = { /* Length codes 257..285 extra */ static const unsigned short lext[31] = { /* Length codes 257..285 extra */
16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 18, 18, 18, 18, 16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 18, 18, 18, 18,
19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 16, 201, 196}; 19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 16, 73, 195};
static const unsigned short dbase[32] = { /* Distance codes 0..29 base */ static const unsigned short dbase[32] = { /* Distance codes 0..29 base */
1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193,
257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145,
@ -81,9 +82,9 @@ int inflate_table(codetype type, unsigned short FAR *lens, unsigned codes,
are incremented backwards. are incremented backwards.
This routine assumes, but does not check, that all of the entries in This routine assumes, but does not check, that all of the entries in
lens[] are in the range 0..MAXBITS. The caller must assure This. lens[] are in the range 0..MAXBITS. The caller must assure this.
1..MAXBITS is interpreted as that code length. zero means that that 1..MAXBITS is interpreted as that code length. zero means that that
symbol does not occur in This code. symbol does not occur in this code.
The codes are sorted by computing a count of codes for each length, The codes are sorted by computing a count of codes for each length,
creating from that a table of starting indices for each length in the creating from that a table of starting indices for each length in the
@ -110,15 +111,15 @@ int inflate_table(codetype type, unsigned short FAR *lens, unsigned codes,
if (count[max] != 0) break; if (count[max] != 0) break;
if (root > max) root = max; if (root > max) root = max;
if (max == 0) { /* no symbols to code at all */ if (max == 0) { /* no symbols to code at all */
This.op = (unsigned char)64; /* invalid code marker */ here.op = (unsigned char)64; /* invalid code marker */
This.bits = (unsigned char)1; here.bits = (unsigned char)1;
This.val = (unsigned short)0; here.val = (unsigned short)0;
*(*table)++ = This; /* make a table to force an error */ *(*table)++ = here; /* make a table to force an error */
*(*table)++ = This; *(*table)++ = here;
*bits = 1; *bits = 1;
return 0; /* no symbols, but wait for decoding to report error */ return 0; /* no symbols, but wait for decoding to report error */
} }
for (min = 1; min <= MAXBITS; min++) for (min = 1; min < max; min++)
if (count[min] != 0) break; if (count[min] != 0) break;
if (root < min) root = min; if (root < min) root = min;
@ -142,7 +143,7 @@ int inflate_table(codetype type, unsigned short FAR *lens, unsigned codes,
if (lens[sym] != 0) work[offs[lens[sym]]++] = (unsigned short)sym; if (lens[sym] != 0) work[offs[lens[sym]]++] = (unsigned short)sym;
/* /*
Create and fill in decoding tables. In This loop, the table being Create and fill in decoding tables. In this loop, the table being
filled is at next and has curr index bits. The code being used is huff filled is at next and has curr index bits. The code being used is huff
with length len. That code is converted to an index by dropping drop with length len. That code is converted to an index by dropping drop
bits off of the bottom. For codes where len is less than drop + curr, bits off of the bottom. For codes where len is less than drop + curr,
@ -157,19 +158,18 @@ int inflate_table(codetype type, unsigned short FAR *lens, unsigned codes,
When a new sub-table is needed, it is necessary to look ahead in the When a new sub-table is needed, it is necessary to look ahead in the
code lengths to determine what size sub-table is needed. The length code lengths to determine what size sub-table is needed. The length
counts are used for This, and so count[] is decremented as codes are counts are used for this, and so count[] is decremented as codes are
entered in the tables. entered in the tables.
used keeps track of how many table entries have been allocated from the used keeps track of how many table entries have been allocated from the
provided *table space. It is checked when a LENS table is being made provided *table space. It is checked for LENS and DIST tables against
against the space in *table, ENOUGH, minus the maximum space needed by the constants ENOUGH_LENS and ENOUGH_DISTS to guard against changes in
the worst case distance code, MAXD. This should never happen, but the the initial root table size constants. See the comments in inftrees.h
sufficiency of ENOUGH has not been proven exhaustively, hence the check. for more information.
This assumes that when type == LENS, bits == 9.
sym increments through all symbols, and the loop terminates when sym increments through all symbols, and the loop terminates when
all codes of length max, i.e. all codes, have been processed. This all codes of length max, i.e. all codes, have been processed. This
routine permits incomplete codes, so another loop after This one fills routine permits incomplete codes, so another loop after this one fills
in the rest of the decoding tables with invalid code markers. in the rest of the decoding tables with invalid code markers.
*/ */
@ -204,24 +204,25 @@ int inflate_table(codetype type, unsigned short FAR *lens, unsigned codes,
mask = used - 1; /* mask for comparing low */ mask = used - 1; /* mask for comparing low */
/* check available table space */ /* check available table space */
if (type == LENS && used >= ENOUGH - MAXD) if ((type == LENS && used >= ENOUGH_LENS) ||
(type == DISTS && used >= ENOUGH_DISTS))
return 1; return 1;
/* process all codes and make table entries */ /* process all codes and make table entries */
for (;;) { for (;;) {
/* create table entry */ /* create table entry */
This.bits = (unsigned char)(len - drop); here.bits = (unsigned char)(len - drop);
if ((int)(work[sym]) < end) { if ((int)(work[sym]) < end) {
This.op = (unsigned char)0; here.op = (unsigned char)0;
This.val = work[sym]; here.val = work[sym];
} }
else if ((int)(work[sym]) > end) { else if ((int)(work[sym]) > end) {
This.op = (unsigned char)(extra[work[sym]]); here.op = (unsigned char)(extra[work[sym]]);
This.val = base[work[sym]]; here.val = base[work[sym]];
} }
else { else {
This.op = (unsigned char)(32 + 64); /* end of block */ here.op = (unsigned char)(32 + 64); /* end of block */
This.val = 0; here.val = 0;
} }
/* replicate for those indices with low len bits equal to huff */ /* replicate for those indices with low len bits equal to huff */
@ -230,7 +231,7 @@ int inflate_table(codetype type, unsigned short FAR *lens, unsigned codes,
min = fill; /* save offset to next table */ min = fill; /* save offset to next table */
do { do {
fill -= incr; fill -= incr;
next[(huff >> drop) + fill] = This; next[(huff >> drop) + fill] = here;
} while (fill != 0); } while (fill != 0);
/* backwards increment the len-bit code huff */ /* backwards increment the len-bit code huff */
@ -272,7 +273,8 @@ int inflate_table(codetype type, unsigned short FAR *lens, unsigned codes,
/* check for enough space */ /* check for enough space */
used += 1U << curr; used += 1U << curr;
if (type == LENS && used >= ENOUGH - MAXD) if ((type == LENS && used >= ENOUGH_LENS) ||
(type == DISTS && used >= ENOUGH_DISTS))
return 1; return 1;
/* point entry in root table to sub-table */ /* point entry in root table to sub-table */
@ -290,20 +292,20 @@ int inflate_table(codetype type, unsigned short FAR *lens, unsigned codes,
through high index bits. When the current sub-table is filled, the loop through high index bits. When the current sub-table is filled, the loop
drops back to the root table to fill in any remaining entries there. drops back to the root table to fill in any remaining entries there.
*/ */
This.op = (unsigned char)64; /* invalid code marker */ here.op = (unsigned char)64; /* invalid code marker */
This.bits = (unsigned char)(len - drop); here.bits = (unsigned char)(len - drop);
This.val = (unsigned short)0; here.val = (unsigned short)0;
while (huff != 0) { while (huff != 0) {
/* when done with sub-table, drop back to root table */ /* when done with sub-table, drop back to root table */
if (drop != 0 && (huff & mask) != low) { if (drop != 0 && (huff & mask) != low) {
drop = 0; drop = 0;
len = root; len = root;
next = *table; next = *table;
This.bits = (unsigned char)len; here.bits = (unsigned char)len;
} }
/* put invalid code marker in table */ /* put invalid code marker in table */
next[huff >> drop] = This; next[huff >> drop] = here;
/* backwards increment the len-bit code huff */ /* backwards increment the len-bit code huff */
incr = 1U << (len - 1); incr = 1U << (len - 1);

View File

@ -1,5 +1,5 @@
/* inftrees.h -- header to use inftrees.c /* inftrees.h -- header to use inftrees.c
* Copyright (C) 1995-2005 Mark Adler * Copyright (C) 1995-2005, 2010 Mark Adler
* For conditions of distribution and use, see copyright notice in zlib.h * For conditions of distribution and use, see copyright notice in zlib.h
*/ */
@ -35,21 +35,28 @@ typedef struct {
01000000 - invalid code 01000000 - invalid code
*/ */
/* Maximum size of dynamic tree. The maximum found in a long but non- /* Maximum size of the dynamic table. The maximum number of code structures is
exhaustive search was 1444 code structures (852 for length/literals 1444, which is the sum of 852 for literal/length codes and 592 for distance
and 592 for distances, the latter actually the result of an codes. These values were found by exhaustive searches using the program
exhaustive search). The true maximum is not known, but the value examples/enough.c found in the zlib distribtution. The arguments to that
below is more than safe. */ program are the number of symbols, the initial root table size, and the
#define ENOUGH 2048 maximum bit length of a code. "enough 286 9 15" for literal/length codes
#define MAXD 592 returns returns 852, and "enough 30 6 15" for distance codes returns 592.
The initial root table size (9 or 6) is found in the fifth argument of the
inflate_table() calls in inflate.c and infback.c. If the root table size is
changed, then these maximum sizes would be need to be recalculated and
updated. */
#define ENOUGH_LENS 852
#define ENOUGH_DISTS 592
#define ENOUGH (ENOUGH_LENS+ENOUGH_DISTS)
/* Type of code to build for inftable() */ /* Type of code to build for inflate_table() */
typedef enum { typedef enum {
CODES, CODES,
LENS, LENS,
DISTS DISTS
} codetype; } codetype;
extern int inflate_table OF((codetype type, unsigned short FAR *lens, int ZLIB_INTERNAL inflate_table OF((codetype type, unsigned short FAR *lens,
unsigned codes, code FAR * FAR *table, unsigned codes, code FAR * FAR *table,
unsigned FAR *bits, unsigned short FAR *work)); unsigned FAR *bits, unsigned short FAR *work));

View File

@ -1,5 +1,5 @@
/* minigzip.c -- simulate gzip using the zlib compression library /* minigzip.c -- simulate gzip using the zlib compression library
* Copyright (C) 1995-2005 Jean-loup Gailly. * Copyright (C) 1995-2006, 2010 Jean-loup Gailly.
* For conditions of distribution and use, see copyright notice in zlib.h * For conditions of distribution and use, see copyright notice in zlib.h
*/ */
@ -15,8 +15,8 @@
/* @(#) $Id$ */ /* @(#) $Id$ */
#include <stdio.h>
#include "zlib.h" #include "zlib.h"
#include <stdio.h>
#ifdef STDC #ifdef STDC
# include <string.h> # include <string.h>
@ -32,6 +32,9 @@
#if defined(MSDOS) || defined(OS2) || defined(WIN32) || defined(__CYGWIN__) #if defined(MSDOS) || defined(OS2) || defined(WIN32) || defined(__CYGWIN__)
# include <fcntl.h> # include <fcntl.h>
# include <io.h> # include <io.h>
# ifdef UNDER_CE
# include <stdlib.h>
# endif
# define SET_BINARY_MODE(file) setmode(fileno(file), O_BINARY) # define SET_BINARY_MODE(file) setmode(fileno(file), O_BINARY)
#else #else
# define SET_BINARY_MODE(file) # define SET_BINARY_MODE(file)
@ -50,9 +53,73 @@
# include <unix.h> /* for fileno */ # include <unix.h> /* for fileno */
#endif #endif
#if !defined(Z_HAVE_UNISTD_H) && !defined(_LARGEFILE64_SOURCE)
#ifndef WIN32 /* unlink already in stdio.h for WIN32 */ #ifndef WIN32 /* unlink already in stdio.h for WIN32 */
extern int unlink OF((const char *)); extern int unlink OF((const char *));
#endif #endif
#endif
#if defined(UNDER_CE)
# include <windows.h>
# define perror(s) pwinerror(s)
/* Map the Windows error number in ERROR to a locale-dependent error
message string and return a pointer to it. Typically, the values
for ERROR come from GetLastError.
The string pointed to shall not be modified by the application,
but may be overwritten by a subsequent call to strwinerror
The strwinerror function does not change the current setting
of GetLastError. */
static char *strwinerror (DWORD error)
{
static char buf[1024];
wchar_t *msgbuf;
DWORD lasterr = GetLastError();
DWORD chars = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM
| FORMAT_MESSAGE_ALLOCATE_BUFFER,
NULL,
error,
0, /* Default language */
(LPVOID)&msgbuf,
0,
NULL);
if (chars != 0) {
/* If there is an \r\n appended, zap it. */
if (chars >= 2
&& msgbuf[chars - 2] == '\r' && msgbuf[chars - 1] == '\n') {
chars -= 2;
msgbuf[chars] = 0;
}
if (chars > sizeof (buf) - 1) {
chars = sizeof (buf) - 1;
msgbuf[chars] = 0;
}
wcstombs(buf, msgbuf, chars + 1);
LocalFree(msgbuf);
}
else {
sprintf(buf, "unknown win32 error (%ld)", error);
}
SetLastError(lasterr);
return buf;
}
static void pwinerror (const char *s)
{
if (s && *s)
fprintf(stderr, "%s: %s\n", s, strwinerror(GetLastError ()));
else
fprintf(stderr, "%s\n", strwinerror(GetLastError ()));
}
#endif /* UNDER_CE */
#ifndef GZ_SUFFIX #ifndef GZ_SUFFIX
# define GZ_SUFFIX ".gz" # define GZ_SUFFIX ".gz"
@ -189,6 +256,11 @@ void file_compress(char *file, char *mode)
FILE *in; FILE *in;
gzFile out; gzFile out;
if (strlen(file) + strlen(GZ_SUFFIX) >= sizeof(outfile)) {
fprintf(stderr, "%s: filename too long\n", prog);
exit(1);
}
strcpy(outfile, file); strcpy(outfile, file);
strcat(outfile, GZ_SUFFIX); strcat(outfile, GZ_SUFFIX);
@ -217,7 +289,12 @@ void file_uncompress(char *file)
char *infile, *outfile; char *infile, *outfile;
FILE *out; FILE *out;
gzFile in; gzFile in;
uInt len = (uInt)strlen(file); size_t len = strlen(file);
if (len + strlen(GZ_SUFFIX) >= sizeof(buf)) {
fprintf(stderr, "%s: filename too long\n", prog);
exit(1);
}
strcpy(buf, file); strcpy(buf, file);
@ -248,7 +325,8 @@ void file_uncompress(char *file)
/* =========================================================================== /* ===========================================================================
* Usage: minigzip [-d] [-f] [-h] [-r] [-1 to -9] [files...] * Usage: minigzip [-c] [-d] [-f] [-h] [-r] [-1 to -9] [files...]
* -c : write to standard output
* -d : decompress * -d : decompress
* -f : compress with Z_FILTERED * -f : compress with Z_FILTERED
* -h : compress with Z_HUFFMAN_ONLY * -h : compress with Z_HUFFMAN_ONLY
@ -258,17 +336,30 @@ void file_uncompress(char *file)
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
int copyout = 0;
int uncompr = 0; int uncompr = 0;
gzFile file; gzFile file;
char outmode[20]; char *bname, outmode[20];
strcpy(outmode, "wb6 "); strcpy(outmode, "wb6 ");
prog = argv[0]; prog = argv[0];
bname = strrchr(argv[0], '/');
if (bname)
bname++;
else
bname = argv[0];
argc--, argv++; argc--, argv++;
if (!strcmp(bname, "gunzip"))
uncompr = 1;
else if (!strcmp(bname, "zcat"))
copyout = uncompr = 1;
while (argc > 0) { while (argc > 0) {
if (strcmp(*argv, "-d") == 0) if (strcmp(*argv, "-c") == 0)
copyout = 1;
else if (strcmp(*argv, "-d") == 0)
uncompr = 1; uncompr = 1;
else if (strcmp(*argv, "-f") == 0) else if (strcmp(*argv, "-f") == 0)
outmode[3] = 'f'; outmode[3] = 'f';
@ -298,12 +389,37 @@ int main(int argc, char *argv[])
gz_compress(stdin, file); gz_compress(stdin, file);
} }
} else { } else {
if (copyout) {
SET_BINARY_MODE(stdout);
}
do { do {
if (uncompr) { if (uncompr) {
if (copyout) {
file = gzopen(*argv, "rb");
if (file == NULL)
fprintf(stderr, "%s: can't gzopen %s\n", prog, *argv);
else
gz_uncompress(file, stdout);
} else {
file_uncompress(*argv); file_uncompress(*argv);
}
} else {
if (copyout) {
FILE * in = fopen(*argv, "rb");
if (in == NULL) {
perror(*argv);
} else {
file = gzdopen(fileno(stdout), outmode);
if (file == NULL) error("can't gzdopen stdout");
gz_compress(in, file);
}
} else { } else {
file_compress(*argv, outmode); file_compress(*argv, outmode);
} }
}
} while (argv++, --argc); } while (argv++, --argc);
} }
return 0; return 0;

View File

@ -4,7 +4,10 @@ MODULE_OBJS := \
src/zlib/adler32.o \ src/zlib/adler32.o \
src/zlib/compress.o \ src/zlib/compress.o \
src/zlib/crc32.o \ src/zlib/crc32.o \
src/zlib/gzio.o \ src/zlib/gzclose.o \
src/zlib/gzlib.o \
src/zlib/gzread.o \
src/zlib/gzwrite.o \
src/zlib/uncompr.o \ src/zlib/uncompr.o \
src/zlib/deflate.o \ src/zlib/deflate.o \
src/zlib/trees.o \ src/zlib/trees.o \

View File

@ -1,5 +1,6 @@
/* trees.c -- output deflated data using Huffman coding /* trees.c -- output deflated data using Huffman coding
* Copyright (C) 1995-2005 Jean-loup Gailly * Copyright (C) 1995-2010 Jean-loup Gailly
* detect_data_type() function provided freely by Cosmin Truta, 2006
* For conditions of distribution and use, see copyright notice in zlib.h * For conditions of distribution and use, see copyright notice in zlib.h
*/ */
@ -152,7 +153,7 @@ local void send_all_trees OF((deflate_state *s, int lcodes, int dcodes,
int blcodes)); int blcodes));
local void compress_block OF((deflate_state *s, ct_data *ltree, local void compress_block OF((deflate_state *s, ct_data *ltree,
ct_data *dtree)); ct_data *dtree));
local void set_data_type OF((deflate_state *s)); local int detect_data_type OF((deflate_state *s));
local unsigned bi_reverse OF((unsigned value, int length)); local unsigned bi_reverse OF((unsigned value, int length));
local void bi_windup OF((deflate_state *s)); local void bi_windup OF((deflate_state *s));
local void bi_flush OF((deflate_state *s)); local void bi_flush OF((deflate_state *s));
@ -189,7 +190,10 @@ local void gen_trees_header OF((void));
#ifdef DEBUG #ifdef DEBUG
local void send_bits OF((deflate_state *s, int value, int length)); local void send_bits OF((deflate_state *s, int value, int length));
local void send_bits(deflate_state *s, int value, int length) local void send_bits(s, value, length)
deflate_state *s;
int value; /* value to send */
int length; /* number of bits */
{ {
Tracevv((stderr," l %2d v %4x ", length, value)); Tracevv((stderr," l %2d v %4x ", length, value));
Assert(length > 0 && length <= 15, "invalid length"); Assert(length > 0 && length <= 15, "invalid length");
@ -200,12 +204,12 @@ local void send_bits(deflate_state *s, int value, int length)
* unused bits in value. * unused bits in value.
*/ */
if (s->bi_valid > (int)Buf_size - length) { if (s->bi_valid > (int)Buf_size - length) {
s->bi_buf |= (value << s->bi_valid); s->bi_buf |= (ush)value << s->bi_valid;
put_short(s, s->bi_buf); put_short(s, s->bi_buf);
s->bi_buf = (ush)value >> (Buf_size - s->bi_valid); s->bi_buf = (ush)value >> (Buf_size - s->bi_valid);
s->bi_valid += length - Buf_size; s->bi_valid += length - Buf_size;
} else { } else {
s->bi_buf |= value << s->bi_valid; s->bi_buf |= (ush)value << s->bi_valid;
s->bi_valid += length; s->bi_valid += length;
} }
} }
@ -215,12 +219,12 @@ local void send_bits(deflate_state *s, int value, int length)
{ int len = length;\ { int len = length;\
if (s->bi_valid > (int)Buf_size - len) {\ if (s->bi_valid > (int)Buf_size - len) {\
int val = value;\ int val = value;\
s->bi_buf |= (val << s->bi_valid);\ s->bi_buf |= (ush)val << s->bi_valid;\
put_short(s, s->bi_buf);\ put_short(s, s->bi_buf);\
s->bi_buf = (ush)val >> (Buf_size - s->bi_valid);\ s->bi_buf = (ush)val >> (Buf_size - s->bi_valid);\
s->bi_valid += len - Buf_size;\ s->bi_valid += len - Buf_size;\
} else {\ } else {\
s->bi_buf |= (value) << s->bi_valid;\ s->bi_buf |= (ush)(value) << s->bi_valid;\
s->bi_valid += len;\ s->bi_valid += len;\
}\ }\
} }
@ -247,11 +251,13 @@ local void tr_static_init()
if (static_init_done) return; if (static_init_done) return;
/* For some embedded targets, global variables are not initialized: */ /* For some embedded targets, global variables are not initialized: */
#ifdef NO_INIT_GLOBAL_POINTERS
static_l_desc.static_tree = static_ltree; static_l_desc.static_tree = static_ltree;
static_l_desc.extra_bits = extra_lbits; static_l_desc.extra_bits = extra_lbits;
static_d_desc.static_tree = static_dtree; static_d_desc.static_tree = static_dtree;
static_d_desc.extra_bits = extra_dbits; static_d_desc.extra_bits = extra_dbits;
static_bl_desc.extra_bits = extra_blbits; static_bl_desc.extra_bits = extra_blbits;
#endif
/* Initialize the mapping length (0..255) -> length code (0..28) */ /* Initialize the mapping length (0..255) -> length code (0..28) */
length = 0; length = 0;
@ -345,13 +351,14 @@ void gen_trees_header()
static_dtree[i].Len, SEPARATOR(i, D_CODES-1, 5)); static_dtree[i].Len, SEPARATOR(i, D_CODES-1, 5));
} }
fprintf(header, "const uch _dist_code[DIST_CODE_LEN] = {\n"); fprintf(header, "const uch ZLIB_INTERNAL _dist_code[DIST_CODE_LEN] = {\n");
for (i = 0; i < DIST_CODE_LEN; i++) { for (i = 0; i < DIST_CODE_LEN; i++) {
fprintf(header, "%2u%s", _dist_code[i], fprintf(header, "%2u%s", _dist_code[i],
SEPARATOR(i, DIST_CODE_LEN-1, 20)); SEPARATOR(i, DIST_CODE_LEN-1, 20));
} }
fprintf(header, "const uch _length_code[MAX_MATCH-MIN_MATCH+1]= {\n"); fprintf(header,
"const uch ZLIB_INTERNAL _length_code[MAX_MATCH-MIN_MATCH+1]= {\n");
for (i = 0; i < MAX_MATCH-MIN_MATCH+1; i++) { for (i = 0; i < MAX_MATCH-MIN_MATCH+1; i++) {
fprintf(header, "%2u%s", _length_code[i], fprintf(header, "%2u%s", _length_code[i],
SEPARATOR(i, MAX_MATCH-MIN_MATCH, 20)); SEPARATOR(i, MAX_MATCH-MIN_MATCH, 20));
@ -376,7 +383,7 @@ void gen_trees_header()
/* =========================================================================== /* ===========================================================================
* Initialize the tree data structures for a new zlib stream. * Initialize the tree data structures for a new zlib stream.
*/ */
void _tr_init(deflate_state *s) void ZLIB_INTERNAL _tr_init(deflate_state *s)
{ {
tr_static_init(); tr_static_init();
@ -447,7 +454,11 @@ local void init_block(deflate_state *s)
* when the heap property is re-established (each father smaller than its * when the heap property is re-established (each father smaller than its
* two sons). * two sons).
*/ */
local void pqdownheap(deflate_state *s, ct_data *tree, int k) local void pqdownheap(
deflate_state *s,
ct_data *tree, /* the tree to restore */
int k /* node to move down */
)
{ {
int v = s->heap[k]; int v = s->heap[k];
int j = k << 1; /* left son of k */ int j = k << 1; /* left son of k */
@ -479,7 +490,10 @@ local void pqdownheap(deflate_state *s, ct_data *tree, int k)
* The length opt_len is updated; static_len is also updated if stree is * The length opt_len is updated; static_len is also updated if stree is
* not null. * not null.
*/ */
local void gen_bitlen(deflate_state *s, tree_desc *desc) local void gen_bitlen(
deflate_state *s,
tree_desc *desc /* the tree descriptor */
)
{ {
ct_data *tree = desc->dyn_tree; ct_data *tree = desc->dyn_tree;
int max_code = desc->max_code; int max_code = desc->max_code;
@ -564,7 +578,11 @@ local void gen_bitlen(deflate_state *s, tree_desc *desc)
* OUT assertion: the field code is set for all tree elements of non * OUT assertion: the field code is set for all tree elements of non
* zero code length. * zero code length.
*/ */
local void gen_codes (ct_data *tree, int max_code, ushf *bl_count) local void gen_codes (
ct_data *tree, /* the tree to decorate */
int max_code, /* largest code with non zero frequency */
ushf *bl_count /* number of codes at each bit length */
)
{ {
ush next_code[MAX_BITS+1]; /* next code value for each bit length */ ush next_code[MAX_BITS+1]; /* next code value for each bit length */
ush code = 0; /* running code value */ ush code = 0; /* running code value */
@ -603,7 +621,10 @@ local void gen_codes (ct_data *tree, int max_code, ushf *bl_count)
* and corresponding code. The length opt_len is updated; static_len is * and corresponding code. The length opt_len is updated; static_len is
* also updated if stree is not null. The field max_code is set. * also updated if stree is not null. The field max_code is set.
*/ */
local void build_tree(deflate_state *s, tree_desc *desc) local void build_tree(
deflate_state *s,
tree_desc *desc /* the tree descriptor */
)
{ {
ct_data *tree = desc->dyn_tree; ct_data *tree = desc->dyn_tree;
const ct_data *stree = desc->stat_desc->static_tree; const ct_data *stree = desc->stat_desc->static_tree;
@ -689,7 +710,11 @@ local void build_tree(deflate_state *s, tree_desc *desc)
* Scan a literal or distance tree to determine the frequencies of the codes * Scan a literal or distance tree to determine the frequencies of the codes
* in the bit length tree. * in the bit length tree.
*/ */
local void scan_tree (deflate_state *s, ct_data *tree, int max_code) local void scan_tree (
deflate_state *s,
ct_data *tree, /* the tree to be scanned */
int max_code /* and its largest code of non zero frequency */
)
{ {
int n; /* iterates over all tree elements */ int n; /* iterates over all tree elements */
int prevlen = -1; /* last emitted length */ int prevlen = -1; /* last emitted length */
@ -731,7 +756,11 @@ local void scan_tree (deflate_state *s, ct_data *tree, int max_code)
* Send a literal or distance tree in compressed form, using the codes in * Send a literal or distance tree in compressed form, using the codes in
* bl_tree. * bl_tree.
*/ */
local void send_tree (deflate_state *s, ct_data *tree, int max_code) local void send_tree (
deflate_state *s,
ct_data *tree, /* the tree to be scanned */
int max_code /* and its largest code of non zero frequency */
)
{ {
int n; /* iterates over all tree elements */ int n; /* iterates over all tree elements */
int prevlen = -1; /* last emitted length */ int prevlen = -1; /* last emitted length */
@ -813,7 +842,10 @@ local int build_bl_tree(deflate_state *s)
* lengths of the bit length codes, the literal tree and the distance tree. * lengths of the bit length codes, the literal tree and the distance tree.
* IN assertion: lcodes >= 257, dcodes >= 1, blcodes >= 4. * IN assertion: lcodes >= 257, dcodes >= 1, blcodes >= 4.
*/ */
local void send_all_trees(deflate_state *s, int lcodes, int dcodes, int blcodes) local void send_all_trees(
deflate_state *s,
int lcodes, int dcodes, int blcodes /* number of codes for each tree */
)
{ {
int rank; /* index in bl_order */ int rank; /* index in bl_order */
@ -840,9 +872,14 @@ local void send_all_trees(deflate_state *s, int lcodes, int dcodes, int blcodes)
/* =========================================================================== /* ===========================================================================
* Send a stored block * Send a stored block
*/ */
void _tr_stored_block(deflate_state *s, charf *buf, ulg stored_len, int eof) void ZLIB_INTERNAL _tr_stored_block(
deflate_state *s,
charf *buf, /* input block */
ulg stored_len, /* length of input block */
int last /* one if this is the last block for a file */
)
{ {
send_bits(s, (STORED_BLOCK<<1)+eof, 3); /* send block type */ send_bits(s, (STORED_BLOCK<<1)+last, 3); /* send block type */
#ifdef DEBUG #ifdef DEBUG
s->compressed_len = (s->compressed_len + 3 + 7) & (ulg)~7L; s->compressed_len = (s->compressed_len + 3 + 7) & (ulg)~7L;
s->compressed_len += (stored_len + 4) << 3; s->compressed_len += (stored_len + 4) << 3;
@ -861,7 +898,7 @@ void _tr_stored_block(deflate_state *s, charf *buf, ulg stored_len, int eof)
* To simplify the code, we assume the worst case of last real code encoded * To simplify the code, we assume the worst case of last real code encoded
* on one bit only. * on one bit only.
*/ */
void _tr_align(deflate_state *s) void ZLIB_INTERNAL _tr_align(deflate_state *s)
{ {
send_bits(s, STATIC_TREES<<1, 3); send_bits(s, STATIC_TREES<<1, 3);
send_code(s, END_BLOCK, static_ltree); send_code(s, END_BLOCK, static_ltree);
@ -889,7 +926,12 @@ void _tr_align(deflate_state *s)
* Determine the best encoding for the current block: dynamic trees, static * Determine the best encoding for the current block: dynamic trees, static
* trees or store, and output the encoded block to the zip file. * trees or store, and output the encoded block to the zip file.
*/ */
void _tr_flush_block(deflate_state *s, charf *buf, ulg stored_len, int eof) void ZLIB_INTERNAL _tr_flush_block(
deflate_state *s,
charf *buf, /* input block, or NULL if too old */
ulg stored_len, /* length of input block */
int last /* one if this is the last block for a file */
)
{ {
ulg opt_lenb, static_lenb; /* opt_len and static_len in bytes */ ulg opt_lenb, static_lenb; /* opt_len and static_len in bytes */
int max_blindex = 0; /* index of last bit length code of non zero freq */ int max_blindex = 0; /* index of last bit length code of non zero freq */
@ -898,8 +940,8 @@ void _tr_flush_block(deflate_state *s, charf *buf, ulg stored_len, int eof)
if (s->level > 0) { if (s->level > 0) {
/* Check if the file is binary or text */ /* Check if the file is binary or text */
if (stored_len > 0 && s->strm->data_type == Z_UNKNOWN) if (s->strm->data_type == Z_UNKNOWN)
set_data_type(s); s->strm->data_type = detect_data_type(s);
/* Construct the literal and distance trees */ /* Construct the literal and distance trees */
build_tree(s, (tree_desc *)(&(s->l_desc))); build_tree(s, (tree_desc *)(&(s->l_desc)));
@ -945,20 +987,20 @@ void _tr_flush_block(deflate_state *s, charf *buf, ulg stored_len, int eof)
* successful. If LIT_BUFSIZE <= WSIZE, it is never too late to * successful. If LIT_BUFSIZE <= WSIZE, it is never too late to
* transform a block into a stored block. * transform a block into a stored block.
*/ */
_tr_stored_block(s, buf, stored_len, eof); _tr_stored_block(s, buf, stored_len, last);
#ifdef FORCE_STATIC #ifdef FORCE_STATIC
} else if (static_lenb >= 0) { /* force static trees */ } else if (static_lenb >= 0) { /* force static trees */
#else #else
} else if (s->strategy == Z_FIXED || static_lenb == opt_lenb) { } else if (s->strategy == Z_FIXED || static_lenb == opt_lenb) {
#endif #endif
send_bits(s, (STATIC_TREES<<1)+eof, 3); send_bits(s, (STATIC_TREES<<1)+last, 3);
compress_block(s, (ct_data *)static_ltree, (ct_data *)static_dtree); compress_block(s, (ct_data *)static_ltree, (ct_data *)static_dtree);
#ifdef DEBUG #ifdef DEBUG
s->compressed_len += 3 + s->static_len; s->compressed_len += 3 + s->static_len;
#endif #endif
} else { } else {
send_bits(s, (DYN_TREES<<1)+eof, 3); send_bits(s, (DYN_TREES<<1)+last, 3);
send_all_trees(s, s->l_desc.max_code+1, s->d_desc.max_code+1, send_all_trees(s, s->l_desc.max_code+1, s->d_desc.max_code+1,
max_blindex+1); max_blindex+1);
compress_block(s, (ct_data *)s->dyn_ltree, (ct_data *)s->dyn_dtree); compress_block(s, (ct_data *)s->dyn_ltree, (ct_data *)s->dyn_dtree);
@ -972,21 +1014,25 @@ void _tr_flush_block(deflate_state *s, charf *buf, ulg stored_len, int eof)
*/ */
init_block(s); init_block(s);
if (eof) { if (last) {
bi_windup(s); bi_windup(s);
#ifdef DEBUG #ifdef DEBUG
s->compressed_len += 7; /* align on byte boundary */ s->compressed_len += 7; /* align on byte boundary */
#endif #endif
} }
Tracev((stderr,"\ncomprlen %lu(%lu) ", s->compressed_len>>3, Tracev((stderr,"\ncomprlen %lu(%lu) ", s->compressed_len>>3,
s->compressed_len-7*eof)); s->compressed_len-7*last));
} }
/* =========================================================================== /* ===========================================================================
* Save the match info and tally the frequency counts. Return true if * Save the match info and tally the frequency counts. Return true if
* the current block must be flushed. * the current block must be flushed.
*/ */
int _tr_tally (deflate_state *s, unsigned dist, unsigned lc) int ZLIB_INTERNAL _tr_tally (
deflate_state *s,
unsigned dist, /* distance of matched string */
unsigned lc /* match length-MIN_MATCH or unmatched char (if dist==0) */
)
{ {
s->d_buf[s->last_lit] = (ush)dist; s->d_buf[s->last_lit] = (ush)dist;
s->l_buf[s->last_lit++] = (uch)lc; s->l_buf[s->last_lit++] = (uch)lc;
@ -1033,7 +1079,11 @@ int _tr_tally (deflate_state *s, unsigned dist, unsigned lc)
/* =========================================================================== /* ===========================================================================
* Send the block data compressed using the given Huffman trees * Send the block data compressed using the given Huffman trees
*/ */
local void compress_block(deflate_state *s, ct_data *ltree, ct_data *dtree) local void compress_block(
deflate_state *s,
ct_data *ltree, /* literal tree */
ct_data *dtree /* distance tree */
)
{ {
unsigned dist; /* distance of matched string */ unsigned dist; /* distance of matched string */
int lc; /* match length or unmatched char (if dist == 0) */ int lc; /* match length or unmatched char (if dist == 0) */
@ -1079,23 +1129,44 @@ local void compress_block(deflate_state *s, ct_data *ltree, ct_data *dtree)
} }
/* =========================================================================== /* ===========================================================================
* Set the data type to BINARY or TEXT, using a crude approximation: * Check if the data type is TEXT or BINARY, using the following algorithm:
* set it to Z_TEXT if all symbols are either printable characters (33 to 255) * - TEXT if the two conditions below are satisfied:
* or white spaces (9 to 13, or 32); or set it to Z_BINARY otherwise. * a) There are no non-portable control characters belonging to the
* "black list" (0..6, 14..25, 28..31).
* b) There is at least one printable character belonging to the
* "white list" (9 {TAB}, 10 {LF}, 13 {CR}, 32..255).
* - BINARY otherwise.
* - The following partially-portable control characters form a
* "gray list" that is ignored in this detection algorithm:
* (7 {BEL}, 8 {BS}, 11 {VT}, 12 {FF}, 26 {SUB}, 27 {ESC}).
* IN assertion: the fields Freq of dyn_ltree are set. * IN assertion: the fields Freq of dyn_ltree are set.
*/ */
local void set_data_type(deflate_state *s) local int detect_data_type(deflate_state *s)
{ {
/* black_mask is the bit mask of black-listed bytes
* set bits 0..6, 14..25, and 28..31
* 0xf3ffc07f = binary 11110011111111111100000001111111
*/
unsigned long black_mask = 0xf3ffc07fUL;
int n; int n;
for (n = 0; n < 9; n++) /* Check for non-textual ("black-listed") bytes. */
for (n = 0; n <= 31; n++, black_mask >>= 1)
if ((black_mask & 1) && (s->dyn_ltree[n].Freq != 0))
return Z_BINARY;
/* Check for textual ("white-listed") bytes. */
if (s->dyn_ltree[9].Freq != 0 || s->dyn_ltree[10].Freq != 0
|| s->dyn_ltree[13].Freq != 0)
return Z_TEXT;
for (n = 32; n < LITERALS; n++)
if (s->dyn_ltree[n].Freq != 0) if (s->dyn_ltree[n].Freq != 0)
break; return Z_TEXT;
if (n == 9)
for (n = 14; n < 32; n++) /* There are no "black-listed" or "white-listed" bytes:
if (s->dyn_ltree[n].Freq != 0) * this stream either is empty or has tolerated ("gray-listed") bytes only.
break; */
s->strm->data_type = (n == 32) ? Z_TEXT : Z_BINARY; return Z_BINARY;
} }
/* =========================================================================== /* ===========================================================================
@ -1103,7 +1174,10 @@ local void set_data_type(deflate_state *s)
* method would use a table) * method would use a table)
* IN assertion: 1 <= len <= 15 * IN assertion: 1 <= len <= 15
*/ */
local unsigned bi_reverse(unsigned code, int len) local unsigned bi_reverse(
unsigned code, /* the value to invert */
int len /* its bit length */
)
{ {
register unsigned res = 0; register unsigned res = 0;
do { do {
@ -1150,7 +1224,12 @@ local void bi_windup(deflate_state *s)
* Copy a stored block, storing first the length and its * Copy a stored block, storing first the length and its
* one's complement if requested. * one's complement if requested.
*/ */
local void copy_block(deflate_state *s, charf *buf, unsigned len, int header) local void copy_block(
deflate_state *s,
charf *buf, /* the input data */
unsigned len, /* its length */
int header /* true if block header must be written */
)
{ {
bi_windup(s); /* align on byte boundary */ bi_windup(s); /* align on byte boundary */
s->last_eob_len = 8; /* enough lookahead for inflate */ s->last_eob_len = 8; /* enough lookahead for inflate */

View File

@ -70,7 +70,7 @@ local const ct_data static_dtree[D_CODES] = {
{{19},{ 5}}, {{11},{ 5}}, {{27},{ 5}}, {{ 7},{ 5}}, {{23},{ 5}} {{19},{ 5}}, {{11},{ 5}}, {{27},{ 5}}, {{ 7},{ 5}}, {{23},{ 5}}
}; };
const uch _dist_code[DIST_CODE_LEN] = { const uch ZLIB_INTERNAL _dist_code[DIST_CODE_LEN] = {
0, 1, 2, 3, 4, 4, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8, 0, 1, 2, 3, 4, 4, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8,
8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10, 8, 8, 8, 8, 9, 9, 9, 9, 9, 9, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10,
10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 10, 10, 10, 10, 10, 10, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11, 11,
@ -99,7 +99,7 @@ const uch _dist_code[DIST_CODE_LEN] = {
29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, 29
}; };
const uch _length_code[MAX_MATCH-MIN_MATCH+1]= { const uch ZLIB_INTERNAL _length_code[MAX_MATCH-MIN_MATCH+1]= {
0, 1, 2, 3, 4, 5, 6, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 12, 12, 0, 1, 2, 3, 4, 5, 6, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 12, 12,
13, 13, 13, 13, 14, 14, 14, 14, 15, 15, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16, 13, 13, 13, 13, 14, 14, 14, 14, 15, 15, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16,
17, 17, 17, 17, 17, 17, 17, 17, 18, 18, 18, 18, 18, 18, 18, 18, 19, 19, 19, 19, 17, 17, 17, 17, 17, 17, 17, 17, 18, 18, 18, 18, 18, 18, 18, 18, 19, 19, 19, 19,

View File

@ -1,5 +1,5 @@
/* uncompr.c -- decompress a memory buffer /* uncompr.c -- decompress a memory buffer
* Copyright (C) 1995-2003 Jean-loup Gailly. * Copyright (C) 1995-2003, 2010 Jean-loup Gailly.
* For conditions of distribution and use, see copyright notice in zlib.h * For conditions of distribution and use, see copyright notice in zlib.h
*/ */
@ -16,8 +16,6 @@
been saved previously by the compressor and transmitted to the decompressor been saved previously by the compressor and transmitted to the decompressor
by some mechanism outside the scope of this compression library.) by some mechanism outside the scope of this compression library.)
Upon exit, destLen is the actual size of the compressed buffer. Upon exit, destLen is the actual size of the compressed buffer.
This function can be used to decompress a whole file at once if the
input file is mmap'ed.
uncompress returns Z_OK if success, Z_MEM_ERROR if there was not uncompress returns Z_OK if success, Z_MEM_ERROR if there was not
enough memory, Z_BUF_ERROR if there was not enough room in the output enough memory, Z_BUF_ERROR if there was not enough room in the output

View File

@ -1,5 +1,5 @@
/* zconf.h -- configuration of the zlib compression library /* zconf.h -- configuration of the zlib compression library
* Copyright (C) 1995-2005 Jean-loup Gailly. * Copyright (C) 1995-2010 Jean-loup Gailly.
* For conditions of distribution and use, see copyright notice in zlib.h * For conditions of distribution and use, see copyright notice in zlib.h
*/ */
@ -11,52 +11,124 @@
/* /*
* If you *really* need a unique prefix for all types and library functions, * If you *really* need a unique prefix for all types and library functions,
* compile with -DZ_PREFIX. The "standard" zlib should be compiled without it. * compile with -DZ_PREFIX. The "standard" zlib should be compiled without it.
* Even better than compiling with -DZ_PREFIX would be to use configure to set
* this permanently in zconf.h using "./configure --zprefix".
*/ */
#ifdef Z_PREFIX #ifdef Z_PREFIX /* may be set to #if 1 by ./configure */
# define deflateInit_ z_deflateInit_
# define deflate z_deflate /* all linked symbols */
# define deflateEnd z_deflateEnd # define _dist_code z__dist_code
# define inflateInit_ z_inflateInit_ # define _length_code z__length_code
# define inflate z_inflate # define _tr_align z__tr_align
# define inflateEnd z_inflateEnd # define _tr_flush_block z__tr_flush_block
# define deflateInit2_ z_deflateInit2_ # define _tr_init z__tr_init
# define deflateSetDictionary z_deflateSetDictionary # define _tr_stored_block z__tr_stored_block
# define deflateCopy z_deflateCopy # define _tr_tally z__tr_tally
# define deflateReset z_deflateReset # define adler32 z_adler32
# define deflateParams z_deflateParams # define adler32_combine z_adler32_combine
# define deflateBound z_deflateBound # define adler32_combine64 z_adler32_combine64
# define deflatePrime z_deflatePrime
# define inflateInit2_ z_inflateInit2_
# define inflateSetDictionary z_inflateSetDictionary
# define inflateSync z_inflateSync
# define inflateSyncPoint z_inflateSyncPoint
# define inflateCopy z_inflateCopy
# define inflateReset z_inflateReset
# define inflateBack z_inflateBack
# define inflateBackEnd z_inflateBackEnd
# define compress z_compress # define compress z_compress
# define compress2 z_compress2 # define compress2 z_compress2
# define compressBound z_compressBound # define compressBound z_compressBound
# define uncompress z_uncompress
# define adler32 z_adler32
# define crc32 z_crc32 # define crc32 z_crc32
# define crc32_combine z_crc32_combine
# define crc32_combine64 z_crc32_combine64
# define deflate z_deflate
# define deflateBound z_deflateBound
# define deflateCopy z_deflateCopy
# define deflateEnd z_deflateEnd
# define deflateInit2_ z_deflateInit2_
# define deflateInit_ z_deflateInit_
# define deflateParams z_deflateParams
# define deflatePrime z_deflatePrime
# define deflateReset z_deflateReset
# define deflateSetDictionary z_deflateSetDictionary
# define deflateSetHeader z_deflateSetHeader
# define deflateTune z_deflateTune
# define deflate_copyright z_deflate_copyright
# define get_crc_table z_get_crc_table # define get_crc_table z_get_crc_table
# define gz_error z_gz_error
# define gz_intmax z_gz_intmax
# define gz_strwinerror z_gz_strwinerror
# define gzbuffer z_gzbuffer
# define gzclearerr z_gzclearerr
# define gzclose z_gzclose
# define gzclose_r z_gzclose_r
# define gzclose_w z_gzclose_w
# define gzdirect z_gzdirect
# define gzdopen z_gzdopen
# define gzeof z_gzeof
# define gzerror z_gzerror
# define gzflush z_gzflush
# define gzgetc z_gzgetc
# define gzgets z_gzgets
# define gzoffset z_gzoffset
# define gzoffset64 z_gzoffset64
# define gzopen z_gzopen
# define gzopen64 z_gzopen64
# define gzprintf z_gzprintf
# define gzputc z_gzputc
# define gzputs z_gzputs
# define gzread z_gzread
# define gzrewind z_gzrewind
# define gzseek z_gzseek
# define gzseek64 z_gzseek64
# define gzsetparams z_gzsetparams
# define gztell z_gztell
# define gztell64 z_gztell64
# define gzungetc z_gzungetc
# define gzwrite z_gzwrite
# define inflate z_inflate
# define inflateBack z_inflateBack
# define inflateBackEnd z_inflateBackEnd
# define inflateBackInit_ z_inflateBackInit_
# define inflateCopy z_inflateCopy
# define inflateEnd z_inflateEnd
# define inflateGetHeader z_inflateGetHeader
# define inflateInit2_ z_inflateInit2_
# define inflateInit_ z_inflateInit_
# define inflateMark z_inflateMark
# define inflatePrime z_inflatePrime
# define inflateReset z_inflateReset
# define inflateReset2 z_inflateReset2
# define inflateSetDictionary z_inflateSetDictionary
# define inflateSync z_inflateSync
# define inflateSyncPoint z_inflateSyncPoint
# define inflateUndermine z_inflateUndermine
# define inflate_copyright z_inflate_copyright
# define inflate_fast z_inflate_fast
# define inflate_table z_inflate_table
# define uncompress z_uncompress
# define zError z_zError # define zError z_zError
# define zcalloc z_zcalloc
# define zcfree z_zcfree
# define zlibCompileFlags z_zlibCompileFlags
# define zlibVersion z_zlibVersion
# define alloc_func z_alloc_func /* all zlib typedefs in zlib.h and zconf.h */
# define free_func z_free_func
# define in_func z_in_func
# define out_func z_out_func
# define Byte z_Byte # define Byte z_Byte
# define uInt z_uInt
# define uLong z_uLong
# define Bytef z_Bytef # define Bytef z_Bytef
# define alloc_func z_alloc_func
# define charf z_charf # define charf z_charf
# define free_func z_free_func
# define gzFile z_gzFile
# define gz_header z_gz_header
# define gz_headerp z_gz_headerp
# define in_func z_in_func
# define intf z_intf # define intf z_intf
# define out_func z_out_func
# define uInt z_uInt
# define uIntf z_uIntf # define uIntf z_uIntf
# define uLong z_uLong
# define uLongf z_uLongf # define uLongf z_uLongf
# define voidpf z_voidpf
# define voidp z_voidp # define voidp z_voidp
# define voidpc z_voidpc
# define voidpf z_voidpf
/* all zlib structs in zlib.h and zconf.h */
# define gz_header_s z_gz_header_s
# define internal_state z_internal_state
#endif #endif
#if defined(__MSDOS__) && !defined(MSDOS) #if defined(__MSDOS__) && !defined(MSDOS)
@ -284,49 +356,73 @@ typedef uLong FAR uLongf;
typedef Byte *voidp; typedef Byte *voidp;
#endif #endif
#if 0 /* HAVE_UNISTD_H -- this line is updated by ./configure */ #ifdef HAVE_UNISTD_H /* may be set to #if 1 by ./configure */
# define Z_HAVE_UNISTD_H
#endif
#ifdef STDC
# include <sys/types.h> /* for off_t */ # include <sys/types.h> /* for off_t */
#endif
/* a little trick to accommodate both "#define _LARGEFILE64_SOURCE" and
* "#define _LARGEFILE64_SOURCE 1" as requesting 64-bit operations, (even
* though the former does not conform to the LFS document), but considering
* both "#undef _LARGEFILE64_SOURCE" and "#define _LARGEFILE64_SOURCE 0" as
* equivalently requesting no 64-bit operations
*/
#if -_LARGEFILE64_SOURCE - -1 == 1
# undef _LARGEFILE64_SOURCE
#endif
#if defined(Z_HAVE_UNISTD_H) || defined(_LARGEFILE64_SOURCE)
# include <unistd.h> /* for SEEK_* and off_t */ # include <unistd.h> /* for SEEK_* and off_t */
# ifdef VMS # ifdef VMS
# include <unixio.h> /* for off_t */ # include <unixio.h> /* for off_t */
# endif # endif
# ifndef z_off_t
# define z_off_t off_t # define z_off_t off_t
# endif
#endif #endif
#ifndef SEEK_SET #ifndef SEEK_SET
# define SEEK_SET 0 /* Seek from beginning of file. */ # define SEEK_SET 0 /* Seek from beginning of file. */
# define SEEK_CUR 1 /* Seek from current position. */ # define SEEK_CUR 1 /* Seek from current position. */
# define SEEK_END 2 /* Set file pointer to EOF plus "offset" */ # define SEEK_END 2 /* Set file pointer to EOF plus "offset" */
#endif #endif
#ifndef z_off_t #ifndef z_off_t
# define z_off_t long # define z_off_t long
#endif #endif
#if defined(_LARGEFILE64_SOURCE) && _LFS64_LARGEFILE-0
# define z_off64_t off64_t
#else
# define z_off64_t z_off_t
#endif
#if defined(__OS400__) #if defined(__OS400__)
# define NO_vsnprintf # define NO_vsnprintf
#endif #endif
#if defined(__MVS__) #if defined(__MVS__)
# define NO_vsnprintf # define NO_vsnprintf
# ifdef FAR
# undef FAR
# endif
#endif #endif
/* MVS linker does not support external names larger than 8 bytes */ /* MVS linker does not support external names larger than 8 bytes */
#if defined(__MVS__) #if defined(__MVS__)
# pragma map(deflateInit_,"DEIN") #pragma map(deflateInit_,"DEIN")
# pragma map(deflateInit2_,"DEIN2") #pragma map(deflateInit2_,"DEIN2")
# pragma map(deflateEnd,"DEEND") #pragma map(deflateEnd,"DEEND")
# pragma map(deflateBound,"DEBND") #pragma map(deflateBound,"DEBND")
# pragma map(inflateInit_,"ININ") #pragma map(inflateInit_,"ININ")
# pragma map(inflateInit2_,"ININ2") #pragma map(inflateInit2_,"ININ2")
# pragma map(inflateEnd,"INEND") #pragma map(inflateEnd,"INEND")
# pragma map(inflateSync,"INSY") #pragma map(inflateSync,"INSY")
# pragma map(inflateSetDictionary,"INSEDI") #pragma map(inflateSetDictionary,"INSEDI")
# pragma map(compressBound,"CMBND") #pragma map(compressBound,"CMBND")
# pragma map(inflate_table,"INTABL") #pragma map(inflate_table,"INTABL")
# pragma map(inflate_fast,"INFA") #pragma map(inflate_fast,"INFA")
# pragma map(inflate_copyright,"INCOPY") #pragma map(inflate_copyright,"INCOPY")
#endif #endif
#endif /* ZCONF_H */ #endif /* ZCONF_H */

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,5 @@
/* zutil.c -- target dependent utility functions for the compression library /* zutil.c -- target dependent utility functions for the compression library
* Copyright (C) 1995-2005 Jean-loup Gailly. * Copyright (C) 1995-2005, 2010 Jean-loup Gailly.
* For conditions of distribution and use, see copyright notice in zlib.h * For conditions of distribution and use, see copyright notice in zlib.h
*/ */
@ -34,25 +34,25 @@ uLong ZEXPORT zlibCompileFlags()
uLong flags; uLong flags;
flags = 0; flags = 0;
switch (sizeof(uInt)) { switch ((int)(sizeof(uInt))) {
case 2: break; case 2: break;
case 4: flags += 1; break; case 4: flags += 1; break;
case 8: flags += 2; break; case 8: flags += 2; break;
default: flags += 3; default: flags += 3;
} }
switch (sizeof(uLong)) { switch ((int)(sizeof(uLong))) {
case 2: break; case 2: break;
case 4: flags += 1 << 2; break; case 4: flags += 1 << 2; break;
case 8: flags += 2 << 2; break; case 8: flags += 2 << 2; break;
default: flags += 3 << 2; default: flags += 3 << 2;
} }
switch (sizeof(voidpf)) { switch ((int)(sizeof(voidpf))) {
case 2: break; case 2: break;
case 4: flags += 1 << 4; break; case 4: flags += 1 << 4; break;
case 8: flags += 2 << 4; break; case 8: flags += 2 << 4; break;
default: flags += 3 << 4; default: flags += 3 << 4;
} }
switch (sizeof(z_off_t)) { switch ((int)(sizeof(z_off_t))) {
case 2: break; case 2: break;
case 4: flags += 1 << 6; break; case 4: flags += 1 << 6; break;
case 8: flags += 2 << 6; break; case 8: flags += 2 << 6; break;
@ -117,9 +117,9 @@ uLong ZEXPORT zlibCompileFlags()
# ifndef verbose # ifndef verbose
# define verbose 0 # define verbose 0
# endif # endif
int z_verbose = verbose; int ZLIB_INTERNAL z_verbose = verbose;
void z_error (char *m) void ZLIB_INTERNAL z_error (char *m)
{ {
fprintf(stderr, "%s\n", m); fprintf(stderr, "%s\n", m);
exit(1); exit(1);
@ -144,7 +144,7 @@ const char * ZEXPORT zError(int err)
#ifndef HAVE_MEMCPY #ifndef HAVE_MEMCPY
void zmemcpy(Bytef* dest, const Bytef* source, uInt len) void ZLIB_INTERNAL zmemcpy(Bytef* dest, const Bytef* source, uInt len)
{ {
if (len == 0) return; if (len == 0) return;
do { do {
@ -152,7 +152,7 @@ void zmemcpy(Bytef* dest, const Bytef* source, uInt len)
} while (--len != 0); } while (--len != 0);
} }
int zmemcmp(const Bytef* s1, const Bytef* s2, uInt len) int ZLIB_INTERNAL zmemcmp(const Bytef* s1, const Bytef* s2, uInt len)
{ {
uInt j; uInt j;
@ -162,7 +162,7 @@ int zmemcmp(const Bytef* s1, const Bytef* s2, uInt len)
return 0; return 0;
} }
void zmemzero(Bytef* dest, uInt len) void ZLIB_INTERNAL zmemzero(Bytef* dest, uInt len)
{ {
if (len == 0) return; if (len == 0) return;
do { do {
@ -203,7 +203,7 @@ local ptr_table table[MAX_PTR];
* a protected system like OS/2. Use Microsoft C instead. * a protected system like OS/2. Use Microsoft C instead.
*/ */
voidpf zcalloc (voidpf opaque, unsigned items, unsigned size) voidpf ZLIB_INTERNAL zcalloc (voidpf opaque, unsigned items, unsigned size)
{ {
voidpf buf = opaque; /* just to make some compilers happy */ voidpf buf = opaque; /* just to make some compilers happy */
ulg bsize = (ulg)items*size; ulg bsize = (ulg)items*size;
@ -227,7 +227,7 @@ voidpf zcalloc (voidpf opaque, unsigned items, unsigned size)
return buf; return buf;
} }
void zcfree (voidpf opaque, voidpf ptr) void ZLIB_INTERNAL zcfree (voidpf opaque, voidpf ptr)
{ {
int n; int n;
if (*(ush*)&ptr != 0) { /* object < 64K */ if (*(ush*)&ptr != 0) { /* object < 64K */
@ -262,13 +262,13 @@ void zcfree (voidpf opaque, voidpf ptr)
# define _hfree hfree # define _hfree hfree
#endif #endif
voidpf zcalloc (voidpf opaque, unsigned items, unsigned size) voidpf ZLIB_INTERNAL zcalloc (voidpf opaque, uInt items, uInt size)
{ {
if (opaque) opaque = 0; /* to make compiler happy */ if (opaque) opaque = 0; /* to make compiler happy */
return _halloc((long)items, size); return _halloc((long)items, size);
} }
void zcfree (voidpf opaque, voidpf ptr) void ZLIB_INTERNAL zcfree (voidpf opaque, voidpf ptr)
{ {
if (opaque) opaque = 0; /* to make compiler happy */ if (opaque) opaque = 0; /* to make compiler happy */
_hfree(ptr); _hfree(ptr);
@ -287,14 +287,14 @@ extern voidp calloc OF((uInt items, uInt size));
extern void free OF((voidpf ptr)); extern void free OF((voidpf ptr));
#endif #endif
voidpf zcalloc (voidpf opaque, unsigned items, unsigned size) voidpf ZLIB_INTERNAL zcalloc (voidpf opaque, unsigned items, unsigned size)
{ {
if (opaque) items += size - size; /* make compiler happy */ if (opaque) items += size - size; /* make compiler happy */
return sizeof(uInt) > 2 ? (voidpf)malloc(items * size) : return sizeof(uInt) > 2 ? (voidpf)malloc(items * size) :
(voidpf)calloc(items, size); (voidpf)calloc(items, size);
} }
void zcfree (voidpf opaque, voidpf ptr) void ZLIB_INTERNAL zcfree (voidpf opaque, voidpf ptr)
{ {
free(ptr); free(ptr);
if (opaque) return; /* make compiler happy */ if (opaque) return; /* make compiler happy */

View File

@ -1,5 +1,5 @@
/* zutil.h -- internal interface and configuration of the compression library /* zutil.h -- internal interface and configuration of the compression library
* Copyright (C) 1995-2005 Jean-loup Gailly. * Copyright (C) 1995-2010 Jean-loup Gailly.
* For conditions of distribution and use, see copyright notice in zlib.h * For conditions of distribution and use, see copyright notice in zlib.h
*/ */
@ -13,31 +13,21 @@
#ifndef ZUTIL_H #ifndef ZUTIL_H
#define ZUTIL_H #define ZUTIL_H
#define ZLIB_INTERNAL #if ((__GNUC__-0) * 10 + __GNUC_MINOR__-0 >= 33) && !defined(NO_VIZ)
# define ZLIB_INTERNAL __attribute__((visibility ("hidden")))
#else
# define ZLIB_INTERNAL
#endif
#include "zlib.h" #include "zlib.h"
#ifdef STDC #ifdef STDC
# ifndef _WIN32_WCE # if !(defined(_WIN32_WCE) && defined(_MSC_VER))
# include <stddef.h> # include <stddef.h>
# endif # endif
# include <string.h> # include <string.h>
# include <stdlib.h> # include <stdlib.h>
#endif #endif
#ifdef NO_ERRNO_H
# ifdef _WIN32_WCE
/* The Microsoft C Run-Time Library for Windows CE doesn't have
* errno. We define it as a global variable to simplify porting.
* Its value is always 0 and should not be used. We rename it to
* avoid conflict with other libraries that use the same workaround.
*/
# define errno z_errno
# endif
extern int errno;
#else
# ifndef _WIN32_WCE
# include <errno.h>
# endif
#endif
#ifndef local #ifndef local
# define local static # define local static
@ -89,7 +79,7 @@ extern const char * const z_errmsg[10]; /* indexed by 2-zlib_error */
#if defined(MSDOS) || (defined(WINDOWS) && !defined(WIN32)) #if defined(MSDOS) || (defined(WINDOWS) && !defined(WIN32))
# define OS_CODE 0x00 # define OS_CODE 0x00
# if defined(__TURBOC__) || defined(__BORLANDC__) # if defined(__TURBOC__) || defined(__BORLANDC__)
# if(__STDC__ == 1) && (defined(__LARGE__) || defined(__COMPACT__)) # if (__STDC__ == 1) && (defined(__LARGE__) || defined(__COMPACT__))
/* Allow compilation with ANSI keywords only enabled */ /* Allow compilation with ANSI keywords only enabled */
void _Cdecl farfree( void *block ); void _Cdecl farfree( void *block );
void *_Cdecl farmalloc( unsigned long nbytes ); void *_Cdecl farmalloc( unsigned long nbytes );
@ -118,7 +108,7 @@ extern const char * const z_errmsg[10]; /* indexed by 2-zlib_error */
#ifdef OS2 #ifdef OS2
# define OS_CODE 0x06 # define OS_CODE 0x06
# ifdef M_I86 # ifdef M_I86
#include <malloc.h> # include <malloc.h>
# endif # endif
#endif #endif
@ -151,7 +141,7 @@ extern const char * const z_errmsg[10]; /* indexed by 2-zlib_error */
# define fdopen(fd,mode) NULL /* No fdopen() */ # define fdopen(fd,mode) NULL /* No fdopen() */
#endif #endif
#if (defined(_MSC_VER) && (_MSC_VER > 600)) #if (defined(_MSC_VER) && (_MSC_VER > 600)) && !defined __INTERIX
# if defined(_WIN32_WCE) # if defined(_WIN32_WCE)
# define fdopen(fd,mode) NULL /* No fdopen() */ # define fdopen(fd,mode) NULL /* No fdopen() */
# ifndef _PTRDIFF_T_DEFINED # ifndef _PTRDIFF_T_DEFINED
@ -163,6 +153,18 @@ extern const char * const z_errmsg[10]; /* indexed by 2-zlib_error */
# endif # endif
#endif #endif
#if defined(__BORLANDC__)
#pragma warn -8004
#pragma warn -8008
#pragma warn -8066
#endif
/* provide prototypes for these when building zlib without LFS */
#if !defined(_LARGEFILE64_SOURCE) || _LFS64_LARGEFILE-0 == 0
ZEXTERN uLong ZEXPORT adler32_combine64 OF((uLong, uLong, z_off_t));
ZEXTERN uLong ZEXPORT crc32_combine64 OF((uLong, uLong, z_off_t));
#endif
/* common defaults */ /* common defaults */
#ifndef OS_CODE #ifndef OS_CODE
@ -197,9 +199,11 @@ extern const char * const z_errmsg[10]; /* indexed by 2-zlib_error */
# ifdef WIN32 # ifdef WIN32
/* In Win32, vsnprintf is available as the "non-ANSI" _vsnprintf. */ /* In Win32, vsnprintf is available as the "non-ANSI" _vsnprintf. */
# if !defined(vsnprintf) && !defined(NO_vsnprintf) # if !defined(vsnprintf) && !defined(NO_vsnprintf)
# if !defined(_MSC_VER) || ( defined(_MSC_VER) && _MSC_VER < 1500 )
# define vsnprintf _vsnprintf # define vsnprintf _vsnprintf
# endif # endif
# endif # endif
# endif
# ifdef __SASC # ifdef __SASC
# define NO_vsnprintf # define NO_vsnprintf
# endif # endif
@ -232,16 +236,16 @@ extern const char * const z_errmsg[10]; /* indexed by 2-zlib_error */
# define zmemzero(dest, len) memset(dest, 0, len) # define zmemzero(dest, len) memset(dest, 0, len)
# endif # endif
#else #else
extern void zmemcpy OF((Bytef* dest, const Bytef* source, uInt len)); void ZLIB_INTERNAL zmemcpy OF((Bytef* dest, const Bytef* source, uInt len));
extern int zmemcmp OF((const Bytef* s1, const Bytef* s2, uInt len)); int ZLIB_INTERNAL zmemcmp OF((const Bytef* s1, const Bytef* s2, uInt len));
extern void zmemzero OF((Bytef* dest, uInt len)); void ZLIB_INTERNAL zmemzero OF((Bytef* dest, uInt len));
#endif #endif
/* Diagnostic functions */ /* Diagnostic functions */
#ifdef DEBUG #ifdef DEBUG
# include <stdio.h> # include <stdio.h>
extern int z_verbose; extern int ZLIB_INTERNAL z_verbose;
extern void z_error OF((char *m)); extern void ZLIB_INTERNAL z_error OF((char *m));
# define Assert(cond,msg) {if(!(cond)) z_error(msg);} # define Assert(cond,msg) {if(!(cond)) z_error(msg);}
# define Trace(x) {if (z_verbose>=0) fprintf x ;} # define Trace(x) {if (z_verbose>=0) fprintf x ;}
# define Tracev(x) {if (z_verbose>0) fprintf x ;} # define Tracev(x) {if (z_verbose>0) fprintf x ;}
@ -258,8 +262,9 @@ extern const char * const z_errmsg[10]; /* indexed by 2-zlib_error */
#endif #endif
voidpf zcalloc OF((voidpf opaque, unsigned items, unsigned size)); voidpf ZLIB_INTERNAL zcalloc OF((voidpf opaque, unsigned items,
void zcfree OF((voidpf opaque, voidpf ptr)); unsigned size));
void ZLIB_INTERNAL zcfree OF((voidpf opaque, voidpf ptr));
#define ZALLOC(strm, items, size) \ #define ZALLOC(strm, items, size) \
(*((strm)->zalloc))((strm)->opaque, (items), (size)) (*((strm)->zalloc))((strm)->opaque, (items), (size))