Compare commits

...

2 Commits

Author SHA1 Message Date
Mark Adler
6b8233bfe0 zlib 1.2.2.3 2011-09-09 23:24:43 -07:00
Mark Adler
0484693e17 zlib 1.2.2.2 2011-09-09 23:24:33 -07:00
79 changed files with 13720 additions and 9009 deletions

View File

@@ -1,6 +1,47 @@
ChangeLog file for zlib ChangeLog file for zlib
Changes in 1.2.2.3 (27 May 2005)
- Replace 1U constants in inflate.c and inftrees.c for 64-bit compile
- Typecast fread() return values in gzio.c [Vollant]
- Remove trailing space in minigzip.c outmode (VC++ can't deal with it)
- Fix crc check bug in gzread() after gzungetc() [Heiner]
- Add the deflateTune() function to adjust internal compression parameters
- Add a fast gzip decompressor, gun.c, to examples (use of inflateBack)
- Remove an incorrect assertion in examples/zpipe.c
- Add C++ wrapper in infback9.h [Donais]
- Fix bug in inflateCopy() when decoding fixed codes
- Note in zlib.h how much deflateSetDictionary() actually uses
- Remove USE_DICT_HEAD in deflate.c (would mess up inflate if used)
- Add _WIN32_WCE to define WIN32 in zconf.in.h [Spencer]
- Don't include stderr.h or errno.h for _WIN32_WCE in zutil.h [Spencer]
- Add gzdirect() function to indicate transparent reads
- Update contrib/minizip [Vollant]
- Fix compilation of deflate.c when both ASMV and FASTEST [Oberhumer]
- Add casts in crc32.c to avoid warnings [Oberhumer]
- Add contrib/masmx64 [Vollant]
- Update contrib/asm586, asm686, masmx86, testzlib, vstudio [Vollant]
Changes in 1.2.2.2 (30 December 2004)
- Replace structure assignments in deflate.c and inflate.c with zmemcpy to
avoid implicit memcpy calls (portability for no-library compilation)
- Increase sprintf() buffer size in gzdopen() to allow for large numbers
- Add INFLATE_STRICT to check distances against zlib header
- Improve WinCE errno handling and comments [Chang]
- Remove comment about no gzip header processing in FAQ
- Add Z_FIXED strategy option to deflateInit2() to force fixed trees
- Add updated make_vms.com [Coghlan], update README
- Create a new "examples" directory, move gzappend.c there, add zpipe.c,
fitblk.c, gzlog.[ch], gzjoin.c, and zlib_how.html.
- Add FAQ entry and comments in deflate.c on uninitialized memory access
- Add Solaris 9 make options in configure [Gilbert]
- Allow strerror() usage in gzio.c for STDC
- Fix DecompressBuf in contrib/delphi/ZLib.pas [ManChesTer]
- Update contrib/masmx86/inffas32.asm and gvmat32.asm [Vollant]
- Use z_off_t for adler32_combine() and crc32_combine() lengths
- Make adler32() much faster for small len
- Use OS_CODE in deflate() default gzip header
Changes in 1.2.2.1 (31 October 2004) Changes in 1.2.2.1 (31 October 2004)
- Allow inflateSetDictionary() call for raw inflate - Allow inflateSetDictionary() call for raw inflate
- Fix inflate header crc check bug for file names and comments - Fix inflate header crc check bug for file names and comments
@@ -20,6 +61,7 @@ Changes in 1.2.2.1 (31 October 2004)
- Do not define an exit() prototype in zutil.c unless DEBUG defined - Do not define an exit() prototype in zutil.c unless DEBUG defined
- Remove prototype of exit() from zutil.c, example.c, minigzip.c [Truta] - Remove prototype of exit() from zutil.c, example.c, minigzip.c [Truta]
- Add comment in zlib.h for Z_NO_FLUSH parameter to deflate() - Add comment in zlib.h for Z_NO_FLUSH parameter to deflate()
- Fix Darwin build version identification [Peterson]
Changes in 1.2.2 (3 October 2004) Changes in 1.2.2 (3 October 2004)
- Update zlib.h comments on gzip in-memory processing - Update zlib.h comments on gzip in-memory processing

26
FAQ
View File

@@ -148,13 +148,6 @@ The lastest zlib FAQ is at http://www.gzip.org/zlib/zlib_faq.html
format using deflateInit2(). You can also request that inflate decode format using deflateInit2(). You can also request that inflate decode
the gzip format using inflateInit2(). Read zlib.h for more details. the gzip format using inflateInit2(). Read zlib.h for more details.
Note that you cannot specify special gzip header contents (e.g. a file
name or modification date), nor will inflate tell you what was in the
gzip header. If you need to customize the header or see what's in it,
you can use the raw deflate and inflate operations and the crc32()
function and roll your own gzip encoding and decoding. Read the gzip
RFC 1952 for details of the header and trailer format.
21. Is zlib thread-safe? 21. Is zlib thread-safe?
Yes. However any library routines that zlib uses and any application- Yes. However any library routines that zlib uses and any application-
@@ -295,20 +288,29 @@ The lastest zlib FAQ is at http://www.gzip.org/zlib/zlib_faq.html
were downright silly. So now, we simply make sure that the code always were downright silly. So now, we simply make sure that the code always
works. works.
36. Will zlib read the (insert any ancient or arcane format here) compressed 36. Valgrind (or some similar memory access checker) says that deflate is
performing a conditional jump that depends on an uninitialized value.
Isn't that a bug?
No. That is intentional for performance reasons, and the output of
deflate is not affected. This only started showing up recently since
zlib 1.2.x uses malloc() by default for allocations, whereas earlier
versions used calloc(), which zeros out the allocated memory.
37. Will zlib read the (insert any ancient or arcane format here) compressed
data format? data format?
Probably not. Look in the comp.compression FAQ for pointers to various Probably not. Look in the comp.compression FAQ for pointers to various
formats and associated software. formats and associated software.
37. How can I encrypt/decrypt zip files with zlib? 38. How can I encrypt/decrypt zip files with zlib?
zlib doesn't support encryption. The original PKZIP encryption is very weak zlib doesn't support encryption. The original PKZIP encryption is very weak
and can be broken with freely available programs. To get strong encryption, and can be broken with freely available programs. To get strong encryption,
use GnuPG, http://www.gnupg.org/ , which already includes zlib compression. use GnuPG, http://www.gnupg.org/ , which already includes zlib compression.
For PKZIP compatible "encryption", look at http://www.info-zip.org/ For PKZIP compatible "encryption", look at http://www.info-zip.org/
38. What's the difference between the "gzip" and "deflate" HTTP 1.1 encodings? 39. What's the difference between the "gzip" and "deflate" HTTP 1.1 encodings?
"gzip" is the gzip format, and "deflate" is the zlib format. They should "gzip" is the gzip format, and "deflate" is the zlib format. They should
probably have called the second one "zlib" instead to avoid confusion probably have called the second one "zlib" instead to avoid confusion
@@ -324,14 +326,14 @@ The lastest zlib FAQ is at http://www.gzip.org/zlib/zlib_faq.html
Bottom line: use the gzip format for HTTP 1.1 encoding. Bottom line: use the gzip format for HTTP 1.1 encoding.
39. Does zlib support the new "Deflate64" format introduced by PKWare? 40. Does zlib support the new "Deflate64" format introduced by PKWare?
No. PKWare has apparently decided to keep that format proprietary, since No. PKWare has apparently decided to keep that format proprietary, since
they have not documented it as they have previous compression formats. they have not documented it as they have previous compression formats.
In any case, the compression improvements are so modest compared to other In any case, the compression improvements are so modest compared to other
more modern approaches, that it's not worth the effort to implement. more modern approaches, that it's not worth the effort to implement.
40. Can you please sign these lengthy legal documents and fax them back to us 41. Can you please sign these lengthy legal documents and fax them back to us
so that we can use your software in our product? so that we can use your software in our product?
No. Go away. Shoo. No. Go away. Shoo.

View File

@@ -30,7 +30,7 @@ CPP=$(CC) -E
LIBS=libz.a LIBS=libz.a
SHAREDLIB=libz.so SHAREDLIB=libz.so
SHAREDLIBV=libz.so.1.2.2.1 SHAREDLIBV=libz.so.1.2.2.3
SHAREDLIBM=libz.so.1 SHAREDLIBM=libz.so.1
AR=ar rc AR=ar rc

View File

@@ -30,7 +30,7 @@ CPP=$(CC) -E
LIBS=libz.a LIBS=libz.a
SHAREDLIB=libz.so SHAREDLIB=libz.so
SHAREDLIBV=libz.so.1.2.2.1 SHAREDLIBV=libz.so.1.2.2.3
SHAREDLIBM=libz.so.1 SHAREDLIBM=libz.so.1
AR=ar rc AR=ar rc

9
README
View File

@@ -1,6 +1,6 @@
ZLIB DATA COMPRESSION LIBRARY ZLIB DATA COMPRESSION LIBRARY
zlib 1.2.2.1 is a general purpose data compression library. All the code is zlib 1.2.2.3 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)
@@ -16,9 +16,8 @@ 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 short "make test; make install" should work for most
machines. For Unix: "./configure; make test; make install" For MSDOS, use one machines. For Unix: "./configure; make test; make install". For MSDOS, use one
of the special makefiles such as Makefile.msc. For VMS, use Make_vms.com or of the special makefiles such as Makefile.msc. For VMS, use make_vms.com.
descrip.mms.
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
@@ -34,7 +33,7 @@ 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 in
http://dogma.net/markn/articles/zlibtool/zlibtool.htm http://dogma.net/markn/articles/zlibtool/zlibtool.htm
The changes made in version 1.2.2.1 are documented in the file ChangeLog. The changes made in version 1.2.2.3 are documented in the file ChangeLog.
Unsupported third party contributions are provided in directory "contrib". Unsupported third party contributions are provided in directory "contrib".

115
adler32.c
View File

@@ -12,12 +12,13 @@
#define NMAX 5552 #define NMAX 5552
/* NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */ /* NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */
#define DO1(buf,i) {s1 += buf[i]; s2 += s1;} #define DO1(buf,i) {adler += (buf)[i]; sum2 += adler;}
#define DO2(buf,i) DO1(buf,i); DO1(buf,i+1); #define DO2(buf,i) DO1(buf,i); DO1(buf,i+1);
#define DO4(buf,i) DO2(buf,i); DO2(buf,i+2); #define DO4(buf,i) DO2(buf,i); DO2(buf,i+2);
#define DO8(buf,i) DO4(buf,i); DO4(buf,i+4); #define DO8(buf,i) DO4(buf,i); DO4(buf,i+4);
#define DO16(buf) DO8(buf,0); DO8(buf,8); #define DO16(buf) DO8(buf,0); DO8(buf,8);
/* use NO_DIVIDE if your processor does not do division in hardware */
#ifdef NO_DIVIDE #ifdef NO_DIVIDE
# define MOD(a) \ # define MOD(a) \
do { \ do { \
@@ -39,8 +40,17 @@
if (a >= (BASE << 1)) a -= (BASE << 1); \ if (a >= (BASE << 1)) a -= (BASE << 1); \
if (a >= BASE) a -= BASE; \ if (a >= BASE) a -= BASE; \
} while (0) } while (0)
# define MOD4(a) \
do { \
if (a >= (BASE << 4)) a -= (BASE << 4); \
if (a >= (BASE << 3)) a -= (BASE << 3); \
if (a >= (BASE << 2)) a -= (BASE << 2); \
if (a >= (BASE << 1)) a -= (BASE << 1); \
if (a >= BASE) a -= BASE; \
} while (0)
#else #else
# define MOD(a) a %= BASE # define MOD(a) a %= BASE
# define MOD4(a) a %= BASE
#endif #endif
/* ========================================================================= */ /* ========================================================================= */
@@ -49,48 +59,91 @@ uLong ZEXPORT adler32(adler, buf, len)
const Bytef *buf; const Bytef *buf;
uInt len; uInt len;
{ {
unsigned long s1 = adler & 0xffff; unsigned long sum2;
unsigned long s2 = (adler >> 16) & 0xffff; unsigned n;
int k;
if (buf == Z_NULL) return 1L; /* split Adler-32 into component sums */
sum2 = (adler >> 16) & 0xffff;
adler &= 0xffff;
while (len > 0) { /* in case user likes doing a byte at a time, keep it fast */
k = len < NMAX ? (int)len : NMAX; if (len == 1) {
len -= k; adler += buf[0];
while (k >= 16) { if (adler >= BASE)
adler -= BASE;
sum2 += adler;
if (sum2 >= BASE)
sum2 -= BASE;
return adler | (sum2 << 16);
}
/* initial Adler-32 value (deferred check for len == 1 speed) */
if (buf == Z_NULL)
return 1L;
/* in case short lengths are provided, keep it somewhat fast */
if (len < 16) {
while (len--) {
adler += *buf++;
sum2 += adler;
}
if (adler >= BASE)
adler -= BASE;
MOD4(sum2); /* only added so many BASE's */
return adler | (sum2 << 16);
}
/* do length NMAX blocks -- requires just one modulo operation */
while (len >= NMAX) {
len -= NMAX;
n = NMAX / 16; /* NMAX is divisible by 16 */
do {
DO16(buf); /* 16 sums unrolled */
buf += 16;
} while (--n);
MOD(adler);
MOD(sum2);
}
/* do remaining bytes (less than NMAX, still just one modulo) */
if (len) { /* avoid modulos if none remaining */
while (len >= 16) {
len -= 16;
DO16(buf); DO16(buf);
buf += 16; buf += 16;
k -= 16;
} }
if (k != 0) do { while (len--) {
s1 += *buf++; adler += *buf++;
s2 += s1; sum2 += adler;
} while (--k); }
MOD(s1); MOD(adler);
MOD(s2); MOD(sum2);
} }
return (s2 << 16) | s1;
/* return recombined sums */
return adler | (sum2 << 16);
} }
/* ========================================================================= */ /* ========================================================================= */
uLong ZEXPORT adler32_combine(adler1, adler2, len2) uLong ZEXPORT adler32_combine(adler1, adler2, len2)
uLong adler1; uLong adler1;
uLong adler2; uLong adler2;
uLong len2; z_off_t len2;
{ {
unsigned long s1; unsigned long sum1;
unsigned long s2; unsigned long sum2;
unsigned rem;
len2 %= BASE; /* the derivation of this formula is left as an exercise for the reader */
s1 = adler1 & 0xffff; rem = (unsigned)(len2 % BASE);
s2 = len2 * s1; sum1 = adler1 & 0xffff;
MOD(s2); sum2 = rem * sum1;
s1 += (adler2 & 0xffff) + BASE - 1; MOD(sum2);
s2 += ((adler1 >> 16) & 0xffff) + ((adler2 >> 16) & 0xffff) + BASE - len2; sum1 += (adler2 & 0xffff) + BASE - 1;
if (s1 > BASE) s1 -= BASE; sum2 += ((adler1 >> 16) & 0xffff) + ((adler2 >> 16) & 0xffff) + BASE - rem;
if (s1 > BASE) s1 -= BASE; if (sum1 > BASE) sum1 -= BASE;
if (s2 > (BASE << 1)) s2 -= (BASE << 1); if (sum1 > BASE) sum1 -= BASE;
if (s2 > BASE) s2 -= BASE; if (sum2 > (BASE << 1)) sum2 -= (BASE << 1);
return (s2 << 16) | s1; if (sum2 > BASE) sum2 -= BASE;
return sum1 | (sum2 << 16);
} }

View File

@@ -1,7 +1,7 @@
* ZLIB.INC - Interface to the general purpose compression library * ZLIB.INC - Interface to the general purpose compression library
* *
* ILE RPG400 version by Patrick Monnerat, DATASPHERE. * ILE RPG400 version by Patrick Monnerat, DATASPHERE.
* Version 1.2.2.1 * Version 1.2.2.3
* *
* *
* WARNING: * WARNING:
@@ -20,8 +20,12 @@
* Constants * Constants
************************************************************************** **************************************************************************
* *
D ZLIB_VERSION C '1.2.2.1' Header's version * Versioning information.
D ZLIB_VERNUM C X'1221' *
D ZLIB_VERSION C '1.2.2.3'
D ZLIB_VERNUM C X'1223'
*
* Other equates.
* *
D Z_NO_FLUSH C 0 D Z_NO_FLUSH C 0
D Z_SYNC_FLUSH C 2 D Z_SYNC_FLUSH C 2

5
configure vendored
View File

@@ -89,7 +89,7 @@ if test "$gcc" -eq 1 && ($cc -c $cflags $test.c) 2>/dev/null; then
SHAREDLIB=libz$shared_ext SHAREDLIB=libz$shared_ext
SHAREDLIBV=libz.$VER$shared_ext SHAREDLIBV=libz.$VER$shared_ext
SHAREDLIBM=libz.$VER1$shared_ext SHAREDLIBM=libz.$VER1$shared_ext
LDSHARED=${LDSHARED-"$cc -dynamiclib -install_name $libdir/$SHAREDLIBV -compatibility_version $VER2 -current_version $VER"};; LDSHARED=${LDSHARED-"$cc -dynamiclib -install_name $libdir/$SHAREDLIBM -compatibility_version $VER1 -current_version $VER"};;
*) LDSHARED=${LDSHARED-"$cc -shared"};; *) LDSHARED=${LDSHARED-"$cc -shared"};;
esac esac
else else
@@ -125,6 +125,9 @@ else
SunOS\ 4*) SFLAGS=${CFLAGS-"-O2 -PIC"} SunOS\ 4*) SFLAGS=${CFLAGS-"-O2 -PIC"}
CFLAGS=${CFLAGS-"-O2"} CFLAGS=${CFLAGS-"-O2"}
LDSHARED=${LDSHARED-"ld"};; LDSHARED=${LDSHARED-"ld"};;
SunStudio\ 9*) SFLAGS=${CFLAGS-"-DUSE_MMAP -fast -xcode=pic32 -xtarget=ultra3 -xarch=v9b"}
CFLAGS=${CFLAGS-"-DUSE_MMAP -fast -xtarget=ultra3 -xarch=v9b"}
LDSHARED=${LDSHARED-"cc -xarch=v9b"};;
UNIX_System_V\ 4.2.0) UNIX_System_V\ 4.2.0)
SFLAGS=${CFLAGS-"-KPIC -O"} SFLAGS=${CFLAGS-"-KPIC -O"}
CFLAGS=${CFLAGS-"-O"} CFLAGS=${CFLAGS-"-O"}

View File

@@ -22,9 +22,6 @@ delphi/ by Cosmin Truta <cosmint@cs.ubbcluj.ro>
dotzlib/ by Henrik Ravn <henrik@ravn.com> dotzlib/ by Henrik Ravn <henrik@ravn.com>
Support for Microsoft .Net and Visual C++ .Net Support for Microsoft .Net and Visual C++ .Net
gzappend/ by Mark Adler <madler@alumni.caltech.edu>
append to a gzip file -- illustrates the use of Z_BLOCK
infback9/ by Mark Adler <madler@alumni.caltech.edu> infback9/ by Mark Adler <madler@alumni.caltech.edu>
Unsupported diffs to infback to decode the deflate64 format Unsupported diffs to infback to decode the deflate64 format
@@ -45,6 +42,10 @@ masm686/ by Dan Higdon <hdan@kinesoft.com>
and Chuck Walbourn <chuckw@kinesoft.com> and Chuck Walbourn <chuckw@kinesoft.com>
asm code for Pentium Pro/PII, using the MASM syntax asm code for Pentium Pro/PII, using the MASM syntax
masmx64/ by Gilles Vollant <info@winimage.com>
x86 64-bit (AMD64 and Intel EM64t) code for x64 assembler to
replace longest_match() and inflate_fast()
masmx86/ by Gilles Vollant <info@winimage.com> masmx86/ by Gilles Vollant <info@winimage.com>
x86 asm code to replace longest_match() and inflate_fast(), x86 asm code to replace longest_match() and inflate_fast(),
for Visual C++ and MASM for Visual C++ and MASM

View File

@@ -1,354 +1,364 @@
/* match.s -- Pentium-optimized version of longest_match() /* match.s -- Pentium-optimized version of longest_match()
* Written for zlib 1.1.2 * Written for zlib 1.1.2
* Copyright (C) 1998 Brian Raiter <breadbox@muppetlabs.com> * Copyright (C) 1998 Brian Raiter <breadbox@muppetlabs.com>
* *
* This is free software; you can redistribute it and/or modify it * This is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License. * under the terms of the GNU General Public License.
*/ */
#ifndef NO_UNDERLINE #ifndef NO_UNDERLINE
#define match_init _match_init #define match_init _match_init
#define longest_match _longest_match #define longest_match _longest_match
#endif #endif
#define MAX_MATCH (258) #define MAX_MATCH (258)
#define MIN_MATCH (3) #define MIN_MATCH (3)
#define MIN_LOOKAHEAD (MAX_MATCH + MIN_MATCH + 1) #define MIN_LOOKAHEAD (MAX_MATCH + MIN_MATCH + 1)
#define MAX_MATCH_8 ((MAX_MATCH + 7) & ~7) #define MAX_MATCH_8 ((MAX_MATCH + 7) & ~7)
/* stack frame offsets */ /* stack frame offsets */
#define wmask 0 /* local copy of s->wmask */ #define wmask 0 /* local copy of s->wmask */
#define window 4 /* local copy of s->window */ #define window 4 /* local copy of s->window */
#define windowbestlen 8 /* s->window + bestlen */ #define windowbestlen 8 /* s->window + bestlen */
#define chainlenscanend 12 /* high word: current chain len */ #define chainlenscanend 12 /* high word: current chain len */
/* low word: last bytes sought */ /* low word: last bytes sought */
#define scanstart 16 /* first two bytes of string */ #define scanstart 16 /* first two bytes of string */
#define scanalign 20 /* dword-misalignment of string */ #define scanalign 20 /* dword-misalignment of string */
#define nicematch 24 /* a good enough match size */ #define nicematch 24 /* a good enough match size */
#define bestlen 28 /* size of best match so far */ #define bestlen 28 /* size of best match so far */
#define scan 32 /* ptr to string wanting match */ #define scan 32 /* ptr to string wanting match */
#define LocalVarsSize (36) #define LocalVarsSize (36)
/* saved ebx 36 */ /* saved ebx 36 */
/* saved edi 40 */ /* saved edi 40 */
/* saved esi 44 */ /* saved esi 44 */
/* saved ebp 48 */ /* saved ebp 48 */
/* return address 52 */ /* return address 52 */
#define deflatestate 56 /* the function arguments */ #define deflatestate 56 /* the function arguments */
#define curmatch 60 #define curmatch 60
/* Offsets for fields in the deflate_state structure. These numbers /* Offsets for fields in the deflate_state structure. These numbers
* are calculated from the definition of deflate_state, with the * are calculated from the definition of deflate_state, with the
* assumption that the compiler will dword-align the fields. (Thus, * assumption that the compiler will dword-align the fields. (Thus,
* changing the definition of deflate_state could easily cause this * changing the definition of deflate_state could easily cause this
* program to crash horribly, without so much as a warning at * program to crash horribly, without so much as a warning at
* compile time. Sigh.) * compile time. Sigh.)
*/ */
#define dsWSize 36
#define dsWMask 44 /* All the +zlib1222add offsets are due to the addition of fields
#define dsWindow 48 * in zlib in the deflate_state structure since the asm code was first written
#define dsPrev 56 * (if you compile with zlib 1.0.4 or older, use "zlib1222add equ (-4)").
#define dsMatchLen 88 * (if you compile with zlib between 1.0.5 and 1.2.2.1, use "zlib1222add equ 0").
#define dsPrevMatch 92 * if you compile with zlib 1.2.2.2 or later , use "zlib1222add equ 8").
#define dsStrStart 100 */
#define dsMatchStart 104
#define dsLookahead 108 #define zlib1222add (8)
#define dsPrevLen 112
#define dsMaxChainLen 116 #define dsWSize (36+zlib1222add)
#define dsGoodMatch 132 #define dsWMask (44+zlib1222add)
#define dsNiceMatch 136 #define dsWindow (48+zlib1222add)
#define dsPrev (56+zlib1222add)
#define dsMatchLen (88+zlib1222add)
.file "match.S" #define dsPrevMatch (92+zlib1222add)
#define dsStrStart (100+zlib1222add)
.globl match_init, longest_match #define dsMatchStart (104+zlib1222add)
#define dsLookahead (108+zlib1222add)
.text #define dsPrevLen (112+zlib1222add)
#define dsMaxChainLen (116+zlib1222add)
/* uInt longest_match(deflate_state *deflatestate, IPos curmatch) */ #define dsGoodMatch (132+zlib1222add)
#define dsNiceMatch (136+zlib1222add)
longest_match:
/* Save registers that the compiler may be using, and adjust %esp to */ .file "match.S"
/* make room for our stack frame. */
.globl match_init, longest_match
pushl %ebp
pushl %edi .text
pushl %esi
pushl %ebx /* uInt longest_match(deflate_state *deflatestate, IPos curmatch) */
subl $LocalVarsSize, %esp
longest_match:
/* Retrieve the function arguments. %ecx will hold cur_match */
/* throughout the entire function. %edx will hold the pointer to the */ /* Save registers that the compiler may be using, and adjust %esp to */
/* deflate_state structure during the function's setup (before */ /* make room for our stack frame. */
/* entering the main loop). */
pushl %ebp
movl deflatestate(%esp), %edx pushl %edi
movl curmatch(%esp), %ecx pushl %esi
pushl %ebx
/* if ((uInt)nice_match > s->lookahead) nice_match = s->lookahead; */ subl $LocalVarsSize, %esp
movl dsNiceMatch(%edx), %eax /* Retrieve the function arguments. %ecx will hold cur_match */
movl dsLookahead(%edx), %ebx /* throughout the entire function. %edx will hold the pointer to the */
cmpl %eax, %ebx /* deflate_state structure during the function's setup (before */
jl LookaheadLess /* entering the main loop). */
movl %eax, %ebx
LookaheadLess: movl %ebx, nicematch(%esp) movl deflatestate(%esp), %edx
movl curmatch(%esp), %ecx
/* register Bytef *scan = s->window + s->strstart; */
/* if ((uInt)nice_match > s->lookahead) nice_match = s->lookahead; */
movl dsWindow(%edx), %esi
movl %esi, window(%esp) movl dsNiceMatch(%edx), %eax
movl dsStrStart(%edx), %ebp movl dsLookahead(%edx), %ebx
lea (%esi,%ebp), %edi cmpl %eax, %ebx
movl %edi, scan(%esp) jl LookaheadLess
movl %eax, %ebx
/* Determine how many bytes the scan ptr is off from being */ LookaheadLess: movl %ebx, nicematch(%esp)
/* dword-aligned. */
/* register Bytef *scan = s->window + s->strstart; */
movl %edi, %eax
negl %eax movl dsWindow(%edx), %esi
andl $3, %eax movl %esi, window(%esp)
movl %eax, scanalign(%esp) movl dsStrStart(%edx), %ebp
lea (%esi,%ebp), %edi
/* IPos limit = s->strstart > (IPos)MAX_DIST(s) ? */ movl %edi, scan(%esp)
/* s->strstart - (IPos)MAX_DIST(s) : NIL; */
/* Determine how many bytes the scan ptr is off from being */
movl dsWSize(%edx), %eax /* dword-aligned. */
subl $MIN_LOOKAHEAD, %eax
subl %eax, %ebp movl %edi, %eax
jg LimitPositive negl %eax
xorl %ebp, %ebp andl $3, %eax
LimitPositive: movl %eax, scanalign(%esp)
/* unsigned chain_length = s->max_chain_length; */ /* IPos limit = s->strstart > (IPos)MAX_DIST(s) ? */
/* if (s->prev_length >= s->good_match) { */ /* s->strstart - (IPos)MAX_DIST(s) : NIL; */
/* chain_length >>= 2; */
/* } */ movl dsWSize(%edx), %eax
subl $MIN_LOOKAHEAD, %eax
movl dsPrevLen(%edx), %eax subl %eax, %ebp
movl dsGoodMatch(%edx), %ebx jg LimitPositive
cmpl %ebx, %eax xorl %ebp, %ebp
movl dsMaxChainLen(%edx), %ebx LimitPositive:
jl LastMatchGood
shrl $2, %ebx /* unsigned chain_length = s->max_chain_length; */
LastMatchGood: /* if (s->prev_length >= s->good_match) { */
/* chain_length >>= 2; */
/* chainlen is decremented once beforehand so that the function can */ /* } */
/* use the sign flag instead of the zero flag for the exit test. */
/* It is then shifted into the high word, to make room for the scanend */ movl dsPrevLen(%edx), %eax
/* scanend value, which it will always accompany. */ movl dsGoodMatch(%edx), %ebx
cmpl %ebx, %eax
decl %ebx movl dsMaxChainLen(%edx), %ebx
shll $16, %ebx jl LastMatchGood
shrl $2, %ebx
/* int best_len = s->prev_length; */ LastMatchGood:
movl dsPrevLen(%edx), %eax /* chainlen is decremented once beforehand so that the function can */
movl %eax, bestlen(%esp) /* use the sign flag instead of the zero flag for the exit test. */
/* It is then shifted into the high word, to make room for the scanend */
/* Store the sum of s->window + best_len in %esi locally, and in %esi. */ /* scanend value, which it will always accompany. */
addl %eax, %esi decl %ebx
movl %esi, windowbestlen(%esp) shll $16, %ebx
/* register ush scan_start = *(ushf*)scan; */ /* int best_len = s->prev_length; */
/* register ush scan_end = *(ushf*)(scan+best_len-1); */
movl dsPrevLen(%edx), %eax
movw (%edi), %bx movl %eax, bestlen(%esp)
movw %bx, scanstart(%esp)
movw -1(%edi,%eax), %bx /* Store the sum of s->window + best_len in %esi locally, and in %esi. */
movl %ebx, chainlenscanend(%esp)
addl %eax, %esi
/* Posf *prev = s->prev; */ movl %esi, windowbestlen(%esp)
/* uInt wmask = s->w_mask; */
/* register ush scan_start = *(ushf*)scan; */
movl dsPrev(%edx), %edi /* register ush scan_end = *(ushf*)(scan+best_len-1); */
movl dsWMask(%edx), %edx
mov %edx, wmask(%esp) movw (%edi), %bx
movw %bx, scanstart(%esp)
/* Jump into the main loop. */ movw -1(%edi,%eax), %bx
movl %ebx, chainlenscanend(%esp)
jmp LoopEntry
/* Posf *prev = s->prev; */
.balign 16 /* uInt wmask = s->w_mask; */
/* do { movl dsPrev(%edx), %edi
* match = s->window + cur_match; movl dsWMask(%edx), %edx
* if (*(ushf*)(match+best_len-1) != scan_end || mov %edx, wmask(%esp)
* *(ushf*)match != scan_start) continue;
* [...] /* Jump into the main loop. */
* } while ((cur_match = prev[cur_match & wmask]) > limit
* && --chain_length != 0); jmp LoopEntry
*
* Here is the inner loop of the function. The function will spend the .balign 16
* majority of its time in this loop, and majority of that time will
* be spent in the first ten instructions. /* do {
* * match = s->window + cur_match;
* Within this loop: * if (*(ushf*)(match+best_len-1) != scan_end ||
* %ebx = chainlenscanend - i.e., ((chainlen << 16) | scanend) * *(ushf*)match != scan_start) continue;
* %ecx = curmatch * [...]
* %edx = curmatch & wmask * } while ((cur_match = prev[cur_match & wmask]) > limit
* %esi = windowbestlen - i.e., (window + bestlen) * && --chain_length != 0);
* %edi = prev *
* %ebp = limit * Here is the inner loop of the function. The function will spend the
* * majority of its time in this loop, and majority of that time will
* Two optimization notes on the choice of instructions: * be spent in the first ten instructions.
* *
* The first instruction uses a 16-bit address, which costs an extra, * Within this loop:
* unpairable cycle. This is cheaper than doing a 32-bit access and * %ebx = chainlenscanend - i.e., ((chainlen << 16) | scanend)
* zeroing the high word, due to the 3-cycle misalignment penalty which * %ecx = curmatch
* would occur half the time. This also turns out to be cheaper than * %edx = curmatch & wmask
* doing two separate 8-bit accesses, as the memory is so rarely in the * %esi = windowbestlen - i.e., (window + bestlen)
* L1 cache. * %edi = prev
* * %ebp = limit
* The window buffer, however, apparently spends a lot of time in the *
* cache, and so it is faster to retrieve the word at the end of the * Two optimization notes on the choice of instructions:
* match string with two 8-bit loads. The instructions that test the *
* word at the beginning of the match string, however, are executed * The first instruction uses a 16-bit address, which costs an extra,
* much less frequently, and there it was cheaper to use 16-bit * unpairable cycle. This is cheaper than doing a 32-bit access and
* instructions, which avoided the necessity of saving off and * zeroing the high word, due to the 3-cycle misalignment penalty which
* subsequently reloading one of the other registers. * would occur half the time. This also turns out to be cheaper than
*/ * doing two separate 8-bit accesses, as the memory is so rarely in the
LookupLoop: * L1 cache.
/* 1 U & V */ *
movw (%edi,%edx,2), %cx /* 2 U pipe */ * The window buffer, however, apparently spends a lot of time in the
movl wmask(%esp), %edx /* 2 V pipe */ * cache, and so it is faster to retrieve the word at the end of the
cmpl %ebp, %ecx /* 3 U pipe */ * match string with two 8-bit loads. The instructions that test the
jbe LeaveNow /* 3 V pipe */ * word at the beginning of the match string, however, are executed
subl $0x00010000, %ebx /* 4 U pipe */ * much less frequently, and there it was cheaper to use 16-bit
js LeaveNow /* 4 V pipe */ * instructions, which avoided the necessity of saving off and
LoopEntry: movb -1(%esi,%ecx), %al /* 5 U pipe */ * subsequently reloading one of the other registers.
andl %ecx, %edx /* 5 V pipe */ */
cmpb %bl, %al /* 6 U pipe */ LookupLoop:
jnz LookupLoop /* 6 V pipe */ /* 1 U & V */
movb (%esi,%ecx), %ah movw (%edi,%edx,2), %cx /* 2 U pipe */
cmpb %bh, %ah movl wmask(%esp), %edx /* 2 V pipe */
jnz LookupLoop cmpl %ebp, %ecx /* 3 U pipe */
movl window(%esp), %eax jbe LeaveNow /* 3 V pipe */
movw (%eax,%ecx), %ax subl $0x00010000, %ebx /* 4 U pipe */
cmpw scanstart(%esp), %ax js LeaveNow /* 4 V pipe */
jnz LookupLoop LoopEntry: movb -1(%esi,%ecx), %al /* 5 U pipe */
andl %ecx, %edx /* 5 V pipe */
/* Store the current value of chainlen. */ cmpb %bl, %al /* 6 U pipe */
jnz LookupLoop /* 6 V pipe */
movl %ebx, chainlenscanend(%esp) movb (%esi,%ecx), %ah
cmpb %bh, %ah
/* Point %edi to the string under scrutiny, and %esi to the string we */ jnz LookupLoop
/* are hoping to match it up with. In actuality, %esi and %edi are */ movl window(%esp), %eax
/* both pointed (MAX_MATCH_8 - scanalign) bytes ahead, and %edx is */ movw (%eax,%ecx), %ax
/* initialized to -(MAX_MATCH_8 - scanalign). */ cmpw scanstart(%esp), %ax
jnz LookupLoop
movl window(%esp), %esi
movl scan(%esp), %edi /* Store the current value of chainlen. */
addl %ecx, %esi
movl scanalign(%esp), %eax movl %ebx, chainlenscanend(%esp)
movl $(-MAX_MATCH_8), %edx
lea MAX_MATCH_8(%edi,%eax), %edi /* Point %edi to the string under scrutiny, and %esi to the string we */
lea MAX_MATCH_8(%esi,%eax), %esi /* are hoping to match it up with. In actuality, %esi and %edi are */
/* both pointed (MAX_MATCH_8 - scanalign) bytes ahead, and %edx is */
/* Test the strings for equality, 8 bytes at a time. At the end, /* initialized to -(MAX_MATCH_8 - scanalign). */
* adjust %edx so that it is offset to the exact byte that mismatched.
* movl window(%esp), %esi
* We already know at this point that the first three bytes of the movl scan(%esp), %edi
* strings match each other, and they can be safely passed over before addl %ecx, %esi
* starting the compare loop. So what this code does is skip over 0-3 movl scanalign(%esp), %eax
* bytes, as much as necessary in order to dword-align the %edi movl $(-MAX_MATCH_8), %edx
* pointer. (%esi will still be misaligned three times out of four.) lea MAX_MATCH_8(%edi,%eax), %edi
* lea MAX_MATCH_8(%esi,%eax), %esi
* It should be confessed that this loop usually does not represent
* much of the total running time. Replacing it with a more /* Test the strings for equality, 8 bytes at a time. At the end,
* straightforward "rep cmpsb" would not drastically degrade * adjust %edx so that it is offset to the exact byte that mismatched.
* performance. *
*/ * We already know at this point that the first three bytes of the
LoopCmps: * strings match each other, and they can be safely passed over before
movl (%esi,%edx), %eax * starting the compare loop. So what this code does is skip over 0-3
movl (%edi,%edx), %ebx * bytes, as much as necessary in order to dword-align the %edi
xorl %ebx, %eax * pointer. (%esi will still be misaligned three times out of four.)
jnz LeaveLoopCmps *
movl 4(%esi,%edx), %eax * It should be confessed that this loop usually does not represent
movl 4(%edi,%edx), %ebx * much of the total running time. Replacing it with a more
xorl %ebx, %eax * straightforward "rep cmpsb" would not drastically degrade
jnz LeaveLoopCmps4 * performance.
addl $8, %edx */
jnz LoopCmps LoopCmps:
jmp LenMaximum movl (%esi,%edx), %eax
LeaveLoopCmps4: addl $4, %edx movl (%edi,%edx), %ebx
LeaveLoopCmps: testl $0x0000FFFF, %eax xorl %ebx, %eax
jnz LenLower jnz LeaveLoopCmps
addl $2, %edx movl 4(%esi,%edx), %eax
shrl $16, %eax movl 4(%edi,%edx), %ebx
LenLower: subb $1, %al xorl %ebx, %eax
adcl $0, %edx jnz LeaveLoopCmps4
addl $8, %edx
/* Calculate the length of the match. If it is longer than MAX_MATCH, */ jnz LoopCmps
/* then automatically accept it as the best possible match and leave. */ jmp LenMaximum
LeaveLoopCmps4: addl $4, %edx
lea (%edi,%edx), %eax LeaveLoopCmps: testl $0x0000FFFF, %eax
movl scan(%esp), %edi jnz LenLower
subl %edi, %eax addl $2, %edx
cmpl $MAX_MATCH, %eax shrl $16, %eax
jge LenMaximum LenLower: subb $1, %al
adcl $0, %edx
/* If the length of the match is not longer than the best match we */
/* have so far, then forget it and return to the lookup loop. */ /* Calculate the length of the match. If it is longer than MAX_MATCH, */
/* then automatically accept it as the best possible match and leave. */
movl deflatestate(%esp), %edx
movl bestlen(%esp), %ebx lea (%edi,%edx), %eax
cmpl %ebx, %eax movl scan(%esp), %edi
jg LongerMatch subl %edi, %eax
movl chainlenscanend(%esp), %ebx cmpl $MAX_MATCH, %eax
movl windowbestlen(%esp), %esi jge LenMaximum
movl dsPrev(%edx), %edi
movl wmask(%esp), %edx /* If the length of the match is not longer than the best match we */
andl %ecx, %edx /* have so far, then forget it and return to the lookup loop. */
jmp LookupLoop
movl deflatestate(%esp), %edx
/* s->match_start = cur_match; */ movl bestlen(%esp), %ebx
/* best_len = len; */ cmpl %ebx, %eax
/* if (len >= nice_match) break; */ jg LongerMatch
/* scan_end = *(ushf*)(scan+best_len-1); */ movl chainlenscanend(%esp), %ebx
movl windowbestlen(%esp), %esi
LongerMatch: movl nicematch(%esp), %ebx movl dsPrev(%edx), %edi
movl %eax, bestlen(%esp) movl wmask(%esp), %edx
movl %ecx, dsMatchStart(%edx) andl %ecx, %edx
cmpl %ebx, %eax jmp LookupLoop
jge LeaveNow
movl window(%esp), %esi /* s->match_start = cur_match; */
addl %eax, %esi /* best_len = len; */
movl %esi, windowbestlen(%esp) /* if (len >= nice_match) break; */
movl chainlenscanend(%esp), %ebx /* scan_end = *(ushf*)(scan+best_len-1); */
movw -1(%edi,%eax), %bx
movl dsPrev(%edx), %edi LongerMatch: movl nicematch(%esp), %ebx
movl %ebx, chainlenscanend(%esp) movl %eax, bestlen(%esp)
movl wmask(%esp), %edx movl %ecx, dsMatchStart(%edx)
andl %ecx, %edx cmpl %ebx, %eax
jmp LookupLoop jge LeaveNow
movl window(%esp), %esi
/* Accept the current string, with the maximum possible length. */ addl %eax, %esi
movl %esi, windowbestlen(%esp)
LenMaximum: movl deflatestate(%esp), %edx movl chainlenscanend(%esp), %ebx
movl $MAX_MATCH, bestlen(%esp) movw -1(%edi,%eax), %bx
movl %ecx, dsMatchStart(%edx) movl dsPrev(%edx), %edi
movl %ebx, chainlenscanend(%esp)
/* if ((uInt)best_len <= s->lookahead) return (uInt)best_len; */ movl wmask(%esp), %edx
/* return s->lookahead; */ andl %ecx, %edx
jmp LookupLoop
LeaveNow:
movl deflatestate(%esp), %edx /* Accept the current string, with the maximum possible length. */
movl bestlen(%esp), %ebx
movl dsLookahead(%edx), %eax LenMaximum: movl deflatestate(%esp), %edx
cmpl %eax, %ebx movl $MAX_MATCH, bestlen(%esp)
jg LookaheadRet movl %ecx, dsMatchStart(%edx)
movl %ebx, %eax
LookaheadRet: /* if ((uInt)best_len <= s->lookahead) return (uInt)best_len; */
/* return s->lookahead; */
/* Restore the stack and return from whence we came. */
LeaveNow:
addl $LocalVarsSize, %esp movl deflatestate(%esp), %edx
popl %ebx movl bestlen(%esp), %ebx
popl %esi movl dsLookahead(%edx), %eax
popl %edi cmpl %eax, %ebx
popl %ebp jg LookaheadRet
match_init: ret movl %ebx, %eax
LookaheadRet:
/* Restore the stack and return from whence we came. */
addl $LocalVarsSize, %esp
popl %ebx
popl %esi
popl %edi
popl %ebp
match_init: ret

View File

@@ -1,327 +1,329 @@
/* match.s -- Pentium-Pro-optimized version of longest_match() /* match.s -- Pentium-Pro-optimized version of longest_match()
* Written for zlib 1.1.2 * Written for zlib 1.1.2
* Copyright (C) 1998 Brian Raiter <breadbox@muppetlabs.com> * Copyright (C) 1998 Brian Raiter <breadbox@muppetlabs.com>
* *
* This is free software; you can redistribute it and/or modify it * This is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License. * under the terms of the GNU General Public License.
*/ */
#ifndef NO_UNDERLINE #ifndef NO_UNDERLINE
#define match_init _match_init #define match_init _match_init
#define longest_match _longest_match #define longest_match _longest_match
#endif #endif
#define MAX_MATCH (258) #define MAX_MATCH (258)
#define MIN_MATCH (3) #define MIN_MATCH (3)
#define MIN_LOOKAHEAD (MAX_MATCH + MIN_MATCH + 1) #define MIN_LOOKAHEAD (MAX_MATCH + MIN_MATCH + 1)
#define MAX_MATCH_8 ((MAX_MATCH + 7) & ~7) #define MAX_MATCH_8 ((MAX_MATCH + 7) & ~7)
/* stack frame offsets */ /* stack frame offsets */
#define chainlenwmask 0 /* high word: current chain len */ #define chainlenwmask 0 /* high word: current chain len */
/* low word: s->wmask */ /* low word: s->wmask */
#define window 4 /* local copy of s->window */ #define window 4 /* local copy of s->window */
#define windowbestlen 8 /* s->window + bestlen */ #define windowbestlen 8 /* s->window + bestlen */
#define scanstart 16 /* first two bytes of string */ #define scanstart 16 /* first two bytes of string */
#define scanend 12 /* last two bytes of string */ #define scanend 12 /* last two bytes of string */
#define scanalign 20 /* dword-misalignment of string */ #define scanalign 20 /* dword-misalignment of string */
#define nicematch 24 /* a good enough match size */ #define nicematch 24 /* a good enough match size */
#define bestlen 28 /* size of best match so far */ #define bestlen 28 /* size of best match so far */
#define scan 32 /* ptr to string wanting match */ #define scan 32 /* ptr to string wanting match */
#define LocalVarsSize (36) #define LocalVarsSize (36)
/* saved ebx 36 */ /* saved ebx 36 */
/* saved edi 40 */ /* saved edi 40 */
/* saved esi 44 */ /* saved esi 44 */
/* saved ebp 48 */ /* saved ebp 48 */
/* return address 52 */ /* return address 52 */
#define deflatestate 56 /* the function arguments */ #define deflatestate 56 /* the function arguments */
#define curmatch 60 #define curmatch 60
/* Offsets for fields in the deflate_state structure. These numbers /* All the +zlib1222add offsets are due to the addition of fields
* are calculated from the definition of deflate_state, with the * in zlib in the deflate_state structure since the asm code was first written
* assumption that the compiler will dword-align the fields. (Thus, * (if you compile with zlib 1.0.4 or older, use "zlib1222add equ (-4)").
* changing the definition of deflate_state could easily cause this * (if you compile with zlib between 1.0.5 and 1.2.2.1, use "zlib1222add equ 0").
* program to crash horribly, without so much as a warning at * if you compile with zlib 1.2.2.2 or later , use "zlib1222add equ 8").
* compile time. Sigh.) */
*/
#define dsWSize 36 #define zlib1222add (8)
#define dsWMask 44
#define dsWindow 48 #define dsWSize (36+zlib1222add)
#define dsPrev 56 #define dsWMask (44+zlib1222add)
#define dsMatchLen 88 #define dsWindow (48+zlib1222add)
#define dsPrevMatch 92 #define dsPrev (56+zlib1222add)
#define dsStrStart 100 #define dsMatchLen (88+zlib1222add)
#define dsMatchStart 104 #define dsPrevMatch (92+zlib1222add)
#define dsLookahead 108 #define dsStrStart (100+zlib1222add)
#define dsPrevLen 112 #define dsMatchStart (104+zlib1222add)
#define dsMaxChainLen 116 #define dsLookahead (108+zlib1222add)
#define dsGoodMatch 132 #define dsPrevLen (112+zlib1222add)
#define dsNiceMatch 136 #define dsMaxChainLen (116+zlib1222add)
#define dsGoodMatch (132+zlib1222add)
#define dsNiceMatch (136+zlib1222add)
.file "match.S"
.globl match_init, longest_match .file "match.S"
.text .globl match_init, longest_match
/* uInt longest_match(deflate_state *deflatestate, IPos curmatch) */ .text
longest_match: /* uInt longest_match(deflate_state *deflatestate, IPos curmatch) */
/* Save registers that the compiler may be using, and adjust %esp to */ longest_match:
/* make room for our stack frame. */
/* Save registers that the compiler may be using, and adjust %esp to */
pushl %ebp /* make room for our stack frame. */
pushl %edi
pushl %esi pushl %ebp
pushl %ebx pushl %edi
subl $LocalVarsSize, %esp pushl %esi
pushl %ebx
/* Retrieve the function arguments. %ecx will hold cur_match */ subl $LocalVarsSize, %esp
/* throughout the entire function. %edx will hold the pointer to the */
/* deflate_state structure during the function's setup (before */ /* Retrieve the function arguments. %ecx will hold cur_match */
/* entering the main loop). */ /* throughout the entire function. %edx will hold the pointer to the */
/* deflate_state structure during the function's setup (before */
movl deflatestate(%esp), %edx /* entering the main loop). */
movl curmatch(%esp), %ecx
movl deflatestate(%esp), %edx
/* uInt wmask = s->w_mask; */ movl curmatch(%esp), %ecx
/* unsigned chain_length = s->max_chain_length; */
/* if (s->prev_length >= s->good_match) { */ /* uInt wmask = s->w_mask; */
/* chain_length >>= 2; */ /* unsigned chain_length = s->max_chain_length; */
/* } */ /* if (s->prev_length >= s->good_match) { */
/* chain_length >>= 2; */
movl dsPrevLen(%edx), %eax /* } */
movl dsGoodMatch(%edx), %ebx
cmpl %ebx, %eax movl dsPrevLen(%edx), %eax
movl dsWMask(%edx), %eax movl dsGoodMatch(%edx), %ebx
movl dsMaxChainLen(%edx), %ebx cmpl %ebx, %eax
jl LastMatchGood movl dsWMask(%edx), %eax
shrl $2, %ebx movl dsMaxChainLen(%edx), %ebx
LastMatchGood: jl LastMatchGood
shrl $2, %ebx
/* chainlen is decremented once beforehand so that the function can */ LastMatchGood:
/* use the sign flag instead of the zero flag for the exit test. */
/* It is then shifted into the high word, to make room for the wmask */ /* chainlen is decremented once beforehand so that the function can */
/* value, which it will always accompany. */ /* use the sign flag instead of the zero flag for the exit test. */
/* It is then shifted into the high word, to make room for the wmask */
decl %ebx /* value, which it will always accompany. */
shll $16, %ebx
orl %eax, %ebx decl %ebx
movl %ebx, chainlenwmask(%esp) shll $16, %ebx
orl %eax, %ebx
/* if ((uInt)nice_match > s->lookahead) nice_match = s->lookahead; */ movl %ebx, chainlenwmask(%esp)
movl dsNiceMatch(%edx), %eax /* if ((uInt)nice_match > s->lookahead) nice_match = s->lookahead; */
movl dsLookahead(%edx), %ebx
cmpl %eax, %ebx movl dsNiceMatch(%edx), %eax
jl LookaheadLess movl dsLookahead(%edx), %ebx
movl %eax, %ebx cmpl %eax, %ebx
LookaheadLess: movl %ebx, nicematch(%esp) jl LookaheadLess
movl %eax, %ebx
/* register Bytef *scan = s->window + s->strstart; */ LookaheadLess: movl %ebx, nicematch(%esp)
movl dsWindow(%edx), %esi /* register Bytef *scan = s->window + s->strstart; */
movl %esi, window(%esp)
movl dsStrStart(%edx), %ebp movl dsWindow(%edx), %esi
lea (%esi,%ebp), %edi movl %esi, window(%esp)
movl %edi, scan(%esp) movl dsStrStart(%edx), %ebp
lea (%esi,%ebp), %edi
/* Determine how many bytes the scan ptr is off from being */ movl %edi, scan(%esp)
/* dword-aligned. */
/* Determine how many bytes the scan ptr is off from being */
movl %edi, %eax /* dword-aligned. */
negl %eax
andl $3, %eax movl %edi, %eax
movl %eax, scanalign(%esp) negl %eax
andl $3, %eax
/* IPos limit = s->strstart > (IPos)MAX_DIST(s) ? */ movl %eax, scanalign(%esp)
/* s->strstart - (IPos)MAX_DIST(s) : NIL; */
/* IPos limit = s->strstart > (IPos)MAX_DIST(s) ? */
movl dsWSize(%edx), %eax /* s->strstart - (IPos)MAX_DIST(s) : NIL; */
subl $MIN_LOOKAHEAD, %eax
subl %eax, %ebp movl dsWSize(%edx), %eax
jg LimitPositive subl $MIN_LOOKAHEAD, %eax
xorl %ebp, %ebp subl %eax, %ebp
LimitPositive: jg LimitPositive
xorl %ebp, %ebp
/* int best_len = s->prev_length; */ LimitPositive:
movl dsPrevLen(%edx), %eax /* int best_len = s->prev_length; */
movl %eax, bestlen(%esp)
movl dsPrevLen(%edx), %eax
/* Store the sum of s->window + best_len in %esi locally, and in %esi. */ movl %eax, bestlen(%esp)
addl %eax, %esi /* Store the sum of s->window + best_len in %esi locally, and in %esi. */
movl %esi, windowbestlen(%esp)
addl %eax, %esi
/* register ush scan_start = *(ushf*)scan; */ movl %esi, windowbestlen(%esp)
/* register ush scan_end = *(ushf*)(scan+best_len-1); */
/* Posf *prev = s->prev; */ /* register ush scan_start = *(ushf*)scan; */
/* register ush scan_end = *(ushf*)(scan+best_len-1); */
movzwl (%edi), %ebx /* Posf *prev = s->prev; */
movl %ebx, scanstart(%esp)
movzwl -1(%edi,%eax), %ebx movzwl (%edi), %ebx
movl %ebx, scanend(%esp) movl %ebx, scanstart(%esp)
movl dsPrev(%edx), %edi movzwl -1(%edi,%eax), %ebx
movl %ebx, scanend(%esp)
/* Jump into the main loop. */ movl dsPrev(%edx), %edi
movl chainlenwmask(%esp), %edx /* Jump into the main loop. */
jmp LoopEntry
movl chainlenwmask(%esp), %edx
.balign 16 jmp LoopEntry
/* do { .balign 16
* match = s->window + cur_match;
* if (*(ushf*)(match+best_len-1) != scan_end || /* do {
* *(ushf*)match != scan_start) continue; * match = s->window + cur_match;
* [...] * if (*(ushf*)(match+best_len-1) != scan_end ||
* } while ((cur_match = prev[cur_match & wmask]) > limit * *(ushf*)match != scan_start) continue;
* && --chain_length != 0); * [...]
* * } while ((cur_match = prev[cur_match & wmask]) > limit
* Here is the inner loop of the function. The function will spend the * && --chain_length != 0);
* majority of its time in this loop, and majority of that time will *
* be spent in the first ten instructions. * Here is the inner loop of the function. The function will spend the
* * majority of its time in this loop, and majority of that time will
* Within this loop: * be spent in the first ten instructions.
* %ebx = scanend *
* %ecx = curmatch * Within this loop:
* %edx = chainlenwmask - i.e., ((chainlen << 16) | wmask) * %ebx = scanend
* %esi = windowbestlen - i.e., (window + bestlen) * %ecx = curmatch
* %edi = prev * %edx = chainlenwmask - i.e., ((chainlen << 16) | wmask)
* %ebp = limit * %esi = windowbestlen - i.e., (window + bestlen)
*/ * %edi = prev
LookupLoop: * %ebp = limit
andl %edx, %ecx */
movzwl (%edi,%ecx,2), %ecx LookupLoop:
cmpl %ebp, %ecx andl %edx, %ecx
jbe LeaveNow movzwl (%edi,%ecx,2), %ecx
subl $0x00010000, %edx cmpl %ebp, %ecx
js LeaveNow jbe LeaveNow
LoopEntry: movzwl -1(%esi,%ecx), %eax subl $0x00010000, %edx
cmpl %ebx, %eax js LeaveNow
jnz LookupLoop LoopEntry: movzwl -1(%esi,%ecx), %eax
movl window(%esp), %eax cmpl %ebx, %eax
movzwl (%eax,%ecx), %eax jnz LookupLoop
cmpl scanstart(%esp), %eax movl window(%esp), %eax
jnz LookupLoop movzwl (%eax,%ecx), %eax
cmpl scanstart(%esp), %eax
/* Store the current value of chainlen. */ jnz LookupLoop
movl %edx, chainlenwmask(%esp) /* Store the current value of chainlen. */
/* Point %edi to the string under scrutiny, and %esi to the string we */ movl %edx, chainlenwmask(%esp)
/* are hoping to match it up with. In actuality, %esi and %edi are */
/* both pointed (MAX_MATCH_8 - scanalign) bytes ahead, and %edx is */ /* Point %edi to the string under scrutiny, and %esi to the string we */
/* initialized to -(MAX_MATCH_8 - scanalign). */ /* are hoping to match it up with. In actuality, %esi and %edi are */
/* both pointed (MAX_MATCH_8 - scanalign) bytes ahead, and %edx is */
movl window(%esp), %esi /* initialized to -(MAX_MATCH_8 - scanalign). */
movl scan(%esp), %edi
addl %ecx, %esi movl window(%esp), %esi
movl scanalign(%esp), %eax movl scan(%esp), %edi
movl $(-MAX_MATCH_8), %edx addl %ecx, %esi
lea MAX_MATCH_8(%edi,%eax), %edi movl scanalign(%esp), %eax
lea MAX_MATCH_8(%esi,%eax), %esi movl $(-MAX_MATCH_8), %edx
lea MAX_MATCH_8(%edi,%eax), %edi
/* Test the strings for equality, 8 bytes at a time. At the end, lea MAX_MATCH_8(%esi,%eax), %esi
* adjust %edx so that it is offset to the exact byte that mismatched.
* /* Test the strings for equality, 8 bytes at a time. At the end,
* We already know at this point that the first three bytes of the * adjust %edx so that it is offset to the exact byte that mismatched.
* strings match each other, and they can be safely passed over before *
* starting the compare loop. So what this code does is skip over 0-3 * We already know at this point that the first three bytes of the
* bytes, as much as necessary in order to dword-align the %edi * strings match each other, and they can be safely passed over before
* pointer. (%esi will still be misaligned three times out of four.) * starting the compare loop. So what this code does is skip over 0-3
* * bytes, as much as necessary in order to dword-align the %edi
* It should be confessed that this loop usually does not represent * pointer. (%esi will still be misaligned three times out of four.)
* much of the total running time. Replacing it with a more *
* straightforward "rep cmpsb" would not drastically degrade * It should be confessed that this loop usually does not represent
* performance. * much of the total running time. Replacing it with a more
*/ * straightforward "rep cmpsb" would not drastically degrade
LoopCmps: * performance.
movl (%esi,%edx), %eax */
xorl (%edi,%edx), %eax LoopCmps:
jnz LeaveLoopCmps movl (%esi,%edx), %eax
movl 4(%esi,%edx), %eax xorl (%edi,%edx), %eax
xorl 4(%edi,%edx), %eax jnz LeaveLoopCmps
jnz LeaveLoopCmps4 movl 4(%esi,%edx), %eax
addl $8, %edx xorl 4(%edi,%edx), %eax
jnz LoopCmps jnz LeaveLoopCmps4
jmp LenMaximum addl $8, %edx
LeaveLoopCmps4: addl $4, %edx jnz LoopCmps
LeaveLoopCmps: testl $0x0000FFFF, %eax jmp LenMaximum
jnz LenLower LeaveLoopCmps4: addl $4, %edx
addl $2, %edx LeaveLoopCmps: testl $0x0000FFFF, %eax
shrl $16, %eax jnz LenLower
LenLower: subb $1, %al addl $2, %edx
adcl $0, %edx shrl $16, %eax
LenLower: subb $1, %al
/* Calculate the length of the match. If it is longer than MAX_MATCH, */ adcl $0, %edx
/* then automatically accept it as the best possible match and leave. */
/* Calculate the length of the match. If it is longer than MAX_MATCH, */
lea (%edi,%edx), %eax /* then automatically accept it as the best possible match and leave. */
movl scan(%esp), %edi
subl %edi, %eax lea (%edi,%edx), %eax
cmpl $MAX_MATCH, %eax movl scan(%esp), %edi
jge LenMaximum subl %edi, %eax
cmpl $MAX_MATCH, %eax
/* If the length of the match is not longer than the best match we */ jge LenMaximum
/* have so far, then forget it and return to the lookup loop. */
/* If the length of the match is not longer than the best match we */
movl deflatestate(%esp), %edx /* have so far, then forget it and return to the lookup loop. */
movl bestlen(%esp), %ebx
cmpl %ebx, %eax movl deflatestate(%esp), %edx
jg LongerMatch movl bestlen(%esp), %ebx
movl windowbestlen(%esp), %esi cmpl %ebx, %eax
movl dsPrev(%edx), %edi jg LongerMatch
movl scanend(%esp), %ebx movl windowbestlen(%esp), %esi
movl chainlenwmask(%esp), %edx movl dsPrev(%edx), %edi
jmp LookupLoop movl scanend(%esp), %ebx
movl chainlenwmask(%esp), %edx
/* s->match_start = cur_match; */ jmp LookupLoop
/* best_len = len; */
/* if (len >= nice_match) break; */ /* s->match_start = cur_match; */
/* scan_end = *(ushf*)(scan+best_len-1); */ /* best_len = len; */
/* if (len >= nice_match) break; */
LongerMatch: movl nicematch(%esp), %ebx /* scan_end = *(ushf*)(scan+best_len-1); */
movl %eax, bestlen(%esp)
movl %ecx, dsMatchStart(%edx) LongerMatch: movl nicematch(%esp), %ebx
cmpl %ebx, %eax movl %eax, bestlen(%esp)
jge LeaveNow movl %ecx, dsMatchStart(%edx)
movl window(%esp), %esi cmpl %ebx, %eax
addl %eax, %esi jge LeaveNow
movl %esi, windowbestlen(%esp) movl window(%esp), %esi
movzwl -1(%edi,%eax), %ebx addl %eax, %esi
movl dsPrev(%edx), %edi movl %esi, windowbestlen(%esp)
movl %ebx, scanend(%esp) movzwl -1(%edi,%eax), %ebx
movl chainlenwmask(%esp), %edx movl dsPrev(%edx), %edi
jmp LookupLoop movl %ebx, scanend(%esp)
movl chainlenwmask(%esp), %edx
/* Accept the current string, with the maximum possible length. */ jmp LookupLoop
LenMaximum: movl deflatestate(%esp), %edx /* Accept the current string, with the maximum possible length. */
movl $MAX_MATCH, bestlen(%esp)
movl %ecx, dsMatchStart(%edx) LenMaximum: movl deflatestate(%esp), %edx
movl $MAX_MATCH, bestlen(%esp)
/* if ((uInt)best_len <= s->lookahead) return (uInt)best_len; */ movl %ecx, dsMatchStart(%edx)
/* return s->lookahead; */
/* if ((uInt)best_len <= s->lookahead) return (uInt)best_len; */
LeaveNow: /* return s->lookahead; */
movl deflatestate(%esp), %edx
movl bestlen(%esp), %ebx LeaveNow:
movl dsLookahead(%edx), %eax movl deflatestate(%esp), %edx
cmpl %eax, %ebx movl bestlen(%esp), %ebx
jg LookaheadRet movl dsLookahead(%edx), %eax
movl %ebx, %eax cmpl %eax, %ebx
LookaheadRet: jg LookaheadRet
movl %ebx, %eax
/* Restore the stack and return from whence we came. */ LookaheadRet:
addl $LocalVarsSize, %esp /* Restore the stack and return from whence we came. */
popl %ebx
popl %esi addl $LocalVarsSize, %esp
popl %edi popl %ebx
popl %ebp popl %esi
match_init: ret popl %edi
popl %ebp
match_init: ret

View File

@@ -344,7 +344,7 @@ begin
strm.avail_out := OutBytes; strm.avail_out := OutBytes;
DCheck(inflateInit_(strm, zlib_version, sizeof(strm))); DCheck(inflateInit_(strm, zlib_version, sizeof(strm)));
try try
while DCheck(inflate(strm, Z_FINISH)) <> Z_STREAM_END do while DCheck(inflate(strm, Z_NO_FLUSH)) <> Z_STREAM_END do
begin begin
P := OutBuf; P := OutBuf;
Inc(OutBytes, BufInc); Inc(OutBytes, BufInc);

View File

@@ -16,6 +16,10 @@
* zlib.h must be included before this header file. * zlib.h must be included before this header file.
*/ */
#ifdef __cplusplus
extern "C" {
#endif
ZEXTERN int ZEXPORT inflateBack9 OF((z_stream FAR *strm, ZEXTERN int ZEXPORT inflateBack9 OF((z_stream FAR *strm,
in_func in, void FAR *in_desc, in_func in, void FAR *in_desc,
out_func out, void FAR *out_desc)); out_func out, void FAR *out_desc));
@@ -27,3 +31,7 @@ ZEXTERN int ZEXPORT inflateBack9Init_ OF((z_stream FAR *strm,
#define inflateBack9Init(strm, window) \ #define inflateBack9Init(strm, window) \
inflateBack9Init_((strm), (window), \ inflateBack9Init_((strm), (window), \
ZLIB_VERSION, sizeof(z_stream)) ZLIB_VERSION, sizeof(z_stream))
#ifdef __cplusplus
}
#endif

View File

@@ -1,5 +1,5 @@
/* inftree9.c -- generate Huffman trees for efficient decoding /* inftree9.c -- generate Huffman trees for efficient decoding
* Copyright (C) 1995-2003 Mark Adler * Copyright (C) 1995-2005 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 inflate9_copyright[] = const char inflate9_copyright[] =
" inflate9 1.2.2.1 Copyright 1995-2004 Mark Adler "; " inflate9 1.2.2.3 Copyright 1995-2005 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
@@ -64,7 +64,7 @@ unsigned short FAR *work;
static const unsigned short lext[31] = { /* Length codes 257..285 extra */ static const unsigned short lext[31] = { /* Length codes 257..285 extra */
128, 128, 128, 128, 128, 128, 128, 128, 129, 129, 129, 129, 128, 128, 128, 128, 128, 128, 128, 128, 129, 129, 129, 129,
130, 130, 130, 130, 131, 131, 131, 131, 132, 132, 132, 132, 130, 130, 130, 130, 131, 131, 131, 131, 132, 132, 132, 132,
133, 133, 133, 133, 144, 77, 207}; 133, 133, 133, 133, 144, 66, 71};
static const unsigned short dbase[32] = { /* Distance codes 0..31 base */ static const unsigned short dbase[32] = { /* Distance codes 0..31 base */
1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49,
65, 97, 129, 193, 257, 385, 513, 769, 1025, 1537, 2049, 3073, 65, 97, 129, 193, 257, 385, 513, 769, 1025, 1537, 2049, 3073,

View File

@@ -1,408 +1,413 @@
; match.asm -- Pentium-Pro optimized version of longest_match() ; match.asm -- Pentium-Pro optimized version of longest_match()
; ;
; Updated for zlib 1.1.3 and converted to MASM 6.1x ; Updated for zlib 1.1.3 and converted to MASM 6.1x
; Copyright (C) 2000 Dan Higdon <hdan@kinesoft.com> ; Copyright (C) 2000 Dan Higdon <hdan@kinesoft.com>
; and Chuck Walbourn <chuckw@kinesoft.com> ; and Chuck Walbourn <chuckw@kinesoft.com>
; Corrections by Cosmin Truta <cosmint@cs.ubbcluj.ro> ; Corrections by Cosmin Truta <cosmint@cs.ubbcluj.ro>
; ;
; This is free software; you can redistribute it and/or modify it ; This is free software; you can redistribute it and/or modify it
; under the terms of the GNU General Public License. ; under the terms of the GNU General Public License.
; Based on match.S ; Based on match.S
; Written for zlib 1.1.2 ; Written for zlib 1.1.2
; Copyright (C) 1998 Brian Raiter <breadbox@muppetlabs.com> ; Copyright (C) 1998 Brian Raiter <breadbox@muppetlabs.com>
;
.686P ; Modified by Gilles Vollant (2005) for add gzhead and gzindex
.MODEL FLAT
.686P
;=========================================================================== .MODEL FLAT
; EQUATES
;=========================================================================== ;===========================================================================
; EQUATES
MAX_MATCH EQU 258 ;===========================================================================
MIN_MATCH EQU 3
MIN_LOOKAHEAD EQU (MAX_MATCH + MIN_MATCH + 1) MAX_MATCH EQU 258
MAX_MATCH_8 EQU ((MAX_MATCH + 7) AND (NOT 7)) MIN_MATCH EQU 3
MIN_LOOKAHEAD EQU (MAX_MATCH + MIN_MATCH + 1)
;=========================================================================== MAX_MATCH_8 EQU ((MAX_MATCH + 7) AND (NOT 7))
; STRUCTURES
;=========================================================================== ;===========================================================================
; STRUCTURES
; This STRUCT assumes a 4-byte alignment ;===========================================================================
DEFLATE_STATE STRUCT ; This STRUCT assumes a 4-byte alignment
ds_strm dd ?
ds_status dd ? DEFLATE_STATE STRUCT
ds_pending_buf dd ? ds_strm dd ?
ds_pending_buf_size dd ? ds_status dd ?
ds_pending_out dd ? ds_pending_buf dd ?
ds_pending dd ? ds_pending_buf_size dd ?
ds_wrap dd ? ds_pending_out dd ?
ds_data_type db ? ds_pending dd ?
ds_method db ? ds_wrap dd ?
db ? ; padding ; gzhead and gzindex are added in zlib 1.2.2.2 (see deflate.h)
db ? ; padding ds_gzhead dd ?
ds_last_flush dd ? ds_gzindex dd ?
ds_w_size dd ? ; used ds_data_type db ?
ds_w_bits dd ? ds_method db ?
ds_w_mask dd ? ; used db ? ; padding
ds_window dd ? ; used db ? ; padding
ds_window_size dd ? ds_last_flush dd ?
ds_prev dd ? ; used ds_w_size dd ? ; used
ds_head dd ? ds_w_bits dd ?
ds_ins_h dd ? ds_w_mask dd ? ; used
ds_hash_size dd ? ds_window dd ? ; used
ds_hash_bits dd ? ds_window_size dd ?
ds_hash_mask dd ? ds_prev dd ? ; used
ds_hash_shift dd ? ds_head dd ?
ds_block_start dd ? ds_ins_h dd ?
ds_match_length dd ? ; used ds_hash_size dd ?
ds_prev_match dd ? ; used ds_hash_bits dd ?
ds_match_available dd ? ds_hash_mask dd ?
ds_strstart dd ? ; used ds_hash_shift dd ?
ds_match_start dd ? ; used ds_block_start dd ?
ds_lookahead dd ? ; used ds_match_length dd ? ; used
ds_prev_length dd ? ; used ds_prev_match dd ? ; used
ds_max_chain_length dd ? ; used ds_match_available dd ?
ds_max_laxy_match dd ? ds_strstart dd ? ; used
ds_level dd ? ds_match_start dd ? ; used
ds_strategy dd ? ds_lookahead dd ? ; used
ds_good_match dd ? ; used ds_prev_length dd ? ; used
ds_nice_match dd ? ; used ds_max_chain_length dd ? ; used
ds_max_laxy_match dd ?
; Don't need anymore of the struct for match ds_level dd ?
DEFLATE_STATE ENDS ds_strategy dd ?
ds_good_match dd ? ; used
;=========================================================================== ds_nice_match dd ? ; used
; CODE
;=========================================================================== ; Don't need anymore of the struct for match
_TEXT SEGMENT DEFLATE_STATE ENDS
;--------------------------------------------------------------------------- ;===========================================================================
; match_init ; CODE
;--------------------------------------------------------------------------- ;===========================================================================
ALIGN 4 _TEXT SEGMENT
PUBLIC _match_init
_match_init PROC ;---------------------------------------------------------------------------
; no initialization needed ; match_init
ret ;---------------------------------------------------------------------------
_match_init ENDP ALIGN 4
PUBLIC _match_init
;--------------------------------------------------------------------------- _match_init PROC
; uInt longest_match(deflate_state *deflatestate, IPos curmatch) ; no initialization needed
;--------------------------------------------------------------------------- ret
ALIGN 4 _match_init ENDP
PUBLIC _longest_match ;---------------------------------------------------------------------------
_longest_match PROC ; uInt longest_match(deflate_state *deflatestate, IPos curmatch)
;---------------------------------------------------------------------------
; Since this code uses EBP for a scratch register, the stack frame must ALIGN 4
; be manually constructed and referenced relative to the ESP register.
PUBLIC _longest_match
; Stack image _longest_match PROC
; Variables
chainlenwmask = 0 ; high word: current chain len ; Since this code uses EBP for a scratch register, the stack frame must
; low word: s->wmask ; be manually constructed and referenced relative to the ESP register.
window = 4 ; local copy of s->window
windowbestlen = 8 ; s->window + bestlen ; Stack image
scanend = 12 ; last two bytes of string ; Variables
scanstart = 16 ; first two bytes of string chainlenwmask = 0 ; high word: current chain len
scanalign = 20 ; dword-misalignment of string ; low word: s->wmask
nicematch = 24 ; a good enough match size window = 4 ; local copy of s->window
bestlen = 28 ; size of best match so far windowbestlen = 8 ; s->window + bestlen
scan = 32 ; ptr to string wanting match scanend = 12 ; last two bytes of string
varsize = 36 ; number of bytes (also offset to last saved register) scanstart = 16 ; first two bytes of string
scanalign = 20 ; dword-misalignment of string
; Saved Registers (actually pushed into place) nicematch = 24 ; a good enough match size
ebx_save = 36 bestlen = 28 ; size of best match so far
edi_save = 40 scan = 32 ; ptr to string wanting match
esi_save = 44 varsize = 36 ; number of bytes (also offset to last saved register)
ebp_save = 48
; Saved Registers (actually pushed into place)
; Parameters ebx_save = 36
retaddr = 52 edi_save = 40
deflatestate = 56 esi_save = 44
curmatch = 60 ebp_save = 48
; Save registers that the compiler may be using ; Parameters
push ebp retaddr = 52
push edi deflatestate = 56
push esi curmatch = 60
push ebx
; Save registers that the compiler may be using
; Allocate local variable space push ebp
sub esp,varsize push edi
push esi
; Retrieve the function arguments. ecx will hold cur_match push ebx
; throughout the entire function. edx will hold the pointer to the
; deflate_state structure during the function's setup (before ; Allocate local variable space
; entering the main loop). sub esp,varsize
mov edx, [esp+deflatestate] ; Retrieve the function arguments. ecx will hold cur_match
ASSUME edx:PTR DEFLATE_STATE ; throughout the entire function. edx will hold the pointer to the
; deflate_state structure during the function's setup (before
mov ecx, [esp+curmatch] ; entering the main loop).
; uInt wmask = s->w_mask; mov edx, [esp+deflatestate]
; unsigned chain_length = s->max_chain_length; ASSUME edx:PTR DEFLATE_STATE
; if (s->prev_length >= s->good_match) {
; chain_length >>= 2; mov ecx, [esp+curmatch]
; }
; uInt wmask = s->w_mask;
mov eax, [edx].ds_prev_length ; unsigned chain_length = s->max_chain_length;
mov ebx, [edx].ds_good_match ; if (s->prev_length >= s->good_match) {
cmp eax, ebx ; chain_length >>= 2;
mov eax, [edx].ds_w_mask ; }
mov ebx, [edx].ds_max_chain_length
jl SHORT LastMatchGood mov eax, [edx].ds_prev_length
shr ebx, 2 mov ebx, [edx].ds_good_match
LastMatchGood: cmp eax, ebx
mov eax, [edx].ds_w_mask
; chainlen is decremented once beforehand so that the function can mov ebx, [edx].ds_max_chain_length
; use the sign flag instead of the zero flag for the exit test. jl SHORT LastMatchGood
; It is then shifted into the high word, to make room for the wmask shr ebx, 2
; value, which it will always accompany. LastMatchGood:
dec ebx ; chainlen is decremented once beforehand so that the function can
shl ebx, 16 ; use the sign flag instead of the zero flag for the exit test.
or ebx, eax ; It is then shifted into the high word, to make room for the wmask
mov [esp+chainlenwmask], ebx ; value, which it will always accompany.
; if ((uInt)nice_match > s->lookahead) nice_match = s->lookahead; dec ebx
shl ebx, 16
mov eax, [edx].ds_nice_match or ebx, eax
mov ebx, [edx].ds_lookahead mov [esp+chainlenwmask], ebx
cmp ebx, eax
jl SHORT LookaheadLess ; if ((uInt)nice_match > s->lookahead) nice_match = s->lookahead;
mov ebx, eax
LookaheadLess: mov eax, [edx].ds_nice_match
mov [esp+nicematch], ebx mov ebx, [edx].ds_lookahead
cmp ebx, eax
;/* register Bytef *scan = s->window + s->strstart; */ jl SHORT LookaheadLess
mov ebx, eax
mov esi, [edx].ds_window LookaheadLess:
mov [esp+window], esi mov [esp+nicematch], ebx
mov ebp, [edx].ds_strstart
lea edi, [esi+ebp] ;/* register Bytef *scan = s->window + s->strstart; */
mov [esp+scan],edi
mov esi, [edx].ds_window
;/* Determine how many bytes the scan ptr is off from being */ mov [esp+window], esi
;/* dword-aligned. */ mov ebp, [edx].ds_strstart
lea edi, [esi+ebp]
mov eax, edi mov [esp+scan],edi
neg eax
and eax, 3 ;/* Determine how many bytes the scan ptr is off from being */
mov [esp+scanalign], eax ;/* dword-aligned. */
;/* IPos limit = s->strstart > (IPos)MAX_DIST(s) ? */ mov eax, edi
;/* s->strstart - (IPos)MAX_DIST(s) : NIL; */ neg eax
and eax, 3
mov eax, [edx].ds_w_size mov [esp+scanalign], eax
sub eax, MIN_LOOKAHEAD
sub ebp, eax ;/* IPos limit = s->strstart > (IPos)MAX_DIST(s) ? */
jg SHORT LimitPositive ;/* s->strstart - (IPos)MAX_DIST(s) : NIL; */
xor ebp, ebp
LimitPositive: mov eax, [edx].ds_w_size
sub eax, MIN_LOOKAHEAD
;/* int best_len = s->prev_length; */ sub ebp, eax
jg SHORT LimitPositive
mov eax, [edx].ds_prev_length xor ebp, ebp
mov [esp+bestlen], eax LimitPositive:
;/* Store the sum of s->window + best_len in %esi locally, and in %esi. */ ;/* int best_len = s->prev_length; */
add esi, eax mov eax, [edx].ds_prev_length
mov [esp+windowbestlen], esi mov [esp+bestlen], eax
;/* register ush scan_start = *(ushf*)scan; */ ;/* Store the sum of s->window + best_len in %esi locally, and in %esi. */
;/* register ush scan_end = *(ushf*)(scan+best_len-1); */
;/* Posf *prev = s->prev; */ add esi, eax
mov [esp+windowbestlen], esi
movzx ebx, WORD PTR[edi]
mov [esp+scanstart], ebx ;/* register ush scan_start = *(ushf*)scan; */
movzx ebx, WORD PTR[eax+edi-1] ;/* register ush scan_end = *(ushf*)(scan+best_len-1); */
mov [esp+scanend], ebx ;/* Posf *prev = s->prev; */
mov edi, [edx].ds_prev
movzx ebx, WORD PTR[edi]
;/* Jump into the main loop. */ mov [esp+scanstart], ebx
movzx ebx, WORD PTR[eax+edi-1]
mov edx, [esp+chainlenwmask] mov [esp+scanend], ebx
jmp SHORT LoopEntry mov edi, [edx].ds_prev
;/* do { ;/* Jump into the main loop. */
; * match = s->window + cur_match;
; * if (*(ushf*)(match+best_len-1) != scan_end || mov edx, [esp+chainlenwmask]
; * *(ushf*)match != scan_start) continue; jmp SHORT LoopEntry
; * [...]
; * } while ((cur_match = prev[cur_match & wmask]) > limit ;/* do {
; * && --chain_length != 0); ; * match = s->window + cur_match;
; * ; * if (*(ushf*)(match+best_len-1) != scan_end ||
; * Here is the inner loop of the function. The function will spend the ; * *(ushf*)match != scan_start) continue;
; * majority of its time in this loop, and majority of that time will ; * [...]
; * be spent in the first ten instructions. ; * } while ((cur_match = prev[cur_match & wmask]) > limit
; * ; * && --chain_length != 0);
; * Within this loop: ; *
; * %ebx = scanend ; * Here is the inner loop of the function. The function will spend the
; * %ecx = curmatch ; * majority of its time in this loop, and majority of that time will
; * %edx = chainlenwmask - i.e., ((chainlen << 16) | wmask) ; * be spent in the first ten instructions.
; * %esi = windowbestlen - i.e., (window + bestlen) ; *
; * %edi = prev ; * Within this loop:
; * %ebp = limit ; * %ebx = scanend
; */ ; * %ecx = curmatch
; * %edx = chainlenwmask - i.e., ((chainlen << 16) | wmask)
ALIGN 4 ; * %esi = windowbestlen - i.e., (window + bestlen)
LookupLoop: ; * %edi = prev
and ecx, edx ; * %ebp = limit
movzx ecx, WORD PTR[edi+ecx*2] ; */
cmp ecx, ebp
jbe LeaveNow ALIGN 4
sub edx, 000010000H LookupLoop:
js LeaveNow and ecx, edx
movzx ecx, WORD PTR[edi+ecx*2]
LoopEntry: cmp ecx, ebp
movzx eax, WORD PTR[esi+ecx-1] jbe LeaveNow
cmp eax, ebx sub edx, 000010000H
jnz SHORT LookupLoop js LeaveNow
mov eax, [esp+window] LoopEntry:
movzx eax, WORD PTR[eax+ecx] movzx eax, WORD PTR[esi+ecx-1]
cmp eax, [esp+scanstart] cmp eax, ebx
jnz SHORT LookupLoop jnz SHORT LookupLoop
;/* Store the current value of chainlen. */ mov eax, [esp+window]
movzx eax, WORD PTR[eax+ecx]
mov [esp+chainlenwmask], edx cmp eax, [esp+scanstart]
jnz SHORT LookupLoop
;/* Point %edi to the string under scrutiny, and %esi to the string we */
;/* are hoping to match it up with. In actuality, %esi and %edi are */ ;/* Store the current value of chainlen. */
;/* both pointed (MAX_MATCH_8 - scanalign) bytes ahead, and %edx is */
;/* initialized to -(MAX_MATCH_8 - scanalign). */ mov [esp+chainlenwmask], edx
mov esi, [esp+window] ;/* Point %edi to the string under scrutiny, and %esi to the string we */
mov edi, [esp+scan] ;/* are hoping to match it up with. In actuality, %esi and %edi are */
add esi, ecx ;/* both pointed (MAX_MATCH_8 - scanalign) bytes ahead, and %edx is */
mov eax, [esp+scanalign] ;/* initialized to -(MAX_MATCH_8 - scanalign). */
mov edx, -MAX_MATCH_8
lea edi, [edi+eax+MAX_MATCH_8] mov esi, [esp+window]
lea esi, [esi+eax+MAX_MATCH_8] mov edi, [esp+scan]
add esi, ecx
;/* Test the strings for equality, 8 bytes at a time. At the end, mov eax, [esp+scanalign]
; * adjust %edx so that it is offset to the exact byte that mismatched. mov edx, -MAX_MATCH_8
; * lea edi, [edi+eax+MAX_MATCH_8]
; * We already know at this point that the first three bytes of the lea esi, [esi+eax+MAX_MATCH_8]
; * strings match each other, and they can be safely passed over before
; * starting the compare loop. So what this code does is skip over 0-3 ;/* Test the strings for equality, 8 bytes at a time. At the end,
; * bytes, as much as necessary in order to dword-align the %edi ; * adjust %edx so that it is offset to the exact byte that mismatched.
; * pointer. (%esi will still be misaligned three times out of four.) ; *
; * ; * We already know at this point that the first three bytes of the
; * It should be confessed that this loop usually does not represent ; * strings match each other, and they can be safely passed over before
; * much of the total running time. Replacing it with a more ; * starting the compare loop. So what this code does is skip over 0-3
; * straightforward "rep cmpsb" would not drastically degrade ; * bytes, as much as necessary in order to dword-align the %edi
; * performance. ; * pointer. (%esi will still be misaligned three times out of four.)
; */ ; *
; * It should be confessed that this loop usually does not represent
LoopCmps: ; * much of the total running time. Replacing it with a more
mov eax, DWORD PTR[esi+edx] ; * straightforward "rep cmpsb" would not drastically degrade
xor eax, DWORD PTR[edi+edx] ; * performance.
jnz SHORT LeaveLoopCmps ; */
mov eax, DWORD PTR[esi+edx+4] LoopCmps:
xor eax, DWORD PTR[edi+edx+4] mov eax, DWORD PTR[esi+edx]
jnz SHORT LeaveLoopCmps4 xor eax, DWORD PTR[edi+edx]
jnz SHORT LeaveLoopCmps
add edx, 8
jnz SHORT LoopCmps mov eax, DWORD PTR[esi+edx+4]
jmp LenMaximum xor eax, DWORD PTR[edi+edx+4]
ALIGN 4 jnz SHORT LeaveLoopCmps4
LeaveLoopCmps4: add edx, 8
add edx, 4 jnz SHORT LoopCmps
jmp LenMaximum
LeaveLoopCmps: ALIGN 4
test eax, 00000FFFFH
jnz SHORT LenLower LeaveLoopCmps4:
add edx, 4
add edx, 2
shr eax, 16 LeaveLoopCmps:
test eax, 00000FFFFH
LenLower: jnz SHORT LenLower
sub al, 1
adc edx, 0 add edx, 2
shr eax, 16
;/* Calculate the length of the match. If it is longer than MAX_MATCH, */
;/* then automatically accept it as the best possible match and leave. */ LenLower:
sub al, 1
lea eax, [edi+edx] adc edx, 0
mov edi, [esp+scan]
sub eax, edi ;/* Calculate the length of the match. If it is longer than MAX_MATCH, */
cmp eax, MAX_MATCH ;/* then automatically accept it as the best possible match and leave. */
jge SHORT LenMaximum
lea eax, [edi+edx]
;/* If the length of the match is not longer than the best match we */ mov edi, [esp+scan]
;/* have so far, then forget it and return to the lookup loop. */ sub eax, edi
cmp eax, MAX_MATCH
mov edx, [esp+deflatestate] jge SHORT LenMaximum
mov ebx, [esp+bestlen]
cmp eax, ebx ;/* If the length of the match is not longer than the best match we */
jg SHORT LongerMatch ;/* have so far, then forget it and return to the lookup loop. */
mov esi, [esp+windowbestlen]
mov edi, [edx].ds_prev mov edx, [esp+deflatestate]
mov ebx, [esp+scanend] mov ebx, [esp+bestlen]
mov edx, [esp+chainlenwmask] cmp eax, ebx
jmp LookupLoop jg SHORT LongerMatch
ALIGN 4 mov esi, [esp+windowbestlen]
mov edi, [edx].ds_prev
;/* s->match_start = cur_match; */ mov ebx, [esp+scanend]
;/* best_len = len; */ mov edx, [esp+chainlenwmask]
;/* if (len >= nice_match) break; */ jmp LookupLoop
;/* scan_end = *(ushf*)(scan+best_len-1); */ ALIGN 4
LongerMatch: ;/* s->match_start = cur_match; */
mov ebx, [esp+nicematch] ;/* best_len = len; */
mov [esp+bestlen], eax ;/* if (len >= nice_match) break; */
mov [edx].ds_match_start, ecx ;/* scan_end = *(ushf*)(scan+best_len-1); */
cmp eax, ebx
jge SHORT LeaveNow LongerMatch:
mov esi, [esp+window] mov ebx, [esp+nicematch]
add esi, eax mov [esp+bestlen], eax
mov [esp+windowbestlen], esi mov [edx].ds_match_start, ecx
movzx ebx, WORD PTR[edi+eax-1] cmp eax, ebx
mov edi, [edx].ds_prev jge SHORT LeaveNow
mov [esp+scanend], ebx mov esi, [esp+window]
mov edx, [esp+chainlenwmask] add esi, eax
jmp LookupLoop mov [esp+windowbestlen], esi
ALIGN 4 movzx ebx, WORD PTR[edi+eax-1]
mov edi, [edx].ds_prev
;/* Accept the current string, with the maximum possible length. */ mov [esp+scanend], ebx
mov edx, [esp+chainlenwmask]
LenMaximum: jmp LookupLoop
mov edx, [esp+deflatestate] ALIGN 4
mov DWORD PTR[esp+bestlen], MAX_MATCH
mov [edx].ds_match_start, ecx ;/* Accept the current string, with the maximum possible length. */
;/* if ((uInt)best_len <= s->lookahead) return (uInt)best_len; */ LenMaximum:
;/* return s->lookahead; */ mov edx, [esp+deflatestate]
mov DWORD PTR[esp+bestlen], MAX_MATCH
LeaveNow: mov [edx].ds_match_start, ecx
mov edx, [esp+deflatestate]
mov ebx, [esp+bestlen] ;/* if ((uInt)best_len <= s->lookahead) return (uInt)best_len; */
mov eax, [edx].ds_lookahead ;/* return s->lookahead; */
cmp ebx, eax
jg SHORT LookaheadRet LeaveNow:
mov eax, ebx mov edx, [esp+deflatestate]
LookaheadRet: mov ebx, [esp+bestlen]
mov eax, [edx].ds_lookahead
; Restore the stack and return from whence we came. cmp ebx, eax
jg SHORT LookaheadRet
add esp, varsize mov eax, ebx
pop ebx LookaheadRet:
pop esi
pop edi ; Restore the stack and return from whence we came.
pop ebp
ret add esp, varsize
pop ebx
_longest_match ENDP pop esi
pop edi
_TEXT ENDS pop ebp
END ret
_longest_match ENDP
_TEXT ENDS
END

View File

@@ -0,0 +1,2 @@
ml64.exe /Flinffasx64 /c /Zi inffasx64.asm
ml64.exe /Flgvmat64 /c /Zi gvmat64.asm

464
contrib/masmx64/gvmat64.asm Normal file
View File

@@ -0,0 +1,464 @@
;uInt longest_match_x64(
; deflate_state *s,
; IPos cur_match); /* current match */
; gvmat64.asm -- Asm portion of the optimized longest_match for 32 bits x86
; Copyright (C) 1995-2005 Jean-loup Gailly, Brian Raiter and Gilles Vollant.
; File written by Gilles Vollant, by modifiying the longest_match
; from Jean-loup Gailly in deflate.c
; and modifying asm686 with masm, optimised assembly code from Brian Raiter,
; written 1998
; http://www.zlib.net
; http://www.winimage.com/zLibDll
; http://www.muppetlabs.com/~breadbox/software/assembly.html
;
; to compile this file, I use option
; ml64.exe /Flgvmat64 /c /Zi gvmat64.asm
; with Microsoft Macro Assembler (x64) for AMD64
;
; ml64.exe is given with Visual Studio 2005, Windows 2003 server DDK
;
; (you can get Windows 2003 server DDK with ml64 and cl for AMD64 from
; http://www.microsoft.com/whdc/devtools/ddk/default.mspx for low price)
;
; Be carrefull to adapt zlib1222add below to your version of zLib
;uInt longest_match(s, cur_match)
; deflate_state *s;
; IPos cur_match; /* current match */
.code
longest_match PROC
;LocalVarsSize equ 88
LocalVarsSize equ 72
; register used : rax,rbx,rcx,rdx,rsi,rdi,r8,r9,r10,r11,r12
; free register : r14,r15
; register can be saved : rsp
chainlenwmask equ rsp + 8 - LocalVarsSize ; high word: current chain len
; low word: s->wmask
;window equ rsp + xx - LocalVarsSize ; local copy of s->window ; stored in r10
;windowbestlen equ rsp + xx - LocalVarsSize ; s->window + bestlen , use r10+r11
;scanstart equ rsp + xx - LocalVarsSize ; first two bytes of string ; stored in r12w
;scanend equ rsp + xx - LocalVarsSize ; last two bytes of string use ebx
;scanalign equ rsp + xx - LocalVarsSize ; dword-misalignment of string r13
;bestlen equ rsp + xx - LocalVarsSize ; size of best match so far -> r11d
;scan equ rsp + xx - LocalVarsSize ; ptr to string wanting match -> r9
nicematch equ rsp + 16 - LocalVarsSize ; a good enough match size -> r14
save_rdi equ rsp + 24 - LocalVarsSize
save_rsi equ rsp + 32 - LocalVarsSize
save_rbx equ rsp + 40 - LocalVarsSize
save_rbp equ rsp + 48 - LocalVarsSize
save_r12 equ rsp + 56 - LocalVarsSize
save_r13 equ rsp + 64 - LocalVarsSize
;save_r14 equ rsp + 72 - LocalVarsSize
;save_r15 equ rsp + 80 - LocalVarsSize
; all the +4 offsets are due to the addition of pending_buf_size (in zlib
; in the deflate_state structure since the asm code was first written
; (if you compile with zlib 1.0.4 or older, remove the +4).
; Note : these value are good with a 8 bytes boundary pack structure
MAX_MATCH equ 258
MIN_MATCH equ 3
MIN_LOOKAHEAD equ (MAX_MATCH+MIN_MATCH+1)
;;; Offsets for fields in the deflate_state structure. These numbers
;;; are calculated from the definition of deflate_state, with the
;;; assumption that the compiler will dword-align the fields. (Thus,
;;; changing the definition of deflate_state could easily cause this
;;; program to crash horribly, without so much as a warning at
;;; compile time. Sigh.)
; all the +zlib1222add offsets are due to the addition of fields
; in zlib in the deflate_state structure since the asm code was first written
; (if you compile with zlib 1.0.4 or older, use "zlib1222add equ (-4)").
; (if you compile with zlib between 1.0.5 and 1.2.2.1, use "zlib1222add equ 0").
; if you compile with zlib 1.2.2.2 or later , use "zlib1222add equ 8").
zlib1222add equ 8
dsWSize equ 56+zlib1222add+(zlib1222add/2)
dsWMask equ 64+zlib1222add+(zlib1222add/2)
dsWindow equ 72+zlib1222add
dsPrev equ 88+zlib1222add
dsMatchLen equ 128+zlib1222add
dsPrevMatch equ 132+zlib1222add
dsStrStart equ 140+zlib1222add
dsMatchStart equ 144+zlib1222add
dsLookahead equ 148+zlib1222add
dsPrevLen equ 152+zlib1222add
dsMaxChainLen equ 156+zlib1222add
dsGoodMatch equ 172+zlib1222add
dsNiceMatch equ 176+zlib1222add
; parameter 1 in r8(deflate state s), param 2 in rdx (cur match)
; see http://weblogs.asp.net/oldnewthing/archive/2004/01/14/58579.aspx and
; http://msdn.microsoft.com/library/en-us/kmarch/hh/kmarch/64bitAMD_8e951dd2-ee77-4728-8702-55ce4b5dd24a.xml.asp
;
; All registers must be preserved across the call, except for
; rax, rcx, rdx, r8, r-9, r10, and r11, which are scratch.
;;; Save registers that the compiler may be using, and adjust esp to
;;; make room for our stack frame.
;;; Retrieve the function arguments. r8d will hold cur_match
;;; throughout the entire function. edx will hold the pointer to the
;;; deflate_state structure during the function's setup (before
;;; entering the main loop.
; parameter 1 in rcx (deflate_state* s), param 2 in edx -> r8 (cur match)
; this clear high 32 bits of r8, which can be garbage in both r8 and rdx
mov [save_rdi],rdi
mov [save_rsi],rsi
mov [save_rbx],rbx
mov [save_rbp],rbp
mov r8d,edx
mov [save_r12],r12
mov [save_r13],r13
; mov [save_r14],r14
; mov [save_r15],r15
;;; uInt wmask = s->w_mask;
;;; unsigned chain_length = s->max_chain_length;
;;; if (s->prev_length >= s->good_match) {
;;; chain_length >>= 2;
;;; }
mov edi, [rcx + dsPrevLen]
mov esi, [rcx + dsGoodMatch]
mov eax, [rcx + dsWMask]
mov ebx, [rcx + dsMaxChainLen]
cmp edi, esi
jl LastMatchGood
shr ebx, 2
LastMatchGood:
;;; chainlen is decremented once beforehand so that the function can
;;; use the sign flag instead of the zero flag for the exit test.
;;; It is then shifted into the high word, to make room for the wmask
;;; value, which it will always accompany.
dec ebx
shl ebx, 16
or ebx, eax
mov [chainlenwmask], ebx
;;; if ((uInt)nice_match > s->lookahead) nice_match = s->lookahead;
mov eax, [rcx + dsNiceMatch]
mov r10d, [rcx + dsLookahead]
cmp r10d, eax
cmovnl r10d, eax
mov [nicematch],r10d
LookaheadLess:
;;; register Bytef *scan = s->window + s->strstart;
mov r10, [rcx + dsWindow]
mov ebp, [rcx + dsStrStart]
lea r13, [r10 + rbp]
;;; Determine how many bytes the scan ptr is off from being
;;; dword-aligned.
mov r9,r13
neg r13
and r13,3
;;; IPos limit = s->strstart > (IPos)MAX_DIST(s) ?
;;; s->strstart - (IPos)MAX_DIST(s) : NIL;
mov eax, [rcx + dsWSize]
sub eax, MIN_LOOKAHEAD
xor edi,edi
sub ebp, eax
mov r11d, [rcx + dsPrevLen]
cmovng ebp,edi
;;; int best_len = s->prev_length;
;;; Store the sum of s->window + best_len in esi locally, and in esi.
lea rsi,[r10+r11]
;;; register ush scan_start = *(ushf*)scan;
;;; register ush scan_end = *(ushf*)(scan+best_len-1);
;;; Posf *prev = s->prev;
movzx r12d,word ptr [r9]
movzx ebx, word ptr [r9 + r11 - 1]
mov rdi, [rcx + dsPrev]
;;; Jump into the main loop.
mov edx, [chainlenwmask]
cmp bx,word ptr [rsi + r8 - 1]
jz LookupLoopIsZero
LookupLoop1:
and r8d, edx
movzx r8d, word ptr [rdi + r8*2]
cmp r8d, ebp
jbe LeaveNow
sub edx, 00010000h
js LeaveNow
LoopEntry1:
cmp bx,word ptr [rsi + r8 - 1]
jz LookupLoopIsZero
LookupLoop2:
and r8d, edx
movzx r8d, word ptr [rdi + r8*2]
cmp r8d, ebp
jbe LeaveNow
sub edx, 00010000h
js LeaveNow
LoopEntry2:
cmp bx,word ptr [rsi + r8 - 1]
jz LookupLoopIsZero
LookupLoop4:
and r8d, edx
movzx r8d, word ptr [rdi + r8*2]
cmp r8d, ebp
jbe LeaveNow
sub edx, 00010000h
js LeaveNow
LoopEntry4:
cmp bx,word ptr [rsi + r8 - 1]
jnz LookupLoop1
jmp LookupLoopIsZero
;;; do {
;;; match = s->window + cur_match;
;;; if (*(ushf*)(match+best_len-1) != scan_end ||
;;; *(ushf*)match != scan_start) continue;
;;; [...]
;;; } while ((cur_match = prev[cur_match & wmask]) > limit
;;; && --chain_length != 0);
;;;
;;; Here is the inner loop of the function. The function will spend the
;;; majority of its time in this loop, and majority of that time will
;;; be spent in the first ten instructions.
;;;
;;; Within this loop:
;;; ebx = scanend
;;; r8d = curmatch
;;; edx = chainlenwmask - i.e., ((chainlen << 16) | wmask)
;;; esi = windowbestlen - i.e., (window + bestlen)
;;; edi = prev
;;; ebp = limit
LookupLoop:
and r8d, edx
movzx r8d, word ptr [rdi + r8*2]
cmp r8d, ebp
jbe LeaveNow
sub edx, 00010000h
js LeaveNow
LoopEntry:
cmp bx,word ptr [rsi + r8 - 1]
jnz LookupLoop1
LookupLoopIsZero:
cmp r12w, word ptr [r10 + r8]
jnz LookupLoop1
;;; Store the current value of chainlen.
mov [chainlenwmask], edx
;;; Point edi to the string under scrutiny, and esi to the string we
;;; are hoping to match it up with. In actuality, esi and edi are
;;; both pointed (MAX_MATCH_8 - scanalign) bytes ahead, and edx is
;;; initialized to -(MAX_MATCH_8 - scanalign).
lea rsi,[r8+r10]
mov rdx, 0fffffffffffffef8h; -(MAX_MATCH_8)
lea rsi, [rsi + r13 + 0108h] ;MAX_MATCH_8]
lea rdi, [r9 + r13 + 0108h] ;MAX_MATCH_8]
prefetcht1 [rsi+rdx]
prefetcht1 [rdi+rdx]
;;; Test the strings for equality, 8 bytes at a time. At the end,
;;; adjust edx so that it is offset to the exact byte that mismatched.
;;;
;;; We already know at this point that the first three bytes of the
;;; strings match each other, and they can be safely passed over before
;;; starting the compare loop. So what this code does is skip over 0-3
;;; bytes, as much as necessary in order to dword-align the edi
;;; pointer. (esi will still be misaligned three times out of four.)
;;;
;;; It should be confessed that this loop usually does not represent
;;; much of the total running time. Replacing it with a more
;;; straightforward "rep cmpsb" would not drastically degrade
;;; performance.
;LoopCmps:
; mov eax, [rsi + rdx]
; xor eax, [rdi + rdx]
; jnz LeaveLoopCmps
; mov eax, [rsi + rdx + 4]
; xor eax, [rdi + rdx + 4]
; jnz LeaveLoopCmps4
; add rdx, 8
; jnz LoopCmps
; jmp LenMaximum
;LeaveLoopCmps4: add rdx, 4
;LeaveLoopCmps: test eax, 0000FFFFh
; jnz LenLower
; add rdx, 2
; shr eax, 16
;LenLower: sub al, 1
; adc rdx, 0
LoopCmps:
mov rax, [rsi + rdx]
xor rax, [rdi + rdx]
jnz LeaveLoopCmps
mov rax, [rsi + rdx + 8]
xor rax, [rdi + rdx + 8]
jnz LeaveLoopCmps8
mov rax, [rsi + rdx + 8+8]
xor rax, [rdi + rdx + 8+8]
jnz LeaveLoopCmps16
add rdx,8+8+8
jmp short LoopCmps
LeaveLoopCmps16: add rdx,8
LeaveLoopCmps8: add rdx,8
LeaveLoopCmps:
test eax, 0000FFFFh
jnz LenLower
test eax,0ffffffffh
jnz LenLower32
add rdx,4
shr rax,32
or ax,ax
jnz LenLower
LenLower32:
shr eax,16
add rdx,2
LenLower: sub al, 1
adc rdx, 0
;;; Calculate the length of the match. If it is longer than MAX_MATCH,
;;; then automatically accept it as the best possible match and leave.
lea rax, [rdi + rdx]
sub rax, r9
cmp eax, MAX_MATCH
jge LenMaximum
;;; If the length of the match is not longer than the best match we
;;; have so far, then forget it and return to the lookup loop.
;///////////////////////////////////
cmp eax, r11d
jg LongerMatch
lea rsi,[r10+r11]
mov rdi, [rcx + dsPrev]
mov edx, [chainlenwmask]
jmp LookupLoop
;;; s->match_start = cur_match;
;;; best_len = len;
;;; if (len >= nice_match) break;
;;; scan_end = *(ushf*)(scan+best_len-1);
LongerMatch:
mov r11d, eax
mov [rcx + dsMatchStart], r8d
cmp eax, [nicematch]
jge LeaveNow
lea rsi,[r10+rax]
movzx ebx, word ptr [r9 + rax - 1]
mov rdi, [rcx + dsPrev]
mov edx, [chainlenwmask]
jmp LookupLoop
;;; Accept the current string, with the maximum possible length.
LenMaximum:
mov r11d,MAX_MATCH
mov [rcx + dsMatchStart], r8d
;;; if ((uInt)best_len <= s->lookahead) return (uInt)best_len;
;;; return s->lookahead;
LeaveNow:
mov eax, [rcx + dsLookahead]
cmp r11d, eax
cmovng eax, r11d
;;; Restore the stack and return from whence we came.
mov rsi,[save_rsi]
mov rdi,[save_rdi]
mov rbx,[save_rbx]
mov rbp,[save_rbp]
mov r12,[save_r12]
mov r13,[save_r13]
; mov r14,[save_r14]
; mov r15,[save_r15]
ret 0
; please don't remove this string !
; Your can freely use gvmat32 in any free or commercial app if you don't remove the string in the binary!
db 0dh,0ah,"asm686 with masm, optimised assembly code from Brian Raiter, written 1998, converted to amd 64 by Gilles Vollant 2005",0dh,0ah,0
longest_match ENDP
match_init PROC
ret 0
match_init ENDP
END

BIN
contrib/masmx64/gvmat64.obj Normal file

Binary file not shown.

View File

@@ -0,0 +1,186 @@
/* inffas8664.c is a hand tuned assembler version of inffast.c - fast decoding
* version for AMD64 on Windows using Microsoft C compiler
*
* Copyright (C) 1995-2003 Mark Adler
* For conditions of distribution and use, see copyright notice in zlib.h
*
* Copyright (C) 2003 Chris Anderson <christop@charm.net>
* Please use the copyright conditions above.
*
* 2005 - Adaptation to Microsoft C Compiler for AMD64 by Gilles Vollant
*
* inffas8664.c call function inffas8664fnc in inffasx64.asm
* inffasx64.asm is automatically convert from AMD64 portion of inffas86.c
*
* Dec-29-2003 -- I added AMD64 inflate asm support. This version is also
* slightly quicker on x86 systems because, instead of using rep movsb to copy
* data, it uses rep movsw, which moves data in 2-byte chunks instead of single
* bytes. I've tested the AMD64 code on a Fedora Core 1 + the x86_64 updates
* from http://fedora.linux.duke.edu/fc1_x86_64
* which is running on an Athlon 64 3000+ / Gigabyte GA-K8VT800M system with
* 1GB ram. The 64-bit version is about 4% faster than the 32-bit version,
* when decompressing mozilla-source-1.3.tar.gz.
*
* Mar-13-2003 -- Most of this is derived from inffast.S which is derived from
* the gcc -S output of zlib-1.2.0/inffast.c. Zlib-1.2.0 is in beta release at
* the moment. I have successfully compiled and tested this code with gcc2.96,
* gcc3.2, icc5.0, msvc6.0. It is very close to the speed of inffast.S
* compiled with gcc -DNO_MMX, but inffast.S is still faster on the P3 with MMX
* enabled. I will attempt to merge the MMX code into this version. Newer
* versions of this and inffast.S can be found at
* http://www.eetbeetee.com/zlib/ and http://www.charm.net/~christop/zlib/
*
*/
#include <stdio.h>
#include "zutil.h"
#include "inftrees.h"
#include "inflate.h"
#include "inffast.h"
/* Mark Adler's comments from inffast.c: */
/*
Decode literal, length, and distance codes and write out the resulting
literal and match bytes until either not enough input or output is
available, an end-of-block is encountered, or a data error is encountered.
When large enough input and output buffers are supplied to inflate(), for
example, a 16K input buffer and a 64K output buffer, more than 95% of the
inflate execution time is spent in this routine.
Entry assumptions:
state->mode == LEN
strm->avail_in >= 6
strm->avail_out >= 258
start >= strm->avail_out
state->bits < 8
On return, state->mode is one of:
LEN -- ran out of enough output space or enough available input
TYPE -- reached end of block code, inflate() to interpret next block
BAD -- error in block data
Notes:
- The maximum input bits used by a length/distance pair is 15 bits for the
length code, 5 bits for the length extra, 15 bits for the distance code,
and 13 bits for the distance extra. This totals 48 bits, or six bytes.
Therefore if strm->avail_in >= 6, then there is enough input to avoid
checking for available input while decoding.
- The maximum bytes that a single length/distance pair can output is 258
bytes, which is the maximum length that can be coded. inflate_fast()
requires strm->avail_out >= 258 for each loop to avoid checking for
output space.
*/
typedef struct inffast_ar {
/* 64 32 x86 x86_64 */
/* ar offset register */
/* 0 0 */ void *esp; /* esp save */
/* 8 4 */ void *ebp; /* ebp save */
/* 16 8 */ unsigned char FAR *in; /* esi rsi local strm->next_in */
/* 24 12 */ unsigned char FAR *last; /* r9 while in < last */
/* 32 16 */ unsigned char FAR *out; /* edi rdi local strm->next_out */
/* 40 20 */ unsigned char FAR *beg; /* inflate()'s init next_out */
/* 48 24 */ unsigned char FAR *end; /* r10 while out < end */
/* 56 28 */ unsigned char FAR *window;/* size of window, wsize!=0 */
/* 64 32 */ code const FAR *lcode; /* ebp rbp local strm->lencode */
/* 72 36 */ code const FAR *dcode; /* r11 local strm->distcode */
/* 80 40 */ size_t /*unsigned long */hold; /* edx rdx local strm->hold */
/* 88 44 */ unsigned bits; /* ebx rbx local strm->bits */
/* 92 48 */ unsigned wsize; /* window size */
/* 96 52 */ unsigned write; /* window write index */
/*100 56 */ unsigned lmask; /* r12 mask for lcode */
/*104 60 */ unsigned dmask; /* r13 mask for dcode */
/*108 64 */ unsigned len; /* r14 match length */
/*112 68 */ unsigned dist; /* r15 match distance */
/*116 72 */ unsigned status; /* set when state chng*/
} type_ar;
#ifdef ASMINF
void inflate_fast(strm, start)
z_streamp strm;
unsigned start; /* inflate()'s starting value for strm->avail_out */
{
struct inflate_state FAR *state;
type_ar ar;
void inffas8664fnc(struct inffast_ar * par);
#if (defined( __GNUC__ ) && defined( __amd64__ ) && ! defined( __i386 )) || (defined(_MSC_VER) && defined(_M_AMD64))
#define PAD_AVAIL_IN 6
#define PAD_AVAIL_OUT 258
#else
#define PAD_AVAIL_IN 5
#define PAD_AVAIL_OUT 257
#endif
/* copy state to local variables */
state = (struct inflate_state FAR *)strm->state;
ar.in = strm->next_in;
ar.last = ar.in + (strm->avail_in - PAD_AVAIL_IN);
ar.out = strm->next_out;
ar.beg = ar.out - (start - strm->avail_out);
ar.end = ar.out + (strm->avail_out - PAD_AVAIL_OUT);
ar.wsize = state->wsize;
ar.write = state->write;
ar.window = state->window;
ar.hold = state->hold;
ar.bits = state->bits;
ar.lcode = state->lencode;
ar.dcode = state->distcode;
ar.lmask = (1U << state->lenbits) - 1;
ar.dmask = (1U << state->distbits) - 1;
/* decode literals and length/distances until end-of-block or not enough
input data or output space */
/* align in on 1/2 hold size boundary */
while (((size_t)(void *)ar.in & (sizeof(ar.hold) / 2 - 1)) != 0) {
ar.hold += (unsigned long)*ar.in++ << ar.bits;
ar.bits += 8;
}
inffas8664fnc(&ar);
if (ar.status > 1) {
if (ar.status == 2)
strm->msg = "invalid literal/length code";
else if (ar.status == 3)
strm->msg = "invalid distance code";
else
strm->msg = "invalid distance too far back";
state->mode = BAD;
}
else if ( ar.status == 1 ) {
state->mode = TYPE;
}
/* return unused bytes (on entry, bits < 8, so in won't go too far back) */
ar.len = ar.bits >> 3;
ar.in -= ar.len;
ar.bits -= ar.len << 3;
ar.hold &= (1U << ar.bits) - 1;
/* update state and return */
strm->next_in = ar.in;
strm->next_out = ar.out;
strm->avail_in = (unsigned)(ar.in < ar.last ?
PAD_AVAIL_IN + (ar.last - ar.in) :
PAD_AVAIL_IN - (ar.in - ar.last));
strm->avail_out = (unsigned)(ar.out < ar.end ?
PAD_AVAIL_OUT + (ar.end - ar.out) :
PAD_AVAIL_OUT - (ar.out - ar.end));
state->hold = (unsigned long)ar.hold;
state->bits = ar.bits;
return;
}
#endif

View File

@@ -0,0 +1,392 @@
; inffasx64.asm is a hand tuned assembler version of inffast.c - fast decoding
; version for AMD64 on Windows using Microsoft C compiler
;
; inffasx64.asm is automatically convert from AMD64 portion of inffas86.c
; inffasx64.asm is called by inffas8664.c, which contain more info.
; to compile this file, I use option
; ml64.exe /Flinffasx64 /c /Zi inffasx64.asm
; with Microsoft Macro Assembler (x64) for AMD64
;
; ml64.exe is given with Visual Studio 2005, Windows 2003 server DDK
;
; (you can get Windows 2003 server DDK with ml64 and cl.exe for AMD64 from
; http://www.microsoft.com/whdc/devtools/ddk/default.mspx for low price)
;
.code
inffas8664fnc PROC
; see http://weblogs.asp.net/oldnewthing/archive/2004/01/14/58579.aspx and
; http://msdn.microsoft.com/library/en-us/kmarch/hh/kmarch/64bitAMD_8e951dd2-ee77-4728-8702-55ce4b5dd24a.xml.asp
;
; All registers must be preserved across the call, except for
; rax, rcx, rdx, r8, r-9, r10, and r11, which are scratch.
mov [rsp-8],rsi
mov [rsp-16],rdi
mov [rsp-24],r12
mov [rsp-32],r13
mov [rsp-40],r14
mov [rsp-48],r15
mov [rsp-56],rbx
mov rax,rcx
mov [rax+8], rbp ; /* save regs rbp and rsp */
mov [rax], rsp
mov rsp, rax ; /* make rsp point to &ar */
mov rsi, [rsp+16] ; /* rsi = in */
mov rdi, [rsp+32] ; /* rdi = out */
mov r9, [rsp+24] ; /* r9 = last */
mov r10, [rsp+48] ; /* r10 = end */
mov rbp, [rsp+64] ; /* rbp = lcode */
mov r11, [rsp+72] ; /* r11 = dcode */
mov rdx, [rsp+80] ; /* rdx = hold */
mov ebx, [rsp+88] ; /* ebx = bits */
mov r12d, [rsp+100] ; /* r12d = lmask */
mov r13d, [rsp+104] ; /* r13d = dmask */
; /* r14d = len */
; /* r15d = dist */
cld
cmp r10, rdi
je L_one_time ; /* if only one decode left */
cmp r9, rsi
jne L_do_loop
L_one_time:
mov r8, r12 ; /* r8 = lmask */
cmp bl, 32
ja L_get_length_code_one_time
lodsd ; /* eax = *(uint *)in++ */
mov cl, bl ; /* cl = bits, needs it for shifting */
add bl, 32 ; /* bits += 32 */
shl rax, cl
or rdx, rax ; /* hold |= *((uint *)in)++ << bits */
jmp L_get_length_code_one_time
ALIGN 4
L_while_test:
cmp r10, rdi
jbe L_break_loop
cmp r9, rsi
jbe L_break_loop
L_do_loop:
mov r8, r12 ; /* r8 = lmask */
cmp bl, 32
ja L_get_length_code ; /* if (32 < bits) */
lodsd ; /* eax = *(uint *)in++ */
mov cl, bl ; /* cl = bits, needs it for shifting */
add bl, 32 ; /* bits += 32 */
shl rax, cl
or rdx, rax ; /* hold |= *((uint *)in)++ << bits */
L_get_length_code:
and r8, rdx ; /* r8 &= hold */
mov eax, [rbp+r8*4] ; /* eax = lcode[hold & lmask] */
mov cl, ah ; /* cl = this.bits */
sub bl, ah ; /* bits -= this.bits */
shr rdx, cl ; /* hold >>= this.bits */
test al, al
jnz L_test_for_length_base ; /* if (op != 0) 45.7% */
mov r8, r12 ; /* r8 = lmask */
shr eax, 16 ; /* output this.val char */
stosb
L_get_length_code_one_time:
and r8, rdx ; /* r8 &= hold */
mov eax, [rbp+r8*4] ; /* eax = lcode[hold & lmask] */
L_dolen:
mov cl, ah ; /* cl = this.bits */
sub bl, ah ; /* bits -= this.bits */
shr rdx, cl ; /* hold >>= this.bits */
test al, al
jnz L_test_for_length_base ; /* if (op != 0) 45.7% */
shr eax, 16 ; /* output this.val char */
stosb
jmp L_while_test
ALIGN 4
L_test_for_length_base:
mov r14d, eax ; /* len = this */
shr r14d, 16 ; /* len = this.val */
mov cl, al
test al, 16
jz L_test_for_second_level_length ; /* if ((op & 16) == 0) 8% */
and cl, 15 ; /* op &= 15 */
jz L_decode_distance ; /* if (!op) */
L_add_bits_to_len:
sub bl, cl
xor eax, eax
inc eax
shl eax, cl
dec eax
and eax, edx ; /* eax &= hold */
shr rdx, cl
add r14d, eax ; /* len += hold & mask[op] */
L_decode_distance:
mov r8, r13 ; /* r8 = dmask */
cmp bl, 32
ja L_get_distance_code ; /* if (32 < bits) */
lodsd ; /* eax = *(uint *)in++ */
mov cl, bl ; /* cl = bits, needs it for shifting */
add bl, 32 ; /* bits += 32 */
shl rax, cl
or rdx, rax ; /* hold |= *((uint *)in)++ << bits */
L_get_distance_code:
and r8, rdx ; /* r8 &= hold */
mov eax, [r11+r8*4] ; /* eax = dcode[hold & dmask] */
L_dodist:
mov r15d, eax ; /* dist = this */
shr r15d, 16 ; /* dist = this.val */
mov cl, ah
sub bl, ah ; /* bits -= this.bits */
shr rdx, cl ; /* hold >>= this.bits */
mov cl, al ; /* cl = this.op */
test al, 16 ; /* if ((op & 16) == 0) */
jz L_test_for_second_level_dist
and cl, 15 ; /* op &= 15 */
jz L_check_dist_one
L_add_bits_to_dist:
sub bl, cl
xor eax, eax
inc eax
shl eax, cl
dec eax ; /* (1 << op) - 1 */
and eax, edx ; /* eax &= hold */
shr rdx, cl
add r15d, eax ; /* dist += hold & ((1 << op) - 1) */
L_check_window:
mov r8, rsi ; /* save in so from can use it's reg */
mov rax, rdi
sub rax, [rsp+40] ; /* nbytes = out - beg */
cmp eax, r15d
jb L_clip_window ; /* if (dist > nbytes) 4.2% */
mov ecx, r14d ; /* ecx = len */
mov rsi, rdi
sub rsi, r15 ; /* from = out - dist */
sar ecx, 1
jnc L_copy_two ; /* if len % 2 == 0 */
rep movsw
mov al, [rsi]
mov [rdi], al
inc rdi
mov rsi, r8 ; /* move in back to %rsi, toss from */
jmp L_while_test
L_copy_two:
rep movsw
mov rsi, r8 ; /* move in back to %rsi, toss from */
jmp L_while_test
ALIGN 4
L_check_dist_one:
cmp r15d, 1 ; /* if dist 1, is a memset */
jne L_check_window
cmp [rsp+40], rdi ; /* if out == beg, outside window */
je L_check_window
mov ecx, r14d ; /* ecx = len */
mov al, [rdi-1]
mov ah, al
sar ecx, 1
jnc L_set_two
mov [rdi], al
inc rdi
L_set_two:
rep stosw
jmp L_while_test
ALIGN 4
L_test_for_second_level_length:
test al, 64
jnz L_test_for_end_of_block ; /* if ((op & 64) != 0) */
xor eax, eax
inc eax
shl eax, cl
dec eax
and eax, edx ; /* eax &= hold */
add eax, r14d ; /* eax += len */
mov eax, [rbp+rax*4] ; /* eax = lcode[val+(hold&mask[op])]*/
jmp L_dolen
ALIGN 4
L_test_for_second_level_dist:
test al, 64
jnz L_invalid_distance_code ; /* if ((op & 64) != 0) */
xor eax, eax
inc eax
shl eax, cl
dec eax
and eax, edx ; /* eax &= hold */
add eax, r15d ; /* eax += dist */
mov eax, [r11+rax*4] ; /* eax = dcode[val+(hold&mask[op])]*/
jmp L_dodist
ALIGN 4
L_clip_window:
mov ecx, eax ; /* ecx = nbytes */
mov eax, [rsp+92] ; /* eax = wsize, prepare for dist cmp */
neg ecx ; /* nbytes = -nbytes */
cmp eax, r15d
jb L_invalid_distance_too_far ; /* if (dist > wsize) */
add ecx, r15d ; /* nbytes = dist - nbytes */
cmp dword ptr [rsp+96], 0
jne L_wrap_around_window ; /* if (write != 0) */
mov rsi, [rsp+56] ; /* from = window */
sub eax, ecx ; /* eax -= nbytes */
add rsi, rax ; /* from += wsize - nbytes */
mov eax, r14d ; /* eax = len */
cmp r14d, ecx
jbe L_do_copy ; /* if (nbytes >= len) */
sub eax, ecx ; /* eax -= nbytes */
rep movsb
mov rsi, rdi
sub rsi, r15 ; /* from = &out[ -dist ] */
jmp L_do_copy
ALIGN 4
L_wrap_around_window:
mov eax, [rsp+96] ; /* eax = write */
cmp ecx, eax
jbe L_contiguous_in_window ; /* if (write >= nbytes) */
mov esi, [rsp+92] ; /* from = wsize */
add rsi, [rsp+56] ; /* from += window */
add rsi, rax ; /* from += write */
sub rsi, rcx ; /* from -= nbytes */
sub ecx, eax ; /* nbytes -= write */
mov eax, r14d ; /* eax = len */
cmp eax, ecx
jbe L_do_copy ; /* if (nbytes >= len) */
sub eax, ecx ; /* len -= nbytes */
rep movsb
mov rsi, [rsp+56] ; /* from = window */
mov ecx, [rsp+96] ; /* nbytes = write */
cmp eax, ecx
jbe L_do_copy ; /* if (nbytes >= len) */
sub eax, ecx ; /* len -= nbytes */
rep movsb
mov rsi, rdi
sub rsi, r15 ; /* from = out - dist */
jmp L_do_copy
ALIGN 4
L_contiguous_in_window:
mov rsi, [rsp+56] ; /* rsi = window */
add rsi, rax
sub rsi, rcx ; /* from += write - nbytes */
mov eax, r14d ; /* eax = len */
cmp eax, ecx
jbe L_do_copy ; /* if (nbytes >= len) */
sub eax, ecx ; /* len -= nbytes */
rep movsb
mov rsi, rdi
sub rsi, r15 ; /* from = out - dist */
jmp L_do_copy ; /* if (nbytes >= len) */
ALIGN 4
L_do_copy:
mov ecx, eax ; /* ecx = len */
rep movsb
mov rsi, r8 ; /* move in back to %esi, toss from */
jmp L_while_test
L_test_for_end_of_block:
test al, 32
jz L_invalid_literal_length_code
mov dword ptr [rsp+116], 1
jmp L_break_loop_with_status
L_invalid_literal_length_code:
mov dword ptr [rsp+116], 2
jmp L_break_loop_with_status
L_invalid_distance_code:
mov dword ptr [rsp+116], 3
jmp L_break_loop_with_status
L_invalid_distance_too_far:
mov dword ptr [rsp+116], 4
jmp L_break_loop_with_status
L_break_loop:
mov dword ptr [rsp+116], 0
L_break_loop_with_status:
; /* put in, out, bits, and hold back into ar and pop esp */
mov [rsp+16], rsi ; /* in */
mov [rsp+32], rdi ; /* out */
mov [rsp+88], ebx ; /* bits */
mov [rsp+80], rdx ; /* hold */
mov rax, [rsp] ; /* restore rbp and rsp */
mov rbp, [rsp+8]
mov rsp, rax
mov rsi,[rsp-8]
mov rdi,[rsp-16]
mov r12,[rsp-24]
mov r13,[rsp-32]
mov r14,[rsp-40]
mov r15,[rsp-48]
mov rbx,[rsp-56]
ret 0
; :
; : "m" (ar)
; : "memory", "%rax", "%rbx", "%rcx", "%rdx", "%rsi", "%rdi",
; "%r8", "%r9", "%r10", "%r11", "%r12", "%r13", "%r14", "%r15"
; );
inffas8664fnc ENDP
;_TEXT ENDS
END

Binary file not shown.

View File

@@ -0,0 +1,28 @@
Summary
-------
This directory contains ASM implementations of the functions
longest_match() and inflate_fast(), for 64 bits x86 (both AMD64 and Intel EM64t),
for use with Microsoft Macro Assembler (x64) for AMD64 and Microsoft C++ 64 bits.
gvmat64.asm is written by Gilles Vollant (2005), by using Brian Raiter 686/32 bits
assembly optimized version from Jean-loup Gailly original longest_match function
inffasx64.asm and inffas8664.c were written by Chris Anderson, by optimizing
original function from Mark Adler
Use instructions
----------------
Copy these files into the zlib source directory.
define ASMV and ASMINF in your project. Include inffas8664.c in your source tree,
and inffasx64.obj and gvmat64.obj as object to link.
Build instructions
------------------
run bld_64.bat with Microsoft Macro Assembler (x64) for AMD64 (ml64.exe)
ml64.exe is given with Visual Studio 2005, Windows 2003 server DDK
You can get Windows 2003 server DDK with ml64 and cl for AMD64 from
http://www.microsoft.com/whdc/devtools/ddk/default.mspx for low price)

View File

@@ -0,0 +1,2 @@
ml /coff /Zi /c /Flgvmat32.lst gvmat32.asm
ml /coff /Zi /c /Flinffas32.lst inffas32.asm

File diff suppressed because it is too large Load Diff

View File

@@ -1,206 +1,62 @@
/* gvmat32.c -- C portion of the optimized longest_match for 32 bits x86 /* gvmat32.c -- C portion of the optimized longest_match for 32 bits x86
* Copyright (C) 1995-1996 Jean-loup Gailly and Gilles Vollant. * Copyright (C) 1995-1996 Jean-loup Gailly and Gilles Vollant.
* File written by Gilles Vollant, by modifiying the longest_match * File written by Gilles Vollant, by modifiying the longest_match
* from Jean-loup Gailly in deflate.c * from Jean-loup Gailly in deflate.c
* it prepare all parameters and call the assembly longest_match_gvasm * it prepare all parameters and call the assembly longest_match_gvasm
* longest_match execute standard C code is wmask != 0x7fff * longest_match execute standard C code is wmask != 0x7fff
* (assembly code is faster with a fixed wmask) * (assembly code is faster with a fixed wmask)
* *
*/ * Read comment at beginning of gvmat32.asm for more information
*/
#include "deflate.h"
#if defined(ASMV) && (!defined(NOOLDPENTIUMCODE))
#ifdef ASMV #include "deflate.h"
#define NIL 0
/* if your C compiler don't add underline before function name,
#define UNALIGNED_OK define ADD_UNDERLINE_ASMFUNC */
#ifdef ADD_UNDERLINE_ASMFUNC
#define longest_match_7fff _longest_match_7fff
/* if your C compiler don't add underline before function name, #define longest_match_686 _longest_match_686
define ADD_UNDERLINE_ASMFUNC */ #define cpudetect32 _cpudetect32
#ifdef ADD_UNDERLINE_ASMFUNC #endif
#define longest_match_7fff _longest_match_7fff
#define longest_match_686 _longest_match_686
#define cpudetect32 _cpudetect32 unsigned long cpudetect32();
#endif
uInt longest_match_c(
deflate_state *s,
IPos cur_match); /* current match */
void match_init()
{
} uInt longest_match_7fff(
deflate_state *s,
unsigned long cpudetect32(); IPos cur_match); /* current match */
uInt longest_match_c( uInt longest_match_686(
deflate_state *s, deflate_state *s,
IPos cur_match); /* current match */ IPos cur_match); /* current match */
uInt longest_match_7fff( static uInt iIsPPro=2;
deflate_state *s,
IPos cur_match); /* current match */ void match_init ()
{
uInt longest_match_686( iIsPPro = (((cpudetect32()/0x100)&0xf)>=6) ? 1 : 0;
deflate_state *s, }
IPos cur_match); /* current match */
uInt longest_match(
uInt longest_match( deflate_state *s,
deflate_state *s, IPos cur_match) /* current match */
IPos cur_match) /* current match */ {
{ if (iIsPPro!=0)
static uInt iIsPPro=2; return longest_match_686(s,cur_match);
if ((s->w_mask == 0x7fff) && (iIsPPro==0)) if (s->w_mask != 0x7fff)
return longest_match_7fff(s,cur_match); return longest_match_686(s,cur_match);
if (iIsPPro==1) /* now ((s->w_mask == 0x7fff) && (iIsPPro==0)) */
return longest_match_686(s,cur_match); return longest_match_7fff(s,cur_match);
}
if (iIsPPro==2)
iIsPPro = (((cpudetect32()/0x100)&0xf)>=6) ? 1 : 0;
#endif /* defined(ASMV) && (!defined(NOOLDPENTIUMCODE)) */
return longest_match_c(s,cur_match);
}
uInt longest_match_c(s, cur_match)
deflate_state *s;
IPos cur_match; /* current match */
{
unsigned chain_length = s->max_chain_length;/* max hash chain length */
register Bytef *scan = s->window + s->strstart; /* current string */
register Bytef *match; /* matched string */
register int len; /* length of current match */
int best_len = s->prev_length; /* best match length so far */
int nice_match = s->nice_match; /* stop if match long enough */
IPos limit = s->strstart > (IPos)MAX_DIST(s) ?
s->strstart - (IPos)MAX_DIST(s) : NIL;
/* Stop when cur_match becomes <= limit. To simplify the code,
* we prevent matches with the string of window index 0.
*/
Posf *prev = s->prev;
uInt wmask = s->w_mask;
#ifdef UNALIGNED_OK
/* Compare two bytes at a time. Note: this is not always beneficial.
* Try with and without -DUNALIGNED_OK to check.
*/
register Bytef *strend = s->window + s->strstart + MAX_MATCH - 1;
register ush scan_start = *(ushf*)scan;
register ush scan_end = *(ushf*)(scan+best_len-1);
#else
register Bytef *strend = s->window + s->strstart + MAX_MATCH;
register Byte scan_end1 = scan[best_len-1];
register Byte scan_end = scan[best_len];
#endif
/* The code is optimized for HASH_BITS >= 8 and MAX_MATCH-2 multiple of 16.
* It is easy to get rid of this optimization if necessary.
*/
Assert(s->hash_bits >= 8 && MAX_MATCH == 258, "Code too clever");
/* Do not waste too much time if we already have a good match: */
if (s->prev_length >= s->good_match) {
chain_length >>= 2;
}
/* Do not look for matches beyond the end of the input. This is necessary
* to make deflate deterministic.
*/
if ((uInt)nice_match > s->lookahead) nice_match = s->lookahead;
Assert((ulg)s->strstart <= s->window_size-MIN_LOOKAHEAD, "need lookahead");
do {
Assert(cur_match < s->strstart, "no future");
match = s->window + cur_match;
/* Skip to next match if the match length cannot increase
* or if the match length is less than 2:
*/
#if (defined(UNALIGNED_OK) && MAX_MATCH == 258)
/* This code assumes sizeof(unsigned short) == 2. Do not use
* UNALIGNED_OK if your compiler uses a different size.
*/
if (*(ushf*)(match+best_len-1) != scan_end ||
*(ushf*)match != scan_start) continue;
/* It is not necessary to compare scan[2] and match[2] since they are
* always equal when the other bytes match, given that the hash keys
* are equal and that HASH_BITS >= 8. Compare 2 bytes at a time at
* strstart+3, +5, ... up to strstart+257. We check for insufficient
* lookahead only every 4th comparison; the 128th check will be made
* at strstart+257. If MAX_MATCH-2 is not a multiple of 8, it is
* necessary to put more guard bytes at the end of the window, or
* to check more often for insufficient lookahead.
*/
Assert(scan[2] == match[2], "scan[2]?");
scan++, match++;
do {
} while (*(ushf*)(scan+=2) == *(ushf*)(match+=2) &&
*(ushf*)(scan+=2) == *(ushf*)(match+=2) &&
*(ushf*)(scan+=2) == *(ushf*)(match+=2) &&
*(ushf*)(scan+=2) == *(ushf*)(match+=2) &&
scan < strend);
/* The funny "do {}" generates better code on most compilers */
/* Here, scan <= window+strstart+257 */
Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan");
if (*scan == *match) scan++;
len = (MAX_MATCH - 1) - (int)(strend-scan);
scan = strend - (MAX_MATCH-1);
#else /* UNALIGNED_OK */
if (match[best_len] != scan_end ||
match[best_len-1] != scan_end1 ||
*match != *scan ||
*++match != scan[1]) continue;
/* The check at best_len-1 can be removed because it will be made
* again later. (This heuristic is not always a win.)
* It is not necessary to compare scan[2] and match[2] since they
* are always equal when the other bytes match, given that
* the hash keys are equal and that HASH_BITS >= 8.
*/
scan += 2, match++;
Assert(*scan == *match, "match[2]?");
/* We check for insufficient lookahead only every 8th comparison;
* the 256th check will be made at strstart+258.
*/
do {
} while (*++scan == *++match && *++scan == *++match &&
*++scan == *++match && *++scan == *++match &&
*++scan == *++match && *++scan == *++match &&
*++scan == *++match && *++scan == *++match &&
scan < strend);
Assert(scan <= s->window+(unsigned)(s->window_size-1), "wild scan");
len = MAX_MATCH - (int)(strend - scan);
scan = strend - MAX_MATCH;
#endif /* UNALIGNED_OK */
if (len > best_len) {
s->match_start = cur_match;
best_len = len;
if (len >= nice_match) break;
#ifdef UNALIGNED_OK
scan_end = *(ushf*)(scan+best_len-1);
#else
scan_end1 = scan[best_len-1];
scan_end = scan[best_len];
#endif
}
} while ((cur_match = prev[cur_match & wmask]) > limit
&& --chain_length != 0);
if ((uInt)best_len <= s->lookahead) return (uInt)best_len;
return s->lookahead;
}
#endif /* ASMV */

File diff suppressed because it is too large Load Diff

View File

@@ -1,63 +1,67 @@
Change in 1.01b (20 may 04) Change in 1.01e (12 feb 05)
- Integrate patch from Debian package (submited by Mark Brown) - Fix in zipOpen2 for globalcomment (Rolf Kalbermatter)
- Add tools mztools from Xavier Roche - Fix possible memory leak in unzip.c (Zoran Stevanovic)
Change in 1.01 (8 may 04) Change in 1.01b (20 may 04)
- fix buffer overrun risk in unzip.c (Xavier Roche) - Integrate patch from Debian package (submited by Mark Brown)
- fix a minor buffer insecurity in minizip.c (Mike Whittaker) - Add tools mztools from Xavier Roche
Change in 1.00: (10 sept 03) Change in 1.01 (8 may 04)
- rename to 1.00 - fix buffer overrun risk in unzip.c (Xavier Roche)
- cosmetic code change - fix a minor buffer insecurity in minizip.c (Mike Whittaker)
Change in 0.22: (19 May 03) Change in 1.00: (10 sept 03)
- crypting support (unless you define NOCRYPT) - rename to 1.00
- append file in existing zipfile - cosmetic code change
Change in 0.21: (10 Mar 03) Change in 0.22: (19 May 03)
- bug fixes - crypting support (unless you define NOCRYPT)
- append file in existing zipfile
Change in 0.17: (27 Jan 02)
- bug fixes Change in 0.21: (10 Mar 03)
- bug fixes
Change in 0.16: (19 Jan 02)
- Support of ioapi for virtualize zip file access Change in 0.17: (27 Jan 02)
- bug fixes
Change in 0.15: (19 Mar 98)
- fix memory leak in minizip.c Change in 0.16: (19 Jan 02)
- Support of ioapi for virtualize zip file access
Change in 0.14: (10 Mar 98)
- fix bugs in minizip.c sample for zipping big file Change in 0.15: (19 Mar 98)
- fix problem in month in date handling - fix memory leak in minizip.c
- fix bug in unzlocal_GetCurrentFileInfoInternal in unzip.c for
comment handling Change in 0.14: (10 Mar 98)
- fix bugs in minizip.c sample for zipping big file
Change in 0.13: (6 Mar 98) - fix problem in month in date handling
- fix bugs in zip.c - fix bug in unzlocal_GetCurrentFileInfoInternal in unzip.c for
- add real minizip sample comment handling
Change in 0.12: (4 Mar 98) Change in 0.13: (6 Mar 98)
- add zip.c and zip.h for creates .zip file - fix bugs in zip.c
- fix change_file_date in miniunz.c for Unix (Jean-loup Gailly) - add real minizip sample
- fix miniunz.c for file without specific record for directory
Change in 0.12: (4 Mar 98)
Change in 0.11: (3 Mar 98) - add zip.c and zip.h for creates .zip file
- fix bug in unzGetCurrentFileInfo for get extra field and comment - fix change_file_date in miniunz.c for Unix (Jean-loup Gailly)
- enhance miniunz sample, remove the bad unztst.c sample - fix miniunz.c for file without specific record for directory
Change in 0.10: (2 Mar 98) Change in 0.11: (3 Mar 98)
- fix bug in unzReadCurrentFile - fix bug in unzGetCurrentFileInfo for get extra field and comment
- rename unzip* to unz* function and structure - enhance miniunz sample, remove the bad unztst.c sample
- remove Windows-like hungary notation variable name
- modify some structure in unzip.h Change in 0.10: (2 Mar 98)
- add somes comment in source - fix bug in unzReadCurrentFile
- remove unzipGetcCurrentFile function - rename unzip* to unz* function and structure
- replace ZUNZEXPORT by ZEXPORT - remove Windows-like hungary notation variable name
- add unzGetLocalExtrafield for get the local extrafield info - modify some structure in unzip.h
- add a new sample, miniunz.c - add somes comment in source
- remove unzipGetcCurrentFile function
Change in 0.4: (25 Feb 98) - replace ZUNZEXPORT by ZEXPORT
- suppress the type unzipFileInZip. - add unzGetLocalExtrafield for get the local extrafield info
Only on file in the zipfile can be open at the same time - add a new sample, miniunz.c
- fix somes typo in code
- added tm_unz structure in unzip_file_info (date/time in readable format) Change in 0.4: (25 Feb 98)
- suppress the type unzipFileInZip.
Only on file in the zipfile can be open at the same time
- fix somes typo in code
- added tm_unz structure in unzip_file_info (date/time in readable format)

View File

@@ -1,25 +1,25 @@
CC=cc CC=cc
CFLAGS=-O -I../.. CFLAGS=-O -I../..
UNZ_OBJS = miniunz.o unzip.o ioapi.o ../../libz.a UNZ_OBJS = miniunz.o unzip.o ioapi.o ../../libz.a
ZIP_OBJS = minizip.o zip.o ioapi.o ../../libz.a ZIP_OBJS = minizip.o zip.o ioapi.o ../../libz.a
.c.o: .c.o:
$(CC) -c $(CFLAGS) $*.c $(CC) -c $(CFLAGS) $*.c
all: miniunz minizip all: miniunz minizip
miniunz: $(UNZ_OBJS) miniunz: $(UNZ_OBJS)
$(CC) $(CFLAGS) -o $@ $(UNZ_OBJS) $(CC) $(CFLAGS) -o $@ $(UNZ_OBJS)
minizip: $(ZIP_OBJS) minizip: $(ZIP_OBJS)
$(CC) $(CFLAGS) -o $@ $(ZIP_OBJS) $(CC) $(CFLAGS) -o $@ $(ZIP_OBJS)
test: miniunz minizip test: miniunz minizip
./minizip test readme.txt ./minizip test readme.txt
./miniunz -l test.zip ./miniunz -l test.zip
mv readme.txt readme.old mv readme.txt readme.old
./miniunz test.zip ./miniunz test.zip
clean: clean:
/bin/rm -f *.o *~ minizip miniunz /bin/rm -f *.o *~ minizip miniunz

View File

@@ -1,132 +1,132 @@
/* crypt.h -- base code for crypt/uncrypt ZIPfile /* crypt.h -- base code for crypt/uncrypt ZIPfile
Version 1.01, May 8th, 2004 Version 1.01e, February 12th, 2005
Copyright (C) 1998-2004 Gilles Vollant Copyright (C) 1998-2005 Gilles Vollant
This code is a modified version of crypting code in Infozip distribution This code is a modified version of crypting code in Infozip distribution
The encryption/decryption parts of this source code (as opposed to the The encryption/decryption parts of this source code (as opposed to the
non-echoing password parts) were originally written in Europe. The non-echoing password parts) were originally written in Europe. The
whole source package can be freely distributed, including from the USA. whole source package can be freely distributed, including from the USA.
(Prior to January 2000, re-export from the US was a violation of US law.) (Prior to January 2000, re-export from the US was a violation of US law.)
This encryption code is a direct transcription of the algorithm from This encryption code is a direct transcription of the algorithm from
Roger Schlafly, described by Phil Katz in the file appnote.txt. This Roger Schlafly, described by Phil Katz in the file appnote.txt. This
file (appnote.txt) is distributed with the PKZIP program (even in the file (appnote.txt) is distributed with the PKZIP program (even in the
version without encryption capabilities). version without encryption capabilities).
If you don't need crypting in your application, just define symbols If you don't need crypting in your application, just define symbols
NOCRYPT and NOUNCRYPT. NOCRYPT and NOUNCRYPT.
This code support the "Traditional PKWARE Encryption". This code support the "Traditional PKWARE Encryption".
The new AES encryption added on Zip format by Winzip (see the page The new AES encryption added on Zip format by Winzip (see the page
http://www.winzip.com/aes_info.htm ) and PKWare PKZip 5.x Strong http://www.winzip.com/aes_info.htm ) and PKWare PKZip 5.x Strong
Encryption is not supported. Encryption is not supported.
*/ */
#define CRC32(c, b) ((*(pcrc_32_tab+(((int)(c) ^ (b)) & 0xff))) ^ ((c) >> 8)) #define CRC32(c, b) ((*(pcrc_32_tab+(((int)(c) ^ (b)) & 0xff))) ^ ((c) >> 8))
/*********************************************************************** /***********************************************************************
* Return the next byte in the pseudo-random sequence * Return the next byte in the pseudo-random sequence
*/ */
static int decrypt_byte(unsigned long* pkeys, const unsigned long* pcrc_32_tab) static int decrypt_byte(unsigned long* pkeys, const unsigned long* pcrc_32_tab)
{ {
unsigned temp; /* POTENTIAL BUG: temp*(temp^1) may overflow in an unsigned temp; /* POTENTIAL BUG: temp*(temp^1) may overflow in an
* unpredictable manner on 16-bit systems; not a problem * unpredictable manner on 16-bit systems; not a problem
* with any known compiler so far, though */ * with any known compiler so far, though */
temp = ((unsigned)(*(pkeys+2)) & 0xffff) | 2; temp = ((unsigned)(*(pkeys+2)) & 0xffff) | 2;
return (int)(((temp * (temp ^ 1)) >> 8) & 0xff); return (int)(((temp * (temp ^ 1)) >> 8) & 0xff);
} }
/*********************************************************************** /***********************************************************************
* Update the encryption keys with the next byte of plain text * Update the encryption keys with the next byte of plain text
*/ */
static int update_keys(unsigned long* pkeys,const unsigned long* pcrc_32_tab,int c) static int update_keys(unsigned long* pkeys,const unsigned long* pcrc_32_tab,int c)
{ {
(*(pkeys+0)) = CRC32((*(pkeys+0)), c); (*(pkeys+0)) = CRC32((*(pkeys+0)), c);
(*(pkeys+1)) += (*(pkeys+0)) & 0xff; (*(pkeys+1)) += (*(pkeys+0)) & 0xff;
(*(pkeys+1)) = (*(pkeys+1)) * 134775813L + 1; (*(pkeys+1)) = (*(pkeys+1)) * 134775813L + 1;
{ {
register int keyshift = (int)((*(pkeys+1)) >> 24); register int keyshift = (int)((*(pkeys+1)) >> 24);
(*(pkeys+2)) = CRC32((*(pkeys+2)), keyshift); (*(pkeys+2)) = CRC32((*(pkeys+2)), keyshift);
} }
return c; return c;
} }
/*********************************************************************** /***********************************************************************
* Initialize the encryption keys and the random header according to * Initialize the encryption keys and the random header according to
* the given password. * the given password.
*/ */
static void init_keys(const char* passwd,unsigned long* pkeys,const unsigned long* pcrc_32_tab) static void init_keys(const char* passwd,unsigned long* pkeys,const unsigned long* pcrc_32_tab)
{ {
*(pkeys+0) = 305419896L; *(pkeys+0) = 305419896L;
*(pkeys+1) = 591751049L; *(pkeys+1) = 591751049L;
*(pkeys+2) = 878082192L; *(pkeys+2) = 878082192L;
while (*passwd != '\0') { while (*passwd != '\0') {
update_keys(pkeys,pcrc_32_tab,(int)*passwd); update_keys(pkeys,pcrc_32_tab,(int)*passwd);
passwd++; passwd++;
} }
} }
#define zdecode(pkeys,pcrc_32_tab,c) \ #define zdecode(pkeys,pcrc_32_tab,c) \
(update_keys(pkeys,pcrc_32_tab,c ^= decrypt_byte(pkeys,pcrc_32_tab))) (update_keys(pkeys,pcrc_32_tab,c ^= decrypt_byte(pkeys,pcrc_32_tab)))
#define zencode(pkeys,pcrc_32_tab,c,t) \ #define zencode(pkeys,pcrc_32_tab,c,t) \
(t=decrypt_byte(pkeys,pcrc_32_tab), update_keys(pkeys,pcrc_32_tab,c), t^(c)) (t=decrypt_byte(pkeys,pcrc_32_tab), update_keys(pkeys,pcrc_32_tab,c), t^(c))
#ifdef INCLUDECRYPTINGCODE_IFCRYPTALLOWED #ifdef INCLUDECRYPTINGCODE_IFCRYPTALLOWED
#define RAND_HEAD_LEN 12 #define RAND_HEAD_LEN 12
/* "last resort" source for second part of crypt seed pattern */ /* "last resort" source for second part of crypt seed pattern */
# ifndef ZCR_SEED2 # ifndef ZCR_SEED2
# define ZCR_SEED2 3141592654UL /* use PI as default pattern */ # define ZCR_SEED2 3141592654UL /* use PI as default pattern */
# endif # endif
static int crypthead(passwd, buf, bufSize, pkeys, pcrc_32_tab, crcForCrypting) static int crypthead(passwd, buf, bufSize, pkeys, pcrc_32_tab, crcForCrypting)
const char *passwd; /* password string */ const char *passwd; /* password string */
unsigned char *buf; /* where to write header */ unsigned char *buf; /* where to write header */
int bufSize; int bufSize;
unsigned long* pkeys; unsigned long* pkeys;
const unsigned long* pcrc_32_tab; const unsigned long* pcrc_32_tab;
unsigned long crcForCrypting; unsigned long crcForCrypting;
{ {
int n; /* index in random header */ int n; /* index in random header */
int t; /* temporary */ int t; /* temporary */
int c; /* random byte */ int c; /* random byte */
unsigned char header[RAND_HEAD_LEN-2]; /* random header */ unsigned char header[RAND_HEAD_LEN-2]; /* random header */
static unsigned calls = 0; /* ensure different random header each time */ static unsigned calls = 0; /* ensure different random header each time */
if (bufSize<RAND_HEAD_LEN) if (bufSize<RAND_HEAD_LEN)
return 0; return 0;
/* First generate RAND_HEAD_LEN-2 random bytes. We encrypt the /* First generate RAND_HEAD_LEN-2 random bytes. We encrypt the
* output of rand() to get less predictability, since rand() is * output of rand() to get less predictability, since rand() is
* often poorly implemented. * often poorly implemented.
*/ */
if (++calls == 1) if (++calls == 1)
{ {
srand((unsigned)(time(NULL) ^ ZCR_SEED2)); srand((unsigned)(time(NULL) ^ ZCR_SEED2));
} }
init_keys(passwd, pkeys, pcrc_32_tab); init_keys(passwd, pkeys, pcrc_32_tab);
for (n = 0; n < RAND_HEAD_LEN-2; n++) for (n = 0; n < RAND_HEAD_LEN-2; n++)
{ {
c = (rand() >> 7) & 0xff; c = (rand() >> 7) & 0xff;
header[n] = (unsigned char)zencode(pkeys, pcrc_32_tab, c, t); header[n] = (unsigned char)zencode(pkeys, pcrc_32_tab, c, t);
} }
/* Encrypt random header (last two bytes is high word of crc) */ /* Encrypt random header (last two bytes is high word of crc) */
init_keys(passwd, pkeys, pcrc_32_tab); init_keys(passwd, pkeys, pcrc_32_tab);
for (n = 0; n < RAND_HEAD_LEN-2; n++) for (n = 0; n < RAND_HEAD_LEN-2; n++)
{ {
buf[n] = (unsigned char)zencode(pkeys, pcrc_32_tab, header[n], t); buf[n] = (unsigned char)zencode(pkeys, pcrc_32_tab, header[n], t);
} }
buf[n++] = zencode(pkeys, pcrc_32_tab, (int)(crcForCrypting >> 16) & 0xff, t); buf[n++] = zencode(pkeys, pcrc_32_tab, (int)(crcForCrypting >> 16) & 0xff, t);
buf[n++] = zencode(pkeys, pcrc_32_tab, (int)(crcForCrypting >> 24) & 0xff, t); buf[n++] = zencode(pkeys, pcrc_32_tab, (int)(crcForCrypting >> 24) & 0xff, t);
return n; return n;
} }
#endif #endif

View File

@@ -1,177 +1,177 @@
/* ioapi.c -- IO base function header for compress/uncompress .zip /* ioapi.c -- IO base function header for compress/uncompress .zip
files using zlib + zip or unzip API files using zlib + zip or unzip API
Version 1.01, May 8th, 2004 Version 1.01e, February 12th, 2005
Copyright (C) 1998-2004 Gilles Vollant Copyright (C) 1998-2005 Gilles Vollant
*/ */
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include "zlib.h" #include "zlib.h"
#include "ioapi.h" #include "ioapi.h"
/* I've found an old Unix (a SunOS 4.1.3_U1) without all SEEK_* defined.... */ /* I've found an old Unix (a SunOS 4.1.3_U1) without all SEEK_* defined.... */
#ifndef SEEK_CUR #ifndef SEEK_CUR
#define SEEK_CUR 1 #define SEEK_CUR 1
#endif #endif
#ifndef SEEK_END #ifndef SEEK_END
#define SEEK_END 2 #define SEEK_END 2
#endif #endif
#ifndef SEEK_SET #ifndef SEEK_SET
#define SEEK_SET 0 #define SEEK_SET 0
#endif #endif
voidpf ZCALLBACK fopen_file_func OF(( voidpf ZCALLBACK fopen_file_func OF((
voidpf opaque, voidpf opaque,
const char* filename, const char* filename,
int mode)); int mode));
uLong ZCALLBACK fread_file_func OF(( uLong ZCALLBACK fread_file_func OF((
voidpf opaque, voidpf opaque,
voidpf stream, voidpf stream,
void* buf, void* buf,
uLong size)); uLong size));
uLong ZCALLBACK fwrite_file_func OF(( uLong ZCALLBACK fwrite_file_func OF((
voidpf opaque, voidpf opaque,
voidpf stream, voidpf stream,
const void* buf, const void* buf,
uLong size)); uLong size));
long ZCALLBACK ftell_file_func OF(( long ZCALLBACK ftell_file_func OF((
voidpf opaque, voidpf opaque,
voidpf stream)); voidpf stream));
long ZCALLBACK fseek_file_func OF(( long ZCALLBACK fseek_file_func OF((
voidpf opaque, voidpf opaque,
voidpf stream, voidpf stream,
uLong offset, uLong offset,
int origin)); int origin));
int ZCALLBACK fclose_file_func OF(( int ZCALLBACK fclose_file_func OF((
voidpf opaque, voidpf opaque,
voidpf stream)); voidpf stream));
int ZCALLBACK ferror_file_func OF(( int ZCALLBACK ferror_file_func OF((
voidpf opaque, voidpf opaque,
voidpf stream)); voidpf stream));
voidpf ZCALLBACK fopen_file_func (opaque, filename, mode) voidpf ZCALLBACK fopen_file_func (opaque, filename, mode)
voidpf opaque; voidpf opaque;
const char* filename; const char* filename;
int mode; int mode;
{ {
FILE* file = NULL; FILE* file = NULL;
const char* mode_fopen = NULL; const char* mode_fopen = NULL;
if ((mode & ZLIB_FILEFUNC_MODE_READWRITEFILTER)==ZLIB_FILEFUNC_MODE_READ) if ((mode & ZLIB_FILEFUNC_MODE_READWRITEFILTER)==ZLIB_FILEFUNC_MODE_READ)
mode_fopen = "rb"; mode_fopen = "rb";
else else
if (mode & ZLIB_FILEFUNC_MODE_EXISTING) if (mode & ZLIB_FILEFUNC_MODE_EXISTING)
mode_fopen = "r+b"; mode_fopen = "r+b";
else else
if (mode & ZLIB_FILEFUNC_MODE_CREATE) if (mode & ZLIB_FILEFUNC_MODE_CREATE)
mode_fopen = "wb"; mode_fopen = "wb";
if ((filename!=NULL) && (mode_fopen != NULL)) if ((filename!=NULL) && (mode_fopen != NULL))
file = fopen(filename, mode_fopen); file = fopen(filename, mode_fopen);
return file; return file;
} }
uLong ZCALLBACK fread_file_func (opaque, stream, buf, size) uLong ZCALLBACK fread_file_func (opaque, stream, buf, size)
voidpf opaque; voidpf opaque;
voidpf stream; voidpf stream;
void* buf; void* buf;
uLong size; uLong size;
{ {
uLong ret; uLong ret;
ret = (uLong)fread(buf, 1, (size_t)size, (FILE *)stream); ret = (uLong)fread(buf, 1, (size_t)size, (FILE *)stream);
return ret; return ret;
} }
uLong ZCALLBACK fwrite_file_func (opaque, stream, buf, size) uLong ZCALLBACK fwrite_file_func (opaque, stream, buf, size)
voidpf opaque; voidpf opaque;
voidpf stream; voidpf stream;
const void* buf; const void* buf;
uLong size; uLong size;
{ {
uLong ret; uLong ret;
ret = (uLong)fwrite(buf, 1, (size_t)size, (FILE *)stream); ret = (uLong)fwrite(buf, 1, (size_t)size, (FILE *)stream);
return ret; return ret;
} }
long ZCALLBACK ftell_file_func (opaque, stream) long ZCALLBACK ftell_file_func (opaque, stream)
voidpf opaque; voidpf opaque;
voidpf stream; voidpf stream;
{ {
long ret; long ret;
ret = ftell((FILE *)stream); ret = ftell((FILE *)stream);
return ret; return ret;
} }
long ZCALLBACK fseek_file_func (opaque, stream, offset, origin) long ZCALLBACK fseek_file_func (opaque, stream, offset, origin)
voidpf opaque; voidpf opaque;
voidpf stream; voidpf stream;
uLong offset; uLong offset;
int origin; int origin;
{ {
int fseek_origin=0; int fseek_origin=0;
long ret; long ret;
switch (origin) switch (origin)
{ {
case ZLIB_FILEFUNC_SEEK_CUR : case ZLIB_FILEFUNC_SEEK_CUR :
fseek_origin = SEEK_CUR; fseek_origin = SEEK_CUR;
break; break;
case ZLIB_FILEFUNC_SEEK_END : case ZLIB_FILEFUNC_SEEK_END :
fseek_origin = SEEK_END; fseek_origin = SEEK_END;
break; break;
case ZLIB_FILEFUNC_SEEK_SET : case ZLIB_FILEFUNC_SEEK_SET :
fseek_origin = SEEK_SET; fseek_origin = SEEK_SET;
break; break;
default: return -1; default: return -1;
} }
ret = 0; ret = 0;
fseek((FILE *)stream, offset, fseek_origin); fseek((FILE *)stream, offset, fseek_origin);
return ret; return ret;
} }
int ZCALLBACK fclose_file_func (opaque, stream) int ZCALLBACK fclose_file_func (opaque, stream)
voidpf opaque; voidpf opaque;
voidpf stream; voidpf stream;
{ {
int ret; int ret;
ret = fclose((FILE *)stream); ret = fclose((FILE *)stream);
return ret; return ret;
} }
int ZCALLBACK ferror_file_func (opaque, stream) int ZCALLBACK ferror_file_func (opaque, stream)
voidpf opaque; voidpf opaque;
voidpf stream; voidpf stream;
{ {
int ret; int ret;
ret = ferror((FILE *)stream); ret = ferror((FILE *)stream);
return ret; return ret;
} }
void fill_fopen_filefunc (pzlib_filefunc_def) void fill_fopen_filefunc (pzlib_filefunc_def)
zlib_filefunc_def* pzlib_filefunc_def; zlib_filefunc_def* pzlib_filefunc_def;
{ {
pzlib_filefunc_def->zopen_file = fopen_file_func; pzlib_filefunc_def->zopen_file = fopen_file_func;
pzlib_filefunc_def->zread_file = fread_file_func; pzlib_filefunc_def->zread_file = fread_file_func;
pzlib_filefunc_def->zwrite_file = fwrite_file_func; pzlib_filefunc_def->zwrite_file = fwrite_file_func;
pzlib_filefunc_def->ztell_file = ftell_file_func; pzlib_filefunc_def->ztell_file = ftell_file_func;
pzlib_filefunc_def->zseek_file = fseek_file_func; pzlib_filefunc_def->zseek_file = fseek_file_func;
pzlib_filefunc_def->zclose_file = fclose_file_func; pzlib_filefunc_def->zclose_file = fclose_file_func;
pzlib_filefunc_def->zerror_file = ferror_file_func; pzlib_filefunc_def->zerror_file = ferror_file_func;
pzlib_filefunc_def->opaque = NULL; pzlib_filefunc_def->opaque = NULL;
} }

View File

@@ -1,75 +1,75 @@
/* ioapi.h -- IO base function header for compress/uncompress .zip /* ioapi.h -- IO base function header for compress/uncompress .zip
files using zlib + zip or unzip API files using zlib + zip or unzip API
Version 1.01, May 8th, 2004 Version 1.01e, February 12th, 2005
Copyright (C) 1998-2004 Gilles Vollant Copyright (C) 1998-2005 Gilles Vollant
*/ */
#ifndef _ZLIBIOAPI_H #ifndef _ZLIBIOAPI_H
#define _ZLIBIOAPI_H #define _ZLIBIOAPI_H
#define ZLIB_FILEFUNC_SEEK_CUR (1) #define ZLIB_FILEFUNC_SEEK_CUR (1)
#define ZLIB_FILEFUNC_SEEK_END (2) #define ZLIB_FILEFUNC_SEEK_END (2)
#define ZLIB_FILEFUNC_SEEK_SET (0) #define ZLIB_FILEFUNC_SEEK_SET (0)
#define ZLIB_FILEFUNC_MODE_READ (1) #define ZLIB_FILEFUNC_MODE_READ (1)
#define ZLIB_FILEFUNC_MODE_WRITE (2) #define ZLIB_FILEFUNC_MODE_WRITE (2)
#define ZLIB_FILEFUNC_MODE_READWRITEFILTER (3) #define ZLIB_FILEFUNC_MODE_READWRITEFILTER (3)
#define ZLIB_FILEFUNC_MODE_EXISTING (4) #define ZLIB_FILEFUNC_MODE_EXISTING (4)
#define ZLIB_FILEFUNC_MODE_CREATE (8) #define ZLIB_FILEFUNC_MODE_CREATE (8)
#ifndef ZCALLBACK #ifndef ZCALLBACK
#if (defined(WIN32) || defined (WINDOWS) || defined (_WINDOWS)) && defined(CALLBACK) && defined (USEWINDOWS_CALLBACK) #if (defined(WIN32) || defined (WINDOWS) || defined (_WINDOWS)) && defined(CALLBACK) && defined (USEWINDOWS_CALLBACK)
#define ZCALLBACK CALLBACK #define ZCALLBACK CALLBACK
#else #else
#define ZCALLBACK #define ZCALLBACK
#endif #endif
#endif #endif
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
typedef voidpf (ZCALLBACK *open_file_func) OF((voidpf opaque, const char* filename, int mode)); typedef voidpf (ZCALLBACK *open_file_func) OF((voidpf opaque, const char* filename, int mode));
typedef uLong (ZCALLBACK *read_file_func) OF((voidpf opaque, voidpf stream, void* buf, uLong size)); typedef uLong (ZCALLBACK *read_file_func) OF((voidpf opaque, voidpf stream, void* buf, uLong size));
typedef uLong (ZCALLBACK *write_file_func) OF((voidpf opaque, voidpf stream, const void* buf, uLong size)); typedef uLong (ZCALLBACK *write_file_func) OF((voidpf opaque, voidpf stream, const void* buf, uLong size));
typedef long (ZCALLBACK *tell_file_func) OF((voidpf opaque, voidpf stream)); typedef long (ZCALLBACK *tell_file_func) OF((voidpf opaque, voidpf stream));
typedef long (ZCALLBACK *seek_file_func) OF((voidpf opaque, voidpf stream, uLong offset, int origin)); typedef long (ZCALLBACK *seek_file_func) OF((voidpf opaque, voidpf stream, uLong offset, int origin));
typedef int (ZCALLBACK *close_file_func) OF((voidpf opaque, voidpf stream)); typedef int (ZCALLBACK *close_file_func) OF((voidpf opaque, voidpf stream));
typedef int (ZCALLBACK *testerror_file_func) OF((voidpf opaque, voidpf stream)); typedef int (ZCALLBACK *testerror_file_func) OF((voidpf opaque, voidpf stream));
typedef struct zlib_filefunc_def_s typedef struct zlib_filefunc_def_s
{ {
open_file_func zopen_file; open_file_func zopen_file;
read_file_func zread_file; read_file_func zread_file;
write_file_func zwrite_file; write_file_func zwrite_file;
tell_file_func ztell_file; tell_file_func ztell_file;
seek_file_func zseek_file; seek_file_func zseek_file;
close_file_func zclose_file; close_file_func zclose_file;
testerror_file_func zerror_file; testerror_file_func zerror_file;
voidpf opaque; voidpf opaque;
} zlib_filefunc_def; } zlib_filefunc_def;
void fill_fopen_filefunc OF((zlib_filefunc_def* pzlib_filefunc_def)); void fill_fopen_filefunc OF((zlib_filefunc_def* pzlib_filefunc_def));
#define ZREAD(filefunc,filestream,buf,size) ((*((filefunc).zread_file))((filefunc).opaque,filestream,buf,size)) #define ZREAD(filefunc,filestream,buf,size) ((*((filefunc).zread_file))((filefunc).opaque,filestream,buf,size))
#define ZWRITE(filefunc,filestream,buf,size) ((*((filefunc).zwrite_file))((filefunc).opaque,filestream,buf,size)) #define ZWRITE(filefunc,filestream,buf,size) ((*((filefunc).zwrite_file))((filefunc).opaque,filestream,buf,size))
#define ZTELL(filefunc,filestream) ((*((filefunc).ztell_file))((filefunc).opaque,filestream)) #define ZTELL(filefunc,filestream) ((*((filefunc).ztell_file))((filefunc).opaque,filestream))
#define ZSEEK(filefunc,filestream,pos,mode) ((*((filefunc).zseek_file))((filefunc).opaque,filestream,pos,mode)) #define ZSEEK(filefunc,filestream,pos,mode) ((*((filefunc).zseek_file))((filefunc).opaque,filestream,pos,mode))
#define ZCLOSE(filefunc,filestream) ((*((filefunc).zclose_file))((filefunc).opaque,filestream)) #define ZCLOSE(filefunc,filestream) ((*((filefunc).zclose_file))((filefunc).opaque,filestream))
#define ZERROR(filefunc,filestream) ((*((filefunc).zerror_file))((filefunc).opaque,filestream)) #define ZERROR(filefunc,filestream) ((*((filefunc).zerror_file))((filefunc).opaque,filestream))
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif
#endif #endif

View File

@@ -1,270 +1,270 @@
/* iowin32.c -- IO base function header for compress/uncompress .zip /* iowin32.c -- IO base function header for compress/uncompress .zip
files using zlib + zip or unzip API files using zlib + zip or unzip API
This IO API version uses the Win32 API (for Microsoft Windows) This IO API version uses the Win32 API (for Microsoft Windows)
Version 1.01, May 8th, 2004 Version 1.01e, February 12th, 2005
Copyright (C) 1998-2004 Gilles Vollant Copyright (C) 1998-2005 Gilles Vollant
*/ */
#include <stdlib.h> #include <stdlib.h>
#include "zlib.h" #include "zlib.h"
#include "ioapi.h" #include "ioapi.h"
#include "iowin32.h" #include "iowin32.h"
#ifndef INVALID_HANDLE_VALUE #ifndef INVALID_HANDLE_VALUE
#define INVALID_HANDLE_VALUE (0xFFFFFFFF) #define INVALID_HANDLE_VALUE (0xFFFFFFFF)
#endif #endif
#ifndef INVALID_SET_FILE_POINTER #ifndef INVALID_SET_FILE_POINTER
#define INVALID_SET_FILE_POINTER ((DWORD)-1) #define INVALID_SET_FILE_POINTER ((DWORD)-1)
#endif #endif
voidpf ZCALLBACK win32_open_file_func OF(( voidpf ZCALLBACK win32_open_file_func OF((
voidpf opaque, voidpf opaque,
const char* filename, const char* filename,
int mode)); int mode));
uLong ZCALLBACK win32_read_file_func OF(( uLong ZCALLBACK win32_read_file_func OF((
voidpf opaque, voidpf opaque,
voidpf stream, voidpf stream,
void* buf, void* buf,
uLong size)); uLong size));
uLong ZCALLBACK win32_write_file_func OF(( uLong ZCALLBACK win32_write_file_func OF((
voidpf opaque, voidpf opaque,
voidpf stream, voidpf stream,
const void* buf, const void* buf,
uLong size)); uLong size));
long ZCALLBACK win32_tell_file_func OF(( long ZCALLBACK win32_tell_file_func OF((
voidpf opaque, voidpf opaque,
voidpf stream)); voidpf stream));
long ZCALLBACK win32_seek_file_func OF(( long ZCALLBACK win32_seek_file_func OF((
voidpf opaque, voidpf opaque,
voidpf stream, voidpf stream,
uLong offset, uLong offset,
int origin)); int origin));
int ZCALLBACK win32_close_file_func OF(( int ZCALLBACK win32_close_file_func OF((
voidpf opaque, voidpf opaque,
voidpf stream)); voidpf stream));
int ZCALLBACK win32_error_file_func OF(( int ZCALLBACK win32_error_file_func OF((
voidpf opaque, voidpf opaque,
voidpf stream)); voidpf stream));
typedef struct typedef struct
{ {
HANDLE hf; HANDLE hf;
int error; int error;
} WIN32FILE_IOWIN; } WIN32FILE_IOWIN;
voidpf ZCALLBACK win32_open_file_func (opaque, filename, mode) voidpf ZCALLBACK win32_open_file_func (opaque, filename, mode)
voidpf opaque; voidpf opaque;
const char* filename; const char* filename;
int mode; int mode;
{ {
const char* mode_fopen = NULL; const char* mode_fopen = NULL;
DWORD dwDesiredAccess,dwCreationDisposition,dwShareMode,dwFlagsAndAttributes ; DWORD dwDesiredAccess,dwCreationDisposition,dwShareMode,dwFlagsAndAttributes ;
HANDLE hFile = 0; HANDLE hFile = 0;
voidpf ret=NULL; voidpf ret=NULL;
dwDesiredAccess = dwShareMode = dwFlagsAndAttributes = 0; dwDesiredAccess = dwShareMode = dwFlagsAndAttributes = 0;
if ((mode & ZLIB_FILEFUNC_MODE_READWRITEFILTER)==ZLIB_FILEFUNC_MODE_READ) if ((mode & ZLIB_FILEFUNC_MODE_READWRITEFILTER)==ZLIB_FILEFUNC_MODE_READ)
{ {
dwDesiredAccess = GENERIC_READ; dwDesiredAccess = GENERIC_READ;
dwCreationDisposition = OPEN_EXISTING; dwCreationDisposition = OPEN_EXISTING;
dwShareMode = FILE_SHARE_READ; dwShareMode = FILE_SHARE_READ;
} }
else else
if (mode & ZLIB_FILEFUNC_MODE_EXISTING) if (mode & ZLIB_FILEFUNC_MODE_EXISTING)
{ {
dwDesiredAccess = GENERIC_WRITE | GENERIC_READ; dwDesiredAccess = GENERIC_WRITE | GENERIC_READ;
dwCreationDisposition = OPEN_EXISTING; dwCreationDisposition = OPEN_EXISTING;
} }
else else
if (mode & ZLIB_FILEFUNC_MODE_CREATE) if (mode & ZLIB_FILEFUNC_MODE_CREATE)
{ {
dwDesiredAccess = GENERIC_WRITE | GENERIC_READ; dwDesiredAccess = GENERIC_WRITE | GENERIC_READ;
dwCreationDisposition = CREATE_ALWAYS; dwCreationDisposition = CREATE_ALWAYS;
} }
if ((filename!=NULL) && (dwDesiredAccess != 0)) if ((filename!=NULL) && (dwDesiredAccess != 0))
hFile = CreateFile((LPCTSTR)filename, dwDesiredAccess, dwShareMode, NULL, hFile = CreateFile((LPCTSTR)filename, dwDesiredAccess, dwShareMode, NULL,
dwCreationDisposition, dwFlagsAndAttributes, NULL); dwCreationDisposition, dwFlagsAndAttributes, NULL);
if (hFile == INVALID_HANDLE_VALUE) if (hFile == INVALID_HANDLE_VALUE)
hFile = NULL; hFile = NULL;
if (hFile != NULL) if (hFile != NULL)
{ {
WIN32FILE_IOWIN w32fiow; WIN32FILE_IOWIN w32fiow;
w32fiow.hf = hFile; w32fiow.hf = hFile;
w32fiow.error = 0; w32fiow.error = 0;
ret = malloc(sizeof(WIN32FILE_IOWIN)); ret = malloc(sizeof(WIN32FILE_IOWIN));
if (ret==NULL) if (ret==NULL)
CloseHandle(hFile); CloseHandle(hFile);
else *((WIN32FILE_IOWIN*)ret) = w32fiow; else *((WIN32FILE_IOWIN*)ret) = w32fiow;
} }
return ret; return ret;
} }
uLong ZCALLBACK win32_read_file_func (opaque, stream, buf, size) uLong ZCALLBACK win32_read_file_func (opaque, stream, buf, size)
voidpf opaque; voidpf opaque;
voidpf stream; voidpf stream;
void* buf; void* buf;
uLong size; uLong size;
{ {
uLong ret=0; uLong ret=0;
HANDLE hFile = NULL; HANDLE hFile = NULL;
if (stream!=NULL) if (stream!=NULL)
hFile = ((WIN32FILE_IOWIN*)stream) -> hf; hFile = ((WIN32FILE_IOWIN*)stream) -> hf;
if (hFile != NULL) if (hFile != NULL)
if (!ReadFile(hFile, buf, size, &ret, NULL)) if (!ReadFile(hFile, buf, size, &ret, NULL))
{ {
DWORD dwErr = GetLastError(); DWORD dwErr = GetLastError();
if (dwErr == ERROR_HANDLE_EOF) if (dwErr == ERROR_HANDLE_EOF)
dwErr = 0; dwErr = 0;
((WIN32FILE_IOWIN*)stream) -> error=(int)dwErr; ((WIN32FILE_IOWIN*)stream) -> error=(int)dwErr;
} }
return ret; return ret;
} }
uLong ZCALLBACK win32_write_file_func (opaque, stream, buf, size) uLong ZCALLBACK win32_write_file_func (opaque, stream, buf, size)
voidpf opaque; voidpf opaque;
voidpf stream; voidpf stream;
const void* buf; const void* buf;
uLong size; uLong size;
{ {
uLong ret=0; uLong ret=0;
HANDLE hFile = NULL; HANDLE hFile = NULL;
if (stream!=NULL) if (stream!=NULL)
hFile = ((WIN32FILE_IOWIN*)stream) -> hf; hFile = ((WIN32FILE_IOWIN*)stream) -> hf;
if (hFile !=NULL) if (hFile !=NULL)
if (!WriteFile(hFile, buf, size, &ret, NULL)) if (!WriteFile(hFile, buf, size, &ret, NULL))
{ {
DWORD dwErr = GetLastError(); DWORD dwErr = GetLastError();
if (dwErr == ERROR_HANDLE_EOF) if (dwErr == ERROR_HANDLE_EOF)
dwErr = 0; dwErr = 0;
((WIN32FILE_IOWIN*)stream) -> error=(int)dwErr; ((WIN32FILE_IOWIN*)stream) -> error=(int)dwErr;
} }
return ret; return ret;
} }
long ZCALLBACK win32_tell_file_func (opaque, stream) long ZCALLBACK win32_tell_file_func (opaque, stream)
voidpf opaque; voidpf opaque;
voidpf stream; voidpf stream;
{ {
long ret=-1; long ret=-1;
HANDLE hFile = NULL; HANDLE hFile = NULL;
if (stream!=NULL) if (stream!=NULL)
hFile = ((WIN32FILE_IOWIN*)stream) -> hf; hFile = ((WIN32FILE_IOWIN*)stream) -> hf;
if (hFile != NULL) if (hFile != NULL)
{ {
DWORD dwSet = SetFilePointer(hFile, 0, NULL, FILE_CURRENT); DWORD dwSet = SetFilePointer(hFile, 0, NULL, FILE_CURRENT);
if (dwSet == INVALID_SET_FILE_POINTER) if (dwSet == INVALID_SET_FILE_POINTER)
{ {
DWORD dwErr = GetLastError(); DWORD dwErr = GetLastError();
((WIN32FILE_IOWIN*)stream) -> error=(int)dwErr; ((WIN32FILE_IOWIN*)stream) -> error=(int)dwErr;
ret = -1; ret = -1;
} }
else else
ret=(long)dwSet; ret=(long)dwSet;
} }
return ret; return ret;
} }
long ZCALLBACK win32_seek_file_func (opaque, stream, offset, origin) long ZCALLBACK win32_seek_file_func (opaque, stream, offset, origin)
voidpf opaque; voidpf opaque;
voidpf stream; voidpf stream;
uLong offset; uLong offset;
int origin; int origin;
{ {
DWORD dwMoveMethod=0xFFFFFFFF; DWORD dwMoveMethod=0xFFFFFFFF;
HANDLE hFile = NULL; HANDLE hFile = NULL;
long ret=-1; long ret=-1;
if (stream!=NULL) if (stream!=NULL)
hFile = ((WIN32FILE_IOWIN*)stream) -> hf; hFile = ((WIN32FILE_IOWIN*)stream) -> hf;
switch (origin) switch (origin)
{ {
case ZLIB_FILEFUNC_SEEK_CUR : case ZLIB_FILEFUNC_SEEK_CUR :
dwMoveMethod = FILE_CURRENT; dwMoveMethod = FILE_CURRENT;
break; break;
case ZLIB_FILEFUNC_SEEK_END : case ZLIB_FILEFUNC_SEEK_END :
dwMoveMethod = FILE_END; dwMoveMethod = FILE_END;
break; break;
case ZLIB_FILEFUNC_SEEK_SET : case ZLIB_FILEFUNC_SEEK_SET :
dwMoveMethod = FILE_BEGIN; dwMoveMethod = FILE_BEGIN;
break; break;
default: return -1; default: return -1;
} }
if (hFile != NULL) if (hFile != NULL)
{ {
DWORD dwSet = SetFilePointer(hFile, offset, NULL, dwMoveMethod); DWORD dwSet = SetFilePointer(hFile, offset, NULL, dwMoveMethod);
if (dwSet == INVALID_SET_FILE_POINTER) if (dwSet == INVALID_SET_FILE_POINTER)
{ {
DWORD dwErr = GetLastError(); DWORD dwErr = GetLastError();
((WIN32FILE_IOWIN*)stream) -> error=(int)dwErr; ((WIN32FILE_IOWIN*)stream) -> error=(int)dwErr;
ret = -1; ret = -1;
} }
else else
ret=0; ret=0;
} }
return ret; return ret;
} }
int ZCALLBACK win32_close_file_func (opaque, stream) int ZCALLBACK win32_close_file_func (opaque, stream)
voidpf opaque; voidpf opaque;
voidpf stream; voidpf stream;
{ {
int ret=-1; int ret=-1;
if (stream!=NULL) if (stream!=NULL)
{ {
HANDLE hFile; HANDLE hFile;
hFile = ((WIN32FILE_IOWIN*)stream) -> hf; hFile = ((WIN32FILE_IOWIN*)stream) -> hf;
if (hFile != NULL) if (hFile != NULL)
{ {
CloseHandle(hFile); CloseHandle(hFile);
ret=0; ret=0;
} }
free(stream); free(stream);
} }
return ret; return ret;
} }
int ZCALLBACK win32_error_file_func (opaque, stream) int ZCALLBACK win32_error_file_func (opaque, stream)
voidpf opaque; voidpf opaque;
voidpf stream; voidpf stream;
{ {
int ret=-1; int ret=-1;
if (stream!=NULL) if (stream!=NULL)
{ {
ret = ((WIN32FILE_IOWIN*)stream) -> error; ret = ((WIN32FILE_IOWIN*)stream) -> error;
} }
return ret; return ret;
} }
void fill_win32_filefunc (pzlib_filefunc_def) void fill_win32_filefunc (pzlib_filefunc_def)
zlib_filefunc_def* pzlib_filefunc_def; zlib_filefunc_def* pzlib_filefunc_def;
{ {
pzlib_filefunc_def->zopen_file = win32_open_file_func; pzlib_filefunc_def->zopen_file = win32_open_file_func;
pzlib_filefunc_def->zread_file = win32_read_file_func; pzlib_filefunc_def->zread_file = win32_read_file_func;
pzlib_filefunc_def->zwrite_file = win32_write_file_func; pzlib_filefunc_def->zwrite_file = win32_write_file_func;
pzlib_filefunc_def->ztell_file = win32_tell_file_func; pzlib_filefunc_def->ztell_file = win32_tell_file_func;
pzlib_filefunc_def->zseek_file = win32_seek_file_func; pzlib_filefunc_def->zseek_file = win32_seek_file_func;
pzlib_filefunc_def->zclose_file = win32_close_file_func; pzlib_filefunc_def->zclose_file = win32_close_file_func;
pzlib_filefunc_def->zerror_file = win32_error_file_func; pzlib_filefunc_def->zerror_file = win32_error_file_func;
pzlib_filefunc_def->opaque=NULL; pzlib_filefunc_def->opaque=NULL;
} }

View File

@@ -1,21 +1,21 @@
/* iowin32.h -- IO base function header for compress/uncompress .zip /* iowin32.h -- IO base function header for compress/uncompress .zip
files using zlib + zip or unzip API files using zlib + zip or unzip API
This IO API version uses the Win32 API (for Microsoft Windows) This IO API version uses the Win32 API (for Microsoft Windows)
Version 1.01, May 8th, 2004 Version 1.01e, February 12th, 2005
Copyright (C) 1998-2004 Gilles Vollant Copyright (C) 1998-2005 Gilles Vollant
*/ */
#include <windows.h> #include <windows.h>
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
void fill_win32_filefunc OF((zlib_filefunc_def* pzlib_filefunc_def)); void fill_win32_filefunc OF((zlib_filefunc_def* pzlib_filefunc_def));
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

File diff suppressed because it is too large Load Diff

View File

@@ -1,420 +1,420 @@
/* /*
minizip.c minizip.c
Version 1.01b, May 30th, 2004 Version 1.01e, February 12th, 2005
Copyright (C) 1998-2004 Gilles Vollant Copyright (C) 1998-2005 Gilles Vollant
*/ */
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <time.h> #include <time.h>
#include <errno.h> #include <errno.h>
#include <fcntl.h> #include <fcntl.h>
#ifdef unix #ifdef unix
# include <unistd.h> # include <unistd.h>
# include <utime.h> # include <utime.h>
# include <sys/types.h> # include <sys/types.h>
# include <sys/stat.h> # include <sys/stat.h>
#else #else
# include <direct.h> # include <direct.h>
# include <io.h> # include <io.h>
#endif #endif
#include "zip.h" #include "zip.h"
#ifdef WIN32 #ifdef WIN32
#define USEWIN32IOAPI #define USEWIN32IOAPI
#include "iowin32.h" #include "iowin32.h"
#endif #endif
#define WRITEBUFFERSIZE (16384) #define WRITEBUFFERSIZE (16384)
#define MAXFILENAME (256) #define MAXFILENAME (256)
#ifdef WIN32 #ifdef WIN32
uLong filetime(f, tmzip, dt) uLong filetime(f, tmzip, dt)
char *f; /* name of file to get info on */ char *f; /* name of file to get info on */
tm_zip *tmzip; /* return value: access, modific. and creation times */ tm_zip *tmzip; /* return value: access, modific. and creation times */
uLong *dt; /* dostime */ uLong *dt; /* dostime */
{ {
int ret = 0; int ret = 0;
{ {
FILETIME ftLocal; FILETIME ftLocal;
HANDLE hFind; HANDLE hFind;
WIN32_FIND_DATA ff32; WIN32_FIND_DATA ff32;
hFind = FindFirstFile(f,&ff32); hFind = FindFirstFile(f,&ff32);
if (hFind != INVALID_HANDLE_VALUE) if (hFind != INVALID_HANDLE_VALUE)
{ {
FileTimeToLocalFileTime(&(ff32.ftLastWriteTime),&ftLocal); FileTimeToLocalFileTime(&(ff32.ftLastWriteTime),&ftLocal);
FileTimeToDosDateTime(&ftLocal,((LPWORD)dt)+1,((LPWORD)dt)+0); FileTimeToDosDateTime(&ftLocal,((LPWORD)dt)+1,((LPWORD)dt)+0);
FindClose(hFind); FindClose(hFind);
ret = 1; ret = 1;
} }
} }
return ret; return ret;
} }
#else #else
#ifdef unix #ifdef unix
uLong filetime(f, tmzip, dt) uLong filetime(f, tmzip, dt)
char *f; /* name of file to get info on */ char *f; /* name of file to get info on */
tm_zip *tmzip; /* return value: access, modific. and creation times */ tm_zip *tmzip; /* return value: access, modific. and creation times */
uLong *dt; /* dostime */ uLong *dt; /* dostime */
{ {
int ret=0; int ret=0;
struct stat s; /* results of stat() */ struct stat s; /* results of stat() */
struct tm* filedate; struct tm* filedate;
time_t tm_t=0; time_t tm_t=0;
if (strcmp(f,"-")!=0) if (strcmp(f,"-")!=0)
{ {
char name[MAXFILENAME+1]; char name[MAXFILENAME+1];
int len = strlen(f); int len = strlen(f);
if (len > MAXFILENAME) if (len > MAXFILENAME)
len = MAXFILENAME; len = MAXFILENAME;
strncpy(name, f,MAXFILENAME-1); strncpy(name, f,MAXFILENAME-1);
/* strncpy doesnt append the trailing NULL, of the string is too long. */ /* strncpy doesnt append the trailing NULL, of the string is too long. */
name[ MAXFILENAME ] = '\0'; name[ MAXFILENAME ] = '\0';
if (name[len - 1] == '/') if (name[len - 1] == '/')
name[len - 1] = '\0'; name[len - 1] = '\0';
/* not all systems allow stat'ing a file with / appended */ /* not all systems allow stat'ing a file with / appended */
if (stat(name,&s)==0) if (stat(name,&s)==0)
{ {
tm_t = s.st_mtime; tm_t = s.st_mtime;
ret = 1; ret = 1;
} }
} }
filedate = localtime(&tm_t); filedate = localtime(&tm_t);
tmzip->tm_sec = filedate->tm_sec; tmzip->tm_sec = filedate->tm_sec;
tmzip->tm_min = filedate->tm_min; tmzip->tm_min = filedate->tm_min;
tmzip->tm_hour = filedate->tm_hour; tmzip->tm_hour = filedate->tm_hour;
tmzip->tm_mday = filedate->tm_mday; tmzip->tm_mday = filedate->tm_mday;
tmzip->tm_mon = filedate->tm_mon ; tmzip->tm_mon = filedate->tm_mon ;
tmzip->tm_year = filedate->tm_year; tmzip->tm_year = filedate->tm_year;
return ret; return ret;
} }
#else #else
uLong filetime(f, tmzip, dt) uLong filetime(f, tmzip, dt)
char *f; /* name of file to get info on */ char *f; /* name of file to get info on */
tm_zip *tmzip; /* return value: access, modific. and creation times */ tm_zip *tmzip; /* return value: access, modific. and creation times */
uLong *dt; /* dostime */ uLong *dt; /* dostime */
{ {
return 0; return 0;
} }
#endif #endif
#endif #endif
int check_exist_file(filename) int check_exist_file(filename)
const char* filename; const char* filename;
{ {
FILE* ftestexist; FILE* ftestexist;
int ret = 1; int ret = 1;
ftestexist = fopen(filename,"rb"); ftestexist = fopen(filename,"rb");
if (ftestexist==NULL) if (ftestexist==NULL)
ret = 0; ret = 0;
else else
fclose(ftestexist); fclose(ftestexist);
return ret; return ret;
} }
void do_banner() void do_banner()
{ {
printf("MiniZip 1.01b, demo of zLib + Zip package written by Gilles Vollant\n"); printf("MiniZip 1.01b, demo of zLib + Zip package written by Gilles Vollant\n");
printf("more info at http://www.winimage.com/zLibDll/unzip.html\n\n"); printf("more info at http://www.winimage.com/zLibDll/unzip.html\n\n");
} }
void do_help() void do_help()
{ {
printf("Usage : minizip [-o] [-a] [-0 to -9] [-p password] file.zip [files_to_add]\n\n" \ printf("Usage : minizip [-o] [-a] [-0 to -9] [-p password] file.zip [files_to_add]\n\n" \
" -o Overwrite existing file.zip\n" \ " -o Overwrite existing file.zip\n" \
" -a Append to existing file.zip\n" \ " -a Append to existing file.zip\n" \
" -0 Store only\n" \ " -0 Store only\n" \
" -1 Compress faster\n" \ " -1 Compress faster\n" \
" -9 Compress better\n\n"); " -9 Compress better\n\n");
} }
/* calculate the CRC32 of a file, /* calculate the CRC32 of a file,
because to encrypt a file, we need known the CRC32 of the file before */ because to encrypt a file, we need known the CRC32 of the file before */
int getFileCrc(const char* filenameinzip,void*buf,unsigned long size_buf,unsigned long* result_crc) int getFileCrc(const char* filenameinzip,void*buf,unsigned long size_buf,unsigned long* result_crc)
{ {
unsigned long calculate_crc=0; unsigned long calculate_crc=0;
int err=ZIP_OK; int err=ZIP_OK;
FILE * fin = fopen(filenameinzip,"rb"); FILE * fin = fopen(filenameinzip,"rb");
unsigned long size_read = 0; unsigned long size_read = 0;
unsigned long total_read = 0; unsigned long total_read = 0;
if (fin==NULL) if (fin==NULL)
{ {
err = ZIP_ERRNO; err = ZIP_ERRNO;
} }
if (err == ZIP_OK) if (err == ZIP_OK)
do do
{ {
err = ZIP_OK; err = ZIP_OK;
size_read = (int)fread(buf,1,size_buf,fin); size_read = (int)fread(buf,1,size_buf,fin);
if (size_read < size_buf) if (size_read < size_buf)
if (feof(fin)==0) if (feof(fin)==0)
{ {
printf("error in reading %s\n",filenameinzip); printf("error in reading %s\n",filenameinzip);
err = ZIP_ERRNO; err = ZIP_ERRNO;
} }
if (size_read>0) if (size_read>0)
calculate_crc = crc32(calculate_crc,buf,size_read); calculate_crc = crc32(calculate_crc,buf,size_read);
total_read += size_read; total_read += size_read;
} while ((err == ZIP_OK) && (size_read>0)); } while ((err == ZIP_OK) && (size_read>0));
if (fin) if (fin)
fclose(fin); fclose(fin);
*result_crc=calculate_crc; *result_crc=calculate_crc;
printf("file %s crc %x\n",filenameinzip,calculate_crc); printf("file %s crc %x\n",filenameinzip,calculate_crc);
return err; return err;
} }
int main(argc,argv) int main(argc,argv)
int argc; int argc;
char *argv[]; char *argv[];
{ {
int i; int i;
int opt_overwrite=0; int opt_overwrite=0;
int opt_compress_level=Z_DEFAULT_COMPRESSION; int opt_compress_level=Z_DEFAULT_COMPRESSION;
int zipfilenamearg = 0; int zipfilenamearg = 0;
char filename_try[MAXFILENAME+16]; char filename_try[MAXFILENAME+16];
int zipok; int zipok;
int err=0; int err=0;
int size_buf=0; int size_buf=0;
void* buf=NULL; void* buf=NULL;
const char* password=NULL; const char* password=NULL;
do_banner(); do_banner();
if (argc==1) if (argc==1)
{ {
do_help(); do_help();
return 0; return 0;
} }
else else
{ {
for (i=1;i<argc;i++) for (i=1;i<argc;i++)
{ {
if ((*argv[i])=='-') if ((*argv[i])=='-')
{ {
const char *p=argv[i]+1; const char *p=argv[i]+1;
while ((*p)!='\0') while ((*p)!='\0')
{ {
char c=*(p++);; char c=*(p++);;
if ((c=='o') || (c=='O')) if ((c=='o') || (c=='O'))
opt_overwrite = 1; opt_overwrite = 1;
if ((c=='a') || (c=='A')) if ((c=='a') || (c=='A'))
opt_overwrite = 2; opt_overwrite = 2;
if ((c>='0') && (c<='9')) if ((c>='0') && (c<='9'))
opt_compress_level = c-'0'; opt_compress_level = c-'0';
if (((c=='p') || (c=='P')) && (i+1<argc)) if (((c=='p') || (c=='P')) && (i+1<argc))
{ {
password=argv[i+1]; password=argv[i+1];
i++; i++;
} }
} }
} }
else else
if (zipfilenamearg == 0) if (zipfilenamearg == 0)
zipfilenamearg = i ; zipfilenamearg = i ;
} }
} }
size_buf = WRITEBUFFERSIZE; size_buf = WRITEBUFFERSIZE;
buf = (void*)malloc(size_buf); buf = (void*)malloc(size_buf);
if (buf==NULL) if (buf==NULL)
{ {
printf("Error allocating memory\n"); printf("Error allocating memory\n");
return ZIP_INTERNALERROR; return ZIP_INTERNALERROR;
} }
if (zipfilenamearg==0) if (zipfilenamearg==0)
zipok=0; zipok=0;
else else
{ {
int i,len; int i,len;
int dot_found=0; int dot_found=0;
zipok = 1 ; zipok = 1 ;
strncpy(filename_try, argv[zipfilenamearg],MAXFILENAME-1); strncpy(filename_try, argv[zipfilenamearg],MAXFILENAME-1);
/* strncpy doesnt append the trailing NULL, of the string is too long. */ /* strncpy doesnt append the trailing NULL, of the string is too long. */
filename_try[ MAXFILENAME ] = '\0'; filename_try[ MAXFILENAME ] = '\0';
len=(int)strlen(filename_try); len=(int)strlen(filename_try);
for (i=0;i<len;i++) for (i=0;i<len;i++)
if (filename_try[i]=='.') if (filename_try[i]=='.')
dot_found=1; dot_found=1;
if (dot_found==0) if (dot_found==0)
strcat(filename_try,".zip"); strcat(filename_try,".zip");
if (opt_overwrite==2) if (opt_overwrite==2)
{ {
/* if the file don't exist, we not append file */ /* if the file don't exist, we not append file */
if (check_exist_file(filename_try)==0) if (check_exist_file(filename_try)==0)
opt_overwrite=1; opt_overwrite=1;
} }
else else
if (opt_overwrite==0) if (opt_overwrite==0)
if (check_exist_file(filename_try)!=0) if (check_exist_file(filename_try)!=0)
{ {
char rep=0; char rep=0;
do do
{ {
char answer[128]; char answer[128];
int ret; int ret;
printf("The file %s exists. Overwrite ? [y]es, [n]o, [a]ppend : ",filename_try); printf("The file %s exists. Overwrite ? [y]es, [n]o, [a]ppend : ",filename_try);
ret = scanf("%1s",answer); ret = scanf("%1s",answer);
if (ret != 1) if (ret != 1)
{ {
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
rep = answer[0] ; rep = answer[0] ;
if ((rep>='a') && (rep<='z')) if ((rep>='a') && (rep<='z'))
rep -= 0x20; rep -= 0x20;
} }
while ((rep!='Y') && (rep!='N') && (rep!='A')); while ((rep!='Y') && (rep!='N') && (rep!='A'));
if (rep=='N') if (rep=='N')
zipok = 0; zipok = 0;
if (rep=='A') if (rep=='A')
opt_overwrite = 2; opt_overwrite = 2;
} }
} }
if (zipok==1) if (zipok==1)
{ {
zipFile zf; zipFile zf;
int errclose; int errclose;
# ifdef USEWIN32IOAPI # ifdef USEWIN32IOAPI
zlib_filefunc_def ffunc; zlib_filefunc_def ffunc;
fill_win32_filefunc(&ffunc); fill_win32_filefunc(&ffunc);
zf = zipOpen2(filename_try,(opt_overwrite==2) ? 2 : 0,NULL,&ffunc); zf = zipOpen2(filename_try,(opt_overwrite==2) ? 2 : 0,NULL,&ffunc);
# else # else
zf = zipOpen(filename_try,(opt_overwrite==2) ? 2 : 0); zf = zipOpen(filename_try,(opt_overwrite==2) ? 2 : 0);
# endif # endif
if (zf == NULL) if (zf == NULL)
{ {
printf("error opening %s\n",filename_try); printf("error opening %s\n",filename_try);
err= ZIP_ERRNO; err= ZIP_ERRNO;
} }
else else
printf("creating %s\n",filename_try); printf("creating %s\n",filename_try);
for (i=zipfilenamearg+1;(i<argc) && (err==ZIP_OK);i++) for (i=zipfilenamearg+1;(i<argc) && (err==ZIP_OK);i++)
{ {
if (!((((*(argv[i]))=='-') || ((*(argv[i]))=='/')) && if (!((((*(argv[i]))=='-') || ((*(argv[i]))=='/')) &&
((argv[i][1]=='o') || (argv[i][1]=='O') || ((argv[i][1]=='o') || (argv[i][1]=='O') ||
(argv[i][1]=='a') || (argv[i][1]=='A') || (argv[i][1]=='a') || (argv[i][1]=='A') ||
(argv[i][1]=='p') || (argv[i][1]=='P') || (argv[i][1]=='p') || (argv[i][1]=='P') ||
((argv[i][1]>='0') || (argv[i][1]<='9'))) && ((argv[i][1]>='0') || (argv[i][1]<='9'))) &&
(strlen(argv[i]) == 2))) (strlen(argv[i]) == 2)))
{ {
FILE * fin; FILE * fin;
int size_read; int size_read;
const char* filenameinzip = argv[i]; const char* filenameinzip = argv[i];
zip_fileinfo zi; zip_fileinfo zi;
unsigned long crcFile=0; unsigned long crcFile=0;
zi.tmz_date.tm_sec = zi.tmz_date.tm_min = zi.tmz_date.tm_hour = zi.tmz_date.tm_sec = zi.tmz_date.tm_min = zi.tmz_date.tm_hour =
zi.tmz_date.tm_mday = zi.tmz_date.tm_mon = zi.tmz_date.tm_year = 0; zi.tmz_date.tm_mday = zi.tmz_date.tm_mon = zi.tmz_date.tm_year = 0;
zi.dosDate = 0; zi.dosDate = 0;
zi.internal_fa = 0; zi.internal_fa = 0;
zi.external_fa = 0; zi.external_fa = 0;
filetime(filenameinzip,&zi.tmz_date,&zi.dosDate); filetime(filenameinzip,&zi.tmz_date,&zi.dosDate);
/* /*
err = zipOpenNewFileInZip(zf,filenameinzip,&zi, err = zipOpenNewFileInZip(zf,filenameinzip,&zi,
NULL,0,NULL,0,NULL / * comment * /, NULL,0,NULL,0,NULL / * comment * /,
(opt_compress_level != 0) ? Z_DEFLATED : 0, (opt_compress_level != 0) ? Z_DEFLATED : 0,
opt_compress_level); opt_compress_level);
*/ */
if ((password != NULL) && (err==ZIP_OK)) if ((password != NULL) && (err==ZIP_OK))
err = getFileCrc(filenameinzip,buf,size_buf,&crcFile); err = getFileCrc(filenameinzip,buf,size_buf,&crcFile);
err = zipOpenNewFileInZip3(zf,filenameinzip,&zi, err = zipOpenNewFileInZip3(zf,filenameinzip,&zi,
NULL,0,NULL,0,NULL /* comment*/, NULL,0,NULL,0,NULL /* comment*/,
(opt_compress_level != 0) ? Z_DEFLATED : 0, (opt_compress_level != 0) ? Z_DEFLATED : 0,
opt_compress_level,0, opt_compress_level,0,
/* -MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY, */ /* -MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY, */
-MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY, -MAX_WBITS, DEF_MEM_LEVEL, Z_DEFAULT_STRATEGY,
password,crcFile); password,crcFile);
if (err != ZIP_OK) if (err != ZIP_OK)
printf("error in opening %s in zipfile\n",filenameinzip); printf("error in opening %s in zipfile\n",filenameinzip);
else else
{ {
fin = fopen(filenameinzip,"rb"); fin = fopen(filenameinzip,"rb");
if (fin==NULL) if (fin==NULL)
{ {
err=ZIP_ERRNO; err=ZIP_ERRNO;
printf("error in opening %s for reading\n",filenameinzip); printf("error in opening %s for reading\n",filenameinzip);
} }
} }
if (err == ZIP_OK) if (err == ZIP_OK)
do do
{ {
err = ZIP_OK; err = ZIP_OK;
size_read = (int)fread(buf,1,size_buf,fin); size_read = (int)fread(buf,1,size_buf,fin);
if (size_read < size_buf) if (size_read < size_buf)
if (feof(fin)==0) if (feof(fin)==0)
{ {
printf("error in reading %s\n",filenameinzip); printf("error in reading %s\n",filenameinzip);
err = ZIP_ERRNO; err = ZIP_ERRNO;
} }
if (size_read>0) if (size_read>0)
{ {
err = zipWriteInFileInZip (zf,buf,size_read); err = zipWriteInFileInZip (zf,buf,size_read);
if (err<0) if (err<0)
{ {
printf("error in writing %s in the zipfile\n", printf("error in writing %s in the zipfile\n",
filenameinzip); filenameinzip);
} }
} }
} while ((err == ZIP_OK) && (size_read>0)); } while ((err == ZIP_OK) && (size_read>0));
if (fin) if (fin)
fclose(fin); fclose(fin);
if (err<0) if (err<0)
err=ZIP_ERRNO; err=ZIP_ERRNO;
else else
{ {
err = zipCloseFileInZip(zf); err = zipCloseFileInZip(zf);
if (err!=ZIP_OK) if (err!=ZIP_OK)
printf("error in closing %s in the zipfile\n", printf("error in closing %s in the zipfile\n",
filenameinzip); filenameinzip);
} }
} }
} }
errclose = zipClose(zf,NULL); errclose = zipClose(zf,NULL);
if (errclose != ZIP_OK) if (errclose != ZIP_OK)
printf("error in closing %s\n",filename_try); printf("error in closing %s\n",filename_try);
} }
else else
{ {
do_help(); do_help();
} }
free(buf); free(buf);
return 0; return 0;
} }

View File

@@ -1,281 +1,281 @@
/* /*
Additional tools for Minizip Additional tools for Minizip
Code: Xavier Roche '2004 Code: Xavier Roche '2004
License: Same as ZLIB (www.gzip.org) License: Same as ZLIB (www.gzip.org)
*/ */
/* Code */ /* Code */
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include "zlib.h" #include "zlib.h"
#include "unzip.h" #include "unzip.h"
#define READ_8(adr) ((unsigned char)*(adr)) #define READ_8(adr) ((unsigned char)*(adr))
#define READ_16(adr) ( READ_8(adr) | (READ_8(adr+1) << 8) ) #define READ_16(adr) ( READ_8(adr) | (READ_8(adr+1) << 8) )
#define READ_32(adr) ( READ_16(adr) | (READ_16((adr)+2) << 16) ) #define READ_32(adr) ( READ_16(adr) | (READ_16((adr)+2) << 16) )
#define WRITE_8(buff, n) do { \ #define WRITE_8(buff, n) do { \
*((unsigned char*)(buff)) = (unsigned char) ((n) & 0xff); \ *((unsigned char*)(buff)) = (unsigned char) ((n) & 0xff); \
} while(0) } while(0)
#define WRITE_16(buff, n) do { \ #define WRITE_16(buff, n) do { \
WRITE_8((unsigned char*)(buff), n); \ WRITE_8((unsigned char*)(buff), n); \
WRITE_8(((unsigned char*)(buff)) + 1, (n) >> 8); \ WRITE_8(((unsigned char*)(buff)) + 1, (n) >> 8); \
} while(0) } while(0)
#define WRITE_32(buff, n) do { \ #define WRITE_32(buff, n) do { \
WRITE_16((unsigned char*)(buff), (n) & 0xffff); \ WRITE_16((unsigned char*)(buff), (n) & 0xffff); \
WRITE_16((unsigned char*)(buff) + 2, (n) >> 16); \ WRITE_16((unsigned char*)(buff) + 2, (n) >> 16); \
} while(0) } while(0)
extern int ZEXPORT unzRepair(file, fileOut, fileOutTmp, nRecovered, bytesRecovered) extern int ZEXPORT unzRepair(file, fileOut, fileOutTmp, nRecovered, bytesRecovered)
const char* file; const char* file;
const char* fileOut; const char* fileOut;
const char* fileOutTmp; const char* fileOutTmp;
uLong* nRecovered; uLong* nRecovered;
uLong* bytesRecovered; uLong* bytesRecovered;
{ {
int err = Z_OK; int err = Z_OK;
FILE* fpZip = fopen(file, "rb"); FILE* fpZip = fopen(file, "rb");
FILE* fpOut = fopen(fileOut, "wb"); FILE* fpOut = fopen(fileOut, "wb");
FILE* fpOutCD = fopen(fileOutTmp, "wb"); FILE* fpOutCD = fopen(fileOutTmp, "wb");
if (fpZip != NULL && fpOut != NULL) { if (fpZip != NULL && fpOut != NULL) {
int entries = 0; int entries = 0;
uLong totalBytes = 0; uLong totalBytes = 0;
char header[30]; char header[30];
char filename[256]; char filename[256];
char extra[1024]; char extra[1024];
int offset = 0; int offset = 0;
int offsetCD = 0; int offsetCD = 0;
while ( fread(header, 1, 30, fpZip) == 30 ) { while ( fread(header, 1, 30, fpZip) == 30 ) {
int currentOffset = offset; int currentOffset = offset;
/* File entry */ /* File entry */
if (READ_32(header) == 0x04034b50) { if (READ_32(header) == 0x04034b50) {
unsigned int version = READ_16(header + 4); unsigned int version = READ_16(header + 4);
unsigned int gpflag = READ_16(header + 6); unsigned int gpflag = READ_16(header + 6);
unsigned int method = READ_16(header + 8); unsigned int method = READ_16(header + 8);
unsigned int filetime = READ_16(header + 10); unsigned int filetime = READ_16(header + 10);
unsigned int filedate = READ_16(header + 12); unsigned int filedate = READ_16(header + 12);
unsigned int crc = READ_32(header + 14); /* crc */ unsigned int crc = READ_32(header + 14); /* crc */
unsigned int cpsize = READ_32(header + 18); /* compressed size */ unsigned int cpsize = READ_32(header + 18); /* compressed size */
unsigned int uncpsize = READ_32(header + 22); /* uncompressed sz */ unsigned int uncpsize = READ_32(header + 22); /* uncompressed sz */
unsigned int fnsize = READ_16(header + 26); /* file name length */ unsigned int fnsize = READ_16(header + 26); /* file name length */
unsigned int extsize = READ_16(header + 28); /* extra field length */ unsigned int extsize = READ_16(header + 28); /* extra field length */
filename[0] = extra[0] = '\0'; filename[0] = extra[0] = '\0';
/* Header */ /* Header */
if (fwrite(header, 1, 30, fpOut) == 30) { if (fwrite(header, 1, 30, fpOut) == 30) {
offset += 30; offset += 30;
} else { } else {
err = Z_ERRNO; err = Z_ERRNO;
break; break;
} }
/* Filename */ /* Filename */
if (fnsize > 0) { if (fnsize > 0) {
if (fread(filename, 1, fnsize, fpZip) == fnsize) { if (fread(filename, 1, fnsize, fpZip) == fnsize) {
if (fwrite(filename, 1, fnsize, fpOut) == fnsize) { if (fwrite(filename, 1, fnsize, fpOut) == fnsize) {
offset += fnsize; offset += fnsize;
} else { } else {
err = Z_ERRNO; err = Z_ERRNO;
break; break;
} }
} else { } else {
err = Z_ERRNO; err = Z_ERRNO;
break; break;
} }
} else { } else {
err = Z_STREAM_ERROR; err = Z_STREAM_ERROR;
break; break;
} }
/* Extra field */ /* Extra field */
if (extsize > 0) { if (extsize > 0) {
if (fread(extra, 1, extsize, fpZip) == extsize) { if (fread(extra, 1, extsize, fpZip) == extsize) {
if (fwrite(extra, 1, extsize, fpOut) == extsize) { if (fwrite(extra, 1, extsize, fpOut) == extsize) {
offset += extsize; offset += extsize;
} else { } else {
err = Z_ERRNO; err = Z_ERRNO;
break; break;
} }
} else { } else {
err = Z_ERRNO; err = Z_ERRNO;
break; break;
} }
} }
/* Data */ /* Data */
{ {
int dataSize = cpsize; int dataSize = cpsize;
if (dataSize == 0) { if (dataSize == 0) {
dataSize = uncpsize; dataSize = uncpsize;
} }
if (dataSize > 0) { if (dataSize > 0) {
char* data = malloc(dataSize); char* data = malloc(dataSize);
if (data != NULL) { if (data != NULL) {
if ((int)fread(data, 1, dataSize, fpZip) == dataSize) { if ((int)fread(data, 1, dataSize, fpZip) == dataSize) {
if ((int)fwrite(data, 1, dataSize, fpOut) == dataSize) { if ((int)fwrite(data, 1, dataSize, fpOut) == dataSize) {
offset += dataSize; offset += dataSize;
totalBytes += dataSize; totalBytes += dataSize;
} else { } else {
err = Z_ERRNO; err = Z_ERRNO;
} }
} else { } else {
err = Z_ERRNO; err = Z_ERRNO;
} }
free(data); free(data);
if (err != Z_OK) { if (err != Z_OK) {
break; break;
} }
} else { } else {
err = Z_MEM_ERROR; err = Z_MEM_ERROR;
break; break;
} }
} }
} }
/* Central directory entry */ /* Central directory entry */
{ {
char header[46]; char header[46];
char* comment = ""; char* comment = "";
int comsize = (int) strlen(comment); int comsize = (int) strlen(comment);
WRITE_32(header, 0x02014b50); WRITE_32(header, 0x02014b50);
WRITE_16(header + 4, version); WRITE_16(header + 4, version);
WRITE_16(header + 6, version); WRITE_16(header + 6, version);
WRITE_16(header + 8, gpflag); WRITE_16(header + 8, gpflag);
WRITE_16(header + 10, method); WRITE_16(header + 10, method);
WRITE_16(header + 12, filetime); WRITE_16(header + 12, filetime);
WRITE_16(header + 14, filedate); WRITE_16(header + 14, filedate);
WRITE_32(header + 16, crc); WRITE_32(header + 16, crc);
WRITE_32(header + 20, cpsize); WRITE_32(header + 20, cpsize);
WRITE_32(header + 24, uncpsize); WRITE_32(header + 24, uncpsize);
WRITE_16(header + 28, fnsize); WRITE_16(header + 28, fnsize);
WRITE_16(header + 30, extsize); WRITE_16(header + 30, extsize);
WRITE_16(header + 32, comsize); WRITE_16(header + 32, comsize);
WRITE_16(header + 34, 0); /* disk # */ WRITE_16(header + 34, 0); /* disk # */
WRITE_16(header + 36, 0); /* int attrb */ WRITE_16(header + 36, 0); /* int attrb */
WRITE_32(header + 38, 0); /* ext attrb */ WRITE_32(header + 38, 0); /* ext attrb */
WRITE_32(header + 42, currentOffset); WRITE_32(header + 42, currentOffset);
/* Header */ /* Header */
if (fwrite(header, 1, 46, fpOutCD) == 46) { if (fwrite(header, 1, 46, fpOutCD) == 46) {
offsetCD += 46; offsetCD += 46;
/* Filename */ /* Filename */
if (fnsize > 0) { if (fnsize > 0) {
if (fwrite(filename, 1, fnsize, fpOutCD) == fnsize) { if (fwrite(filename, 1, fnsize, fpOutCD) == fnsize) {
offsetCD += fnsize; offsetCD += fnsize;
} else { } else {
err = Z_ERRNO; err = Z_ERRNO;
break; break;
} }
} else { } else {
err = Z_STREAM_ERROR; err = Z_STREAM_ERROR;
break; break;
} }
/* Extra field */ /* Extra field */
if (extsize > 0) { if (extsize > 0) {
if (fwrite(extra, 1, extsize, fpOutCD) == extsize) { if (fwrite(extra, 1, extsize, fpOutCD) == extsize) {
offsetCD += extsize; offsetCD += extsize;
} else { } else {
err = Z_ERRNO; err = Z_ERRNO;
break; break;
} }
} }
/* Comment field */ /* Comment field */
if (comsize > 0) { if (comsize > 0) {
if ((int)fwrite(comment, 1, comsize, fpOutCD) == comsize) { if ((int)fwrite(comment, 1, comsize, fpOutCD) == comsize) {
offsetCD += comsize; offsetCD += comsize;
} else { } else {
err = Z_ERRNO; err = Z_ERRNO;
break; break;
} }
} }
} else { } else {
err = Z_ERRNO; err = Z_ERRNO;
break; break;
} }
} }
/* Success */ /* Success */
entries++; entries++;
} else { } else {
break; break;
} }
} }
/* Final central directory */ /* Final central directory */
{ {
int entriesZip = entries; int entriesZip = entries;
char header[22]; char header[22];
char* comment = ""; // "ZIP File recovered by zlib/minizip/mztools"; char* comment = ""; // "ZIP File recovered by zlib/minizip/mztools";
int comsize = (int) strlen(comment); int comsize = (int) strlen(comment);
if (entriesZip > 0xffff) { if (entriesZip > 0xffff) {
entriesZip = 0xffff; entriesZip = 0xffff;
} }
WRITE_32(header, 0x06054b50); WRITE_32(header, 0x06054b50);
WRITE_16(header + 4, 0); /* disk # */ WRITE_16(header + 4, 0); /* disk # */
WRITE_16(header + 6, 0); /* disk # */ WRITE_16(header + 6, 0); /* disk # */
WRITE_16(header + 8, entriesZip); /* hack */ WRITE_16(header + 8, entriesZip); /* hack */
WRITE_16(header + 10, entriesZip); /* hack */ WRITE_16(header + 10, entriesZip); /* hack */
WRITE_32(header + 12, offsetCD); /* size of CD */ WRITE_32(header + 12, offsetCD); /* size of CD */
WRITE_32(header + 16, offset); /* offset to CD */ WRITE_32(header + 16, offset); /* offset to CD */
WRITE_16(header + 20, comsize); /* comment */ WRITE_16(header + 20, comsize); /* comment */
/* Header */ /* Header */
if (fwrite(header, 1, 22, fpOutCD) == 22) { if (fwrite(header, 1, 22, fpOutCD) == 22) {
/* Comment field */ /* Comment field */
if (comsize > 0) { if (comsize > 0) {
if ((int)fwrite(comment, 1, comsize, fpOutCD) != comsize) { if ((int)fwrite(comment, 1, comsize, fpOutCD) != comsize) {
err = Z_ERRNO; err = Z_ERRNO;
} }
} }
} else { } else {
err = Z_ERRNO; err = Z_ERRNO;
} }
} }
/* Final merge (file + central directory) */ /* Final merge (file + central directory) */
fclose(fpOutCD); fclose(fpOutCD);
if (err == Z_OK) { if (err == Z_OK) {
fpOutCD = fopen(fileOutTmp, "rb"); fpOutCD = fopen(fileOutTmp, "rb");
if (fpOutCD != NULL) { if (fpOutCD != NULL) {
int nRead; int nRead;
char buffer[8192]; char buffer[8192];
while ( (nRead = fread(buffer, 1, sizeof(buffer), fpOutCD)) > 0) { while ( (nRead = (int)fread(buffer, 1, sizeof(buffer), fpOutCD)) > 0) {
if ((int)fwrite(buffer, 1, nRead, fpOut) != nRead) { if ((int)fwrite(buffer, 1, nRead, fpOut) != nRead) {
err = Z_ERRNO; err = Z_ERRNO;
break; break;
} }
} }
fclose(fpOutCD); fclose(fpOutCD);
} }
} }
/* Close */ /* Close */
fclose(fpZip); fclose(fpZip);
fclose(fpOut); fclose(fpOut);
/* Wipe temporary file */ /* Wipe temporary file */
(void)remove(fileOutTmp); (void)remove(fileOutTmp);
/* Number of recovered entries */ /* Number of recovered entries */
if (err == Z_OK) { if (err == Z_OK) {
if (nRecovered != NULL) { if (nRecovered != NULL) {
*nRecovered = entries; *nRecovered = entries;
} }
if (bytesRecovered != NULL) { if (bytesRecovered != NULL) {
*bytesRecovered = totalBytes; *bytesRecovered = totalBytes;
} }
} }
} else { } else {
err = Z_STREAM_ERROR; err = Z_STREAM_ERROR;
} }
return err; return err;
} }

View File

@@ -1,31 +1,31 @@
/* /*
Additional tools for Minizip Additional tools for Minizip
Code: Xavier Roche '2004 Code: Xavier Roche '2004
License: Same as ZLIB (www.gzip.org) License: Same as ZLIB (www.gzip.org)
*/ */
#ifndef _zip_tools_H #ifndef _zip_tools_H
#define _zip_tools_H #define _zip_tools_H
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
#ifndef _ZLIB_H #ifndef _ZLIB_H
#include "zlib.h" #include "zlib.h"
#endif #endif
#include "unzip.h" #include "unzip.h"
/* Repair a ZIP file (missing central directory) /* Repair a ZIP file (missing central directory)
file: file to recover file: file to recover
fileOut: output file after recovery fileOut: output file after recovery
fileOutTmp: temporary file name used for recovery fileOutTmp: temporary file name used for recovery
*/ */
extern int ZEXPORT unzRepair(const char* file, extern int ZEXPORT unzRepair(const char* file,
const char* fileOut, const char* fileOut,
const char* fileOutTmp, const char* fileOutTmp,
uLong* nRecovered, uLong* nRecovered,
uLong* bytesRecovered); uLong* bytesRecovered);
#endif #endif

File diff suppressed because it is too large Load Diff

View File

@@ -1,352 +1,354 @@
/* unzip.h -- IO for uncompress .zip files using zlib /* unzip.h -- IO for uncompress .zip files using zlib
Version 1.01, May 8th, 2004 Version 1.01e, February 12th, 2005
Copyright (C) 1998-2004 Gilles Vollant Copyright (C) 1998-2005 Gilles Vollant
This unzip package allow extract file from .ZIP file, compatible with PKZip 2.04g This unzip package allow extract file from .ZIP file, compatible with PKZip 2.04g
WinZip, InfoZip tools and compatible. WinZip, InfoZip tools and compatible.
Encryption and multi volume ZipFile (span) are not supported.
Old compressions used by old PKZip 1.x are not supported Multi volume ZipFile (span) are not supported.
Encryption compatible with pkzip 2.04g only supported
Old compressions used by old PKZip 1.x are not supported
I WAIT FEEDBACK at mail info@winimage.com
Visit also http://www.winimage.com/zLibDll/unzip.htm for evolution
I WAIT FEEDBACK at mail info@winimage.com
Condition of use and distribution are the same than zlib : Visit also http://www.winimage.com/zLibDll/unzip.htm for evolution
This software is provided 'as-is', without any express or implied Condition of use and distribution are the same than zlib :
warranty. In no event will the authors be held liable for any damages
arising from the use of this software. This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
Permission is granted to anyone to use this software for any purpose, arising from the use of this software.
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions: Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
1. The origin of this software must not be misrepresented; you must not freely, subject to the following restrictions:
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be 1. The origin of this software must not be misrepresented; you must not
appreciated but is not required. claim that you wrote the original software. If you use this software
2. Altered source versions must be plainly marked as such, and must not be in a product, an acknowledgment in the product documentation would be
misrepresented as being the original software. appreciated but is not required.
3. This notice may not be removed or altered from any source distribution. 2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
/* for more info about .ZIP format, see */
http://www.info-zip.org/pub/infozip/doc/appnote-981119-iz.zip
http://www.info-zip.org/pub/infozip/doc/ /* for more info about .ZIP format, see
PkWare has also a specification at : http://www.info-zip.org/pub/infozip/doc/appnote-981119-iz.zip
ftp://ftp.pkware.com/probdesc.zip http://www.info-zip.org/pub/infozip/doc/
*/ PkWare has also a specification at :
ftp://ftp.pkware.com/probdesc.zip
#ifndef _unz_H */
#define _unz_H
#ifndef _unz_H
#ifdef __cplusplus #define _unz_H
extern "C" {
#endif #ifdef __cplusplus
extern "C" {
#ifndef _ZLIB_H #endif
#include "zlib.h"
#endif #ifndef _ZLIB_H
#include "zlib.h"
#ifndef _ZLIBIOAPI_H #endif
#include "ioapi.h"
#endif #ifndef _ZLIBIOAPI_H
#include "ioapi.h"
#if defined(STRICTUNZIP) || defined(STRICTZIPUNZIP) #endif
/* like the STRICT of WIN32, we define a pointer that cannot be converted
from (void*) without cast */ #if defined(STRICTUNZIP) || defined(STRICTZIPUNZIP)
typedef struct TagunzFile__ { int unused; } unzFile__; /* like the STRICT of WIN32, we define a pointer that cannot be converted
typedef unzFile__ *unzFile; from (void*) without cast */
#else typedef struct TagunzFile__ { int unused; } unzFile__;
typedef voidp unzFile; typedef unzFile__ *unzFile;
#endif #else
typedef voidp unzFile;
#endif
#define UNZ_OK (0)
#define UNZ_END_OF_LIST_OF_FILE (-100)
#define UNZ_ERRNO (Z_ERRNO) #define UNZ_OK (0)
#define UNZ_EOF (0) #define UNZ_END_OF_LIST_OF_FILE (-100)
#define UNZ_PARAMERROR (-102) #define UNZ_ERRNO (Z_ERRNO)
#define UNZ_BADZIPFILE (-103) #define UNZ_EOF (0)
#define UNZ_INTERNALERROR (-104) #define UNZ_PARAMERROR (-102)
#define UNZ_CRCERROR (-105) #define UNZ_BADZIPFILE (-103)
#define UNZ_INTERNALERROR (-104)
/* tm_unz contain date/time info */ #define UNZ_CRCERROR (-105)
typedef struct tm_unz_s
{ /* tm_unz contain date/time info */
uInt tm_sec; /* seconds after the minute - [0,59] */ typedef struct tm_unz_s
uInt tm_min; /* minutes after the hour - [0,59] */ {
uInt tm_hour; /* hours since midnight - [0,23] */ uInt tm_sec; /* seconds after the minute - [0,59] */
uInt tm_mday; /* day of the month - [1,31] */ uInt tm_min; /* minutes after the hour - [0,59] */
uInt tm_mon; /* months since January - [0,11] */ uInt tm_hour; /* hours since midnight - [0,23] */
uInt tm_year; /* years - [1980..2044] */ uInt tm_mday; /* day of the month - [1,31] */
} tm_unz; uInt tm_mon; /* months since January - [0,11] */
uInt tm_year; /* years - [1980..2044] */
/* unz_global_info structure contain global data about the ZIPfile } tm_unz;
These data comes from the end of central dir */
typedef struct unz_global_info_s /* unz_global_info structure contain global data about the ZIPfile
{ These data comes from the end of central dir */
uLong number_entry; /* total number of entries in typedef struct unz_global_info_s
the central dir on this disk */ {
uLong size_comment; /* size of the global comment of the zipfile */ uLong number_entry; /* total number of entries in
} unz_global_info; the central dir on this disk */
uLong size_comment; /* size of the global comment of the zipfile */
} unz_global_info;
/* unz_file_info contain information about a file in the zipfile */
typedef struct unz_file_info_s
{ /* unz_file_info contain information about a file in the zipfile */
uLong version; /* version made by 2 bytes */ typedef struct unz_file_info_s
uLong version_needed; /* version needed to extract 2 bytes */ {
uLong flag; /* general purpose bit flag 2 bytes */ uLong version; /* version made by 2 bytes */
uLong compression_method; /* compression method 2 bytes */ uLong version_needed; /* version needed to extract 2 bytes */
uLong dosDate; /* last mod file date in Dos fmt 4 bytes */ uLong flag; /* general purpose bit flag 2 bytes */
uLong crc; /* crc-32 4 bytes */ uLong compression_method; /* compression method 2 bytes */
uLong compressed_size; /* compressed size 4 bytes */ uLong dosDate; /* last mod file date in Dos fmt 4 bytes */
uLong uncompressed_size; /* uncompressed size 4 bytes */ uLong crc; /* crc-32 4 bytes */
uLong size_filename; /* filename length 2 bytes */ uLong compressed_size; /* compressed size 4 bytes */
uLong size_file_extra; /* extra field length 2 bytes */ uLong uncompressed_size; /* uncompressed size 4 bytes */
uLong size_file_comment; /* file comment length 2 bytes */ uLong size_filename; /* filename length 2 bytes */
uLong size_file_extra; /* extra field length 2 bytes */
uLong disk_num_start; /* disk number start 2 bytes */ uLong size_file_comment; /* file comment length 2 bytes */
uLong internal_fa; /* internal file attributes 2 bytes */
uLong external_fa; /* external file attributes 4 bytes */ uLong disk_num_start; /* disk number start 2 bytes */
uLong internal_fa; /* internal file attributes 2 bytes */
tm_unz tmu_date; uLong external_fa; /* external file attributes 4 bytes */
} unz_file_info;
tm_unz tmu_date;
extern int ZEXPORT unzStringFileNameCompare OF ((const char* fileName1, } unz_file_info;
const char* fileName2,
int iCaseSensitivity)); extern int ZEXPORT unzStringFileNameCompare OF ((const char* fileName1,
/* const char* fileName2,
Compare two filename (fileName1,fileName2). int iCaseSensitivity));
If iCaseSenisivity = 1, comparision is case sensitivity (like strcmp) /*
If iCaseSenisivity = 2, comparision is not case sensitivity (like strcmpi Compare two filename (fileName1,fileName2).
or strcasecmp) If iCaseSenisivity = 1, comparision is case sensitivity (like strcmp)
If iCaseSenisivity = 0, case sensitivity is defaut of your operating system If iCaseSenisivity = 2, comparision is not case sensitivity (like strcmpi
(like 1 on Unix, 2 on Windows) or strcasecmp)
*/ If iCaseSenisivity = 0, case sensitivity is defaut of your operating system
(like 1 on Unix, 2 on Windows)
*/
extern unzFile ZEXPORT unzOpen OF((const char *path));
/*
Open a Zip file. path contain the full pathname (by example, extern unzFile ZEXPORT unzOpen OF((const char *path));
on a Windows XP computer "c:\\zlib\\zlib113.zip" or on an Unix computer /*
"zlib/zlib113.zip". Open a Zip file. path contain the full pathname (by example,
If the zipfile cannot be opened (file don't exist or in not valid), the on a Windows XP computer "c:\\zlib\\zlib113.zip" or on an Unix computer
return value is NULL. "zlib/zlib113.zip".
Else, the return value is a unzFile Handle, usable with other function If the zipfile cannot be opened (file don't exist or in not valid), the
of this unzip package. return value is NULL.
*/ Else, the return value is a unzFile Handle, usable with other function
of this unzip package.
extern unzFile ZEXPORT unzOpen2 OF((const char *path, */
zlib_filefunc_def* pzlib_filefunc_def));
/* extern unzFile ZEXPORT unzOpen2 OF((const char *path,
Open a Zip file, like unzOpen, but provide a set of file low level API zlib_filefunc_def* pzlib_filefunc_def));
for read/write the zip file (see ioapi.h) /*
*/ Open a Zip file, like unzOpen, but provide a set of file low level API
for read/write the zip file (see ioapi.h)
extern int ZEXPORT unzClose OF((unzFile file)); */
/*
Close a ZipFile opened with unzipOpen. extern int ZEXPORT unzClose OF((unzFile file));
If there is files inside the .Zip opened with unzOpenCurrentFile (see later), /*
these files MUST be closed with unzipCloseCurrentFile before call unzipClose. Close a ZipFile opened with unzipOpen.
return UNZ_OK if there is no problem. */ If there is files inside the .Zip opened with unzOpenCurrentFile (see later),
these files MUST be closed with unzipCloseCurrentFile before call unzipClose.
extern int ZEXPORT unzGetGlobalInfo OF((unzFile file, return UNZ_OK if there is no problem. */
unz_global_info *pglobal_info));
/* extern int ZEXPORT unzGetGlobalInfo OF((unzFile file,
Write info about the ZipFile in the *pglobal_info structure. unz_global_info *pglobal_info));
No preparation of the structure is needed /*
return UNZ_OK if there is no problem. */ Write info about the ZipFile in the *pglobal_info structure.
No preparation of the structure is needed
return UNZ_OK if there is no problem. */
extern int ZEXPORT unzGetGlobalComment OF((unzFile file,
char *szComment,
uLong uSizeBuf)); extern int ZEXPORT unzGetGlobalComment OF((unzFile file,
/* char *szComment,
Get the global comment string of the ZipFile, in the szComment buffer. uLong uSizeBuf));
uSizeBuf is the size of the szComment buffer. /*
return the number of byte copied or an error code <0 Get the global comment string of the ZipFile, in the szComment buffer.
*/ uSizeBuf is the size of the szComment buffer.
return the number of byte copied or an error code <0
*/
/***************************************************************************/
/* Unzip package allow you browse the directory of the zipfile */
/***************************************************************************/
extern int ZEXPORT unzGoToFirstFile OF((unzFile file)); /* Unzip package allow you browse the directory of the zipfile */
/*
Set the current file of the zipfile to the first file. extern int ZEXPORT unzGoToFirstFile OF((unzFile file));
return UNZ_OK if there is no problem /*
*/ Set the current file of the zipfile to the first file.
return UNZ_OK if there is no problem
extern int ZEXPORT unzGoToNextFile OF((unzFile file)); */
/*
Set the current file of the zipfile to the next file. extern int ZEXPORT unzGoToNextFile OF((unzFile file));
return UNZ_OK if there is no problem /*
return UNZ_END_OF_LIST_OF_FILE if the actual file was the latest. Set the current file of the zipfile to the next file.
*/ return UNZ_OK if there is no problem
return UNZ_END_OF_LIST_OF_FILE if the actual file was the latest.
extern int ZEXPORT unzLocateFile OF((unzFile file, */
const char *szFileName,
int iCaseSensitivity)); extern int ZEXPORT unzLocateFile OF((unzFile file,
/* const char *szFileName,
Try locate the file szFileName in the zipfile. int iCaseSensitivity));
For the iCaseSensitivity signification, see unzStringFileNameCompare /*
Try locate the file szFileName in the zipfile.
return value : For the iCaseSensitivity signification, see unzStringFileNameCompare
UNZ_OK if the file is found. It becomes the current file.
UNZ_END_OF_LIST_OF_FILE if the file is not found return value :
*/ UNZ_OK if the file is found. It becomes the current file.
UNZ_END_OF_LIST_OF_FILE if the file is not found
*/
/* ****************************************** */
/* Ryan supplied functions */
/* unz_file_info contain information about a file in the zipfile */ /* ****************************************** */
typedef struct unz_file_pos_s /* Ryan supplied functions */
{ /* unz_file_info contain information about a file in the zipfile */
uLong pos_in_zip_directory; /* offset in zip file directory */ typedef struct unz_file_pos_s
uLong num_of_file; /* # of file */ {
} unz_file_pos; uLong pos_in_zip_directory; /* offset in zip file directory */
uLong num_of_file; /* # of file */
extern int ZEXPORT unzGetFilePos( } unz_file_pos;
unzFile file,
unz_file_pos* file_pos); extern int ZEXPORT unzGetFilePos(
unzFile file,
extern int ZEXPORT unzGoToFilePos( unz_file_pos* file_pos);
unzFile file,
unz_file_pos* file_pos); extern int ZEXPORT unzGoToFilePos(
unzFile file,
/* ****************************************** */ unz_file_pos* file_pos);
extern int ZEXPORT unzGetCurrentFileInfo OF((unzFile file, /* ****************************************** */
unz_file_info *pfile_info,
char *szFileName, extern int ZEXPORT unzGetCurrentFileInfo OF((unzFile file,
uLong fileNameBufferSize, unz_file_info *pfile_info,
void *extraField, char *szFileName,
uLong extraFieldBufferSize, uLong fileNameBufferSize,
char *szComment, void *extraField,
uLong commentBufferSize)); uLong extraFieldBufferSize,
/* char *szComment,
Get Info about the current file uLong commentBufferSize));
if pfile_info!=NULL, the *pfile_info structure will contain somes info about /*
the current file Get Info about the current file
if szFileName!=NULL, the filemane string will be copied in szFileName if pfile_info!=NULL, the *pfile_info structure will contain somes info about
(fileNameBufferSize is the size of the buffer) the current file
if extraField!=NULL, the extra field information will be copied in extraField if szFileName!=NULL, the filemane string will be copied in szFileName
(extraFieldBufferSize is the size of the buffer). (fileNameBufferSize is the size of the buffer)
This is the Central-header version of the extra field if extraField!=NULL, the extra field information will be copied in extraField
if szComment!=NULL, the comment string of the file will be copied in szComment (extraFieldBufferSize is the size of the buffer).
(commentBufferSize is the size of the buffer) This is the Central-header version of the extra field
*/ if szComment!=NULL, the comment string of the file will be copied in szComment
(commentBufferSize is the size of the buffer)
/***************************************************************************/ */
/* for reading the content of the current zipfile, you can open it, read data
from it, and close it (you can close it before reading all the file) /***************************************************************************/
*/ /* for reading the content of the current zipfile, you can open it, read data
from it, and close it (you can close it before reading all the file)
extern int ZEXPORT unzOpenCurrentFile OF((unzFile file)); */
/*
Open for reading data the current file in the zipfile. extern int ZEXPORT unzOpenCurrentFile OF((unzFile file));
If there is no error, the return value is UNZ_OK. /*
*/ Open for reading data the current file in the zipfile.
If there is no error, the return value is UNZ_OK.
extern int ZEXPORT unzOpenCurrentFilePassword OF((unzFile file, */
const char* password));
/* extern int ZEXPORT unzOpenCurrentFilePassword OF((unzFile file,
Open for reading data the current file in the zipfile. const char* password));
password is a crypting password /*
If there is no error, the return value is UNZ_OK. Open for reading data the current file in the zipfile.
*/ password is a crypting password
If there is no error, the return value is UNZ_OK.
extern int ZEXPORT unzOpenCurrentFile2 OF((unzFile file, */
int* method,
int* level, extern int ZEXPORT unzOpenCurrentFile2 OF((unzFile file,
int raw)); int* method,
/* int* level,
Same than unzOpenCurrentFile, but open for read raw the file (not uncompress) int raw));
if raw==1 /*
*method will receive method of compression, *level will receive level of Same than unzOpenCurrentFile, but open for read raw the file (not uncompress)
compression if raw==1
note : you can set level parameter as NULL (if you did not want known level, *method will receive method of compression, *level will receive level of
but you CANNOT set method parameter as NULL compression
*/ note : you can set level parameter as NULL (if you did not want known level,
but you CANNOT set method parameter as NULL
extern int ZEXPORT unzOpenCurrentFile3 OF((unzFile file, */
int* method,
int* level, extern int ZEXPORT unzOpenCurrentFile3 OF((unzFile file,
int raw, int* method,
const char* password)); int* level,
/* int raw,
Same than unzOpenCurrentFile, but open for read raw the file (not uncompress) const char* password));
if raw==1 /*
*method will receive method of compression, *level will receive level of Same than unzOpenCurrentFile, but open for read raw the file (not uncompress)
compression if raw==1
note : you can set level parameter as NULL (if you did not want known level, *method will receive method of compression, *level will receive level of
but you CANNOT set method parameter as NULL compression
*/ note : you can set level parameter as NULL (if you did not want known level,
but you CANNOT set method parameter as NULL
*/
extern int ZEXPORT unzCloseCurrentFile OF((unzFile file));
/*
Close the file in zip opened with unzOpenCurrentFile extern int ZEXPORT unzCloseCurrentFile OF((unzFile file));
Return UNZ_CRCERROR if all the file was read but the CRC is not good /*
*/ Close the file in zip opened with unzOpenCurrentFile
Return UNZ_CRCERROR if all the file was read but the CRC is not good
extern int ZEXPORT unzReadCurrentFile OF((unzFile file, */
voidp buf,
unsigned len)); extern int ZEXPORT unzReadCurrentFile OF((unzFile file,
/* voidp buf,
Read bytes from the current file (opened by unzOpenCurrentFile) unsigned len));
buf contain buffer where data must be copied /*
len the size of buf. Read bytes from the current file (opened by unzOpenCurrentFile)
buf contain buffer where data must be copied
return the number of byte copied if somes bytes are copied len the size of buf.
return 0 if the end of file was reached
return <0 with error code if there is an error return the number of byte copied if somes bytes are copied
(UNZ_ERRNO for IO error, or zLib error for uncompress error) return 0 if the end of file was reached
*/ return <0 with error code if there is an error
(UNZ_ERRNO for IO error, or zLib error for uncompress error)
extern z_off_t ZEXPORT unztell OF((unzFile file)); */
/*
Give the current position in uncompressed data extern z_off_t ZEXPORT unztell OF((unzFile file));
*/ /*
Give the current position in uncompressed data
extern int ZEXPORT unzeof OF((unzFile file)); */
/*
return 1 if the end of file was reached, 0 elsewhere extern int ZEXPORT unzeof OF((unzFile file));
*/ /*
return 1 if the end of file was reached, 0 elsewhere
extern int ZEXPORT unzGetLocalExtrafield OF((unzFile file, */
voidp buf,
unsigned len)); extern int ZEXPORT unzGetLocalExtrafield OF((unzFile file,
/* voidp buf,
Read extra field from the current file (opened by unzOpenCurrentFile) unsigned len));
This is the local-header version of the extra field (sometimes, there is /*
more info in the local-header version than in the central-header) Read extra field from the current file (opened by unzOpenCurrentFile)
This is the local-header version of the extra field (sometimes, there is
if buf==NULL, it return the size of the local extra field more info in the local-header version than in the central-header)
if buf!=NULL, len is the size of the buffer, the extra header is copied in if buf==NULL, it return the size of the local extra field
buf.
the return value is the number of bytes copied in buf, or (if <0) if buf!=NULL, len is the size of the buffer, the extra header is copied in
the error code buf.
*/ the return value is the number of bytes copied in buf, or (if <0)
the error code
/***************************************************************************/ */
/* Get the current file offset */ /***************************************************************************/
extern uLong ZEXPORT unzGetOffset (unzFile file);
/* Get the current file offset */
/* Set the current file offset */ extern uLong ZEXPORT unzGetOffset (unzFile file);
extern int ZEXPORT unzSetOffset (unzFile file, uLong pos);
/* Set the current file offset */
extern int ZEXPORT unzSetOffset (unzFile file, uLong pos);
#ifdef __cplusplus
}
#endif #ifdef __cplusplus
}
#endif /* _unz_H */ #endif
#endif /* _unz_H */

File diff suppressed because it is too large Load Diff

View File

@@ -1,234 +1,235 @@
/* zip.h -- IO for compress .zip files using zlib /* zip.h -- IO for compress .zip files using zlib
Version 1.01, May 8th, 2004 Version 1.01e, February 12th, 2005
Copyright (C) 1998-2004 Gilles Vollant Copyright (C) 1998-2005 Gilles Vollant
This unzip package allow creates .ZIP file, compatible with PKZip 2.04g This unzip package allow creates .ZIP file, compatible with PKZip 2.04g
WinZip, InfoZip tools and compatible. WinZip, InfoZip tools and compatible.
Encryption and multi volume ZipFile (span) are not supported. Multi volume ZipFile (span) are not supported.
Old compressions used by old PKZip 1.x are not supported Encryption compatible with pkzip 2.04g only supported
Old compressions used by old PKZip 1.x are not supported
For uncompress .zip file, look at unzip.h
For uncompress .zip file, look at unzip.h
I WAIT FEEDBACK at mail info@winimage.com
Visit also http://www.winimage.com/zLibDll/unzip.html for evolution I WAIT FEEDBACK at mail info@winimage.com
Visit also http://www.winimage.com/zLibDll/unzip.html for evolution
Condition of use and distribution are the same than zlib :
Condition of use and distribution are the same than zlib :
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages This software is provided 'as-is', without any express or implied
arising from the use of this software. warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it Permission is granted to anyone to use this software for any purpose,
freely, subject to the following restrictions: including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software 1. The origin of this software must not be misrepresented; you must not
in a product, an acknowledgment in the product documentation would be claim that you wrote the original software. If you use this software
appreciated but is not required. in a product, an acknowledgment in the product documentation would be
2. Altered source versions must be plainly marked as such, and must not be appreciated but is not required.
misrepresented as being the original software. 2. Altered source versions must be plainly marked as such, and must not be
3. This notice may not be removed or altered from any source distribution. misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/
*/
/* for more info about .ZIP format, see
http://www.info-zip.org/pub/infozip/doc/appnote-981119-iz.zip /* for more info about .ZIP format, see
http://www.info-zip.org/pub/infozip/doc/ http://www.info-zip.org/pub/infozip/doc/appnote-981119-iz.zip
PkWare has also a specification at : http://www.info-zip.org/pub/infozip/doc/
ftp://ftp.pkware.com/probdesc.zip PkWare has also a specification at :
*/ ftp://ftp.pkware.com/probdesc.zip
*/
#ifndef _zip_H
#define _zip_H #ifndef _zip_H
#define _zip_H
#ifdef __cplusplus
extern "C" { #ifdef __cplusplus
#endif extern "C" {
#endif
#ifndef _ZLIB_H
#include "zlib.h" #ifndef _ZLIB_H
#endif #include "zlib.h"
#endif
#ifndef _ZLIBIOAPI_H
#include "ioapi.h" #ifndef _ZLIBIOAPI_H
#endif #include "ioapi.h"
#endif
#if defined(STRICTZIP) || defined(STRICTZIPUNZIP)
/* like the STRICT of WIN32, we define a pointer that cannot be converted #if defined(STRICTZIP) || defined(STRICTZIPUNZIP)
from (void*) without cast */ /* like the STRICT of WIN32, we define a pointer that cannot be converted
typedef struct TagzipFile__ { int unused; } zipFile__; from (void*) without cast */
typedef zipFile__ *zipFile; typedef struct TagzipFile__ { int unused; } zipFile__;
#else typedef zipFile__ *zipFile;
typedef voidp zipFile; #else
#endif typedef voidp zipFile;
#endif
#define ZIP_OK (0)
#define ZIP_EOF (0) #define ZIP_OK (0)
#define ZIP_ERRNO (Z_ERRNO) #define ZIP_EOF (0)
#define ZIP_PARAMERROR (-102) #define ZIP_ERRNO (Z_ERRNO)
#define ZIP_BADZIPFILE (-103) #define ZIP_PARAMERROR (-102)
#define ZIP_INTERNALERROR (-104) #define ZIP_BADZIPFILE (-103)
#define ZIP_INTERNALERROR (-104)
#ifndef DEF_MEM_LEVEL
# if MAX_MEM_LEVEL >= 8 #ifndef DEF_MEM_LEVEL
# define DEF_MEM_LEVEL 8 # if MAX_MEM_LEVEL >= 8
# else # define DEF_MEM_LEVEL 8
# define DEF_MEM_LEVEL MAX_MEM_LEVEL # else
# endif # define DEF_MEM_LEVEL MAX_MEM_LEVEL
#endif # endif
/* default memLevel */ #endif
/* default memLevel */
/* tm_zip contain date/time info */
typedef struct tm_zip_s /* tm_zip contain date/time info */
{ typedef struct tm_zip_s
uInt tm_sec; /* seconds after the minute - [0,59] */ {
uInt tm_min; /* minutes after the hour - [0,59] */ uInt tm_sec; /* seconds after the minute - [0,59] */
uInt tm_hour; /* hours since midnight - [0,23] */ uInt tm_min; /* minutes after the hour - [0,59] */
uInt tm_mday; /* day of the month - [1,31] */ uInt tm_hour; /* hours since midnight - [0,23] */
uInt tm_mon; /* months since January - [0,11] */ uInt tm_mday; /* day of the month - [1,31] */
uInt tm_year; /* years - [1980..2044] */ uInt tm_mon; /* months since January - [0,11] */
} tm_zip; uInt tm_year; /* years - [1980..2044] */
} tm_zip;
typedef struct
{ typedef struct
tm_zip tmz_date; /* date in understandable format */ {
uLong dosDate; /* if dos_date == 0, tmu_date is used */ tm_zip tmz_date; /* date in understandable format */
/* uLong flag; */ /* general purpose bit flag 2 bytes */ uLong dosDate; /* if dos_date == 0, tmu_date is used */
/* uLong flag; */ /* general purpose bit flag 2 bytes */
uLong internal_fa; /* internal file attributes 2 bytes */
uLong external_fa; /* external file attributes 4 bytes */ uLong internal_fa; /* internal file attributes 2 bytes */
} zip_fileinfo; uLong external_fa; /* external file attributes 4 bytes */
} zip_fileinfo;
typedef const char* zipcharpc;
typedef const char* zipcharpc;
#define APPEND_STATUS_CREATE (0)
#define APPEND_STATUS_CREATEAFTER (1) #define APPEND_STATUS_CREATE (0)
#define APPEND_STATUS_ADDINZIP (2) #define APPEND_STATUS_CREATEAFTER (1)
#define APPEND_STATUS_ADDINZIP (2)
extern zipFile ZEXPORT zipOpen OF((const char *pathname, int append));
/* extern zipFile ZEXPORT zipOpen OF((const char *pathname, int append));
Create a zipfile. /*
pathname contain on Windows XP a filename like "c:\\zlib\\zlib113.zip" or on Create a zipfile.
an Unix computer "zlib/zlib113.zip". pathname contain on Windows XP a filename like "c:\\zlib\\zlib113.zip" or on
if the file pathname exist and append==APPEND_STATUS_CREATEAFTER, the zip an Unix computer "zlib/zlib113.zip".
will be created at the end of the file. if the file pathname exist and append==APPEND_STATUS_CREATEAFTER, the zip
(useful if the file contain a self extractor code) will be created at the end of the file.
if the file pathname exist and append==APPEND_STATUS_ADDINZIP, we will (useful if the file contain a self extractor code)
add files in existing zip (be sure you don't add file that doesn't exist) if the file pathname exist and append==APPEND_STATUS_ADDINZIP, we will
If the zipfile cannot be opened, the return value is NULL. add files in existing zip (be sure you don't add file that doesn't exist)
Else, the return value is a zipFile Handle, usable with other function If the zipfile cannot be opened, the return value is NULL.
of this zip package. Else, the return value is a zipFile Handle, usable with other function
*/ of this zip package.
*/
/* Note : there is no delete function into a zipfile.
If you want delete file into a zipfile, you must open a zipfile, and create another /* Note : there is no delete function into a zipfile.
Of couse, you can use RAW reading and writing to copy the file you did not want delte If you want delete file into a zipfile, you must open a zipfile, and create another
*/ Of couse, you can use RAW reading and writing to copy the file you did not want delte
*/
extern zipFile ZEXPORT zipOpen2 OF((const char *pathname,
int append, extern zipFile ZEXPORT zipOpen2 OF((const char *pathname,
zipcharpc* globalcomment, int append,
zlib_filefunc_def* pzlib_filefunc_def)); zipcharpc* globalcomment,
zlib_filefunc_def* pzlib_filefunc_def));
extern int ZEXPORT zipOpenNewFileInZip OF((zipFile file,
const char* filename, extern int ZEXPORT zipOpenNewFileInZip OF((zipFile file,
const zip_fileinfo* zipfi, const char* filename,
const void* extrafield_local, const zip_fileinfo* zipfi,
uInt size_extrafield_local, const void* extrafield_local,
const void* extrafield_global, uInt size_extrafield_local,
uInt size_extrafield_global, const void* extrafield_global,
const char* comment, uInt size_extrafield_global,
int method, const char* comment,
int level)); int method,
/* int level));
Open a file in the ZIP for writing. /*
filename : the filename in zip (if NULL, '-' without quote will be used Open a file in the ZIP for writing.
*zipfi contain supplemental information filename : the filename in zip (if NULL, '-' without quote will be used
if extrafield_local!=NULL and size_extrafield_local>0, extrafield_local *zipfi contain supplemental information
contains the extrafield data the the local header if extrafield_local!=NULL and size_extrafield_local>0, extrafield_local
if extrafield_global!=NULL and size_extrafield_global>0, extrafield_global contains the extrafield data the the local header
contains the extrafield data the the local header if extrafield_global!=NULL and size_extrafield_global>0, extrafield_global
if comment != NULL, comment contain the comment string contains the extrafield data the the local header
method contain the compression method (0 for store, Z_DEFLATED for deflate) if comment != NULL, comment contain the comment string
level contain the level of compression (can be Z_DEFAULT_COMPRESSION) method contain the compression method (0 for store, Z_DEFLATED for deflate)
*/ level contain the level of compression (can be Z_DEFAULT_COMPRESSION)
*/
extern int ZEXPORT zipOpenNewFileInZip2 OF((zipFile file,
const char* filename, extern int ZEXPORT zipOpenNewFileInZip2 OF((zipFile file,
const zip_fileinfo* zipfi, const char* filename,
const void* extrafield_local, const zip_fileinfo* zipfi,
uInt size_extrafield_local, const void* extrafield_local,
const void* extrafield_global, uInt size_extrafield_local,
uInt size_extrafield_global, const void* extrafield_global,
const char* comment, uInt size_extrafield_global,
int method, const char* comment,
int level, int method,
int raw)); int level,
int raw));
/*
Same than zipOpenNewFileInZip, except if raw=1, we write raw file /*
*/ Same than zipOpenNewFileInZip, except if raw=1, we write raw file
*/
extern int ZEXPORT zipOpenNewFileInZip3 OF((zipFile file,
const char* filename, extern int ZEXPORT zipOpenNewFileInZip3 OF((zipFile file,
const zip_fileinfo* zipfi, const char* filename,
const void* extrafield_local, const zip_fileinfo* zipfi,
uInt size_extrafield_local, const void* extrafield_local,
const void* extrafield_global, uInt size_extrafield_local,
uInt size_extrafield_global, const void* extrafield_global,
const char* comment, uInt size_extrafield_global,
int method, const char* comment,
int level, int method,
int raw, int level,
int windowBits, int raw,
int memLevel, int windowBits,
int strategy, int memLevel,
const char* password, int strategy,
uLong crcForCtypting)); const char* password,
uLong crcForCtypting));
/*
Same than zipOpenNewFileInZip2, except /*
windowBits,memLevel,,strategy : see parameter strategy in deflateInit2 Same than zipOpenNewFileInZip2, except
password : crypting password (NULL for no crypting) windowBits,memLevel,,strategy : see parameter strategy in deflateInit2
crcForCtypting : crc of file to compress (needed for crypting) password : crypting password (NULL for no crypting)
*/ crcForCtypting : crc of file to compress (needed for crypting)
*/
extern int ZEXPORT zipWriteInFileInZip OF((zipFile file,
const void* buf, extern int ZEXPORT zipWriteInFileInZip OF((zipFile file,
unsigned len)); const void* buf,
/* unsigned len));
Write data in the zipfile /*
*/ Write data in the zipfile
*/
extern int ZEXPORT zipCloseFileInZip OF((zipFile file));
/* extern int ZEXPORT zipCloseFileInZip OF((zipFile file));
Close the current file in the zipfile /*
*/ Close the current file in the zipfile
*/
extern int ZEXPORT zipCloseFileInZipRaw OF((zipFile file,
uLong uncompressed_size, extern int ZEXPORT zipCloseFileInZipRaw OF((zipFile file,
uLong crc32)); uLong uncompressed_size,
/* uLong crc32));
Close the current file in the zipfile, for fiel opened with /*
parameter raw=1 in zipOpenNewFileInZip2 Close the current file in the zipfile, for fiel opened with
uncompressed_size and crc32 are value for the uncompressed size parameter raw=1 in zipOpenNewFileInZip2
*/ uncompressed_size and crc32 are value for the uncompressed size
*/
extern int ZEXPORT zipClose OF((zipFile file,
const char* global_comment)); extern int ZEXPORT zipClose OF((zipFile file,
/* const char* global_comment));
Close the zipfile /*
*/ Close the zipfile
*/
#ifdef __cplusplus
} #ifdef __cplusplus
#endif }
#endif
#endif /* _zip_H */
#endif /* _zip_H */

View File

@@ -0,0 +1,18 @@
; rdtsc64.asm
;
; unsigned _int64 myrdtsc();
;
; return the performance rdtsc value, on AMD64/Intel EM64T
;
; compile with :
; ml64.exe" /Flrdtsc64 /c /Zi rdtsc64.asm
;
.code
myrdtsc PROC
rdtsc
shl rdx,32
or rax,rdx
ret
myrdtsc ENDP
END

Binary file not shown.

View File

@@ -1,149 +1,258 @@
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <windows.h> #include <windows.h>
#include "zlib.h" #include "zlib.h"
int ReadFileMemory(const char* filename,long* plFileSize,void** pFilePtr)
{ void MyDoMinus64(LARGE_INTEGER *R,LARGE_INTEGER A,LARGE_INTEGER B)
FILE* stream; {
void* ptr; R->HighPart = A.HighPart - B.HighPart;
int retVal=1; if (A.LowPart >= B.LowPart)
stream=fopen(filename, "rb"); R->LowPart = A.LowPart - B.LowPart;
if (stream==NULL) else
return 0; {
R->LowPart = A.LowPart - B.LowPart;
fseek(stream,0,SEEK_END); R->HighPart --;
}
*plFileSize=ftell(stream); }
fseek(stream,0,SEEK_SET);
ptr=malloc((*plFileSize)+1); #ifdef _AMD64_
if (ptr==NULL) unsigned _int64 myrdtsc();
retVal=0; void BeginCountRdtsc(LARGE_INTEGER * pbeginTime64)
else {
{ // printf("rdtsc = %I64x\n",myrdtsc());
if (fread(ptr, 1, *plFileSize,stream) != (*plFileSize)) pbeginTime64->QuadPart=myrdtsc();
retVal=0; }
}
fclose(stream); LARGE_INTEGER GetResRdtsc(LARGE_INTEGER beginTime64,BOOL fComputeTimeQueryPerf)
*pFilePtr=ptr; {
return retVal; LARGE_INTEGER LIres;
} unsigned _int64 res=myrdtsc()-((unsigned _int64)(beginTime64.QuadPart));
LIres.QuadPart=res;
int main(int argc, char *argv[]) // printf("rdtsc = %I64x\n",myrdtsc());
{ return LIres;
int BlockSizeCompress=0x8000; }
int BlockSizeUncompress=0x8000; #else
int cprLevel=Z_DEFAULT_COMPRESSION ; void myGetRDTSC32(LARGE_INTEGER * pbeginTime64)
long lFileSize; {
unsigned char* FilePtr; DWORD dwEdx,dwEax;
long lBufferSizeCpr; _asm
long lBufferSizeUncpr; {
long lCompressedSize=0; rdtsc
unsigned char* CprPtr; mov dwEax,eax
unsigned char* UncprPtr; mov dwEdx,edx
long lSizeCpr,lSizeUncpr; }
DWORD dwGetTick; pbeginTime64->LowPart=dwEax;
pbeginTime64->HighPart=dwEdx;
if (argc<=1) }
{
printf("run TestZlib <File> [BlockSizeCompress] [BlockSizeUncompress] [compres. level]\n"); void BeginCountRdtsc(LARGE_INTEGER * pbeginTime64)
return 0; {
} myGetRDTSC32(pbeginTime64);
}
if (ReadFileMemory(argv[1],&lFileSize,&FilePtr)==0)
{ LARGE_INTEGER GetResRdtsc(LARGE_INTEGER beginTime64,BOOL fComputeTimeQueryPerf)
printf("error reading %s\n",argv[1]); {
return 1; LARGE_INTEGER LIres,endTime64;
} myGetRDTSC32(&endTime64);
else printf("file %s read, %u bytes\n",argv[1],lFileSize);
LIres.LowPart=LIres.HighPart=0;
if (argc>=3) MyDoMinus64(&LIres,endTime64,beginTime64);
BlockSizeCompress=atol(argv[2]); return LIres;
}
if (argc>=4) #endif
BlockSizeUncompress=atol(argv[3]);
if (argc>=5) void BeginCountPerfCounter(LARGE_INTEGER * pbeginTime64,BOOL fComputeTimeQueryPerf)
cprLevel=(int)atol(argv[4]); {
if ((!fComputeTimeQueryPerf) || (!QueryPerformanceCounter(pbeginTime64)))
lBufferSizeCpr = lFileSize + (lFileSize/0x10) + 0x200; {
lBufferSizeUncpr = lBufferSizeCpr; pbeginTime64->LowPart = GetTickCount();
pbeginTime64->HighPart = 0;
CprPtr=(unsigned char*)malloc(lBufferSizeCpr + BlockSizeCompress); }
UncprPtr=(unsigned char*)malloc(lBufferSizeUncpr + BlockSizeUncompress); }
dwGetTick=GetTickCount(); DWORD GetMsecSincePerfCounter(LARGE_INTEGER beginTime64,BOOL fComputeTimeQueryPerf)
{ {
z_stream zcpr; LARGE_INTEGER endTime64,ticksPerSecond,ticks;
int ret=Z_OK; DWORDLONG ticksShifted,tickSecShifted;
long lOrigToDo = lFileSize; DWORD dwLog=16+0;
long lOrigDone = 0; DWORD dwRet;
int step=0; if ((!fComputeTimeQueryPerf) || (!QueryPerformanceCounter(&endTime64)))
memset(&zcpr,0,sizeof(z_stream)); dwRet = (GetTickCount() - beginTime64.LowPart)*1;
deflateInit(&zcpr,cprLevel); else
{
zcpr.next_in = FilePtr; MyDoMinus64(&ticks,endTime64,beginTime64);
zcpr.next_out = CprPtr; QueryPerformanceFrequency(&ticksPerSecond);
do {
{ ticksShifted = Int64ShrlMod32(*(DWORDLONG*)&ticks,dwLog);
long all_read_before = zcpr.total_in; tickSecShifted = Int64ShrlMod32(*(DWORDLONG*)&ticksPerSecond,dwLog);
zcpr.avail_in = min(lOrigToDo,BlockSizeCompress);
zcpr.avail_out = BlockSizeCompress; }
ret=deflate(&zcpr,(zcpr.avail_in==lOrigToDo) ? Z_FINISH : Z_SYNC_FLUSH);
lOrigDone += (zcpr.total_in-all_read_before); dwRet = (DWORD)((((DWORD)ticksShifted)*1000)/(DWORD)(tickSecShifted));
lOrigToDo -= (zcpr.total_in-all_read_before); dwRet *=1;
step++; }
} while (ret==Z_OK); return dwRet;
}
lSizeCpr=zcpr.total_out;
deflateEnd(&zcpr); int ReadFileMemory(const char* filename,long* plFileSize,void** pFilePtr)
dwGetTick=GetTickCount()-dwGetTick; {
printf("total compress size = %u, in %u step\n",lSizeCpr,step); FILE* stream;
printf("time = %u msec = %f sec\n\n",dwGetTick,dwGetTick/(double)1000.); void* ptr;
} int retVal=1;
stream=fopen(filename, "rb");
dwGetTick=GetTickCount(); if (stream==NULL)
{ return 0;
z_stream zcpr;
int ret=Z_OK; fseek(stream,0,SEEK_END);
long lOrigToDo = lSizeCpr;
long lOrigDone = 0; *plFileSize=ftell(stream);
int step=0; fseek(stream,0,SEEK_SET);
memset(&zcpr,0,sizeof(z_stream)); ptr=malloc((*plFileSize)+1);
inflateInit(&zcpr); if (ptr==NULL)
retVal=0;
zcpr.next_in = CprPtr; else
zcpr.next_out = UncprPtr; {
if (fread(ptr, 1, *plFileSize,stream) != (*plFileSize))
retVal=0;
do }
{ fclose(stream);
long all_read_before = zcpr.total_in; *pFilePtr=ptr;
zcpr.avail_in = min(lOrigToDo,BlockSizeUncompress); return retVal;
zcpr.avail_out = BlockSizeUncompress; }
ret=inflate(&zcpr,Z_SYNC_FLUSH);
lOrigDone += (zcpr.total_in-all_read_before); int main(int argc, char *argv[])
lOrigToDo -= (zcpr.total_in-all_read_before); {
step++; int BlockSizeCompress=0x8000;
} while (ret==Z_OK); int BlockSizeUncompress=0x8000;
int cprLevel=Z_DEFAULT_COMPRESSION ;
lSizeUncpr=zcpr.total_out; long lFileSize;
inflateEnd(&zcpr); unsigned char* FilePtr;
dwGetTick=GetTickCount()-dwGetTick; long lBufferSizeCpr;
printf("total uncompress size = %u, in %u step\n",lSizeUncpr,step); long lBufferSizeUncpr;
printf("time = %u msec = %f sec\n\n",dwGetTick,dwGetTick/(double)1000.); long lCompressedSize=0;
} unsigned char* CprPtr;
unsigned char* UncprPtr;
if (lSizeUncpr==lFileSize) long lSizeCpr,lSizeUncpr;
{ DWORD dwGetTick,dwMsecQP;
if (memcmp(FilePtr,UncprPtr,lFileSize)==0) LARGE_INTEGER li_qp,li_rdtsc,dwResRdtsc;
printf("compare ok\n");
if (argc<=1)
} {
printf("run TestZlib <File> [BlockSizeCompress] [BlockSizeUncompress] [compres. level]\n");
return 0; return 0;
}
}
if (ReadFileMemory(argv[1],&lFileSize,&FilePtr)==0)
{
printf("error reading %s\n",argv[1]);
return 1;
}
else printf("file %s read, %u bytes\n",argv[1],lFileSize);
if (argc>=3)
BlockSizeCompress=atol(argv[2]);
if (argc>=4)
BlockSizeUncompress=atol(argv[3]);
if (argc>=5)
cprLevel=(int)atol(argv[4]);
lBufferSizeCpr = lFileSize + (lFileSize/0x10) + 0x200;
lBufferSizeUncpr = lBufferSizeCpr;
CprPtr=(unsigned char*)malloc(lBufferSizeCpr + BlockSizeCompress);
BeginCountPerfCounter(&li_qp,TRUE);
dwGetTick=GetTickCount();
BeginCountRdtsc(&li_rdtsc);
{
z_stream zcpr;
int ret=Z_OK;
long lOrigToDo = lFileSize;
long lOrigDone = 0;
int step=0;
memset(&zcpr,0,sizeof(z_stream));
deflateInit(&zcpr,cprLevel);
zcpr.next_in = FilePtr;
zcpr.next_out = CprPtr;
do
{
long all_read_before = zcpr.total_in;
zcpr.avail_in = min(lOrigToDo,BlockSizeCompress);
zcpr.avail_out = BlockSizeCompress;
ret=deflate(&zcpr,(zcpr.avail_in==lOrigToDo) ? Z_FINISH : Z_SYNC_FLUSH);
lOrigDone += (zcpr.total_in-all_read_before);
lOrigToDo -= (zcpr.total_in-all_read_before);
step++;
} while (ret==Z_OK);
lSizeCpr=zcpr.total_out;
deflateEnd(&zcpr);
dwGetTick=GetTickCount()-dwGetTick;
dwMsecQP=GetMsecSincePerfCounter(li_qp,TRUE);
dwResRdtsc=GetResRdtsc(li_rdtsc,TRUE);
printf("total compress size = %u, in %u step\n",lSizeCpr,step);
printf("time = %u msec = %f sec\n",dwGetTick,dwGetTick/(double)1000.);
printf("defcpr time QP = %u msec = %f sec\n",dwMsecQP,dwMsecQP/(double)1000.);
printf("defcpr result rdtsc = %I64x\n\n",dwResRdtsc.QuadPart);
}
CprPtr=(unsigned char*)realloc(CprPtr,lSizeCpr);
UncprPtr=(unsigned char*)malloc(lBufferSizeUncpr + BlockSizeUncompress);
BeginCountPerfCounter(&li_qp,TRUE);
dwGetTick=GetTickCount();
BeginCountRdtsc(&li_rdtsc);
{
z_stream zcpr;
int ret=Z_OK;
long lOrigToDo = lSizeCpr;
long lOrigDone = 0;
int step=0;
memset(&zcpr,0,sizeof(z_stream));
inflateInit(&zcpr);
zcpr.next_in = CprPtr;
zcpr.next_out = UncprPtr;
do
{
long all_read_before = zcpr.total_in;
zcpr.avail_in = min(lOrigToDo,BlockSizeUncompress);
zcpr.avail_out = BlockSizeUncompress;
ret=inflate(&zcpr,Z_SYNC_FLUSH);
lOrigDone += (zcpr.total_in-all_read_before);
lOrigToDo -= (zcpr.total_in-all_read_before);
step++;
} while (ret==Z_OK);
lSizeUncpr=zcpr.total_out;
inflateEnd(&zcpr);
dwGetTick=GetTickCount()-dwGetTick;
dwMsecQP=GetMsecSincePerfCounter(li_qp,TRUE);
dwResRdtsc=GetResRdtsc(li_rdtsc,TRUE);
printf("total uncompress size = %u, in %u step\n",lSizeUncpr,step);
printf("time = %u msec = %f sec\n",dwGetTick,dwGetTick/(double)1000.);
printf("uncpr time QP = %u msec = %f sec\n",dwMsecQP,dwMsecQP/(double)1000.);
printf("uncpr result rdtsc = %I64x\n\n",dwResRdtsc.QuadPart);
}
if (lSizeUncpr==lFileSize)
{
if (memcmp(FilePtr,UncprPtr,lFileSize)==0)
printf("compare ok\n");
}
return 0;
}

View File

@@ -0,0 +1,10 @@
To build testzLib with Visual Studio 2005:
copy to a directory file from :
- root of zLib tree
- contrib/testzlib
- contrib/masmx86
- contrib/masmx64
- contrib/vstudio/vc7
and open testzlib8.sln

View File

@@ -0,0 +1,32 @@

Microsoft Visual Studio Solution File, Format Version 9.00
# Visual Studio 2005
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "testzlib8", "testzlib8.vcproj", "{AA6666AA-E09F-4135-9C0C-4FE50C3C654B}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32
Debug|Win64 (AMD64) = Debug|Win64 (AMD64)
Release|Win32 = Release|Win32
Release|Win64 (AMD64) = Release|Win64 (AMD64)
ReleaseAsm|Win32 = ReleaseAsm|Win32
ReleaseAsm|Win64 (AMD64) = ReleaseAsm|Win64 (AMD64)
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Debug|Win32.ActiveCfg = Debug|Win32
{AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Debug|Win32.Build.0 = Debug|Win32
{AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Debug|Win64 (AMD64).ActiveCfg = Debug|Win64 (AMD64)
{AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Debug|Win64 (AMD64).Build.0 = Debug|Win64 (AMD64)
{AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Release|Win32.ActiveCfg = Release|Win32
{AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Release|Win32.Build.0 = Release|Win32
{AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Release|Win64 (AMD64).ActiveCfg = Release|Win64 (AMD64)
{AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.Release|Win64 (AMD64).Build.0 = Release|Win64 (AMD64)
{AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.ReleaseAsm|Win32.ActiveCfg = ReleaseAsm|Win32
{AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.ReleaseAsm|Win32.Build.0 = ReleaseAsm|Win32
{AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.ReleaseAsm|Win64 (AMD64).ActiveCfg = ReleaseAsm|Win64 (AMD64)
{AA6666AA-E09F-4135-9C0C-4FE50C3C654B}.ReleaseAsm|Win64 (AMD64).Build.0 = ReleaseAsm|Win64 (AMD64)
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal

View File

@@ -0,0 +1,638 @@
<?xml version="1.0" encoding="Windows-1252"?>
<VisualStudioProject
ProjectType="Visual C++"
Version="8,00"
Name="testzlib8"
ProjectGUID="{AA6666AA-E09F-4135-9C0C-4FE50C3C654B}"
Keyword="Win32Proj"
>
<Platforms>
<Platform
Name="Win32"
/>
<Platform
Name="Win64 (AMD64)"
/>
</Platforms>
<ToolFiles>
<DefaultToolFile
FileName="masm.tool"
/>
</ToolFiles>
<Configurations>
<Configuration
Name="Debug|Win32"
OutputDirectory="x86\$(ConfigurationName)"
IntermediateDirectory="x86\$(ConfigurationName)"
ConfigurationType="1"
CharacterSet="2"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="MASM"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="0"
PreprocessorDefinitions="ASMV;ASMINF;WIN32;ZLIB_WINAPI;_DEBUG;_CONSOLE;_CRT_SECURE_NO_DEPRECATE"
MinimalRebuild="TRUE"
BasicRuntimeChecks="3"
RuntimeLibrary="1"
UsePrecompiledHeader="0"
AssemblerOutput="4"
WarningLevel="3"
Detect64BitPortabilityProblems="TRUE"
DebugInformationFormat="4"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="gvmat32.obj inffas32.obj"
OutputFile="$(OutDir)/testzlib.exe"
LinkIncremental="2"
GenerateDebugInformation="TRUE"
ProgramDatabaseFile="$(OutDir)/testzlib.pdb"
SubSystem="1"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCWebDeploymentTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Debug|Win64 (AMD64)"
OutputDirectory="amd64\$(ConfigurationName)"
IntermediateDirectory="amd64\$(ConfigurationName)"
ConfigurationType="1"
CharacterSet="2"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="MASM"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
TargetEnvironment="3"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="0"
PreprocessorDefinitions="ASMV;ASMINF;WIN32;ZLIB_WINAPI;_DEBUG;_CONSOLE;_CRT_SECURE_NO_DEPRECATE"
MinimalRebuild="TRUE"
BasicRuntimeChecks="3"
RuntimeLibrary="1"
UsePrecompiledHeader="0"
AssemblerOutput="4"
WarningLevel="3"
Detect64BitPortabilityProblems="TRUE"
DebugInformationFormat="3"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
CommandLine=""
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="gvmat64.obj inffasx64.obj rdtsc64.obj"
OutputFile="$(OutDir)/testzlib.exe"
LinkIncremental="2"
GenerateDebugInformation="TRUE"
ProgramDatabaseFile="$(OutDir)/testzlib.pdb"
SubSystem="1"
TargetMachine="17"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCWebDeploymentTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Release|Win32"
OutputDirectory="x86\$(ConfigurationName)"
IntermediateDirectory="x86\$(ConfigurationName)"
ConfigurationType="1"
CharacterSet="2"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="MASM"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="2"
InlineFunctionExpansion="1"
OmitFramePointers="TRUE"
PreprocessorDefinitions="WIN32;ZLIB_WINAPI;NDEBUG;_CONSOLE;_CRT_SECURE_NO_DEPRECATE"
StringPooling="TRUE"
RuntimeLibrary="0"
EnableFunctionLevelLinking="TRUE"
UsePrecompiledHeader="0"
WarningLevel="3"
Detect64BitPortabilityProblems="TRUE"
DebugInformationFormat="3"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
OutputFile="$(OutDir)/testzlib.exe"
LinkIncremental="1"
GenerateDebugInformation="TRUE"
SubSystem="1"
OptimizeReferences="2"
EnableCOMDATFolding="2"
OptimizeForWindows98="1"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCWebDeploymentTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="Release|Win64 (AMD64)"
OutputDirectory="amd64\$(ConfigurationName)"
IntermediateDirectory="amd64\$(ConfigurationName)"
ConfigurationType="1"
CharacterSet="2"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="MASM"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
TargetEnvironment="3"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="2"
InlineFunctionExpansion="1"
OmitFramePointers="TRUE"
PreprocessorDefinitions="WIN32;ZLIB_WINAPI;NDEBUG;_CONSOLE;_CRT_SECURE_NO_DEPRECATE"
StringPooling="TRUE"
RuntimeLibrary="0"
EnableFunctionLevelLinking="TRUE"
UsePrecompiledHeader="0"
WarningLevel="3"
Detect64BitPortabilityProblems="TRUE"
DebugInformationFormat="3"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="rdtsc64.obj"
OutputFile="$(OutDir)/testzlib.exe"
LinkIncremental="1"
GenerateDebugInformation="TRUE"
SubSystem="1"
OptimizeReferences="2"
EnableCOMDATFolding="2"
OptimizeForWindows98="1"
TargetMachine="17"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCWebDeploymentTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="ReleaseAsm|Win32"
OutputDirectory="x86\$(ConfigurationName)"
IntermediateDirectory="x86\$(ConfigurationName)"
ConfigurationType="1"
CharacterSet="2"
>
<Tool
Name="VCPreBuildEventTool"
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="MASM"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="2"
InlineFunctionExpansion="1"
OmitFramePointers="TRUE"
PreprocessorDefinitions="ASMV;ASMINF;WIN32;ZLIB_WINAPI;NDEBUG;_CONSOLE;_CRT_SECURE_NO_DEPRECATE"
StringPooling="TRUE"
RuntimeLibrary="0"
EnableFunctionLevelLinking="TRUE"
UsePrecompiledHeader="0"
WarningLevel="3"
Detect64BitPortabilityProblems="TRUE"
DebugInformationFormat="3"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="gvmat32.obj inffas32.obj"
OutputFile="$(OutDir)/testzlib.exe"
LinkIncremental="1"
GenerateDebugInformation="TRUE"
SubSystem="1"
OptimizeReferences="2"
EnableCOMDATFolding="2"
OptimizeForWindows98="1"
TargetMachine="1"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCAppVerifierTool"
/>
<Tool
Name="VCWebDeploymentTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
<Configuration
Name="ReleaseAsm|Win64 (AMD64)"
OutputDirectory="amd64\$(ConfigurationName)"
IntermediateDirectory="amd64\$(ConfigurationName)"
ConfigurationType="1"
CharacterSet="2"
>
<Tool
Name="VCPreBuildEventTool"
CommandLine=""
/>
<Tool
Name="VCCustomBuildTool"
/>
<Tool
Name="MASM"
/>
<Tool
Name="VCXMLDataGeneratorTool"
/>
<Tool
Name="VCWebServiceProxyGeneratorTool"
/>
<Tool
Name="VCMIDLTool"
TargetEnvironment="3"
/>
<Tool
Name="VCCLCompilerTool"
Optimization="2"
InlineFunctionExpansion="1"
OmitFramePointers="TRUE"
PreprocessorDefinitions="ASMV;ASMINF;WIN32;ZLIB_WINAPI;NDEBUG;_CONSOLE;_CRT_SECURE_NO_DEPRECATE"
StringPooling="TRUE"
RuntimeLibrary="0"
EnableFunctionLevelLinking="TRUE"
UsePrecompiledHeader="0"
AssemblerOutput="4"
WarningLevel="3"
Detect64BitPortabilityProblems="TRUE"
DebugInformationFormat="3"
/>
<Tool
Name="VCManagedResourceCompilerTool"
/>
<Tool
Name="VCResourceCompilerTool"
/>
<Tool
Name="VCPreLinkEventTool"
CommandLine=""
/>
<Tool
Name="VCLinkerTool"
AdditionalDependencies="gvmat64.obj inffasx64.obj rdtsc64.obj"
OutputFile="$(OutDir)/testzlib.exe"
LinkIncremental="1"
GenerateDebugInformation="TRUE"
SubSystem="1"
OptimizeReferences="2"
EnableCOMDATFolding="2"
OptimizeForWindows98="1"
TargetMachine="17"
/>
<Tool
Name="VCALinkTool"
/>
<Tool
Name="VCManifestTool"
/>
<Tool
Name="VCXDCMakeTool"
/>
<Tool
Name="VCBscMakeTool"
/>
<Tool
Name="VCWebDeploymentTool"
/>
<Tool
Name="VCPostBuildEventTool"
/>
</Configuration>
</Configurations>
<References>
</References>
<Files>
<Filter
Name="Source Files"
Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm"
>
<File
RelativePath=".\adler32.c"
>
</File>
<File
RelativePath=".\compress.c"
>
</File>
<File
RelativePath=".\crc32.c"
>
</File>
<File
RelativePath=".\deflate.c"
>
</File>
<File
RelativePath=".\gvmat32c.c"
>
<FileConfiguration
Name="Debug|Win64 (AMD64)"
ExcludedFromBuild="TRUE"
>
<Tool
Name="VCCLCompilerTool"
/>
</FileConfiguration>
<FileConfiguration
Name="Release|Win64 (AMD64)"
ExcludedFromBuild="TRUE"
>
<Tool
Name="VCCLCompilerTool"
/>
</FileConfiguration>
<FileConfiguration
Name="ReleaseAsm|Win32"
>
<Tool
Name="VCCLCompilerTool"
/>
</FileConfiguration>
<FileConfiguration
Name="ReleaseAsm|Win64 (AMD64)"
ExcludedFromBuild="TRUE"
>
<Tool
Name="VCCLCompilerTool"
/>
</FileConfiguration>
</File>
<File
RelativePath=".\infback.c"
>
</File>
<File
RelativePath=".\inffas8664.c"
>
<FileConfiguration
Name="Debug|Win32"
ExcludedFromBuild="TRUE"
>
<Tool
Name="VCCLCompilerTool"
/>
</FileConfiguration>
<FileConfiguration
Name="Release|Win32"
>
<Tool
Name="VCCLCompilerTool"
/>
</FileConfiguration>
<FileConfiguration
Name="ReleaseAsm|Win32"
ExcludedFromBuild="TRUE"
>
<Tool
Name="VCCLCompilerTool"
/>
</FileConfiguration>
</File>
<File
RelativePath=".\inffast.c"
>
</File>
<File
RelativePath=".\inflate.c"
>
</File>
<File
RelativePath=".\inftrees.c"
>
</File>
<File
RelativePath="testzlib.c"
>
</File>
<File
RelativePath=".\trees.c"
>
</File>
<File
RelativePath=".\uncompr.c"
>
</File>
<File
RelativePath=".\zutil.c"
>
</File>
</Filter>
<Filter
Name="Header Files"
Filter="h;hpp;hxx;hm;inl;inc"
>
</Filter>
<Filter
Name="Resource Files"
Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
>
</Filter>
</Files>
<Globals>
</Globals>
</VisualStudioProject>

View File

@@ -1,4 +1,4 @@
Building instructions for the DLL versions of Zlib 1.21 Building instructions for the DLL versions of Zlib 1.2.x
======================================================= =======================================================
This directory contains projects that build zlib and minizip using This directory contains projects that build zlib and minizip using

Binary file not shown.

Binary file not shown.

View File

@@ -2,8 +2,8 @@
#define IDR_VERSION1 1 #define IDR_VERSION1 1
IDR_VERSION1 VERSIONINFO MOVEABLE IMPURE LOADONCALL DISCARDABLE IDR_VERSION1 VERSIONINFO MOVEABLE IMPURE LOADONCALL DISCARDABLE
FILEVERSION 1,2,2,1 FILEVERSION 1,2,2,3
PRODUCTVERSION 1,2,2,1 PRODUCTVERSION 1,2,2,3
FILEFLAGSMASK VS_FFI_FILEFLAGSMASK FILEFLAGSMASK VS_FFI_FILEFLAGSMASK
FILEFLAGS 0 FILEFLAGS 0
FILEOS VOS_DOS_WINDOWS32 FILEOS VOS_DOS_WINDOWS32
@@ -17,7 +17,7 @@ BEGIN
BEGIN BEGIN
VALUE "FileDescription", "zlib data compression library\0" VALUE "FileDescription", "zlib data compression library\0"
VALUE "FileVersion", "1.2.2.1\0" VALUE "FileVersion", "1.2.2.3\0"
VALUE "InternalName", "zlib\0" VALUE "InternalName", "zlib\0"
VALUE "OriginalFilename", "zlib.dll\0" VALUE "OriginalFilename", "zlib.dll\0"
VALUE "ProductName", "ZLib.DLL\0" VALUE "ProductName", "ZLib.DLL\0"

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-2004 Mark Adler * Copyright (C) 1995-2005 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
@@ -273,7 +273,7 @@ local unsigned long crc32_little(crc, buf, len)
len--; len--;
} }
buf4 = (const u4 FAR *)buf; buf4 = (const u4 FAR *)(const void FAR *)buf;
while (len >= 32) { while (len >= 32) {
DOLIT32; DOLIT32;
len -= 32; len -= 32;
@@ -313,7 +313,7 @@ local unsigned long crc32_big(crc, buf, len)
len--; len--;
} }
buf4 = (const u4 FAR *)buf; buf4 = (const u4 FAR *)(const void FAR *)buf;
buf4--; buf4--;
while (len >= 32) { while (len >= 32) {
DOBIG32; DOBIG32;
@@ -369,7 +369,7 @@ local void gf2_matrix_square(square, mat)
uLong ZEXPORT crc32_combine(crc1, crc2, len2) uLong ZEXPORT crc32_combine(crc1, crc2, len2)
uLong crc1; uLong crc1;
uLong crc2; uLong crc2;
uLong len2; z_off_t len2;
{ {
int n; int n;
unsigned long row; unsigned long row;

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-2004 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
*/ */
@@ -52,7 +52,7 @@
#include "deflate.h" #include "deflate.h"
const char deflate_copyright[] = const char deflate_copyright[] =
" deflate 1.2.2.1 Copyright 1995-2004 Jean-loup Gailly "; " deflate 1.2.2.3 Copyright 1995-2005 Jean-loup Gailly ";
/* /*
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
@@ -264,7 +264,7 @@ int ZEXPORT deflateInit2_(strm, level, method, windowBits, memLevel, strategy,
#endif #endif
if (memLevel < 1 || memLevel > MAX_MEM_LEVEL || method != Z_DEFLATED || if (memLevel < 1 || memLevel > MAX_MEM_LEVEL || method != Z_DEFLATED ||
windowBits < 8 || windowBits > 15 || level < 0 || level > 9 || windowBits < 8 || windowBits > 15 || level < 0 || level > 9 ||
strategy < 0 || strategy > Z_RLE) { strategy < 0 || strategy > Z_FIXED) {
return Z_STREAM_ERROR; return Z_STREAM_ERROR;
} }
if (windowBits == 8) windowBits = 9; /* until 256-byte window bug fixed */ if (windowBits == 8) windowBits = 9; /* until 256-byte window bug fixed */
@@ -334,9 +334,7 @@ int ZEXPORT deflateSetDictionary (strm, dictionary, dictLength)
if (length < MIN_MATCH) return Z_OK; if (length < MIN_MATCH) return Z_OK;
if (length > MAX_DIST(s)) { if (length > MAX_DIST(s)) {
length = MAX_DIST(s); length = MAX_DIST(s);
#ifndef USE_DICT_HEAD
dictionary += dictLength - length; /* use the tail of the dictionary */ dictionary += dictLength - length; /* use the tail of the dictionary */
#endif
} }
zmemcpy(s->window, dictionary, length); zmemcpy(s->window, dictionary, length);
s->strstart = length; s->strstart = length;
@@ -432,7 +430,7 @@ int ZEXPORT deflateParams(strm, level, strategy)
#else #else
if (level == Z_DEFAULT_COMPRESSION) level = 6; if (level == Z_DEFAULT_COMPRESSION) level = 6;
#endif #endif
if (level < 0 || level > 9 || strategy < 0 || strategy > Z_RLE) { if (level < 0 || level > 9 || strategy < 0 || strategy > Z_FIXED) {
return Z_STREAM_ERROR; return Z_STREAM_ERROR;
} }
func = configuration_table[s->level].func; func = configuration_table[s->level].func;
@@ -452,6 +450,25 @@ int ZEXPORT deflateParams(strm, level, strategy)
return err; return err;
} }
/* ========================================================================= */
int ZEXPORT deflateTune(strm, good_length, max_lazy, nice_length, max_chain)
z_streamp strm;
int good_length;
int max_lazy;
int nice_length;
int max_chain;
{
deflate_state *s;
if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR;
s = strm->state;
s->good_match = good_length;
s->max_lazy_match = max_lazy;
s->nice_match = nice_length;
s->max_chain_length = max_chain;
return Z_OK;
}
/* ========================================================================= /* =========================================================================
* For the default windowBits of 15 and memLevel of 8, this function returns * For the default windowBits of 15 and memLevel of 8, this function returns
* a close to exact, as well as small, upper bound on the compressed size. * a close to exact, as well as small, upper bound on the compressed size.
@@ -573,7 +590,7 @@ int ZEXPORT deflate (strm, flush)
put_byte(s, s->level == 9 ? 2 : put_byte(s, s->level == 9 ? 2 :
(s->strategy >= Z_HUFFMAN_ONLY || s->level < 2 ? (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2 ?
4 : 0)); 4 : 0));
put_byte(s, 255); put_byte(s, OS_CODE);
s->status = BUSY_STATE; s->status = BUSY_STATE;
} }
else { else {
@@ -892,12 +909,12 @@ int ZEXPORT deflateCopy (dest, source)
ss = source->state; ss = source->state;
*dest = *source; zmemcpy(dest, source, sizeof(z_stream));
ds = (deflate_state *) ZALLOC(dest, 1, sizeof(deflate_state)); ds = (deflate_state *) ZALLOC(dest, 1, sizeof(deflate_state));
if (ds == Z_NULL) return Z_MEM_ERROR; if (ds == Z_NULL) return Z_MEM_ERROR;
dest->state = (struct internal_state FAR *) ds; dest->state = (struct internal_state FAR *) ds;
*ds = *ss; zmemcpy(ds, ss, sizeof(deflate_state));
ds->strm = dest; ds->strm = dest;
ds->window = (Bytef *) ZALLOC(dest, ds->w_size, 2*sizeof(Byte)); ds->window = (Bytef *) ZALLOC(dest, ds->w_size, 2*sizeof(Byte));
@@ -986,9 +1003,11 @@ local void lm_init (s)
s->match_length = s->prev_length = MIN_MATCH-1; s->match_length = s->prev_length = MIN_MATCH-1;
s->match_available = 0; s->match_available = 0;
s->ins_h = 0; s->ins_h = 0;
#ifndef FASTEST
#ifdef ASMV #ifdef ASMV
match_init(); /* initialize the asm code */ match_init(); /* initialize the asm code */
#endif #endif
#endif
} }
#ifndef FASTEST #ifndef FASTEST
@@ -1057,7 +1076,12 @@ local uInt longest_match(s, cur_match)
match = s->window + cur_match; match = s->window + cur_match;
/* Skip to next match if the match length cannot increase /* Skip to next match if the match length cannot increase
* or if the match length is less than 2: * or if the match length is less than 2. Note that the checks below
* for insufficient lookahead only occur occasionally for performance
* reasons. Therefore uninitialized memory will be accessed, and
* conditional jumps will be made that depend on those values.
* However the length of the match is limited to the lookahead, so
* the output of deflate is not affected by the uninitialized values.
*/ */
#if (defined(UNALIGNED_OK) && MAX_MATCH == 258) #if (defined(UNALIGNED_OK) && MAX_MATCH == 258)
/* This code assumes sizeof(unsigned short) == 2. Do not use /* This code assumes sizeof(unsigned short) == 2. Do not use
@@ -1457,12 +1481,12 @@ local block_state deflate_fast(s, flush)
* 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 #ifdef FASTEST
if ((s->strategy < Z_HUFFMAN_ONLY) || if ((s->strategy != Z_HUFFMAN_ONLY && s->strategy != Z_RLE) ||
(s->strategy == Z_RLE && s->strstart - hash_head == 1)) { (s->strategy == Z_RLE && s->strstart - hash_head == 1)) {
s->match_length = longest_match_fast (s, hash_head); s->match_length = longest_match_fast (s, hash_head);
} }
#else #else
if (s->strategy < Z_HUFFMAN_ONLY) { 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) { } else if (s->strategy == Z_RLE && s->strstart - hash_head == 1) {
s->match_length = longest_match_fast (s, hash_head); s->match_length = longest_match_fast (s, hash_head);
@@ -1566,7 +1590,7 @@ local block_state deflate_slow(s, 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) { 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) { } else if (s->strategy == Z_RLE && s->strstart - hash_head == 1) {
s->match_length = longest_match_fast (s, hash_head); s->match_length = longest_match_fast (s, hash_head);

37
examples/README.examples Normal file
View File

@@ -0,0 +1,37 @@
This directory contains examples of the use of zlib.
fitblk.c
compress just enough input to nearly fill a requested output size
- zlib isn't designed to do this, but fitblk does it anyway
gun.c
uncompress a gzip file
- illustrates the use of inflateBack() for high speed file-to-file
decompression using call-back functions
- is approximately twice as fast as gzip -d
- also provides Unix uncompress functionality, again twice as fast
gzappend.c
append to a gzip file
- illustrates the use of the Z_BLOCK flush parameter for inflate()
- illustrates the use of deflatePrime() to start at any bit
gzjoin.c
join gzip files without recalculating the crc or recompressing
- illustrates the use of the Z_BLOCK flush parameter for inflate()
- illustrates the use of crc32_combine()
gzlog.c
gzlog.h
efficiently maintain a message log file in gzip format
- illustrates use of raw deflate and Z_SYNC_FLUSH
- illustrates use of gzip header extra field
zlib_how.html
painfully comprehensive description of zpipe.c (see below)
- describes in excruciating detail the use of deflate() and inflate()
zpipe.c
reads and writes zlib streams from stdin to stdout
- illustrates the proper use of deflate() and inflate()
- deeply commented in zlib_how.html (see above)

235
examples/fitblk.c Normal file
View File

@@ -0,0 +1,235 @@
/* fitblk.c: example of fitting compressed output to a specified size
Not copyrighted -- provided to the public domain
Version 1.1 25 November 2004 Mark Adler */
/* Version history:
1.0 24 Nov 2004 First version
1.1 25 Nov 2004 Change deflateInit2() to deflateInit()
Use fixed-size, stack-allocated raw buffers
Simplify code moving compression to subroutines
Use assert() for internal errors
Add detailed description of approach
*/
/* Approach to just fitting a requested compressed size:
fitblk performs three compression passes on a portion of the input
data in order to determine how much of that input will compress to
nearly the requested output block size. The first pass generates
enough deflate blocks to produce output to fill the requested
output size plus a specfied excess amount (see the EXCESS define
below). The last deflate block may go quite a bit past that, but
is discarded. The second pass decompresses and recompresses just
the compressed data that fit in the requested plus excess sized
buffer. The deflate process is terminated after that amount of
input, which is less than the amount consumed on the first pass.
The last deflate block of the result will be of a comparable size
to the final product, so that the header for that deflate block and
the compression ratio for that block will be about the same as in
the final product. The third compression pass decompresses the
result of the second step, but only the compressed data up to the
requested size minus an amount to allow the compressed stream to
complete (see the MARGIN define below). That will result in a
final compressed stream whose length is less than or equal to the
requested size. Assuming sufficient input and a requested size
greater than a few hundred bytes, the shortfall will typically be
less than ten bytes.
If the input is short enough that the first compression completes
before filling the requested output size, then that compressed
stream is return with no recompression.
EXCESS is chosen to be just greater than the shortfall seen in a
two pass approach similar to the above. That shortfall is due to
the last deflate block compressing more efficiently with a smaller
header on the second pass. EXCESS is set to be large enough so
that there is enough uncompressed data for the second pass to fill
out the requested size, and small enough so that the final deflate
block of the second pass will be close in size to the final deflate
block of the third and final pass. MARGIN is chosen to be just
large enough to assure that the final compression has enough room
to complete in all cases.
*/
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include "zlib.h"
#define local static
/* print nastygram and leave */
local void quit(char *why)
{
fprintf(stderr, "fitblk abort: %s\n", why);
exit(1);
}
#define RAWLEN 4096 /* intermediate uncompressed buffer size */
/* compress from file to def until provided buffer is full or end of
input reached; return last deflate() return value, or Z_ERRNO if
there was read error on the file */
local int partcompress(FILE *in, z_streamp def)
{
int ret, flush;
char raw[RAWLEN];
flush = Z_NO_FLUSH;
do {
def->avail_in = fread(raw, 1, RAWLEN, in);
if (ferror(in))
return Z_ERRNO;
def->next_in = raw;
if (feof(in))
flush = Z_FINISH;
ret = deflate(def, flush);
assert(ret != Z_STREAM_ERROR);
} while (def->avail_out != 0 && flush == Z_NO_FLUSH);
return ret;
}
/* recompress from inf's input to def's output; the input for inf and
the output for def are set in those structures before calling;
return last deflate() return value, or Z_MEM_ERROR if inflate()
was not able to allocate enough memory when it needed to */
local int recompress(z_streamp inf, z_streamp def)
{
int ret, flush;
char raw[RAWLEN];
flush = Z_NO_FLUSH;
do {
/* decompress */
inf->avail_out = RAWLEN;
inf->next_out = raw;
ret = inflate(inf, Z_NO_FLUSH);
assert(ret != Z_STREAM_ERROR && ret != Z_DATA_ERROR &&
ret != Z_NEED_DICT);
if (ret == Z_MEM_ERROR)
return ret;
/* compress what was decompresed until done or no room */
def->avail_in = RAWLEN - inf->avail_out;
def->next_in = raw;
if (inf->avail_out != 0)
flush = Z_FINISH;
ret = deflate(def, flush);
assert(ret != Z_STREAM_ERROR);
} while (ret != Z_STREAM_END && def->avail_out != 0);
return ret;
}
#define EXCESS 256 /* empirically determined stream overage */
#define MARGIN 8 /* amount to back off for completion */
/* compress from stdin to fixed-size block on stdout */
int main(int argc, char **argv)
{
int ret; /* return code */
unsigned size; /* requested fixed output block size */
unsigned have; /* bytes written by deflate() call */
char *blk; /* intermediate and final stream */
char *tmp; /* close to desired size stream */
z_stream def, inf; /* zlib deflate and inflate states */
/* get requested output size */
if (argc != 2)
quit("need one argument: size of output block");
ret = strtol(argv[1], argv + 1, 10);
if (argv[1][0] != 0)
quit("argument must be a number");
if (ret < 8) /* 8 is minimum zlib stream size */
quit("need positive size of 8 or greater");
size = (unsigned)ret;
/* allocate memory for buffers and compression engine */
blk = malloc(size + EXCESS);
def.zalloc = Z_NULL;
def.zfree = Z_NULL;
def.opaque = Z_NULL;
ret = deflateInit(&def, Z_DEFAULT_COMPRESSION);
if (ret != Z_OK || blk == NULL)
quit("out of memory");
/* compress from stdin until output full, or no more input */
def.avail_out = size + EXCESS;
def.next_out = blk;
ret = partcompress(stdin, &def);
if (ret == Z_ERRNO)
quit("error reading input");
/* if it all fit, then size was undersubscribed -- done! */
if (ret == Z_STREAM_END && def.avail_out >= EXCESS) {
/* write block to stdout */
have = size + EXCESS - def.avail_out;
ret = fwrite(blk, 1, have, stdout);
if (ret != have || ferror(stdout))
quit("error writing output");
/* clean up and print results to stderr */
ret = deflateEnd(&def);
assert(ret != Z_STREAM_ERROR);
free(blk);
fprintf(stderr,
"%u bytes unused out of %u requested (all input)\n",
size - have, size);
return 0;
}
/* it didn't all fit -- set up for recompression */
inf.zalloc = Z_NULL;
inf.zfree = Z_NULL;
inf.opaque = Z_NULL;
inf.avail_in = 0;
inf.next_in = Z_NULL;
ret = inflateInit(&inf);
tmp = malloc(size + EXCESS);
if (ret != Z_OK || tmp == NULL)
quit("out of memory");
ret = deflateReset(&def);
assert(ret != Z_STREAM_ERROR);
/* do first recompression close to the right amount */
inf.avail_in = size + EXCESS;
inf.next_in = blk;
def.avail_out = size + EXCESS;
def.next_out = tmp;
ret = recompress(&inf, &def);
if (ret == Z_MEM_ERROR)
quit("out of memory");
/* set up for next reocmpression */
ret = inflateReset(&inf);
assert(ret != Z_STREAM_ERROR);
ret = deflateReset(&def);
assert(ret != Z_STREAM_ERROR);
/* do second and final recompression (third compression) */
inf.avail_in = size - MARGIN; /* assure stream will complete */
inf.next_in = tmp;
def.avail_out = size;
def.next_out = blk;
ret = recompress(&inf, &def);
if (ret == Z_MEM_ERROR)
quit("out of memory");
assert(ret == Z_STREAM_END); /* otherwise MARGIN too small */
/* done -- write block to stdout */
have = size - def.avail_out;
ret = fwrite(blk, 1, have, stdout);
if (ret != have || ferror(stdout))
quit("error writing output");
/* clean up and print results to stderr */
free(tmp);
ret = inflateEnd(&inf);
assert(ret != Z_STREAM_ERROR);
ret = deflateEnd(&def);
assert(ret != Z_STREAM_ERROR);
free(blk);
fprintf(stderr,
"%u bytes unused out of %u requested (%lu input)\n",
size - have, size, def.total_in);
return 0;
}

692
examples/gun.c Normal file
View File

@@ -0,0 +1,692 @@
/* gun.c -- simple gunzip to give an example of the use of inflateBack()
* Copyright (C) 2003, 2005 Mark Adler
* For conditions of distribution and use, see copyright notice in zlib.h
Version 1.2 20 March 2005 Mark Adler */
/* Version history:
1.0 16 Feb 2003 First version for testing of inflateBack()
1.1 21 Feb 2005 Decompress concatenated gzip streams
Remove use of "this" variable (C++ keyword)
Fix return value for in()
Improve allocation failure checking
Add typecasting for void * structures
Add -h option for command version and usage
Add a bunch of comments
1.2 20 Mar 2005 Add Unix compress (LZW) decompression
Copy file attributes from input file to output file
*/
/*
gun [ -t ] [ name ... ]
decompresses the data in the named gzip files. If no arguments are given,
gun will decompress from stdin to stdout. The names must end in .gz, -gz,
.z, -z, _z, or .Z. The uncompressed data will be written to a file name
with the suffix stripped. On success, the original file is deleted. On
failure, the output file is deleted. For most failures, the command will
continue to process the remaining names on the command line. A memory
allocation failure will abort the command. If -t is specified, then the
listed files or stdin will be tested as gzip files for integrity (without
checking for a proper suffix), no output will be written, and no files
will be deleted.
Like gzip, gun allows concatenated gzip streams and will decompress them,
writing all of the uncompressed data to the output. Unlike gzip, gun allows
an empty file on input, and will produce no error writing an empty output
file.
gun will also decompress files made by Unix compress, which uses LZW
compression. These files are automatically detected by virtue of their
magic header bytes. Since the end of Unix compress stream is marked by the
end-of-file, they cannot be concantenated. If a Unix compress stream is
encountered in an input file, it is the last stream in that file.
Like gunzip and uncompress, the file attributes of the orignal compressed
file are maintained in the final uncompressed file, to the extent that the
user permissions allow it.
On my Mac OS X PowerPC G4, gun is almost twice as fast as gunzip (version
1.2.4) is on the same file, when gun is linked with zlib 1.2.2. Also the
LZW decompression provided by gun is about twice as fast as the standard
Unix uncompress command.
*/
/* external functions and related types and constants */
#include <stdio.h> /* fprintf() */
#include <stdlib.h> /* malloc(), free() */
#include <string.h> /* strerror(), strcmp(), strlen(), memcpy() */
#include <errno.h> /* errno */
#include <fcntl.h> /* open() */
#include <unistd.h> /* read(), write(), close(), chown(), unlink() */
#include <sys/types.h>
#include <sys/stat.h> /* stat(), chmod() */
#include <utime.h> /* utime() */
#include "zlib.h" /* inflateBackInit(), inflateBack(), */
/* inflateBackEnd(), crc32() */
/* function declaration */
#define local static
/* buffer constants */
#define SIZE 32768U /* input and output buffer sizes */
#define PIECE 16384 /* limits i/o chunks for 16-bit int case */
/* structure for infback() to pass to input function in() -- it maintains the
input file and a buffer of size SIZE */
struct ind {
int infile;
unsigned char *inbuf;
};
/* Load input buffer, assumed to be empty, and return bytes loaded and a
pointer to them. read() is called until the buffer is full, or until it
returns end-of-file or error. Return 0 on error. */
local unsigned in(void *in_desc, unsigned char **buf)
{
int ret;
unsigned len;
unsigned char *next;
struct ind *me = (struct ind *)in_desc;
next = me->inbuf;
*buf = next;
len = 0;
do {
ret = PIECE;
if ((unsigned)ret > SIZE - len)
ret = (int)(SIZE - len);
ret = (int)read(me->infile, next, ret);
if (ret == -1) {
len = 0;
break;
}
next += ret;
len += ret;
} while (ret != 0 && len < SIZE);
return len;
}
/* structure for infback() to pass to output function out() -- it maintains the
output file, a running CRC-32 check on the output and the total number of
bytes output, both for checking against the gzip trailer. (The length in
the gzip trailer is stored modulo 2^32, so it's ok if a long is 32 bits and
the output is greater than 4 GB.) */
struct outd {
int outfile;
int check; /* true if checking crc and total */
unsigned long crc;
unsigned long total;
};
/* Write output buffer and update the CRC-32 and total bytes written. write()
is called until all of the output is written or an error is encountered.
On success out() returns 0. For a write failure, out() returns 1. If the
output file descriptor is -1, then nothing is written.
*/
local int out(void *out_desc, unsigned char *buf, unsigned len)
{
int ret;
struct outd *me = (struct outd *)out_desc;
if (me->check) {
me->crc = crc32(me->crc, buf, len);
me->total += len;
}
if (me->outfile != -1)
do {
ret = PIECE;
if ((unsigned)ret > len)
ret = (int)len;
ret = (int)write(me->outfile, buf, ret);
if (ret == -1)
return 1;
buf += ret;
len -= ret;
} while (len != 0);
return 0;
}
/* next input byte macro for use inside lunpipe() and gunpipe() */
#define NEXT() (have ? 0 : (have = in(indp, &next)), \
last = have ? (have--, (int)(*next++)) : -1)
/* memory for gunpipe() and lunpipe() --
the first 256 entries of prefix[] and suffix[] are never used, could
have offset the index, but it's faster to waste the memory */
unsigned char inbuf[SIZE]; /* input buffer */
unsigned char outbuf[SIZE]; /* output buffer */
unsigned short prefix[65536]; /* index to LZW prefix string */
unsigned char suffix[65536]; /* one-character LZW suffix */
unsigned char match[65280 + 2]; /* buffer for reversed match or gzip
32K sliding window */
/* throw out what's left in the current bits byte buffer (this is a vestigial
aspect of the compressed data format derived from an implementation that
made use of a special VAX machine instruction!) */
#define FLUSHCODE() \
do { \
left = 0; \
rem = 0; \
if (chunk > have) { \
chunk -= have; \
have = 0; \
if (NEXT() == -1) \
break; \
chunk--; \
if (chunk > have) { \
chunk = have = 0; \
break; \
} \
} \
have -= chunk; \
next += chunk; \
chunk = 0; \
} while (0)
/* Decompress a compress (LZW) file from indp to outfile. The compress magic
header (two bytes) has already been read and verified. There are have bytes
of buffered input at next. strm is used for passing error information back
to gunpipe().
lunpipe() will return Z_OK on success, Z_BUF_ERROR for an unexpected end of
file, read error, or write error (a write error indicated by strm->next_in
not equal to Z_NULL), or Z_DATA_ERROR for invalid input.
*/
local int lunpipe(unsigned have, unsigned char *next, struct ind *indp,
int outfile, z_stream *strm)
{
int last; /* last byte read by NEXT(), or -1 if EOF */
int chunk; /* bytes left in current chunk */
int left; /* bits left in rem */
unsigned rem; /* unused bits from input */
int bits; /* current bits per code */
unsigned code; /* code, table traversal index */
unsigned mask; /* mask for current bits codes */
int max; /* maximum bits per code for this stream */
int flags; /* compress flags, then block compress flag */
unsigned end; /* last valid entry in prefix/suffix tables */
unsigned temp; /* current code */
unsigned prev; /* previous code */
unsigned final; /* last character written for previous code */
unsigned stack; /* next position for reversed string */
unsigned outcnt; /* bytes in output buffer */
struct outd outd; /* output structure */
/* set up output */
outd.outfile = outfile;
outd.check = 0;
/* process remainder of compress header -- a flags byte */
flags = NEXT();
if (last == -1)
return Z_BUF_ERROR;
if (flags & 0x60) {
strm->msg = "unknown lzw flags set";
return Z_DATA_ERROR;
}
max = flags & 0x1f;
if (max < 9 || max > 16) {
strm->msg = "lzw bits out of range";
return Z_DATA_ERROR;
}
if (max == 9) /* 9 doesn't really mean 9 */
max = 10;
flags &= 0x80; /* true if block compress */
/* clear table */
bits = 9;
mask = 0x1ff;
end = flags ? 256 : 255;
/* set up: get first 9-bit code, which is the first decompressed byte, but
don't create a table entry until the next code */
if (NEXT() == -1) /* no compressed data is ok */
return Z_OK;
final = prev = (unsigned)last; /* low 8 bits of code */
if (NEXT() == -1) /* missing a bit */
return Z_BUF_ERROR;
if (last & 1) { /* code must be < 256 */
strm->msg = "invalid lzw code";
return Z_DATA_ERROR;
}
rem = (unsigned)last >> 1; /* remaining 7 bits */
left = 7;
chunk = bits - 2; /* 7 bytes left in this chunk */
outbuf[0] = (unsigned char)final; /* write first decompressed byte */
outcnt = 1;
/* decode codes */
stack = 0;
for (;;) {
/* if the table will be full after this, increment the code size */
if (end >= mask && bits < max) {
FLUSHCODE();
bits++;
mask <<= 1;
mask++;
}
/* get a code of length bits */
if (chunk == 0) /* decrement chunk modulo bits */
chunk = bits;
code = rem; /* low bits of code */
if (NEXT() == -1) { /* EOF is end of compressed data */
/* write remaining buffered output */
if (outcnt && out(&outd, outbuf, outcnt)) {
strm->next_in = outbuf; /* signal write error */
return Z_BUF_ERROR;
}
return Z_OK;
}
code += (unsigned)last << left; /* middle (or high) bits of code */
left += 8;
chunk--;
if (bits > left) { /* need more bits */
if (NEXT() == -1) /* can't end in middle of code */
return Z_BUF_ERROR;
code += (unsigned)last << left; /* high bits of code */
left += 8;
chunk--;
}
code &= mask; /* mask to current code length */
left -= bits; /* number of unused bits */
rem = (unsigned)last >> (8 - left); /* unused bits from last byte */
/* process clear code (256) */
if (code == 256 && flags) {
FLUSHCODE();
bits = 9; /* initialize bits and mask */
mask = 0x1ff;
end = 255; /* empty table */
continue; /* get next code */
}
/* special code to reuse last match */
temp = code; /* save the current code */
if (code > end) {
/* Be picky on the allowed code here, and make sure that the code
we drop through (prev) will be a valid index so that random
input does not cause an exception. The code != end + 1 check is
empirically derived, and not checked in the original uncompress
code. If this ever causes a problem, that check could be safely
removed. Leaving this check in greatly improves gun's ability
to detect random or corrupted input after a compress header.
In any case, the prev > end check must be retained. */
if (code != end + 1 || prev > end) {
strm->msg = "invalid lzw code";
return Z_DATA_ERROR;
}
match[stack++] = (unsigned char)final;
code = prev;
}
/* walk through linked list to generate output in reverse order */
while (code >= 256) {
match[stack++] = suffix[code];
code = prefix[code];
}
match[stack++] = (unsigned char)code;
final = code;
/* link new table entry */
if (end < mask) {
end++;
prefix[end] = (unsigned short)prev;
suffix[end] = (unsigned char)final;
}
/* set previous code for next iteration */
prev = temp;
/* write output in forward order */
while (stack > SIZE - outcnt) {
while (outcnt < SIZE)
outbuf[outcnt++] = match[--stack];
if (out(&outd, outbuf, outcnt)) {
strm->next_in = outbuf; /* signal write error */
return Z_BUF_ERROR;
}
outcnt = 0;
}
do {
outbuf[outcnt++] = match[--stack];
} while (stack);
/* loop for next code with final and prev as the last match, rem and
left provide the first 0..7 bits of the next code, end is the last
valid table entry */
}
}
/* Decompress a gzip file from infile to outfile. strm is assumed to have been
successfully initialized with inflateBackInit(). The input file may consist
of a series of gzip streams, in which case all of them will be decompressed
to the output file. If outfile is -1, then the gzip stream(s) integrity is
checked and nothing is written.
The return value is a zlib error code: Z_MEM_ERROR if out of memory,
Z_DATA_ERROR if the header or the compressed data is invalid, or if the
trailer CRC-32 check or length doesn't match, Z_BUF_ERROR if the input ends
prematurely or a write error occurs, or Z_ERRNO if junk (not a another gzip
stream) follows a valid gzip stream.
*/
local int gunpipe(z_stream *strm, int infile, int outfile)
{
int ret, first, last;
unsigned have, flags, len;
unsigned char *next;
struct ind ind, *indp;
struct outd outd;
/* setup input buffer */
ind.infile = infile;
ind.inbuf = inbuf;
indp = &ind;
/* decompress concatenated gzip streams */
have = 0; /* no input data read in yet */
first = 1; /* looking for first gzip header */
strm->next_in = Z_NULL; /* so Z_BUF_ERROR means EOF */
for (;;) {
/* look for the two magic header bytes for a gzip stream */
if (NEXT() == -1) {
ret = Z_OK;
break; /* empty gzip stream is ok */
}
if (last != 31 || (NEXT() != 139 && last != 157)) {
strm->msg = "incorrect header check";
ret = first ? Z_DATA_ERROR : Z_ERRNO;
break; /* not a gzip or compress header */
}
first = 0; /* next non-header is junk */
/* process a compress (LZW) file -- can't be concatenated after this */
if (last == 157) {
ret = lunpipe(have, next, indp, outfile, strm);
break;
}
/* process remainder of gzip header */
ret = Z_BUF_ERROR;
if (NEXT() != 8) { /* only deflate method allowed */
if (last == -1) break;
strm->msg = "unknown compression method";
ret = Z_DATA_ERROR;
break;
}
flags = NEXT(); /* header flags */
NEXT(); /* discard mod time, xflgs, os */
NEXT();
NEXT();
NEXT();
NEXT();
NEXT();
if (last == -1) break;
if (flags & 0xe0) {
strm->msg = "unknown header flags set";
ret = Z_DATA_ERROR;
break;
}
if (flags & 4) { /* extra field */
len = NEXT();
len += (unsigned)(NEXT()) << 8;
if (last == -1) break;
while (len > have) {
len -= have;
have = 0;
if (NEXT() == -1) break;
len--;
}
if (last == -1) break;
have -= len;
next += len;
}
if (flags & 8) /* file name */
while (NEXT() != 0 && last != -1)
;
if (flags & 16) /* comment */
while (NEXT() != 0 && last != -1)
;
if (flags & 2) { /* header crc */
NEXT();
NEXT();
}
if (last == -1) break;
/* set up output */
outd.outfile = outfile;
outd.check = 1;
outd.crc = crc32(0L, Z_NULL, 0);
outd.total = 0;
/* decompress data to output */
strm->next_in = next;
strm->avail_in = have;
ret = inflateBack(strm, in, indp, out, &outd);
if (ret != Z_STREAM_END) break;
next = strm->next_in;
have = strm->avail_in;
strm->next_in = Z_NULL; /* so Z_BUF_ERROR means EOF */
/* check trailer */
ret = Z_BUF_ERROR;
if (NEXT() != (outd.crc & 0xff) ||
NEXT() != ((outd.crc >> 8) & 0xff) ||
NEXT() != ((outd.crc >> 16) & 0xff) ||
NEXT() != ((outd.crc >> 24) & 0xff)) {
/* crc error */
if (last != -1) {
strm->msg = "incorrect data check";
ret = Z_DATA_ERROR;
}
break;
}
if (NEXT() != (outd.total & 0xff) ||
NEXT() != ((outd.total >> 8) & 0xff) ||
NEXT() != ((outd.total >> 16) & 0xff) ||
NEXT() != ((outd.total >> 24) & 0xff)) {
/* length error */
if (last != -1) {
strm->msg = "incorrect length check";
ret = Z_DATA_ERROR;
}
break;
}
/* go back and look for another gzip stream */
}
/* clean up and return */
return ret;
}
/* Copy file attributes, from -> to, as best we can. This is best effort, so
no errors are reported. The mode bits, including suid, sgid, and the sticky
bit are copied (if allowed), the owner's user id and group id are copied
(again if allowed), and the access and modify times are copied. */
local void copymeta(char *from, char *to)
{
struct stat was;
struct utimbuf when;
/* get all of from's Unix meta data, return if not a regular file */
if (stat(from, &was) != 0 || (was.st_mode & S_IFMT) != S_IFREG)
return;
/* set to's mode bits, ignore errors */
(void)chmod(to, was.st_mode & 07777);
/* copy owner's user and group, ignore errors */
(void)chown(to, was.st_uid, was.st_gid);
/* copy access and modify times, ignore errors */
when.actime = was.st_atime;
when.modtime = was.st_mtime;
(void)utime(to, &when);
}
/* Decompress the file inname to the file outnname, of if test is true, just
decompress without writing and check the gzip trailer for integrity. If
inname is NULL or an empty string, read from stdin. If outname is NULL or
an empty string, write to stdout. strm is a pre-initialized inflateBack
structure. When appropriate, copy the file attributes from inname to
outname.
gunzip() returns 1 if there is an out-of-memory error or an unexpected
return code from gunpipe(). Otherwise it returns 0.
*/
local int gunzip(z_stream *strm, char *inname, char *outname, int test)
{
int ret;
int infile, outfile;
/* open files */
if (inname == NULL || *inname == 0) {
inname = "-";
infile = 0; /* stdin */
}
else {
infile = open(inname, O_RDONLY, 0);
if (infile == -1) {
fprintf(stderr, "gun cannot open %s\n", inname);
return 0;
}
}
if (test)
outfile = -1;
else if (outname == NULL || *outname == 0) {
outname = "-";
outfile = 1; /* stdout */
}
else {
outfile = open(outname, O_CREAT | O_TRUNC | O_WRONLY, 0666);
if (outfile == -1) {
close(infile);
fprintf(stderr, "gun cannot create %s\n", outname);
return 0;
}
}
errno = 0;
/* decompress */
ret = gunpipe(strm, infile, outfile);
if (outfile > 2) close(outfile);
if (infile > 2) close(infile);
/* interpret result */
switch (ret) {
case Z_OK:
case Z_ERRNO:
if (infile > 2 && outfile > 2) {
copymeta(inname, outname); /* copy attributes */
unlink(inname);
}
if (ret == Z_ERRNO)
fprintf(stderr, "gun warning: trailing garbage ignored in %s\n",
inname);
break;
case Z_DATA_ERROR:
if (outfile > 2) unlink(outname);
fprintf(stderr, "gun data error on %s: %s\n", inname, strm->msg);
break;
case Z_MEM_ERROR:
if (outfile > 2) unlink(outname);
fprintf(stderr, "gun out of memory error--aborting\n");
return 1;
case Z_BUF_ERROR:
if (outfile > 2) unlink(outname);
if (strm->next_in != Z_NULL) {
fprintf(stderr, "gun write error on %s: %s\n",
outname, strerror(errno));
}
else if (errno) {
fprintf(stderr, "gun read error on %s: %s\n",
inname, strerror(errno));
}
else {
fprintf(stderr, "gun unexpected end of file on %s\n",
inname);
}
break;
default:
if (outfile > 2) unlink(outname);
fprintf(stderr, "gun internal error--aborting\n");
return 1;
}
return 0;
}
/* Process the gun command line arguments. See the command syntax near the
beginning of this source file. */
int main(int argc, char **argv)
{
int ret, len, test;
char *outname;
unsigned char *window;
z_stream strm;
/* initialize inflateBack state for repeated use */
window = match; /* reuse LZW match buffer */
strm.zalloc = Z_NULL;
strm.zfree = Z_NULL;
strm.opaque = Z_NULL;
ret = inflateBackInit(&strm, 15, window);
if (ret != Z_OK) {
fprintf(stderr, "gun out of memory error--aborting\n");
return 1;
}
/* decompress each file to the same name with the suffix removed */
argc--;
argv++;
test = 0;
if (argc && strcmp(*argv, "-h") == 0) {
fprintf(stderr, "gun 1.2 (20 Mar 2005)\n");
fprintf(stderr, "Copyright (c) 2005 Mark Adler\n");
fprintf(stderr, "usage: gun [-t] [file1.gz [file2.Z ...]]\n");
return 0;
}
if (argc && strcmp(*argv, "-t") == 0) {
test = 1;
argc--;
argv++;
}
if (argc)
do {
if (test)
outname = NULL;
else {
len = (int)strlen(*argv);
if (strcmp(*argv + len - 3, ".gz") == 0 ||
strcmp(*argv + len - 3, "-gz") == 0)
len -= 3;
else if (strcmp(*argv + len - 2, ".z") == 0 ||
strcmp(*argv + len - 2, "-z") == 0 ||
strcmp(*argv + len - 2, "_z") == 0 ||
strcmp(*argv + len - 2, ".Z") == 0)
len -= 2;
else {
fprintf(stderr, "gun error: no gz type on %s--skipping\n",
*argv);
continue;
}
outname = malloc(len + 1);
if (outname == NULL) {
fprintf(stderr, "gun out of memory error--aborting\n");
ret = 1;
break;
}
memcpy(outname, *argv, len);
outname[len] = 0;
}
ret = gunzip(&strm, *argv, outname, test);
if (outname != NULL) free(outname);
if (ret) break;
} while (argv++, --argc);
else
ret = gunzip(&strm, NULL, NULL, test);
/* clean up */
inflateBackEnd(&strm);
return ret;
}

447
examples/gzjoin.c Normal file
View File

@@ -0,0 +1,447 @@
/* gzjoin -- command to join gzip files into one gzip file
Copyright (C) 2004 Mark Adler, all rights reserved
version 1.0, 11 Dec 2004
This software is provided 'as-is', without any express or implied
warranty. In no event will the author be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
Mark Adler madler@alumni.caltech.edu
*/
/*
* Change history:
*
* 1.0 11 Dec 2004 - First version
*/
/*
gzjoin takes one or more gzip files on the command line and writes out a
single gzip file that will uncompress to the concatenation of the
uncompressed data from the individual gzip files. gzjoin does this without
having to recompress any of the data and without having to calculate a new
crc32 for the concatenated uncompressed data. gzjoin does however have to
decompress all of the input data in order to find the bits in the compressed
data that need to be modified to concatenate the streams.
gzjoin does not do an integrity check on the input gzip files other than
checking the gzip header and decompressing the compressed data. They are
otherwise assumed to be complete and correct.
Each joint between gzip files removes at least 18 bytes of previous trailer
and subsequent header, and inserts an average of about three bytes to the
compressed data in order to connect the streams. The output gzip file
has a minimal ten-byte gzip header with no file name or modification time.
This program was written to illustrate the use of the Z_BLOCK option of
inflate() and the crc32_combine() function. gzjoin will not compile with
versions of zlib earlier than 1.2.3.
*/
#include <stdio.h> /* fputs(), fprintf(), fwrite(), putc() */
#include <stdlib.h> /* exit(), malloc(), free() */
#include <fcntl.h> /* open() */
#include <unistd.h> /* close(), read(), lseek() */
#include "zlib.h"
/* crc32(), crc32_combine(), inflateInit2(), inflate(), inflateEnd() */
#define local static
/* exit with an error (return a value to allow use in an expression) */
local int bail(char *why1, char *why2)
{
fprintf(stderr, "gzjoin error: %s%s, output incomplete\n", why1, why2);
exit(1);
return 0;
}
/* -- simple buffered file input with access to the buffer -- */
#define CHUNK 32768 /* must be a power of two and fit in unsigned */
/* bin buffered input file type */
typedef struct {
char *name; /* name of file for error messages */
int fd; /* file descriptor */
unsigned left; /* bytes remaining at next */
unsigned char *next; /* next byte to read */
unsigned char *buf; /* allocated buffer of length CHUNK */
} bin;
/* close a buffered file and free allocated memory */
local void bclose(bin *in)
{
if (in != NULL) {
if (in->fd != -1)
close(in->fd);
if (in->buf != NULL)
free(in->buf);
free(in);
}
}
/* open a buffered file for input, return a pointer to type bin, or NULL on
failure */
local bin *bopen(char *name)
{
bin *in;
in = malloc(sizeof(bin));
if (in == NULL)
return NULL;
in->buf = malloc(CHUNK);
in->fd = open(name, O_RDONLY, 0);
if (in->buf == NULL || in->fd == -1) {
bclose(in);
return NULL;
}
in->left = 0;
in->next = in->buf;
in->name = name;
return in;
}
/* load buffer from file, return -1 on read error, 0 or 1 on success, with
1 indicating that end-of-file was reached */
local int bload(bin *in)
{
ssize_t len;
if (in == NULL)
return -1;
if (in->left != 0)
return 0;
in->next = in->buf;
do {
len = read(in->fd, in->buf + in->left, CHUNK - in->left);
if (len < 0)
return -1;
in->left += (unsigned)len;
} while (len != 0 && in->left < CHUNK);
return len == 0 ? 1 : 0;
}
/* get a byte from the file, bail if end of file */
#define bget(in) (in->left ? 0 : bload(in), \
in->left ? (in->left--, *(in->next)++) : \
bail("unexpected end of file on ", in->name))
/* get a four-byte little-endian unsigned integer from file */
local unsigned long bget4(bin *in)
{
unsigned long val;
val = bget(in);
val += (unsigned long)(bget(in)) << 8;
val += (unsigned long)(bget(in)) << 16;
val += (unsigned long)(bget(in)) << 24;
return val;
}
/* skip bytes in file */
local void bskip(bin *in, unsigned skip)
{
/* check pointer */
if (in == NULL)
return;
/* easy case -- skip bytes in buffer */
if (skip <= in->left) {
in->left -= skip;
in->next += skip;
return;
}
/* skip what's in buffer, discard buffer contents */
skip -= in->left;
in->left = 0;
/* seek past multiples of CHUNK bytes */
if (skip > CHUNK) {
unsigned left;
left = skip & (CHUNK - 1);
if (left == 0) {
/* exact number of chunks: seek all the way minus one byte to check
for end-of-file with a read */
lseek(in->fd, skip - 1, SEEK_CUR);
if (read(in->fd, in->buf, 1) != 1)
bail("unexpected end of file on ", in->name);
return;
}
/* skip the integral chunks, update skip with remainder */
lseek(in->fd, skip - left, SEEK_CUR);
skip = left;
}
/* read more input and skip remainder */
bload(in);
if (skip > in->left)
bail("unexpected end of file on ", in->name);
in->left -= skip;
in->next += skip;
}
/* -- end of buffered input functions -- */
/* skip the gzip header from file in */
local void gzhead(bin *in)
{
int flags;
/* verify gzip magic header and compression method */
if (bget(in) != 0x1f || bget(in) != 0x8b || bget(in) != 8)
bail(in->name, " is not a valid gzip file");
/* get and verify flags */
flags = bget(in);
if ((flags & 0xe0) != 0)
bail("unknown reserved bits set in ", in->name);
/* skip modification time, extra flags, and os */
bskip(in, 6);
/* skip extra field if present */
if (flags & 4) {
unsigned len;
len = bget(in);
len += (unsigned)(bget(in)) << 8;
bskip(in, len);
}
/* skip file name if present */
if (flags & 8)
while (bget(in) != 0)
;
/* skip comment if present */
if (flags & 16)
while (bget(in) != 0)
;
/* skip header crc if present */
if (flags & 2)
bskip(in, 2);
}
/* write a four-byte little-endian unsigned integer to out */
local void put4(unsigned long val, FILE *out)
{
putc(val & 0xff, out);
putc((val >> 8) & 0xff, out);
putc((val >> 16) & 0xff, out);
putc((val >> 24) & 0xff, out);
}
/* Load up zlib stream from buffered input, bail if end of file */
local void zpull(z_streamp strm, bin *in)
{
if (in->left == 0)
bload(in);
if (in->left == 0)
bail("unexpected end of file on ", in->name);
strm->avail_in = in->left;
strm->next_in = in->next;
}
/* Write header for gzip file to out and initialize trailer. */
local void gzinit(unsigned long *crc, unsigned long *tot, FILE *out)
{
fwrite("\x1f\x8b\x08\0\0\0\0\0\0\xff", 1, 10, out);
*crc = crc32(0L, Z_NULL, 0);
*tot = 0;
}
/* Copy the compressed data from name, zeroing the last block bit of the last
block if clr is true, and adding empty blocks as needed to get to a byte
boundary. If clr is false, then the last block becomes the last block of
the output, and the gzip trailer is written. crc and tot maintains the
crc and length (modulo 2^32) of the output for the trailer. The resulting
gzip file is written to out. gzinit() must be called before the first call
of gzcopy() to write the gzip header and to initialize crc and tot. */
local void gzcopy(char *name, int clr, unsigned long *crc, unsigned long *tot,
FILE *out)
{
int ret; /* return value from zlib functions */
int pos; /* where the "last block" bit is in byte */
int last; /* true if processing the last block */
bin *in; /* buffered input file */
unsigned char *start; /* start of compressed data in buffer */
unsigned char *junk; /* buffer for uncompressed data -- discarded */
z_off_t len; /* length of uncompressed data (support > 4 GB) */
z_stream strm; /* zlib inflate stream */
/* open gzip file and skip header */
in = bopen(name);
if (in == NULL)
bail("could not open ", name);
gzhead(in);
/* allocate buffer for uncompressed data and initialize raw inflate
stream */
junk = malloc(CHUNK);
strm.zalloc = Z_NULL;
strm.zfree = Z_NULL;
strm.opaque = Z_NULL;
strm.avail_in = 0;
strm.next_in = Z_NULL;
ret = inflateInit2(&strm, -15);
if (junk == NULL || ret != Z_OK)
bail("out of memory", "");
/* inflate and copy compressed data, clear last-block bit if requested */
len = 0;
zpull(&strm, in);
start = strm.next_in;
last = start[0] & 1;
if (last && clr)
start[0] &= ~1;
strm.avail_out = 0;
for (;;) {
/* if input used and output done, write used input and get more */
if (strm.avail_in == 0 && strm.avail_out != 0) {
fwrite(start, 1, strm.next_in - start, out);
start = in->buf;
in->left = 0;
zpull(&strm, in);
}
/* decompress -- return early when end-of-block reached */
strm.avail_out = CHUNK;
strm.next_out = junk;
ret = inflate(&strm, Z_BLOCK);
switch (ret) {
case Z_MEM_ERROR:
bail("out of memory", "");
case Z_DATA_ERROR:
bail("invalid compressed data in ", in->name);
}
/* update length of uncompressed data */
len += CHUNK - strm.avail_out;
/* check for block boundary (only get this when block copied out) */
if (strm.data_type & 128) {
/* if that was the last block, then done */
if (last)
break;
/* number of unused bits in last byte */
pos = strm.data_type & 7;
/* find the next last-block bit */
if (pos != 0) {
/* next last-block bit is in last used byte */
pos = 0x100 >> pos;
last = strm.next_in[-1] & pos;
if (last && clr)
strm.next_in[-1] &= ~pos;
}
else {
/* next last-block bit is in next unused byte */
if (strm.avail_in == 0) {
/* don't have that byte yet -- get it */
fwrite(start, 1, strm.next_in - start, out);
start = in->buf;
in->left = 0;
zpull(&strm, in);
}
last = strm.next_in[0] & 1;
if (last && clr)
strm.next_in[0] &= ~1;
}
}
}
/* update buffer with unused input */
in->left = strm.avail_in;
in->next = strm.next_in;
/* copy used input, write empty blocks to get to byte boundary */
pos = strm.data_type & 7;
fwrite(start, 1, in->next - start - 1, out);
last = in->next[-1];
if (pos == 0 || !clr)
/* already at byte boundary, or last file: write last byte */
putc(last, out);
else {
/* append empty blocks to last byte */
last &= ((0x100 >> pos) - 1); /* assure unused bits are zero */
if (pos & 1) {
/* odd -- append an empty stored block */
putc(last, out);
if (pos == 1)
putc(0, out); /* two more bits in block header */
fwrite("\0\0\xff\xff", 1, 4, out);
}
else {
/* even -- append 1, 2, or 3 empty fixed blocks */
switch (pos) {
case 6:
putc(last | 8, out);
last = 0;
case 4:
putc(last | 0x20, out);
last = 0;
case 2:
putc(last | 0x80, out);
putc(0, out);
}
}
}
/* update crc and tot */
*crc = crc32_combine(*crc, bget4(in), len);
*tot += (unsigned long)len;
/* clean up */
inflateEnd(&strm);
free(junk);
bclose(in);
/* write trailer if this is the last gzip file */
if (!clr) {
put4(*crc, out);
put4(*tot, out);
}
}
/* join the gzip files on the command line, write result to stdout */
int main(int argc, char **argv)
{
unsigned long crc, tot; /* running crc and total uncompressed length */
/* skip command name */
argc--;
argv++;
/* show usage if no arguments */
if (argc == 0) {
fputs("gzjoin usage: gzjoin f1.gz [f2.gz [f3.gz ...]] > fjoin.gz\n",
stderr);
return 0;
}
/* join gzip files on command line and write to stdout */
gzinit(&crc, &tot, stdout);
while (argc--)
gzcopy(*argv++, argc, &crc, &tot, stdout);
/* done */
return 0;
}

413
examples/gzlog.c Normal file
View File

@@ -0,0 +1,413 @@
/*
* gzlog.c
* Copyright (C) 2004 Mark Adler
* For conditions of distribution and use, see copyright notice in gzlog.h
* version 1.0, 26 Nov 2004
*
*/
#include <string.h> /* memcmp() */
#include <stdlib.h> /* malloc(), free(), NULL */
#include <sys/types.h> /* size_t, off_t */
#include <unistd.h> /* read(), close(), sleep(), ftruncate(), */
/* lseek() */
#include <fcntl.h> /* open() */
#include <sys/file.h> /* flock() */
#include "zlib.h" /* deflateInit2(), deflate(), deflateEnd() */
#include "gzlog.h" /* interface */
#define local static
/* log object structure */
typedef struct {
int id; /* object identifier */
int fd; /* log file descriptor */
off_t extra; /* offset of extra "ap" subfield */
off_t mark_off; /* offset of marked data */
off_t last_off; /* offset of last block */
unsigned long crc; /* uncompressed crc */
unsigned long len; /* uncompressed length (modulo 2^32) */
unsigned stored; /* length of current stored block */
} gz_log;
#define GZLOGID 19334 /* gz_log object identifier */
#define LOCK_RETRY 1 /* retry lock once a second */
#define LOCK_PATIENCE 1200 /* try about twenty minutes before forcing */
/* acquire a lock on a file */
local int lock(int fd)
{
int patience;
/* try to lock every LOCK_RETRY seconds for LOCK_PATIENCE seconds */
patience = LOCK_PATIENCE;
do {
if (flock(fd, LOCK_EX + LOCK_NB) == 0)
return 0;
(void)sleep(LOCK_RETRY);
patience -= LOCK_RETRY;
} while (patience > 0);
/* we've run out of patience -- give up */
return -1;
}
/* release lock */
local void unlock(int fd)
{
(void)flock(fd, LOCK_UN);
}
/* release a log object */
local void log_clean(gz_log *log)
{
unlock(log->fd);
(void)close(log->fd);
free(log);
}
/* read an unsigned long from a byte buffer little-endian */
local unsigned long make_ulg(unsigned char *buf)
{
int n;
unsigned long val;
val = (unsigned long)(*buf++);
for (n = 8; n < 32; n += 8)
val += (unsigned long)(*buf++) << n;
return val;
}
/* read an off_t from a byte buffer little-endian */
local off_t make_off(unsigned char *buf)
{
int n;
off_t val;
val = (off_t)(*buf++);
for (n = 8; n < 64; n += 8)
val += (off_t)(*buf++) << n;
return val;
}
/* write an unsigned long little-endian to byte buffer */
local void dice_ulg(unsigned long val, unsigned char *buf)
{
int n;
for (n = 0; n < 4; n++) {
*buf++ = val & 0xff;
val >>= 8;
}
}
/* write an off_t little-endian to byte buffer */
local void dice_off(off_t val, unsigned char *buf)
{
int n;
for (n = 0; n < 8; n++) {
*buf++ = val & 0xff;
val >>= 8;
}
}
/* initial, empty gzip file for appending */
local char empty_gz[] = {
0x1f, 0x8b, /* magic gzip id */
8, /* compression method is deflate */
4, /* there is an extra field */
0, 0, 0, 0, /* no modification time provided */
0, 0xff, /* no extra flags, no OS */
20, 0, 'a', 'p', 16, 0, /* extra field with "ap" subfield */
32, 0, 0, 0, 0, 0, 0, 0, /* offset of uncompressed data */
32, 0, 0, 0, 0, 0, 0, 0, /* offset of last block */
1, 0, 0, 0xff, 0xff, /* empty stored block (last) */
0, 0, 0, 0, /* crc */
0, 0, 0, 0 /* uncompressed length */
};
/* initialize a log object with locking */
void *gzlog_open(char *path)
{
unsigned xlen;
unsigned char temp[20];
unsigned sub_len;
int good;
gz_log *log;
/* allocate log structure */
log = malloc(sizeof(gz_log));
if (log == NULL)
return NULL;
log->id = GZLOGID;
/* open file, creating it if necessary, and locking it */
log->fd = open(path, O_RDWR | O_CREAT, 0600);
if (log->fd < 0) {
free(log);
return NULL;
}
if (lock(log->fd)) {
close(log->fd);
free(log);
return NULL;
}
/* if file is empty, write new gzip stream */
if (lseek(log->fd, 0, SEEK_END) == 0) {
if (write(log->fd, empty_gz, sizeof(empty_gz)) != sizeof(empty_gz)) {
log_clean(log);
return NULL;
}
}
/* check gzip header */
(void)lseek(log->fd, 0, SEEK_SET);
if (read(log->fd, temp, 12) != 12 || temp[0] != 0x1f ||
temp[1] != 0x8b || temp[2] != 8 || (temp[3] & 4) == 0) {
log_clean(log);
return NULL;
}
/* process extra field to find "ap" sub-field */
xlen = temp[10] + (temp[11] << 8);
good = 0;
while (xlen) {
if (xlen < 4 || read(log->fd, temp, 4) != 4)
break;
sub_len = temp[2];
sub_len += temp[3] << 8;
xlen -= 4;
if (memcmp(temp, "ap", 2) == 0 && sub_len == 16) {
good = 1;
break;
}
if (xlen < sub_len)
break;
(void)lseek(log->fd, sub_len, SEEK_CUR);
xlen -= sub_len;
}
if (!good) {
log_clean(log);
return NULL;
}
/* read in "ap" sub-field */
log->extra = lseek(log->fd, 0, SEEK_CUR);
if (read(log->fd, temp, 16) != 16) {
log_clean(log);
return NULL;
}
log->mark_off = make_off(temp);
log->last_off = make_off(temp + 8);
/* get crc, length of gzip file */
(void)lseek(log->fd, log->last_off, SEEK_SET);
if (read(log->fd, temp, 13) != 13 ||
memcmp(temp, "\001\000\000\377\377", 5) != 0) {
log_clean(log);
return NULL;
}
log->crc = make_ulg(temp + 5);
log->len = make_ulg(temp + 9);
/* set up to write over empty last block */
(void)lseek(log->fd, log->last_off + 5, SEEK_SET);
log->stored = 0;
return (void *)log;
}
/* maximum amount to put in a stored block before starting a new one */
#define MAX_BLOCK 16384
/* write a block to a log object */
int gzlog_write(void *obj, char *data, size_t len)
{
size_t some;
unsigned char temp[5];
gz_log *log;
/* check object */
log = (gz_log *)obj;
if (log == NULL || log->id != GZLOGID)
return 1;
/* write stored blocks until all of the input is written */
do {
some = MAX_BLOCK - log->stored;
if (some > len)
some = len;
if (write(log->fd, data, some) != some)
return 1;
log->crc = crc32(log->crc, data, some);
log->len += some;
len -= some;
data += some;
log->stored += some;
/* if the stored block is full, end it and start another */
if (log->stored == MAX_BLOCK) {
(void)lseek(log->fd, log->last_off, SEEK_SET);
temp[0] = 0;
dice_ulg(log->stored + ((unsigned long)(~log->stored) << 16),
temp + 1);
if (write(log->fd, temp, 5) != 5)
return 1;
log->last_off = lseek(log->fd, log->stored, SEEK_CUR);
(void)lseek(log->fd, 5, SEEK_CUR);
log->stored = 0;
}
} while (len);
return 0;
}
/* recompress the remaining stored deflate data in place */
local int recomp(gz_log *log)
{
z_stream strm;
size_t len, max;
unsigned char *in;
unsigned char *out;
unsigned char temp[16];
/* allocate space and read it all in (it's around 1 MB) */
len = log->last_off - log->mark_off;
max = len + (len >> 12) + (len >> 14) + 11;
out = malloc(max);
if (out == NULL)
return 1;
in = malloc(len);
if (in == NULL) {
free(out);
return 1;
}
(void)lseek(log->fd, log->mark_off, SEEK_SET);
if (read(log->fd, in, len) != len) {
free(in);
free(out);
return 1;
}
/* recompress in memory, decoding stored data as we go */
/* note: this assumes that unsigned is four bytes or more */
/* consider not making that assumption */
strm.zalloc = Z_NULL;
strm.zfree = Z_NULL;
strm.opaque = Z_NULL;
if (deflateInit2(&strm, Z_BEST_COMPRESSION, Z_DEFLATED, -15, 8,
Z_DEFAULT_STRATEGY) != Z_OK) {
free(in);
free(out);
return 1;
}
strm.next_in = in;
strm.avail_out = max;
strm.next_out = out;
while (len >= 5) {
if (strm.next_in[0] != 0)
break;
strm.avail_in = strm.next_in[1] + (strm.next_in[2] << 8);
strm.next_in += 5;
len -= 5;
if (strm.avail_in != 0) {
if (len < strm.avail_in)
break;
len -= strm.avail_in;
(void)deflate(&strm, Z_NO_FLUSH);
if (strm.avail_in != 0 || strm.avail_out == 0)
break;
}
}
(void)deflate(&strm, Z_SYNC_FLUSH);
(void)deflateEnd(&strm);
free(in);
if (len != 0 || strm.avail_out == 0) {
free(out);
return 1;
}
/* overwrite stored data with compressed data */
(void)lseek(log->fd, log->mark_off, SEEK_SET);
len = max - strm.avail_out;
if (write(log->fd, out, len) != len) {
free(out);
return 1;
}
free(out);
/* write last empty block, crc, and length */
log->mark_off = log->last_off = lseek(log->fd, 0, SEEK_CUR);
temp[0] = 1;
dice_ulg(0xffffL << 16, temp + 1);
dice_ulg(log->crc, temp + 5);
dice_ulg(log->len, temp + 9);
if (write(log->fd, temp, 13) != 13)
return 1;
/* truncate file to discard remaining stored data and old trailer */
ftruncate(log->fd, lseek(log->fd, 0, SEEK_CUR));
/* update extra field to point to new last empty block */
(void)lseek(log->fd, log->extra, SEEK_SET);
dice_off(log->mark_off, temp);
dice_off(log->last_off, temp + 8);
if (write(log->fd, temp, 16) != 16)
return 1;
return 0;
}
/* maximum accumulation of stored blocks before compressing */
#define MAX_STORED 1048576
/* close log object */
int gzlog_close(void *obj)
{
unsigned char temp[8];
gz_log *log;
/* check object */
log = (gz_log *)obj;
if (log == NULL || log->id != GZLOGID)
return 1;
/* go to start of most recent block being written */
(void)lseek(log->fd, log->last_off, SEEK_SET);
/* if some stuff was put there, update block */
if (log->stored) {
temp[0] = 0;
dice_ulg(log->stored + ((unsigned long)(~log->stored) << 16),
temp + 1);
if (write(log->fd, temp, 5) != 5)
return 1;
log->last_off = lseek(log->fd, log->stored, SEEK_CUR);
}
/* write last block (empty) */
if (write(log->fd, "\001\000\000\377\377", 5) != 5)
return 1;
/* write updated crc and uncompressed length */
dice_ulg(log->crc, temp);
dice_ulg(log->len, temp + 4);
if (write(log->fd, temp, 8) != 8)
return 1;
/* put offset of that last block in gzip extra block */
(void)lseek(log->fd, log->extra + 8, SEEK_SET);
dice_off(log->last_off, temp);
if (write(log->fd, temp, 8) != 8)
return 1;
/* if more than 1 MB stored, then time to compress it */
if (log->last_off - log->mark_off > MAX_STORED) {
if (recomp(log))
return 1;
}
/* unlock and close file */
log_clean(log);
return 0;
}

58
examples/gzlog.h Normal file
View File

@@ -0,0 +1,58 @@
/* gzlog.h
Copyright (C) 2004 Mark Adler, all rights reserved
version 1.0, 26 Nov 2004
This software is provided 'as-is', without any express or implied
warranty. In no event will the author be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
Mark Adler madler@alumni.caltech.edu
*/
/*
The gzlog object allows writing short messages to a gzipped log file,
opening the log file locked for small bursts, and then closing it. The log
object works by appending stored data to the gzip file until 1 MB has been
accumulated. At that time, the stored data is compressed, and replaces the
uncompressed data in the file. The log file is truncated to its new size at
that time. After closing, the log file is always valid gzip file that can
decompressed to recover what was written.
A gzip header "extra" field contains two file offsets for appending. The
first points to just after the last compressed data. The second points to
the last stored block in the deflate stream, which is empty. All of the
data between those pointers is uncompressed.
*/
/* Open a gzlog object, creating the log file if it does not exist. Return
NULL on error. Note that gzlog_open() could take a long time to return if
there is difficulty in locking the file. */
void *gzlog_open(char *path);
/* Write to a gzlog object. Return non-zero on error. This function will
simply write data to the file uncompressed. Compression of the data
will not occur until gzlog_close() is called. It is expected that
gzlog_write() is used for a short message, and then gzlog_close() is
called. If a large amount of data is to be written, then the application
should write no more than 1 MB at a time with gzlog_write() before
calling gzlog_close() and then gzlog_open() again. */
int gzlog_write(void *log, char *data, size_t len);
/* Close a gzlog object. Return non-zero on error. The log file is locked
until this function is called. This function will compress stored data
at the end of the gzip file if at least 1 MB has been accumulated. Note
that the file will not be a valid gzip file until this function completes.
*/
int gzlog_close(void *log);

523
examples/zlib_how.html Normal file
View File

@@ -0,0 +1,523 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"
"http://www.w3.org/TR/REC-html40/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>zlib Usage Example</title>
<!-- Copyright (c) 2004 Mark Adler. -->
</head>
<body bgcolor="#FFFFFF" text="#000000" link="#0000FF" vlink="#00A000">
<h2 align="center"> zlib Usage Example </h2>
We often get questions about how the <tt>deflate()</tt> and <tt>inflate()</tt> functions should be used.
Users wonder when they should provide more input, when they should use more output,
what to do with a <tt>Z_BUF_ERROR</tt>, how to make sure the process terminates properly, and
so on. So for those who have read <tt>zlib.h</tt> (a few times), and
would like further edification, below is an annotated example in C of simple routines to compress and decompress
from an input file to an output file using <tt>deflate()</tt> and <tt>inflate()</tt> respectively. The
annotations are interspersed between lines of the code. So please read between the lines.
We hope this helps explain some of the intricacies of <em>zlib</em>.
<p>
Without further adieu, here is the program <a href="zpipe.c"><tt>zpipe.c</tt></a>:
<pre><b>
/* zpipe.c: example of proper use of zlib's inflate() and deflate()
Not copyrighted -- provided to the public domain
Version 1.2 9 November 2004 Mark Adler */
/* Version history:
1.0 30 Oct 2004 First version
1.1 8 Nov 2004 Add void casting for unused return values
Use switch statement for inflate() return values
1.2 9 Nov 2004 Add assertions to document zlib guarantees
*/
</b></pre><!-- -->
We now include the header files for the required definitions. From
<tt>stdio.h</tt> we use <tt>fopen()</tt>, <tt>fread()</tt>, <tt>fwrite()</tt>,
<tt>feof()</tt>, <tt>ferror()</tt>, and <tt>fclose()</tt> for file i/o, and
<tt>fputs()</tt> for error messages. From <tt>string.h</tt> we use
<tt>strcmp()</tt> for command line argument processing.
From <tt>assert.h</tt> we use the <tt>assert()</tt> macro.
From <tt>zlib.h</tt>
we use the basic compression functions <tt>deflateInit()</tt>,
<tt>deflate()</tt>, and <tt>deflateEnd()</tt>, and the basic decompression
functions <tt>inflateInit()</tt>, <tt>inflate()</tt>, and
<tt>inflateEnd()</tt>.
<pre><b>
#include &lt;stdio.h&gt;
#include &lt;string.h&gt;
#include &lt;assert.h&gt;
#include "zlib.h"
</b></pre><!-- -->
<tt>CHUNK</tt> is simply the buffer size for feeding data to and pulling data
from the <em>zlib</em> routines. Larger buffer sizes would be more efficient,
especially for <tt>inflate()</tt>. If the memory is available, buffers sizes
on the order of 128K or 256K bytes should be used.
<pre><b>
#define CHUNK 16384
</b></pre><!-- -->
The <tt>def()</tt> routine compresses data from an input file to an output file. The output data
will be in the <em>zlib</em> format, which is different from the <em>gzip</em> or <em>zip</em>
formats. The <em>zlib</em> format has a very small header of only two bytes to identify it as
a <em>zlib</em> stream and to provide decoding information, and a four-byte trailer with a fast
check value to verify the integrity of the uncompressed data after decoding.
<pre><b>
/* Compress from file source to file dest until EOF on source.
def() returns Z_OK on success, Z_MEM_ERROR if memory could not be
allocated for processing, Z_STREAM_ERROR if an invalid compression
level is supplied, Z_VERSION_ERROR if the version of zlib.h and the
version of the library linked do not match, or Z_ERRNO if there is
an error reading or writing the files. */
int def(FILE *source, FILE *dest, int level)
{
</b></pre>
Here are the local variables for <tt>def()</tt>. <tt>ret</tt> will be used for <em>zlib</em>
return codes. <tt>flush</tt> will keep track of the current flushing state for <tt>deflate()</tt>,
which is either no flushing, or flush to completion after the end of the input file is reached.
<tt>have</tt> is the amount of data returned from <tt>deflate()</tt>. The <tt>strm</tt> structure
is used to pass information to and from the <em>zlib</em> routines, and to maintain the
<tt>deflate()</tt> state. <tt>in</tt> and <tt>out</tt> are the input and output buffers for
<tt>deflate()</tt>.
<pre><b>
int ret, flush;
unsigned have;
z_stream strm;
char in[CHUNK];
char out[CHUNK];
</b></pre><!-- -->
The first thing we do is to initialize the <em>zlib</em> state for compression using
<tt>deflateInit()</tt>. This must be done before the first use of <tt>deflate()</tt>.
The <tt>zalloc</tt>, <tt>zfree</tt>, and <tt>opaque</tt> fields in the <tt>strm</tt>
structure must be initialized before calling <tt>deflateInit()</tt>. Here they are
set to the <em>zlib</em> constant <tt>Z_NULL</tt> to request that <em>zlib</em> use
the default memory allocation routines. An application may also choose to provide
custom memory allocation routines here. <tt>deflateInit()</tt> will allocate on the
order of 256K bytes for the internal state.
(See <a href="zlib_tech.html"><em>zlib Technical Details</em></a>.)
<p>
<tt>deflateInit()</tt> is called with a pointer to the structure to be initialized and
the compression level, which is an integer in the range of -1 to 9. Lower compression
levels result in faster execution, but less compression. Higher levels result in
greater compression, but slower execution. The <em>zlib</em> constant Z_DEFAULT_COMPRESSION,
equal to -1,
provides a good compromise between compression and speed and is equivalent to level 6.
Level 0 actually does no compression at all, and in fact expands the data slightly to produce
the <em>zlib</em> format (it is not a byte-for-byte copy of the input).
More advanced applications of <em>zlib</em>
may use <tt>deflateInit2()</tt> here instead. Such an application may want to reduce how
much memory will be used, at some price in compression. Or it may need to request a
<em>gzip</em> header and trailer instead of a <em>zlib</em> header and trailer, or raw
encoding with no header or trailer at all.
<p>
We must check the return value of <tt>deflateInit()</tt> against the <em>zlib</em> constant
<tt>Z_OK</tt> to make sure that it was able to
allocate memory for the internal state, and that the provided arguments were valid.
<tt>deflateInit()</tt> will also check that the version of <em>zlib</em> that the <tt>zlib.h</tt>
file came from matches the version of <em>zlib</em> actually linked with the program. This
is especially important for environments in which <em>zlib</em> is a shared library.
<p>
Note that an application can initialize multiple, independent <em>zlib</em> streams, which can
operate in parallel. The state information maintained in the structure allows the <em>zlib</em>
routines to be reentrant.
<pre><b>
/* allocate deflate state */
strm.zalloc = Z_NULL;
strm.zfree = Z_NULL;
strm.opaque = Z_NULL;
ret = deflateInit(&amp;strm, level);
if (ret != Z_OK)
return ret;
</b></pre><!-- -->
With the pleasantries out of the way, now we can get down to business. The outer <tt>do</tt>-loop
reads all of the input file and exits at the bottom of the loop once end-of-file is reached.
This loop contains the only call of <tt>deflate()</tt>. So we must make sure that all of the
input data has been processed and that all of the output data has been generated and consumed
before we fall out of the loop at the bottom.
<pre><b>
/* compress until end of file */
do {
</b></pre>
We start off by reading data from the input file. The number of bytes read is put directly
into <tt>avail_in</tt>, and a pointer to those bytes is put into <tt>next_in</tt>. We also
check to see if end-of-file on the input has been reached. If we are at the end of file, then <tt>flush</tt> is set to the
<em>zlib</em> constant <tt>Z_FINISH</tt>, which is later passed to <tt>deflate()</tt> to
indicate that this is the last chunk of input data to compress. We need to use <tt>feof()</tt>
to check for end-of-file as opposed to seeing if fewer than <tt>CHUNK</tt> bytes have been read. The
reason is that if the input file length is an exact multiple of <tt>CHUNK</tt>, we will miss
the fact that we got to the end-of-file, and not know to tell <tt>deflate()</tt> to finish
up the compressed stream. If we are not yet at the end of the input, then the <em>zlib</em>
constant <tt>Z_NO_FLUSH</tt> will be passed to <tt>deflate</tt> to indicate that we are still
in the middle of the uncompressed data.
<p>
If there is an error in reading from the input file, the process is aborted with
<tt>deflateEnd()</tt> being called to free the allocated <em>zlib</em> state before returning
the error. We wouldn't want a memory leak, now would we? <tt>deflateEnd()</tt> can be called
at any time after the state has been initialized. Once that's done, <tt>deflateInit()</tt> (or
<tt>deflateInit2()</tt>) would have to be called to start a new compression process. There is
no point here in checking the <tt>deflateEnd()</tt> return code. The deallocation can't fail.
<pre><b>
strm.avail_in = fread(in, 1, CHUNK, source);
if (ferror(source)) {
(void)deflateEnd(&amp;strm);
return Z_ERRNO;
}
flush = feof(source) ? Z_FINISH : Z_NO_FLUSH;
strm.next_in = in;
</b></pre><!-- -->
The inner <tt>do</tt>-loop passes our chunk of input data to <tt>deflate()</tt>, and then
keeps calling <tt>deflate()</tt> until it is done producing output. Once there is no more
new output, <tt>deflate()</tt> is guaranteed to have consumed all of the input, i.e.,
<tt>avail_in</tt> will be zero.
<pre><b>
/* run deflate() on input until output buffer not full, finish
compression if all of source has been read in */
do {
</b></pre>
Output space is provided to <tt>deflate()</tt> by setting <tt>avail_out</tt> to the number
of available output bytes and <tt>next_out</tt> to a pointer to that space.
<pre><b>
strm.avail_out = CHUNK;
strm.next_out = out;
</b></pre>
Now we call the compression engine itself, <tt>deflate()</tt>. It takes as many of the
<tt>avail_in</tt> bytes at <tt>next_in</tt> as it can process, and writes as many as
<tt>avail_out</tt> bytes to <tt>next_out</tt>. Those counters and pointers are then
updated past the input data consumed and the output data written. It is the amount of
output space available that may limit how much input is consumed.
Hence the inner loop to make sure that
all of the input is consumed by providing more output space each time. Since <tt>avail_in</tt>
and <tt>next_in</tt> are updated by <tt>deflate()</tt>, we don't have to mess with those
between <tt>deflate()</tt> calls until it's all used up.
<p>
The parameters to <tt>deflate()</tt> are a pointer to the <tt>strm</tt> structure containing
the input and output information and the internal compression engine state, and a parameter
indicating whether and how to flush data to the output. Normally <tt>deflate</tt> will consume
several K bytes of input data before producing any output (except for the header), in order
to accumulate statistics on the data for optimum compression. It will then put out a burst of
compressed data, and proceed to consume more input before the next burst. Eventually,
<tt>deflate()</tt>
must be told to terminate the stream, complete the compression with provided input data, and
write out the trailer check value. <tt>deflate()</tt> will continue to compress normally as long
as the flush parameter is <tt>Z_NO_FLUSH</tt>. Once the <tt>Z_FINISH</tt> parameter is provided,
<tt>deflate()</tt> will begin to complete the compressed output stream. However depending on how
much output space is provided, <tt>deflate()</tt> may have to be called several times until it
has provided the complete compressed stream, even after it has consumed all of the input. The flush
parameter must continue to be <tt>Z_FINISH</tt> for those subsequent calls.
<p>
There are other values of the flush parameter that are used in more advanced applications. You can
force <tt>deflate()</tt> to produce a burst of output that encodes all of the input data provided
so far, even if it wouldn't have otherwise, for example to control data latency on a link with
compressed data. You can also ask that <tt>deflate()</tt> do that as well as erase any history up to
that point so that what follows can be decompressed independently, for example for random access
applications. Both requests will degrade compression by an amount depending on how often such
requests are made.
<p>
<tt>deflate()</tt> has a return value that can indicate errors, yet we do not check it here. Why
not? Well, it turns out that <tt>deflate()</tt> can do no wrong here. Let's go through
<tt>deflate()</tt>'s return values and dispense with them one by one. The possible values are
<tt>Z_OK</tt>, <tt>Z_STREAM_END</tt>, <tt>Z_STREAM_ERROR</tt>, or <tt>Z_BUF_ERROR</tt>. <tt>Z_OK</tt>
is, well, ok. <tt>Z_STREAM_END</tt> is also ok and will be returned for the last call of
<tt>deflate()</tt>. This is already guaranteed by calling <tt>deflate()</tt> with <tt>Z_FINISH</tt>
until it has no more output. <tt>Z_STREAM_ERROR</tt> is only possible if the stream is not
initialized properly, but we did initialize it properly. There is no harm in checking for
<tt>Z_STREAM_ERROR</tt> here, for example to check for the possibility that some
other part of the application inadvertently clobbered the memory containing the <em>zlib</em> state.
<tt>Z_BUF_ERROR</tt> will be explained further below, but
suffice it to say that this is simply an indication that <tt>deflate()</tt> could not consume
more input or produce more output. <tt>deflate()</tt> can be called again with more output space
or more available input, which it will be in this code.
<pre><b>
ret = deflate(&amp;strm, flush); /* no bad return value */
assert(ret != Z_STREAM_ERROR); /* state not clobbered */
</b></pre>
Now we compute how much output <tt>deflate()</tt> provided on the last call, which is the
difference between how much space was provided before the call, and how much output space
is still available after the call. Then that data, if any, is written to the output file.
We can then reuse the output buffer for the next call of <tt>deflate()</tt>. Again if there
is a file i/o error, we call <tt>deflateEnd()</tt> before returning to avoid a memory leak.
<pre><b>
have = CHUNK - strm.avail_out;
if (fwrite(out, 1, have, dest) != have || ferror(dest)) {
(void)deflateEnd(&amp;strm);
return Z_ERRNO;
}
</b></pre>
The inner <tt>do</tt>-loop is repeated until the last <tt>deflate()</tt> call fails to fill the
provided output buffer. Then we know that <tt>deflate()</tt> has done as much as it can with
the provided input, and that all of that input has been consumed. We can then fall out of this
loop and reuse the input buffer.
<p>
The way we tell that <tt>deflate()</tt> has no more output is by seeing that it did not fill
the output buffer, leaving <tt>avail_out</tt> greater than zero. However suppose that
<tt>deflate()</tt> has no more output, but just so happened to exactly fill the output buffer!
<tt>avail_out</tt> is zero, and we can't tell that <tt>deflate()</tt> has done all it can.
As far as we know, <tt>deflate()</tt>
has more output for us. So we call it again. But now <tt>deflate()</tt> produces no output
at all, and <tt>avail_out</tt> remains unchanged as <tt>CHUNK</tt>. That <tt>deflate()</tt> call
wasn't able to do anything, either consume input or produce output, and so it returns
<tt>Z_BUF_ERROR</tt>. (See, I told you I'd cover this later.) However this is not a problem at
all. Now we finally have the desired indication that <tt>deflate()</tt> is really done,
and so we drop out of the inner loop to provide more input to <tt>deflate()</tt>.
<p>
With <tt>flush</tt> set to <tt>Z_FINISH</tt>, this final set of <tt>deflate()</tt> calls will
complete the output stream. Once that is done, subsequent calls of <tt>deflate()</tt> would return
<tt>Z_STREAM_ERROR</tt> if the flush parameter is not <tt>Z_FINISH</tt>, and do no more processing
until the state is reinitialized.
<p>
Some applications of <em>zlib</em> have two loops that call <tt>deflate()</tt>
instead of the single inner loop we have here. The first loop would call
without flushing and feed all of the data to <tt>deflate()</tt>. The second loop would call
<tt>deflate()</tt> with no more
data and the <tt>Z_FINISH</tt> parameter to complete the process. As you can see from this
example, that can be avoided by simply keeping track of the current flush state.
<pre><b>
} while (strm.avail_out == 0);
assert(strm.avail_in == 0); /* all input will be used */
</b></pre><!-- -->
Now we check to see if we have already processed all of the input file. That information was
saved in the <tt>flush</tt> variable, so we see if that was set to <tt>Z_FINISH</tt>. If so,
then we're done and we fall out of the outer loop. We're guaranteed to get <tt>Z_STREAM_END</tt>
from the last <tt>deflate()</tt> call, since we ran it until the last chunk of input was
consumed and all of the output was generated.
<pre><b>
/* done when last data in file processed */
} while (flush != Z_FINISH);
assert(ret == Z_STREAM_END); /* stream will be complete */
</b></pre><!-- -->
The process is complete, but we still need to deallocate the state to avoid a memory leak
(or rather more like a memory hemorrhage if you didn't do this). Then
finally we can return with a happy return value.
<pre><b>
/* clean up and return */
(void)deflateEnd(&amp;strm);
return Z_OK;
}
</b></pre><!-- -->
Now we do the same thing for decompression in the <tt>inf()</tt> routine. <tt>inf()</tt>
decompresses what is hopefully a valid <em>zlib</em> stream from the input file and writes the
uncompressed data to the output file. Much of the discussion above for <tt>def()</tt>
applies to <tt>inf()</tt> as well, so the discussion here will focus on the differences between
the two.
<pre><b>
/* Decompress from file source to file dest until stream ends or EOF.
inf() returns Z_OK on success, Z_MEM_ERROR if memory could not be
allocated for processing, Z_DATA_ERROR if the deflate data is
invalid or incomplete, Z_VERSION_ERROR if the version of zlib.h and
the version of the library linked do not match, or Z_ERRNO if there
is an error reading or writing the files. */
int inf(FILE *source, FILE *dest)
{
</b></pre>
The local variables have the same functionality as they do for <tt>def()</tt>. The
only difference is that there is no <tt>flush</tt> variable, since <tt>inflate()</tt>
can tell from the <em>zlib</em> stream itself when the stream is complete.
<pre><b>
int ret;
unsigned have;
z_stream strm;
char in[CHUNK];
char out[CHUNK];
</b></pre><!-- -->
The initialization of the state is the same, except that there is no compression level,
of course, and two more elements of the structure are initialized. <tt>avail_in</tt>
and <tt>next_in</tt> must be initialized before calling <tt>inflateInit()</tt>. This
is because the application has the option to provide the start of the zlib stream in
order for <tt>inflateInit()</tt> to have access to information about the compression
method to aid in memory allocation. In the current implementation of <em>zlib</em>
(up through versions 1.2.x), the method-dependent memory allocations are deferred to the first call of
<tt>inflate()</tt> anyway. However those fields must be initialized since later versions
of <em>zlib</em> that provide more compression methods may take advantage of this interface.
In any case, no decompression is performed by <tt>inflateInit()</tt>, so the
<tt>avail_out</tt> and <tt>next_out</tt> fields do not need to be initialized before calling.
<p>
Here <tt>avail_in</tt> is set to zero and <tt>next_in</tt> is set to <tt>Z_NULL</tt> to
indicate that no input data is being provided.
<pre><b>
/* allocate inflate state */
strm.zalloc = Z_NULL;
strm.zfree = Z_NULL;
strm.opaque = Z_NULL;
strm.avail_in = 0;
strm.next_in = Z_NULL;
ret = inflateInit(&amp;strm);
if (ret != Z_OK)
return ret;
</b></pre><!-- -->
The outer <tt>do</tt>-loop decompresses input until <tt>inflate()</tt> indicates
that it has reached the end of the compressed data and has produced all of the uncompressed
output. This is in contrast to <tt>def()</tt> which processes all of the input file.
If end-of-file is reached before the compressed data self-terminates, then the compressed
data is incomplete and an error is returned.
<pre><b>
/* decompress until deflate stream ends or end of file */
do {
</b></pre>
We read input data and set the <tt>strm</tt> structure accordingly. If we've reached the
end of the input file, then we leave the outer loop and report an error, since the
compressed data is incomplete. Note that we may read more data than is eventually consumed
by <tt>inflate()</tt>, if the input file continues past the <em>zlib</em> stream.
For applications where <em>zlib</em> streams are embedded in other data, this routine would
need to be modified to return the unused data, or at least indicate how much of the input
data was not used, so the application would know where to pick up after the <em>zlib</em> stream.
<pre><b>
strm.avail_in = fread(in, 1, CHUNK, source);
if (ferror(source)) {
(void)inflateEnd(&amp;strm);
return Z_ERRNO;
}
if (strm.avail_in == 0)
break;
strm.next_in = in;
</b></pre><!-- -->
The inner <tt>do</tt>-loop has the same function it did in <tt>def()</tt>, which is to
keep calling <tt>inflate()</tt> until has generated all of the output it can with the
provided input.
<pre><b>
/* run inflate() on input until output buffer not full */
do {
</b></pre>
Just like in <tt>def()</tt>, the same output space is provided for each call of <tt>inflate()</tt>.
<pre><b>
strm.avail_out = CHUNK;
strm.next_out = out;
</b></pre>
Now we run the decompression engine itself. There is no need to adjust the flush parameter, since
the <em>zlib</em> format is self-terminating. The main difference here is that there are
return values that we need to pay attention to. <tt>Z_DATA_ERROR</tt>
indicates that <tt>inflate()</tt> detected an error in the <em>zlib</em> compressed data format,
which means that either the data is not a <em>zlib</em> stream to begin with, or that the data was
corrupted somewhere along the way since it was compressed. The other error to be processed is
<tt>Z_MEM_ERROR</tt>, which can occur since memory allocation is deferred until <tt>inflate()</tt>
needs it, unlike <tt>deflate()</tt>, whose memory is allocated at the start by <tt>deflateInit()</tt>.
<p>
Advanced applications may use
<tt>deflateSetDictionary()</tt> to prime <tt>deflate()</tt> with a set of likely data to improve the
first 32K or so of compression. This is noted in the <em>zlib</em> header, so <tt>inflate()</tt>
requests that that dictionary be provided before it can start to decompress. Without the dictionary,
correct decompression is not possible. For this routine, we have no idea what the dictionary is,
so the <tt>Z_NEED_DICT</tt> indication is converted to a <tt>Z_DATA_ERROR</tt>.
<p>
<tt>inflate()</tt> can also return <tt>Z_STREAM_ERROR</tt>, which should not be possible here,
but could be checked for as noted above for <tt>def()</tt>. <tt>Z_BUF_ERROR</tt> does not need to be
checked for here, for the same reasons noted for <tt>def()</tt>. <tt>Z_STREAM_END</tt> will be
checked for later.
<pre><b>
ret = inflate(&amp;strm, Z_NO_FLUSH);
assert(ret != Z_STREAM_ERROR); /* state not clobbered */
switch (ret) {
case Z_NEED_DICT:
ret = Z_DATA_ERROR; /* and fall through */
case Z_DATA_ERROR:
case Z_MEM_ERROR:
(void)inflateEnd(&amp;strm);
return ret;
}
</b></pre>
The output of <tt>inflate()</tt> is handled identically to that of <tt>deflate()</tt>.
<pre><b>
have = CHUNK - strm.avail_out;
if (fwrite(out, 1, have, dest) != have || ferror(dest)) {
(void)inflateEnd(&amp;strm);
return Z_ERRNO;
}
</b></pre>
The inner <tt>do</tt>-loop ends when <tt>inflate()</tt> has no more output as indicated
by not filling the output buffer, just as for <tt>deflate()</tt>. In this case, we cannot
assert that <tt>strm.avail_in</tt> will be zero, since the deflate stream may end before the file
does.
<pre><b>
} while (strm.avail_out == 0);
</b></pre><!-- -->
The outer <tt>do</tt>-loop ends when <tt>inflate()</tt> reports that it has reached the
end of the input <em>zlib</em> stream, has completed the decompression and integrity
check, and has provided all of the output. This is indicated by the <tt>inflate()</tt>
return value <tt>Z_STREAM_END</tt>. The inner loop is guaranteed to leave <tt>ret</tt>
equal to <tt>Z_STREAM_END</tt> if the last chunk of the input file read contained the end
of the <em>zlib</em> stream. So if the return value is not <tt>Z_STREAM_END</tt>, the
loop continues to read more input.
<pre><b>
/* done when inflate() says it's done */
} while (ret != Z_STREAM_END);
</b></pre><!-- -->
At this point, decompression successfully completed, or we broke out of the loop due to no
more data being available from the input file. If the last <tt>inflate()</tt> return value
is not <tt>Z_STREAM_END</tt>, then the <em>zlib</em> stream was incomplete and a data error
is returned. Otherwise, we return with a happy return value. Of course, <tt>inflateEnd()</tt>
is called first to avoid a memory leak.
<pre><b>
/* clean up and return */
(void)inflateEnd(&amp;strm);
return ret == Z_STREAM_END ? Z_OK : Z_DATA_ERROR;
}
</b></pre><!-- -->
That ends the routines that directly use <em>zlib</em>. The following routines make this
a command-line program by running data through the above routines from <tt>stdin</tt> to
<tt>stdout</tt>, and handling any errors reported by <tt>def()</tt> or <tt>inf()</tt>.
<p>
<tt>zerr()</tt> is used to interpret the possible error codes from <tt>def()</tt>
and <tt>inf()</tt>, as detailed in their comments above, and print out an error message.
Note that these are only a subset of the possible return values from <tt>deflate()</tt>
and <tt>inflate()</tt>.
<pre><b>
/* report a zlib or i/o error */
void zerr(int ret)
{
fputs("zpipe: ", stderr);
switch (ret) {
case Z_ERRNO:
if (ferror(stdin))
fputs("error reading stdin\n", stderr);
if (ferror(stdout))
fputs("error writing stdout\n", stderr);
break;
case Z_STREAM_ERROR:
fputs("invalid compression level\n", stderr);
break;
case Z_DATA_ERROR:
fputs("invalid or incomplete deflate data\n", stderr);
break;
case Z_MEM_ERROR:
fputs("out of memory\n", stderr);
break;
case Z_VERSION_ERROR:
fputs("zlib version mismatch!\n", stderr);
}
}
</b></pre><!-- -->
Here is the <tt>main()</tt> routine used to test <tt>def()</tt> and <tt>inf()</tt>. The
<tt>zpipe</tt> command is simply a compression pipe from <tt>stdin</tt> to <tt>stdout</tt>, if
no arguments are given, or it is a decompression pipe if <tt>zpipe -d</tt> is used. If any other
arguments are provided, no compression or decompression is performed. Instead a usage
message is displayed. Examples are <tt>zpipe < foo.txt > foo.txt.z</tt> to compress, and
<tt>zpipe -d < foo.txt.z > foo.txt</tt> to decompress.
<pre><b>
/* compress or decompress from stdin to stdout */
int main(int argc, char **argv)
{
int ret;
/* do compression if no arguments */
if (argc == 1) {
ret = def(stdin, stdout, Z_DEFAULT_COMPRESSION);
if (ret != Z_OK)
zerr(ret);
return ret;
}
/* do decompression if -d specified */
else if (argc == 2 &amp;&amp; strcmp(argv[1], "-d") == 0) {
ret = inf(stdin, stdout);
if (ret != Z_OK)
zerr(ret);
return ret;
}
/* otherwise, report usage */
else {
fputs("zpipe usage: zpipe [-d] &lt; source &gt; dest\n", stderr);
return 1;
}
}
</b></pre>
<hr>
<i>Copyright (c) 2004 by Mark Adler<br>Last modified 13 November 2004</i>
</body>
</html>

191
examples/zpipe.c Normal file
View File

@@ -0,0 +1,191 @@
/* zpipe.c: example of proper use of zlib's inflate() and deflate()
Not copyrighted -- provided to the public domain
Version 1.2 9 November 2004 Mark Adler */
/* Version history:
1.0 30 Oct 2004 First version
1.1 8 Nov 2004 Add void casting for unused return values
Use switch statement for inflate() return values
1.2 9 Nov 2004 Add assertions to document zlib guarantees
1.3 6 Apr 2005 Remove incorrect assertion in inf()
*/
#include <stdio.h>
#include <string.h>
#include <assert.h>
#include "zlib.h"
#define CHUNK 16384
/* Compress from file source to file dest until EOF on source.
def() returns Z_OK on success, Z_MEM_ERROR if memory could not be
allocated for processing, Z_STREAM_ERROR if an invalid compression
level is supplied, Z_VERSION_ERROR if the version of zlib.h and the
version of the library linked do not match, or Z_ERRNO if there is
an error reading or writing the files. */
int def(FILE *source, FILE *dest, int level)
{
int ret, flush;
unsigned have;
z_stream strm;
char in[CHUNK];
char out[CHUNK];
/* allocate deflate state */
strm.zalloc = Z_NULL;
strm.zfree = Z_NULL;
strm.opaque = Z_NULL;
ret = deflateInit(&strm, level);
if (ret != Z_OK)
return ret;
/* compress until end of file */
do {
strm.avail_in = fread(in, 1, CHUNK, source);
if (ferror(source)) {
(void)deflateEnd(&strm);
return Z_ERRNO;
}
flush = feof(source) ? Z_FINISH : Z_NO_FLUSH;
strm.next_in = in;
/* run deflate() on input until output buffer not full, finish
compression if all of source has been read in */
do {
strm.avail_out = CHUNK;
strm.next_out = out;
ret = deflate(&strm, flush); /* no bad return value */
assert(ret != Z_STREAM_ERROR); /* state not clobbered */
have = CHUNK - strm.avail_out;
if (fwrite(out, 1, have, dest) != have || ferror(dest)) {
(void)deflateEnd(&strm);
return Z_ERRNO;
}
} while (strm.avail_out == 0);
assert(strm.avail_in == 0); /* all input will be used */
/* done when last data in file processed */
} while (flush != Z_FINISH);
assert(ret == Z_STREAM_END); /* stream will be complete */
/* clean up and return */
(void)deflateEnd(&strm);
return Z_OK;
}
/* Decompress from file source to file dest until stream ends or EOF.
inf() returns Z_OK on success, Z_MEM_ERROR if memory could not be
allocated for processing, Z_DATA_ERROR if the deflate data is
invalid or incomplete, Z_VERSION_ERROR if the version of zlib.h and
the version of the library linked do not match, or Z_ERRNO if there
is an error reading or writing the files. */
int inf(FILE *source, FILE *dest)
{
int ret;
unsigned have;
z_stream strm;
char in[CHUNK];
char out[CHUNK];
/* allocate inflate state */
strm.zalloc = Z_NULL;
strm.zfree = Z_NULL;
strm.opaque = Z_NULL;
strm.avail_in = 0;
strm.next_in = Z_NULL;
ret = inflateInit(&strm);
if (ret != Z_OK)
return ret;
/* decompress until deflate stream ends or end of file */
do {
strm.avail_in = fread(in, 1, CHUNK, source);
if (ferror(source)) {
(void)inflateEnd(&strm);
return Z_ERRNO;
}
if (strm.avail_in == 0)
break;
strm.next_in = in;
/* run inflate() on input until output buffer not full */
do {
strm.avail_out = CHUNK;
strm.next_out = out;
ret = inflate(&strm, Z_NO_FLUSH);
assert(ret != Z_STREAM_ERROR); /* state not clobbered */
switch (ret) {
case Z_NEED_DICT:
ret = Z_DATA_ERROR; /* and fall through */
case Z_DATA_ERROR:
case Z_MEM_ERROR:
(void)inflateEnd(&strm);
return ret;
}
have = CHUNK - strm.avail_out;
if (fwrite(out, 1, have, dest) != have || ferror(dest)) {
(void)inflateEnd(&strm);
return Z_ERRNO;
}
} while (strm.avail_out == 0);
/* done when inflate() says it's done */
} while (ret != Z_STREAM_END);
/* clean up and return */
(void)inflateEnd(&strm);
return ret == Z_STREAM_END ? Z_OK : Z_DATA_ERROR;
}
/* report a zlib or i/o error */
void zerr(int ret)
{
fputs("zpipe: ", stderr);
switch (ret) {
case Z_ERRNO:
if (ferror(stdin))
fputs("error reading stdin\n", stderr);
if (ferror(stdout))
fputs("error writing stdout\n", stderr);
break;
case Z_STREAM_ERROR:
fputs("invalid compression level\n", stderr);
break;
case Z_DATA_ERROR:
fputs("invalid or incomplete deflate data\n", stderr);
break;
case Z_MEM_ERROR:
fputs("out of memory\n", stderr);
break;
case Z_VERSION_ERROR:
fputs("zlib version mismatch!\n", stderr);
}
}
/* compress or decompress from stdin to stdout */
int main(int argc, char **argv)
{
int ret;
/* do compression if no arguments */
if (argc == 1) {
ret = def(stdin, stdout, Z_DEFAULT_COMPRESSION);
if (ret != Z_OK)
zerr(ret);
return ret;
}
/* do decompression if -d specified */
else if (argc == 2 && strcmp(argv[1], "-d") == 0) {
ret = inf(stdin, stdout);
if (ret != Z_OK)
zerr(ret);
return ret;
}
/* otherwise, report usage */
else {
fputs("zpipe usage: zpipe [-d] < source > dest\n", stderr);
return 1;
}
}

37
gzio.c
View File

@@ -1,5 +1,5 @@
/* gzio.c -- IO on .gz files /* gzio.c -- IO on .gz files
* Copyright (C) 1995-2004 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
* *
* Compile this file with -DNO_GZCOMPRESS to avoid the compression code. * Compile this file with -DNO_GZCOMPRESS to avoid the compression code.
@@ -220,7 +220,7 @@ gzFile ZEXPORT gzdopen (fd, mode)
int fd; int fd;
const char *mode; const char *mode;
{ {
char name[20]; char name[46]; /* allow for up to 128-bit integers */
if (fd < 0) return (gzFile)Z_NULL; if (fd < 0) return (gzFile)Z_NULL;
sprintf(name, "<fd:%d>", fd); /* for debugging */ sprintf(name, "<fd:%d>", fd); /* for debugging */
@@ -264,7 +264,7 @@ local int get_byte(s)
if (s->z_eof) return EOF; if (s->z_eof) return EOF;
if (s->stream.avail_in == 0) { if (s->stream.avail_in == 0) {
errno = 0; errno = 0;
s->stream.avail_in = fread(s->inbuf, 1, Z_BUFSIZE, s->file); s->stream.avail_in = (uInt)fread(s->inbuf, 1, Z_BUFSIZE, s->file);
if (s->stream.avail_in == 0) { if (s->stream.avail_in == 0) {
s->z_eof = 1; s->z_eof = 1;
if (ferror(s->file)) s->z_err = Z_ERRNO; if (ferror(s->file)) s->z_err = Z_ERRNO;
@@ -300,7 +300,7 @@ local void check_header(s)
if (len < 2) { if (len < 2) {
if (len) s->inbuf[0] = s->stream.next_in[0]; if (len) s->inbuf[0] = s->stream.next_in[0];
errno = 0; errno = 0;
len = fread(s->inbuf + len, 1, Z_BUFSIZE >> len, s->file); len = (uInt)fread(s->inbuf + len, 1, Z_BUFSIZE >> len, s->file);
if (len == 0 && ferror(s->file)) s->z_err = Z_ERRNO; if (len == 0 && ferror(s->file)) s->z_err = Z_ERRNO;
s->stream.avail_in += len; s->stream.avail_in += len;
s->stream.next_in = s->inbuf; s->stream.next_in = s->inbuf;
@@ -415,6 +415,7 @@ int ZEXPORT gzread (file, buf, len)
s->stream.avail_out--; s->stream.avail_out--;
s->back = EOF; s->back = EOF;
s->out++; s->out++;
start++;
if (s->last) { if (s->last) {
s->z_err = Z_STREAM_END; s->z_err = Z_STREAM_END;
return 1; return 1;
@@ -436,8 +437,8 @@ int ZEXPORT gzread (file, buf, len)
s->stream.avail_in -= n; s->stream.avail_in -= n;
} }
if (s->stream.avail_out > 0) { if (s->stream.avail_out > 0) {
s->stream.avail_out -= fread(next_out, 1, s->stream.avail_out, s->stream.avail_out -=
s->file); (uInt)fread(next_out, 1, s->stream.avail_out, s->file);
} }
len -= s->stream.avail_out; len -= s->stream.avail_out;
s->in += len; s->in += len;
@@ -448,17 +449,13 @@ int ZEXPORT gzread (file, buf, len)
if (s->stream.avail_in == 0 && !s->z_eof) { if (s->stream.avail_in == 0 && !s->z_eof) {
errno = 0; errno = 0;
s->stream.avail_in = fread(s->inbuf, 1, Z_BUFSIZE, s->file); s->stream.avail_in = (uInt)fread(s->inbuf, 1, Z_BUFSIZE, s->file);
if (s->stream.avail_in == 0) { if (s->stream.avail_in == 0) {
s->z_eof = 1; s->z_eof = 1;
if (ferror(s->file)) { if (ferror(s->file)) {
s->z_err = Z_ERRNO; s->z_err = Z_ERRNO;
break; break;
} }
if (feof(s->file)) { /* avoid error for empty file */
s->z_err = Z_STREAM_END;
break;
}
} }
s->stream.next_in = s->inbuf; s->stream.next_in = s->inbuf;
} }
@@ -902,6 +899,18 @@ int ZEXPORT gzeof (file)
return s->z_err == Z_STREAM_END; return s->z_err == Z_STREAM_END;
} }
/* ===========================================================================
Returns 1 if reading and doing so transparently, otherwise zero.
*/
int ZEXPORT gzdirect (file)
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 Outputs a long in LSB order to the given file
*/ */
@@ -959,6 +968,12 @@ int ZEXPORT gzclose (file)
return destroy((gz_stream*)file); 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 occured on the Returns the error message for the last error which occured on the
given compressed file. errnum is set to zlib error number. If an given compressed file. errnum is set to zlib error number. If an

View File

@@ -51,6 +51,7 @@ int stream_size;
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 = (voidpf)state; strm->state = (voidpf)state;
state->dmax = 32768U;
state->wbits = windowBits; state->wbits = windowBits;
state->wsize = 1U << windowBits; state->wsize = 1U << windowBits;
state->window = window; state->window = window;

View File

@@ -74,6 +74,9 @@ unsigned start; /* inflate()'s starting value for strm->avail_out */
unsigned char FAR *out; /* local strm->next_out */ unsigned char FAR *out; /* local strm->next_out */
unsigned char FAR *beg; /* inflate()'s initial strm->next_out */ unsigned char FAR *beg; /* inflate()'s initial strm->next_out */
unsigned char FAR *end; /* while out < end, enough space available */ unsigned char FAR *end; /* while out < end, enough space available */
#ifdef INFLATE_STRICT
unsigned dmax; /* maximum distance from zlib header */
#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 write; /* window write index */
@@ -98,6 +101,9 @@ unsigned start; /* inflate()'s starting value for strm->avail_out */
out = strm->next_out - OFF; out = strm->next_out - OFF;
beg = out - (start - strm->avail_out); beg = out - (start - strm->avail_out);
end = out + (strm->avail_out - 257); end = out + (strm->avail_out - 257);
#ifdef INFLATE_STRICT
dmax = state->dmax;
#endif
wsize = state->wsize; wsize = state->wsize;
whave = state->whave; whave = state->whave;
write = state->write; write = state->write;
@@ -167,6 +173,13 @@ unsigned start; /* inflate()'s starting value for strm->avail_out */
} }
} }
dist += (unsigned)hold & ((1U << op) - 1); dist += (unsigned)hold & ((1U << op) - 1);
#ifdef INFLATE_STRICT
if (dist > dmax) {
strm->msg = (char *)"invalid distance too far back";
state->mode = BAD;
break;
}
#endif
hold >>= op; hold >>= op;
bits -= op; bits -= op;
Tracevv((stderr, "inflate: distance %u\n", dist)); Tracevv((stderr, "inflate: distance %u\n", dist));

View File

@@ -1,5 +1,5 @@
/* inflate.c -- zlib decompression /* inflate.c -- zlib decompression
* Copyright (C) 1995-2004 Mark Adler * Copyright (C) 1995-2005 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
*/ */
@@ -113,6 +113,7 @@ z_streamp strm;
state->mode = HEAD; state->mode = HEAD;
state->last = 0; state->last = 0;
state->havedict = 0; state->havedict = 0;
state->dmax = 32768U;
state->head = Z_NULL; state->head = Z_NULL;
state->wsize = 0; state->wsize = 0;
state->whave = 0; state->whave = 0;
@@ -600,11 +601,13 @@ int flush;
break; break;
} }
DROPBITS(4); DROPBITS(4);
if (BITS(4) + 8 > state->wbits) { len = BITS(4) + 8;
if (len > state->wbits) {
strm->msg = (char *)"invalid window size"; strm->msg = (char *)"invalid window size";
state->mode = BAD; state->mode = BAD;
break; break;
} }
state->dmax = 1U << len;
Tracev((stderr, "inflate: zlib header ok\n")); Tracev((stderr, "inflate: zlib header ok\n"));
strm->adler = state->check = adler32(0L, Z_NULL, 0); strm->adler = state->check = adler32(0L, Z_NULL, 0);
state->mode = hold & 0x200 ? DICTID : TYPE; state->mode = hold & 0x200 ? DICTID : TYPE;
@@ -1009,6 +1012,13 @@ int flush;
state->offset += BITS(state->extra); state->offset += BITS(state->extra);
DROPBITS(state->extra); DROPBITS(state->extra);
} }
#ifdef INFLATE_STRICT
if (state->offset > state->dmax) {
strm->msg = (char *)"invalid distance too far back";
state->mode = BAD;
break;
}
#endif
if (state->offset > state->whave + out - left) { if (state->offset > state->whave + out - left) {
strm->msg = (char *)"invalid distance too far back"; strm->msg = (char *)"invalid distance too far back";
state->mode = BAD; state->mode = BAD;
@@ -1322,13 +1332,17 @@ z_streamp source;
} }
/* copy state */ /* copy state */
*dest = *source; zmemcpy(dest, source, sizeof(z_stream));
*copy = *state; zmemcpy(copy, state, sizeof(struct inflate_state));
copy->lencode = copy->codes + (state->lencode - state->codes); if (state->lencode >= state->codes &&
copy->distcode = copy->codes + (state->distcode - state->codes); state->lencode <= state->codes + ENOUGH - 1)
{
copy->lencode = copy->codes + (state->lencode - state->codes);
copy->distcode = copy->codes + (state->distcode - state->codes);
}
copy->next = copy->codes + (state->next - state->codes); copy->next = copy->codes + (state->next - state->codes);
if (window != Z_NULL) if (window != Z_NULL)
zmemcpy(window, state->window, 1U << state->wbits); zmemcpy(window, state->window, (uInt)(1U << state->wbits));
copy->window = window; copy->window = window;
dest->state = (voidpf)copy; dest->state = (voidpf)copy;
return Z_OK; return Z_OK;

View File

@@ -80,6 +80,7 @@ struct inflate_state {
int wrap; /* bit 0 true for zlib, bit 1 true for gzip */ int wrap; /* bit 0 true for zlib, bit 1 true for gzip */
int havedict; /* true if dictionary provided */ int havedict; /* true if dictionary provided */
int flags; /* gzip header method and flags (0 if zlib) */ int flags; /* gzip header method and flags (0 if zlib) */
unsigned dmax; /* zlib header max distance (INFLATE_STRICT) */
unsigned long check; /* protected copy of check value */ unsigned long check; /* protected copy of check value */
unsigned long total; /* protected copy of output count */ unsigned long total; /* protected copy of output count */
gz_headerp head; /* where to save gzip header information */ gz_headerp head; /* where to save gzip header information */

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-2004 Mark Adler * Copyright (C) 1995-2005 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.2.1 Copyright 1995-2004 Mark Adler "; " inflate 1.2.2.3 Copyright 1995-2005 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
@@ -62,7 +62,7 @@ unsigned short FAR *work;
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, 77, 207}; 19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 16, 66, 71};
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,
@@ -262,7 +262,7 @@ unsigned short FAR *work;
drop = root; drop = root;
/* increment past last table */ /* increment past last table */
next += 1U << curr; next += (unsigned)(1U << curr);
/* determine length of next table */ /* determine length of next table */
curr = len - drop; curr = len - drop;

23
old/Make_vms.com → make_vms.com Executable file → Normal file
View File

@@ -32,25 +32,24 @@ $ CALL MAKE adler32.OBJ "CC ''CCOPT' adler32" -
$ CALL MAKE compress.OBJ "CC ''CCOPT' compress" - $ CALL MAKE compress.OBJ "CC ''CCOPT' compress" -
compress.c zlib.h zconf.h compress.c zlib.h zconf.h
$ CALL MAKE crc32.OBJ "CC ''CCOPT' crc32" - $ CALL MAKE crc32.OBJ "CC ''CCOPT' crc32" -
crc32.c zlib.h zconf.h crc32.c crc32.h zlib.h zconf.h zutil.h
$ CALL MAKE deflate.OBJ "CC ''CCOPT' deflate" - $ CALL MAKE deflate.OBJ "CC ''CCOPT' deflate" -
deflate.c deflate.h zutil.h zlib.h zconf.h deflate.c deflate.h zutil.h zlib.h zconf.h
$ CALL MAKE gzio.OBJ "CC ''CCOPT' gzio" - $ CALL MAKE gzio.OBJ "CC ''CCOPT' gzio /define=""NO_vsnprintf""" -
gzio.c zutil.h zlib.h zconf.h gzio.c zutil.h zlib.h zconf.h
$ CALL MAKE infblock.OBJ "CC ''CCOPT' infblock" - $ CALL MAKE infback.OBJ "CC ''CCOPT' infback" -
infblock.c zutil.h zlib.h zconf.h infblock.h infback.c zutil.h zlib.h zconf.h -
$ CALL MAKE infcodes.OBJ "CC ''CCOPT' infcodes" - "inftrees.h inflate.h inffast.h inffixed.h"
infcodes.c zutil.h zlib.h zconf.h inftrees.h
$ CALL MAKE inffast.OBJ "CC ''CCOPT' inffast" - $ CALL MAKE inffast.OBJ "CC ''CCOPT' inffast" -
inffast.c zutil.h zlib.h zconf.h inffast.h inffast.c zutil.h zlib.h zconf.h -
"inftrees.h inflate.h inffast.h"
$ CALL MAKE inflate.OBJ "CC ''CCOPT' inflate" - $ CALL MAKE inflate.OBJ "CC ''CCOPT' inflate" -
inflate.c zutil.h zlib.h zconf.h infblock.h inflate.c zutil.h zlib.h zconf.h -
"inftrees.h inflate.h inffast.h inffixed.h"
$ CALL MAKE inftrees.OBJ "CC ''CCOPT' inftrees" - $ CALL MAKE inftrees.OBJ "CC ''CCOPT' inftrees" -
inftrees.c zutil.h zlib.h zconf.h inftrees.h inftrees.c zutil.h zlib.h zconf.h inftrees.h
$ CALL MAKE infutil.OBJ "CC ''CCOPT' infutil" -
infutil.c zutil.h zlib.h zconf.h inftrees.h infutil.h
$ CALL MAKE trees.OBJ "CC ''CCOPT' trees" - $ CALL MAKE trees.OBJ "CC ''CCOPT' trees" -
trees.c deflate.h zutil.h zlib.h zconf.h trees.c trees.h deflate.h zutil.h zlib.h zconf.h
$ CALL MAKE uncompr.OBJ "CC ''CCOPT' uncompr" - $ CALL MAKE uncompr.OBJ "CC ''CCOPT' uncompr" -
uncompr.c zlib.h zconf.h uncompr.c zlib.h zconf.h
$ CALL MAKE zutil.OBJ "CC ''CCOPT' zutil" - $ CALL MAKE zutil.OBJ "CC ''CCOPT' zutil" -
@@ -65,7 +64,7 @@ $ write sys$output "Building minigzip..."
$ CALL MAKE minigzip.OBJ "CC ''CCOPT' minigzip" - $ CALL MAKE minigzip.OBJ "CC ''CCOPT' minigzip" -
minigzip.c zlib.h zconf.h minigzip.c zlib.h zconf.h
$ call make minigzip.exe - $ call make minigzip.exe -
"LINK minigzip,libz.olb/lib,x11vms:xvmsutils.olb/lib" - "LINK minigzip,libz.olb/lib" -
minigzip.obj libz.olb minigzip.obj libz.olb
$ else $ else
$ mms/macro=('comp') $ mms/macro=('comp')

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-2004 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
*/ */
@@ -295,6 +295,8 @@ int main(argc, argv)
break; break;
argc--, argv++; argc--, argv++;
} }
if (outmode[3] == ' ')
outmode[3] = 0;
if (argc == 0) { if (argc == 0) {
SET_BINARY_MODE(stdin); SET_BINARY_MODE(stdin);
SET_BINARY_MODE(stdout); SET_BINARY_MODE(stdout);

View File

@@ -25,10 +25,10 @@
<QPG:Files> <QPG:Files>
<QPG:Add file="../zconf.h" install="/opt/include/" user="root:sys" permission="644"/> <QPG:Add file="../zconf.h" install="/opt/include/" user="root:sys" permission="644"/>
<QPG:Add file="../zlib.h" install="/opt/include/" user="root:sys" permission="644"/> <QPG:Add file="../zlib.h" install="/opt/include/" user="root:sys" permission="644"/>
<QPG:Add file="../libz.so.1.2.2.1" install="/opt/lib/" user="root:bin" permission="644"/> <QPG:Add file="../libz.so.1.2.2.3" install="/opt/lib/" user="root:bin" permission="644"/>
<QPG:Add file="libz.so" install="/opt/lib/" component="dev" filetype="symlink" linkto="libz.so.1.2.2.1"/> <QPG:Add file="libz.so" install="/opt/lib/" component="dev" filetype="symlink" linkto="libz.so.1.2.2.3"/>
<QPG:Add file="libz.so.1" install="/opt/lib/" filetype="symlink" linkto="libz.so.1.2.2.1"/> <QPG:Add file="libz.so.1" install="/opt/lib/" filetype="symlink" linkto="libz.so.1.2.2.3"/>
<QPG:Add file="../libz.so.1.2.2.1" install="/opt/lib/" component="slib"/> <QPG:Add file="../libz.so.1.2.2.3" install="/opt/lib/" component="slib"/>
</QPG:Files> </QPG:Files>
<QPG:PackageFilter> <QPG:PackageFilter>
@@ -63,7 +63,7 @@
</QPM:ProductDescription> </QPM:ProductDescription>
<QPM:ReleaseDescription> <QPM:ReleaseDescription>
<QPM:ReleaseVersion>1.2.2.1</QPM:ReleaseVersion> <QPM:ReleaseVersion>1.2.2.3</QPM:ReleaseVersion>
<QPM:ReleaseUrgency>Medium</QPM:ReleaseUrgency> <QPM:ReleaseUrgency>Medium</QPM:ReleaseUrgency>
<QPM:ReleaseStability>Stable</QPM:ReleaseStability> <QPM:ReleaseStability>Stable</QPM:ReleaseStability>
<QPM:ReleaseNoteMinor></QPM:ReleaseNoteMinor> <QPM:ReleaseNoteMinor></QPM:ReleaseNoteMinor>

18
trees.c
View File

@@ -934,22 +934,6 @@ void _tr_flush_block(s, buf, stored_len, eof)
if (stored_len > 0 && s->strm->data_type == Z_UNKNOWN) if (stored_len > 0 && s->strm->data_type == Z_UNKNOWN)
set_data_type(s); set_data_type(s);
#ifdef DEBUG
/* Write out literal/length frequencies for benchmarking */
if (z_verbose) {
FILE *freq;
freq = fopen("defreq.txt", "a");
if (freq != NULL) {
int n;
fputs("ltree:", freq);
for (n = 0; n < L_CODES; n++)
fprintf(freq, " %d", s->dyn_ltree[n].Freq);
putc('\n', freq);
fclose(freq);
}
}
#endif
/* 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)));
Tracev((stderr, "\nlit data: dyn %ld, stat %ld", s->opt_len, Tracev((stderr, "\nlit data: dyn %ld, stat %ld", s->opt_len,
@@ -999,7 +983,7 @@ void _tr_flush_block(s, buf, stored_len, eof)
#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 (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)+eof, 3);
compress_block(s, (ct_data *)static_ltree, (ct_data *)static_dtree); compress_block(s, (ct_data *)static_ltree, (ct_data *)static_dtree);

View File

@@ -5,8 +5,8 @@ VS_VERSION_INFO VERSIONINFO
#else #else
VS_VERSION_INFO VERSIONINFO MOVEABLE IMPURE LOADONCALL DISCARDABLE VS_VERSION_INFO VERSIONINFO MOVEABLE IMPURE LOADONCALL DISCARDABLE
#endif #endif
FILEVERSION 1,2,2,1 FILEVERSION 1,2,2,3
PRODUCTVERSION 1,2,2,1 PRODUCTVERSION 1,2,2,3
FILEFLAGSMASK VS_FFI_FILEFLAGSMASK FILEFLAGSMASK VS_FFI_FILEFLAGSMASK
#ifdef _DEBUG #ifdef _DEBUG
FILEFLAGS 1 FILEFLAGS 1
@@ -23,12 +23,12 @@ BEGIN
//language ID = U.S. English, char set = Windows, Multilingual //language ID = U.S. English, char set = Windows, Multilingual
BEGIN BEGIN
VALUE "FileDescription", "zlib data compression library\0" VALUE "FileDescription", "zlib data compression library\0"
VALUE "FileVersion", "1.2.2.1\0" VALUE "FileVersion", "1.2.2.3\0"
VALUE "InternalName", "zlib1.dll\0" VALUE "InternalName", "zlib1.dll\0"
VALUE "LegalCopyright", "(C) 1995-2004 Jean-loup Gailly & Mark Adler\0" VALUE "LegalCopyright", "(C) 1995-2004 Jean-loup Gailly & Mark Adler\0"
VALUE "OriginalFilename", "zlib1.dll\0" VALUE "OriginalFilename", "zlib1.dll\0"
VALUE "ProductName", "zlib\0" VALUE "ProductName", "zlib\0"
VALUE "ProductVersion", "1.2.2.1\0" VALUE "ProductVersion", "1.2.2.3\0"
VALUE "Comments","DLL support by Alessandro Iacopetti & Gilles Vollant\0" VALUE "Comments","DLL support by Alessandro Iacopetti & Gilles Vollant\0"
END END
END END

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-2004 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
*/ */
@@ -68,8 +68,10 @@
#if defined(_WINDOWS) && !defined(WINDOWS) #if defined(_WINDOWS) && !defined(WINDOWS)
# define WINDOWS # define WINDOWS
#endif #endif
#if (defined(_WIN32) || defined(__WIN32__)) && !defined(WIN32) #if defined(_WIN32) || defined(_WIN32_WCE) || defined(__WIN32__)
# define WIN32 # ifndef WIN32
# define WIN32
# endif
#endif #endif
#if (defined(MSDOS) || defined(OS2) || defined(WINDOWS)) && !defined(WIN32) #if (defined(MSDOS) || defined(OS2) || defined(WINDOWS)) && !defined(WIN32)
# if !defined(__GNUC__) && !defined(__FLAT__) && !defined(__386__) # if !defined(__GNUC__) && !defined(__FLAT__) && !defined(__386__)

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-2004 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
*/ */
@@ -68,8 +68,10 @@
#if defined(_WINDOWS) && !defined(WINDOWS) #if defined(_WINDOWS) && !defined(WINDOWS)
# define WINDOWS # define WINDOWS
#endif #endif
#if (defined(_WIN32) || defined(__WIN32__)) && !defined(WIN32) #if defined(_WIN32) || defined(_WIN32_WCE) || defined(__WIN32__)
# define WIN32 # ifndef WIN32
# define WIN32
# endif
#endif #endif
#if (defined(MSDOS) || defined(OS2) || defined(WINDOWS)) && !defined(WIN32) #if (defined(MSDOS) || defined(OS2) || defined(WINDOWS)) && !defined(WIN32)
# if !defined(__GNUC__) && !defined(__FLAT__) && !defined(__386__) # if !defined(__GNUC__) && !defined(__FLAT__) && !defined(__386__)

4
zlib.3
View File

@@ -1,4 +1,4 @@
.TH ZLIB 3 "31 October 2004" .TH ZLIB 3 "27 May 2005"
.SH NAME .SH NAME
zlib \- compression/decompression library zlib \- compression/decompression library
.SH SYNOPSIS .SH SYNOPSIS
@@ -133,7 +133,7 @@ before asking for help.
Send questions and/or comments to zlib@gzip.org, Send questions and/or comments to zlib@gzip.org,
or (for the Windows DLL version) to Gilles Vollant (info@winimage.com). or (for the Windows DLL version) to Gilles Vollant (info@winimage.com).
.SH AUTHORS .SH AUTHORS
Version 1.2.2.1 Version 1.2.2.3
Copyright (C) 1995-2004 Jean-loup Gailly (jloup@gzip.org) Copyright (C) 1995-2004 Jean-loup Gailly (jloup@gzip.org)
and Mark Adler (madler@alumni.caltech.edu). and Mark Adler (madler@alumni.caltech.edu).
.LP .LP

56
zlib.h
View File

@@ -1,7 +1,7 @@
/* zlib.h -- interface of the 'zlib' general purpose compression library /* zlib.h -- interface of the 'zlib' general purpose compression library
version 1.2.2.1, October 31st, 2004 version 1.2.2.3, May 27th, 2005
Copyright (C) 1995-2004 Jean-loup Gailly and Mark Adler Copyright (C) 1995-2005 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
@@ -37,8 +37,8 @@
extern "C" { extern "C" {
#endif #endif
#define ZLIB_VERSION "1.2.2.1" #define ZLIB_VERSION "1.2.2.3"
#define ZLIB_VERNUM 0x1221 #define ZLIB_VERNUM 0x1223
/* /*
The 'zlib' compression library provides in-memory compression and The 'zlib' compression library provides in-memory compression and
@@ -189,6 +189,7 @@ typedef gz_header FAR *gz_headerp;
#define Z_FILTERED 1 #define Z_FILTERED 1
#define Z_HUFFMAN_ONLY 2 #define Z_HUFFMAN_ONLY 2
#define Z_RLE 3 #define Z_RLE 3
#define Z_FIXED 4
#define Z_DEFAULT_STRATEGY 0 #define Z_DEFAULT_STRATEGY 0
/* compression strategy; see deflateInit2() below for details */ /* compression strategy; see deflateInit2() below for details */
@@ -391,11 +392,11 @@ ZEXTERN int ZEXPORT inflate OF((z_streamp strm, int flush));
The flush parameter of inflate() can be Z_NO_FLUSH, Z_SYNC_FLUSH, The flush parameter of inflate() can be Z_NO_FLUSH, Z_SYNC_FLUSH,
Z_FINISH, or Z_BLOCK. Z_SYNC_FLUSH requests that inflate() flush as much Z_FINISH, or Z_BLOCK. Z_SYNC_FLUSH requests that inflate() flush as much
output as possible to the output buffer. Z_BLOCK requests that inflate() stop output as possible to the output buffer. Z_BLOCK requests that inflate() stop
if and when it get to the next deflate block boundary. When decoding the zlib if and when it gets to the next deflate block boundary. When decoding the
or gzip format, this will cause inflate() to return immediately after the zlib or gzip format, this will cause inflate() to return immediately after
header and before the first block. When doing a raw inflate, inflate() will the header and before the first block. When doing a raw inflate, inflate()
go ahead and process the first block, and will return when it gets to the end will go ahead and process the first block, and will return when it gets to
of that block, or when it runs out of data. the end of that block, or when it runs out of data.
The Z_BLOCK option assists in appending to or combining deflate streams. The Z_BLOCK option assists in appending to or combining deflate streams.
Also to assist in this, on return inflate() will set strm->data_type to the Also to assist in this, on return inflate() will set strm->data_type to the
@@ -524,7 +525,9 @@ ZEXTERN int ZEXPORT deflateInit2 OF((z_streamp strm,
Z_DEFAULT and Z_HUFFMAN_ONLY. Z_RLE is designed to be almost as fast as Z_DEFAULT and Z_HUFFMAN_ONLY. Z_RLE is designed to be almost as fast as
Z_HUFFMAN_ONLY, but give better compression for PNG image data. The strategy Z_HUFFMAN_ONLY, but give better compression for PNG image data. The strategy
parameter only affects the compression ratio but not the correctness of the parameter only affects the compression ratio but not the correctness of the
compressed output even if it is not set appropriately. compressed output even if it is not set appropriately. Z_FIXED prevents the
use of dynamic Huffman codes, allowing for a simpler decoder for special
applications.
deflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough deflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough
memory, Z_STREAM_ERROR if a parameter is invalid (such as an invalid memory, Z_STREAM_ERROR if a parameter is invalid (such as an invalid
@@ -553,7 +556,9 @@ ZEXTERN int ZEXPORT deflateSetDictionary OF((z_streamp strm,
deflateInit or deflateInit2, a part of the dictionary may in effect be deflateInit or deflateInit2, a part of the dictionary may in effect be
discarded, for example if the dictionary is larger than the window size in discarded, for example if the dictionary is larger than the window size in
deflate or deflate2. Thus the strings most likely to be useful should be deflate or deflate2. Thus the strings most likely to be useful should be
put at the end of the dictionary, not at the front. put at the end of the dictionary, not at the front. In addition, the
current implementation of deflate will use at most the window size minus
262 bytes of the provided dictionary.
Upon return of this function, strm->adler is set to the adler32 value Upon return of this function, strm->adler is set to the adler32 value
of the dictionary; the decompressor may later use this value to determine of the dictionary; the decompressor may later use this value to determine
@@ -619,6 +624,23 @@ ZEXTERN int ZEXPORT deflateParams OF((z_streamp strm,
if strm->avail_out was zero. if strm->avail_out was zero.
*/ */
ZEXTERN int ZEXPORT deflateTune OF((z_streamp strm,
int good_length,
int max_lazy,
int nice_length,
int max_chain));
/*
Fine tune deflate's internal compression parameters. This should only be
used by someone who understands the algorithm used by zlib's deflate for
searching for the best matching string, and even then only by the most
fanatic optimizer trying to squeeze out the last compressed bit for their
specific input data. Read the deflate.c source code for the meaning of the
max_lazy, good_length, nice_length, and max_chain parameters.
deflateTune() can be called after deflateInit() or deflateInit2(), and
returns Z_OK on success, or Z_STREAM_ERROR for an invalid deflate stream.
*/
ZEXTERN uLong ZEXPORT deflateBound OF((z_streamp strm, ZEXTERN uLong ZEXPORT deflateBound OF((z_streamp strm,
uLong sourceLen)); uLong sourceLen));
/* /*
@@ -700,7 +722,7 @@ ZEXTERN int ZEXPORT inflateInit2 OF((z_streamp strm,
windowBits can also be greater than 15 for optional gzip decoding. Add windowBits can also be greater than 15 for optional gzip decoding. Add
32 to windowBits to enable zlib and gzip decoding with automatic header 32 to windowBits to enable zlib and gzip decoding with automatic header
detection, or add 16 to decode only the gzip format (the zlib format will detection, or add 16 to decode only the gzip format (the zlib format will
return a Z_DATA_ERROR. If a gzip stream is being decoded, strm->adler is return a Z_DATA_ERROR). If a gzip stream is being decoded, strm->adler is
a crc32 instead of an adler32. a crc32 instead of an adler32.
inflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough inflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough
@@ -1182,6 +1204,12 @@ ZEXTERN int ZEXPORT gzeof OF((gzFile file));
input stream, otherwise zero. input stream, otherwise zero.
*/ */
ZEXTERN int ZEXPORT gzdirect OF((gzFile file));
/*
Returns 1 if file is being read directly without decompression, otherwise
zero.
*/
ZEXTERN int ZEXPORT gzclose OF((gzFile file)); ZEXTERN int ZEXPORT gzclose OF((gzFile file));
/* /*
Flushes all pending output if necessary, closes the compressed file Flushes all pending output if necessary, closes the compressed file
@@ -1230,7 +1258,7 @@ ZEXTERN uLong ZEXPORT adler32 OF((uLong adler, const Bytef *buf, uInt len));
*/ */
ZEXTERN uLong ZEXPORT adler32_combine OF((uLong adler1, uLong adler2, ZEXTERN uLong ZEXPORT adler32_combine OF((uLong adler1, uLong adler2,
uLong len2)); z_off_t len2));
/* /*
Combine two Adler-32 checksums into one. For two sequences of bytes, seq1 Combine two Adler-32 checksums into one. For two sequences of bytes, seq1
and seq2 with lengths len1 and len2, Adler-32 checksums were calculated for and seq2 with lengths len1 and len2, Adler-32 checksums were calculated for
@@ -1254,7 +1282,7 @@ ZEXTERN uLong ZEXPORT crc32 OF((uLong crc, const Bytef *buf, uInt len));
if (crc != original_crc) error(); if (crc != original_crc) error();
*/ */
ZEXTERN uLong ZEXPORT crc32_combine OF((uLong crc1, uLong crc2, uLong len2)); ZEXTERN uLong ZEXPORT crc32_combine OF((uLong crc1, uLong crc2, z_off_t len2));
/* /*
Combine two CRC-32 check values into one. For two sequences of bytes, Combine two CRC-32 check values into one. For two sequences of bytes,

View File

@@ -137,7 +137,10 @@ const char * ZEXPORT zError(err)
} }
#if defined(_WIN32_WCE) #if defined(_WIN32_WCE)
/* does not exist on 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.
*/
int errno = 0; int errno = 0;
#endif #endif

27
zutil.h
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-2004 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
*/ */
@@ -17,14 +17,26 @@
#include "zlib.h" #include "zlib.h"
#ifdef STDC #ifdef STDC
# include <stddef.h> # ifndef _WIN32_WCE
# include <stddef.h>
# endif
# include <string.h> # include <string.h>
# include <stdlib.h> # include <stdlib.h>
#endif #endif
#ifdef NO_ERRNO_H #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; extern int errno;
#else #else
# include <errno.h> # ifndef _WIN32_WCE
# include <errno.h>
# endif
#endif #endif
#ifndef local #ifndef local
@@ -193,15 +205,6 @@ extern const char * const z_errmsg[10]; /* indexed by 2-zlib_error */
# define NO_vsnprintf # define NO_vsnprintf
#endif #endif
#ifdef HAVE_STRERROR
# ifndef VMS
extern char *strerror OF((int));
# endif
# define zstrerror(errnum) strerror(errnum)
#else
# define zstrerror(errnum) ""
#endif
#if defined(pyr) #if defined(pyr)
# define NO_MEMCPY # define NO_MEMCPY
#endif #endif