diff options
45 files changed, 3642 insertions, 852 deletions
@@ -1,6 +1,67 @@ | |||
1 | 1 | ||
2 | ChangeLog file for zlib | 2 | ChangeLog file for zlib |
3 | 3 | ||
4 | Changes in 1.2.3.4 (21 Dec 2009) | ||
5 | - Use old school .SUFFIXES in Makefile.in for FreeBSD compatibility | ||
6 | - Update comments in configure and Makefile.in for default --shared | ||
7 | - Fix test -z's in configure [Marquess] | ||
8 | - Build examplesh and minigzipsh when not testing | ||
9 | - Change NULL's to Z_NULL's in deflate.c and in comments in zlib.h | ||
10 | - Import LDFLAGS from the environment in configure | ||
11 | - Fix configure to populate SFLAGS with discovered CFLAGS options | ||
12 | - Adapt make_vms.com to the new Makefile.in [Zinser] | ||
13 | - Add zlib2ansi script for C++ compilation [Marquess] | ||
14 | - Add _FILE_OFFSET_BITS=64 test to make test (when applicable) | ||
15 | - Add AMD64 assembler code for longest match to contrib [Teterin] | ||
16 | - Include options from $SFLAGS when doing $LDSHARED | ||
17 | - Simplify 64-bit file support by introducing z_off64_t type | ||
18 | - Make shared object files in objs directory to work around old Sun cc | ||
19 | - Use only three-part version number for Darwin shared compiles | ||
20 | - Add rc option to ar in Makefile.in for when ./configure not run | ||
21 | - Add -WI,-rpath,. to LDFLAGS for OSF 1 V4* | ||
22 | - Set LD_LIBRARYN32_PATH for SGI IRIX shared compile | ||
23 | - Protect against _FILE_OFFSET_BITS being defined when compiling zlib | ||
24 | - Rename Makefile.in targets allstatic to static and allshared to shared | ||
25 | - Fix static and shared Makefile.in targets to be independent | ||
26 | - Correct error return bug in gz_open() by setting state [Brown] | ||
27 | - Put spaces before ;;'s in configure for better sh compatibility | ||
28 | - Added pigz.c (parallel implementation of gzip) to examples/ | ||
29 | - Correct constant in crc32.c to UL [Leventhal] | ||
30 | - Reject negative lengths in crc32_combine() | ||
31 | - Add inflateReset2() function to work like inflateEnd()/inflateInit2() | ||
32 | - Include sys/types.h for _LARGEFILE64_SOURCE [Brown] | ||
33 | - Correct typo in doc/algorithm.txt [Janik] | ||
34 | - Fix bug in adler32_combine() [Zhu] | ||
35 | - Catch missing-end-of-block-code error in all inflates and in puff | ||
36 | Assures that random input to inflate eventually results in an error | ||
37 | - Added enough.c (calculation of ENOUGH for inftrees.h) to examples/ | ||
38 | - Update ENOUGH and its usage to reflect discovered bounds | ||
39 | - Fix gzerror() error report on empty input file [Brown] | ||
40 | - Add ush casts in trees.c to avoid pedantic runtime errors | ||
41 | - Fix typo in zlib.h uncompress() description [Reiss] | ||
42 | - Correct inflate() comments with regard to automatic header detection | ||
43 | - Remove deprecation comment on Z_PARTIAL_FLUSH (it stays) | ||
44 | - Put new version of gzlog (2.0) in examples with interruption recovery | ||
45 | - Add puff compile option to permit invalid distance-too-far streams | ||
46 | - Add puff TEST command options, ability to read piped input | ||
47 | - Prototype the *64 functions in zlib.h when _FILE_OFFSET_BITS == 64, but | ||
48 | _LARGEFILE64_SOURCE not defined | ||
49 | - Fix Z_FULL_FLUSH to truly erase the past by resetting s->strstart | ||
50 | - Fix deflateSetDictionary() to use all 32K for output consistency | ||
51 | - Remove extraneous #define MIN_LOOKAHEAD in deflate.c (in deflate.h) | ||
52 | - Clear bytes after deflate lookahead to avoid use of uninitialized data | ||
53 | - Change a limit in inftrees.c to be more transparent to Coverity Prevent | ||
54 | - Update win32/zlib.def with exported symbols from zlib.h | ||
55 | - Correct spelling error in zlib.h [Willem] | ||
56 | - Allow Z_BLOCK for deflate() to force a new block | ||
57 | - Allow negative bits in inflatePrime() to delete existing bit buffer | ||
58 | - Add Z_TREES flush option to inflate() to return at end of trees | ||
59 | - Add inflateMark() to return current state information for random access | ||
60 | - Added Makefile for NintendoDS to contrib [Costa] | ||
61 | - Add -w in configure compile tests to avoid spurious warnings [Beucler] | ||
62 | - Fix typos in zlib.h comments for deflateSetDictionary() | ||
63 | - Fix EOF detection in transparent gzread() [Maier] | ||
64 | |||
4 | Changes in 1.2.3.3 (2 October 2006) | 65 | Changes in 1.2.3.3 (2 October 2006) |
5 | - Make --shared the default for configure, add a --static option | 66 | - Make --shared the default for configure, add a --static option |
6 | - Add compile option to permit invalid distance-too-far streams | 67 | - Add compile option to permit invalid distance-too-far streams |
@@ -10,7 +71,7 @@ Changes in 1.2.3.3 (2 October 2006) | |||
10 | - Use ftello() and fseeko() if available instead of ftell() and fseek() | 71 | - Use ftello() and fseeko() if available instead of ftell() and fseek() |
11 | - Provide two versions of all functions that use the z_off_t type for | 72 | - Provide two versions of all functions that use the z_off_t type for |
12 | binary compatibility -- a normal version and a 64-bit offset version, | 73 | binary compatibility -- a normal version and a 64-bit offset version, |
13 | per the Large File Support Extension when _LARGEFILE64_SUPPORT is | 74 | per the Large File Support Extension when _LARGEFILE64_SOURCE is |
14 | defined; use the 64-bit versions by default when _FILE_OFFSET_BITS | 75 | defined; use the 64-bit versions by default when _FILE_OFFSET_BITS |
15 | is defined to be 64 | 76 | is defined to be 64 |
16 | - Add a --uname= option to configure to perhaps help with cross-compiling | 77 | - Add a --uname= option to configure to perhaps help with cross-compiling |
@@ -10,6 +10,7 @@ treebuild.xml see http://treebuild.metux.de/ | |||
10 | zlib.3 Man page for zlib | 10 | zlib.3 Man page for zlib |
11 | zlib.map Linux symbol information | 11 | zlib.map Linux symbol information |
12 | zlib.pc.in Template for pkg-config descriptor | 12 | zlib.pc.in Template for pkg-config descriptor |
13 | zlib2ansi perl script to convert source files for C++ compilation | ||
13 | 14 | ||
14 | amiga/ makefiles for Amiga SAS C | 15 | amiga/ makefiles for Amiga SAS C |
15 | as400/ makefiles for IBM AS/400 | 16 | as400/ makefiles for IBM AS/400 |
@@ -4,8 +4,8 @@ | |||
4 | 4 | ||
5 | # To compile and test, type: | 5 | # To compile and test, type: |
6 | # ./configure; make test | 6 | # ./configure; make test |
7 | # The call of configure is optional if you don't have special requirements | 7 | # Normally configure builds both a static and a shared library. |
8 | # If you wish to build zlib as a shared library, use: ./configure -s | 8 | # If you want to build just a static library, use: ./configure --static |
9 | 9 | ||
10 | # To use the asm code, type: | 10 | # To use the asm code, type: |
11 | # cp contrib/asm?86/match.S ./match.S | 11 | # cp contrib/asm?86/match.S ./match.S |
@@ -26,16 +26,17 @@ CFLAGS=-O | |||
26 | 26 | ||
27 | SFLAGS=-O | 27 | SFLAGS=-O |
28 | 28 | ||
29 | LDFLAGS=libz.a | 29 | LDFLAGS=-L. libz.a |
30 | LDSHARED=$(CC) | 30 | LDSHARED=$(CC) |
31 | CPP=$(CC) -E | 31 | CPP=$(CC) -E |
32 | 32 | ||
33 | LIBS=libz.a | 33 | STATICLIB=libz.a |
34 | SHAREDLIB=libz.so | 34 | SHAREDLIB=libz.so |
35 | SHAREDLIBV=libz.so.1.2.3.3 | 35 | SHAREDLIBV=libz.so.1.2.3.4 |
36 | SHAREDLIBM=libz.so.1 | 36 | SHAREDLIBM=libz.so.1 |
37 | LIBS=$(STATICLIB) $(SHAREDLIB) | ||
37 | 38 | ||
38 | AR=ar | 39 | AR=ar rc |
39 | RANLIB=ranlib | 40 | RANLIB=ranlib |
40 | TAR=tar | 41 | TAR=tar |
41 | SHELL=/bin/sh | 42 | SHELL=/bin/sh |
@@ -52,22 +53,30 @@ pkgconfigdir = ${libdir}/pkgconfig | |||
52 | OBJC = adler32.o compress.o crc32.o gzio.o uncompr.o deflate.o trees.o \ | 53 | OBJC = adler32.o compress.o crc32.o gzio.o uncompr.o deflate.o trees.o \ |
53 | zutil.o inflate.o infback.o inftrees.o inffast.o | 54 | zutil.o inflate.o infback.o inftrees.o inffast.o |
54 | 55 | ||
56 | PIC_OBJC = adler32.lo compress.lo crc32.lo gzio.lo uncompr.lo deflate.lo trees.lo \ | ||
57 | zutil.lo inflate.lo infback.lo inftrees.lo inffast.lo | ||
58 | |||
59 | # to use the asm code: make OBJA=match.o, PIC_OBJA=match.lo | ||
55 | OBJA = | 60 | OBJA = |
56 | # to use the asm code: make OBJA=match.o | 61 | PIC_OBJA = |
57 | 62 | ||
58 | OBJS = $(OBJC) $(OBJA) | 63 | OBJS = $(OBJC) $(OBJA) |
59 | 64 | ||
60 | PIC_OBJS = $(OBJS:%.o=%.lo) | 65 | PIC_OBJS = $(PIC_OBJC) $(PIC_OBJA) |
66 | |||
67 | all: static shared | ||
61 | 68 | ||
62 | TEST_OBJS = example.o minigzip.o | 69 | static: example$(EXE) minigzip$(EXE) |
63 | 70 | ||
64 | allstatic: example$(EXE) minigzip$(EXE) | 71 | shared: examplesh$(EXE) minigzipsh$(EXE) |
65 | 72 | ||
66 | allshared: examplesh$(EXE) minigzipsh$(EXE) | 73 | all64: example64$(EXE) minigzip64$(EXE) |
74 | |||
75 | check: test | ||
67 | 76 | ||
68 | all: allstatic allshared | 77 | test: all teststatic testshared |
69 | 78 | ||
70 | teststatic: allstatic | 79 | teststatic: static |
71 | @echo hello world | ./minigzip | ./minigzip -d || \ | 80 | @echo hello world | ./minigzip | ./minigzip -d || \ |
72 | echo ' *** minigzip test FAILED ***' ; \ | 81 | echo ' *** minigzip test FAILED ***' ; \ |
73 | if ./example; then \ | 82 | if ./example; then \ |
@@ -76,8 +85,9 @@ teststatic: allstatic | |||
76 | echo ' *** zlib test FAILED ***'; \ | 85 | echo ' *** zlib test FAILED ***'; \ |
77 | fi | 86 | fi |
78 | 87 | ||
79 | testshared: allshared | 88 | testshared: shared |
80 | @LD_LIBRARY_PATH=`pwd`:$(LD_LIBRARY_PATH) ; export LD_LIBRARY_PATH; \ | 89 | @LD_LIBRARY_PATH=`pwd`:$(LD_LIBRARY_PATH) ; export LD_LIBRARY_PATH; \ |
90 | LD_LIBRARYN32_PATH=`pwd`:$(LD_LIBRARYN32_PATH) ; export LD_LIBRARYN32_PATH; \ | ||
81 | DYLD_LIBRARY_PATH=`pwd`:$(DYLD_LIBRARY_PATH) ; export DYLD_LIBRARY_PATH; \ | 91 | DYLD_LIBRARY_PATH=`pwd`:$(DYLD_LIBRARY_PATH) ; export DYLD_LIBRARY_PATH; \ |
82 | SHLIB_PATH=`pwd`:$(SHLIB_PATH) ; export SHLIB_PATH; \ | 92 | SHLIB_PATH=`pwd`:$(SHLIB_PATH) ; export SHLIB_PATH; \ |
83 | echo hello world | ./minigzipsh | ./minigzipsh -d || \ | 93 | echo hello world | ./minigzipsh | ./minigzipsh -d || \ |
@@ -88,9 +98,14 @@ testshared: allshared | |||
88 | echo ' *** zlib shared test FAILED ***'; \ | 98 | echo ' *** zlib shared test FAILED ***'; \ |
89 | fi | 99 | fi |
90 | 100 | ||
91 | test: teststatic testshared | 101 | test64: all64 |
92 | 102 | @echo hello world | ./minigzip64 | ./minigzip64 -d || \ | |
93 | check: test | 103 | echo ' *** minigzip 64-bit test FAILED ***' ; \ |
104 | if ./example64; then \ | ||
105 | echo ' *** zlib 64-bit test OK ***'; \ | ||
106 | else \ | ||
107 | echo ' *** zlib 64-bit test FAILED ***'; \ | ||
108 | fi | ||
94 | 109 | ||
95 | libz.a: $(OBJS) | 110 | libz.a: $(OBJS) |
96 | $(AR) $@ $(OBJS) | 111 | $(AR) $@ $(OBJS) |
@@ -108,26 +123,43 @@ match.lo: match.S | |||
108 | mv _match.o match.lo | 123 | mv _match.o match.lo |
109 | rm -f _match.s | 124 | rm -f _match.s |
110 | 125 | ||
111 | %.lo: %.c | 126 | example64.o: example.c zlib.h zconf.h zlibdefs.h |
112 | $(CC) $(SFLAGS) -DPIC -c $< -o $@ | 127 | $(CC) $(CFLAGS) -D_FILE_OFFSET_BITS=64 -c -o $@ $< |
128 | |||
129 | minigzip64.o: minigzip.c zlib.h zconf.h zlibdefs.h | ||
130 | $(CC) $(CFLAGS) -D_FILE_OFFSET_BITS=64 -c -o $@ $< | ||
131 | |||
132 | .SUFFIXES: .lo | ||
133 | |||
134 | .c.lo: | ||
135 | -@if [ ! -d objs ]; then mkdir objs; fi | ||
136 | $(CC) $(SFLAGS) -DPIC -c -o objs/$*.o $< | ||
137 | -@mv objs/$*.o $@ | ||
113 | 138 | ||
114 | $(SHAREDLIBV): $(PIC_OBJS) | 139 | $(SHAREDLIBV): $(PIC_OBJS) |
115 | $(LDSHARED) -o $@ $(PIC_OBJS) -lc | 140 | $(LDSHARED) $(SFLAGS) -o $@ $(PIC_OBJS) -lc |
116 | rm -f $(SHAREDLIB) $(SHAREDLIBM) | 141 | rm -f $(SHAREDLIB) $(SHAREDLIBM) |
117 | ln -s $@ $(SHAREDLIB) | 142 | ln -s $@ $(SHAREDLIB) |
118 | ln -s $@ $(SHAREDLIBM) | 143 | ln -s $@ $(SHAREDLIBM) |
144 | -@rmdir objs | ||
119 | 145 | ||
120 | example$(EXE): example.o $(LIBS) | 146 | example$(EXE): example.o $(STATICLIB) |
121 | $(CC) $(CFLAGS) -o $@ example.o $(LDFLAGS) | 147 | $(CC) $(CFLAGS) -o $@ example.o $(LDFLAGS) |
122 | 148 | ||
123 | minigzip$(EXE): minigzip.o $(LIBS) | 149 | minigzip$(EXE): minigzip.o $(STATICLIB) |
124 | $(CC) $(CFLAGS) -o $@ minigzip.o $(LDFLAGS) | 150 | $(CC) $(CFLAGS) -o $@ minigzip.o $(LDFLAGS) |
125 | 151 | ||
126 | examplesh$(EXE): example.o $(LIBS) | 152 | examplesh$(EXE): example.o $(SHAREDLIBV) |
127 | $(CC) $(CFLAGS) -o $@ example.o -L. $(SHAREDLIB) | 153 | $(CC) $(CFLAGS) -o $@ example.o -L. $(SHAREDLIBV) |
154 | |||
155 | minigzipsh$(EXE): minigzip.o $(SHAREDLIBV) | ||
156 | $(CC) $(CFLAGS) -o $@ minigzip.o -L. $(SHAREDLIBV) | ||
157 | |||
158 | example64$(EXE): example64.o $(STATICLIB) | ||
159 | $(CC) $(CFLAGS) -o $@ example64.o $(LDFLAGS) | ||
128 | 160 | ||
129 | minigzipsh$(EXE): minigzip.o $(LIBS) | 161 | minigzip64$(EXE): minigzip64.o $(STATICLIB) |
130 | $(CC) $(CFLAGS) -o $@ minigzip.o -L. $(SHAREDLIB) | 162 | $(CC) $(CFLAGS) -o $@ minigzip64.o $(LDFLAGS) |
131 | 163 | ||
132 | install-libs: $(LIBS) | 164 | install-libs: $(LIBS) |
133 | -@if [ ! -d $(DESTDIR)$(exec_prefix) ]; then mkdir -p $(DESTDIR)$(exec_prefix); fi | 165 | -@if [ ! -d $(DESTDIR)$(exec_prefix) ]; then mkdir -p $(DESTDIR)$(exec_prefix); fi |
@@ -168,8 +200,10 @@ mostlyclean: clean | |||
168 | clean: | 200 | clean: |
169 | rm -f *.o *.lo *~ \ | 201 | rm -f *.o *.lo *~ \ |
170 | example$(EXE) minigzip$(EXE) examplesh$(EXE) minigzipsh$(EXE) \ | 202 | example$(EXE) minigzip$(EXE) examplesh$(EXE) minigzipsh$(EXE) \ |
203 | example64$(EXE) minigzip64$(EXE) \ | ||
171 | libz.* foo.gz so_locations \ | 204 | libz.* foo.gz so_locations \ |
172 | _match.s maketree contrib/infback9/*.o | 205 | _match.s maketree contrib/infback9/*.o |
206 | rm -rf objs | ||
173 | 207 | ||
174 | maintainer-clean: distclean | 208 | maintainer-clean: distclean |
175 | distclean: clean | 209 | distclean: clean |
@@ -186,30 +220,20 @@ depend: | |||
186 | 220 | ||
187 | # DO NOT DELETE THIS LINE -- make depend depends on it. | 221 | # DO NOT DELETE THIS LINE -- make depend depends on it. |
188 | 222 | ||
189 | adler32.o: zlib.h zconf.h zlibdefs.h | 223 | adler32.o gzio.o zutil.o: zutil.h zlib.h zconf.h zlibdefs.h |
190 | compress.o: zlib.h zconf.h zlibdefs.h | 224 | compress.o example.o minigzip.o uncompr.o: zlib.h zconf.h zlibdefs.h |
191 | crc32.o: crc32.h zlib.h zconf.h zlibdefs.h | 225 | crc32.o: zutil.h zlib.h zconf.h zlibdefs.h crc32.h |
192 | deflate.o: deflate.h zutil.h zlib.h zconf.h zlibdefs.h | 226 | deflate.o: deflate.h zutil.h zlib.h zconf.h zlibdefs.h |
193 | example.o: zlib.h zconf.h zlibdefs.h | 227 | infback.o inflate.o: zutil.h zlib.h zconf.h zlibdefs.h inftrees.h inflate.h inffast.h inffixed.h |
194 | gzio.o: zutil.h zlib.h zconf.h zlibdefs.h | ||
195 | inffast.o: zutil.h zlib.h zconf.h zlibdefs.h inftrees.h inflate.h inffast.h | 228 | inffast.o: zutil.h zlib.h zconf.h zlibdefs.h inftrees.h inflate.h inffast.h |
196 | inflate.o: zutil.h zlib.h zconf.h zlibdefs.h inftrees.h inflate.h inffast.h inffixed.h | ||
197 | infback.o: zutil.h zlib.h zconf.h zlibdefs.h inftrees.h inflate.h inffast.h inffixed.h | ||
198 | inftrees.o: zutil.h zlib.h zconf.h zlibdefs.h inftrees.h | 229 | inftrees.o: zutil.h zlib.h zconf.h zlibdefs.h inftrees.h |
199 | minigzip.o: zlib.h zconf.h zlibdefs.h | ||
200 | trees.o: deflate.h zutil.h zlib.h zconf.h zlibdefs.h trees.h | 230 | trees.o: deflate.h zutil.h zlib.h zconf.h zlibdefs.h trees.h |
201 | uncompr.o: zlib.h zconf.h zlibdefs.h | ||
202 | zutil.o: zutil.h zlib.h zconf.h zlibdefs.h | ||
203 | 231 | ||
204 | adler32.lo: zlib.h zconf.h zlibdefs.h | 232 | adler32.lo gzio.lo zutil.lo: zutil.h zlib.h zconf.h zlibdefs.h |
205 | compress.lo: zlib.h zconf.h zlibdefs.h | 233 | compress.lo example.lo minigzip.lo uncompr.lo: zlib.h zconf.h zlibdefs.h |
206 | crc32.lo: crc32.h zlib.h zconf.h zlibdefs.h | 234 | crc32.lo: zutil.h zlib.h zconf.h zlibdefs.h crc32.h |
207 | deflate.lo: deflate.h zutil.h zlib.h zconf.h zlibdefs.h | 235 | deflate.lo: deflate.h zutil.h zlib.h zconf.h zlibdefs.h |
208 | gzio.lo: zutil.h zlib.h zconf.h zlibdefs.h | 236 | infback.lo inflate.lo: zutil.h zlib.h zconf.h zlibdefs.h inftrees.h inflate.h inffast.h inffixed.h |
209 | inffast.lo: zutil.h zlib.h zconf.h zlibdefs.h inftrees.h inflate.h inffast.h | 237 | inffast.lo: zutil.h zlib.h zconf.h zlibdefs.h inftrees.h inflate.h inffast.h |
210 | inflate.lo: zutil.h zlib.h zconf.h zlibdefs.h inftrees.h inflate.h inffast.h inffixed.h | ||
211 | infback.lo: zutil.h zlib.h zconf.h zlibdefs.h inftrees.h inflate.h inffast.h inffixed.h | ||
212 | inftrees.lo: zutil.h zlib.h zconf.h zlibdefs.h inftrees.h | 238 | inftrees.lo: zutil.h zlib.h zconf.h zlibdefs.h inftrees.h |
213 | trees.lo: deflate.h zutil.h zlib.h zconf.h zlibdefs.h trees.h | 239 | trees.lo: deflate.h zutil.h zlib.h zconf.h zlibdefs.h trees.h |
214 | uncompr.lo: zlib.h zconf.h zlibdefs.h | ||
215 | zutil.lo: zutil.h zlib.h zconf.h zlibdefs.h | ||
diff --git a/Makefile.in b/Makefile.in index 2fa2e25..6ad7a5c 100644 --- a/Makefile.in +++ b/Makefile.in | |||
@@ -4,8 +4,8 @@ | |||
4 | 4 | ||
5 | # To compile and test, type: | 5 | # To compile and test, type: |
6 | # ./configure; make test | 6 | # ./configure; make test |
7 | # The call of configure is optional if you don't have special requirements | 7 | # Normally configure builds both a static and a shared library. |
8 | # If you wish to build zlib as a shared library, use: ./configure -s | 8 | # If you want to build just a static library, use: ./configure --static |
9 | 9 | ||
10 | # To use the asm code, type: | 10 | # To use the asm code, type: |
11 | # cp contrib/asm?86/match.S ./match.S | 11 | # cp contrib/asm?86/match.S ./match.S |
@@ -26,16 +26,17 @@ CFLAGS=-O | |||
26 | 26 | ||
27 | SFLAGS=-O | 27 | SFLAGS=-O |
28 | 28 | ||
29 | LDFLAGS=libz.a | 29 | LDFLAGS=-L. libz.a |
30 | LDSHARED=$(CC) | 30 | LDSHARED=$(CC) |
31 | CPP=$(CC) -E | 31 | CPP=$(CC) -E |
32 | 32 | ||
33 | LIBS=libz.a | 33 | STATICLIB=libz.a |
34 | SHAREDLIB=libz.so | 34 | SHAREDLIB=libz.so |
35 | SHAREDLIBV=libz.so.1.2.3.3 | 35 | SHAREDLIBV=libz.so.1.2.3.4 |
36 | SHAREDLIBM=libz.so.1 | 36 | SHAREDLIBM=libz.so.1 |
37 | LIBS=$(STATICLIB) $(SHAREDLIB) | ||
37 | 38 | ||
38 | AR=ar | 39 | AR=ar rc |
39 | RANLIB=ranlib | 40 | RANLIB=ranlib |
40 | TAR=tar | 41 | TAR=tar |
41 | SHELL=/bin/sh | 42 | SHELL=/bin/sh |
@@ -52,22 +53,30 @@ pkgconfigdir = ${libdir}/pkgconfig | |||
52 | OBJC = adler32.o compress.o crc32.o gzio.o uncompr.o deflate.o trees.o \ | 53 | OBJC = adler32.o compress.o crc32.o gzio.o uncompr.o deflate.o trees.o \ |
53 | zutil.o inflate.o infback.o inftrees.o inffast.o | 54 | zutil.o inflate.o infback.o inftrees.o inffast.o |
54 | 55 | ||
56 | PIC_OBJC = adler32.lo compress.lo crc32.lo gzio.lo uncompr.lo deflate.lo trees.lo \ | ||
57 | zutil.lo inflate.lo infback.lo inftrees.lo inffast.lo | ||
58 | |||
59 | # to use the asm code: make OBJA=match.o, PIC_OBJA=match.lo | ||
55 | OBJA = | 60 | OBJA = |
56 | # to use the asm code: make OBJA=match.o | 61 | PIC_OBJA = |
57 | 62 | ||
58 | OBJS = $(OBJC) $(OBJA) | 63 | OBJS = $(OBJC) $(OBJA) |
59 | 64 | ||
60 | PIC_OBJS = $(OBJS:%.o=%.lo) | 65 | PIC_OBJS = $(PIC_OBJC) $(PIC_OBJA) |
66 | |||
67 | all: static shared | ||
61 | 68 | ||
62 | TEST_OBJS = example.o minigzip.o | 69 | static: example$(EXE) minigzip$(EXE) |
63 | 70 | ||
64 | allstatic: example$(EXE) minigzip$(EXE) | 71 | shared: examplesh$(EXE) minigzipsh$(EXE) |
65 | 72 | ||
66 | allshared: examplesh$(EXE) minigzipsh$(EXE) | 73 | all64: example64$(EXE) minigzip64$(EXE) |
74 | |||
75 | check: test | ||
67 | 76 | ||
68 | all: allstatic allshared | 77 | test: all teststatic testshared |
69 | 78 | ||
70 | teststatic: allstatic | 79 | teststatic: static |
71 | @echo hello world | ./minigzip | ./minigzip -d || \ | 80 | @echo hello world | ./minigzip | ./minigzip -d || \ |
72 | echo ' *** minigzip test FAILED ***' ; \ | 81 | echo ' *** minigzip test FAILED ***' ; \ |
73 | if ./example; then \ | 82 | if ./example; then \ |
@@ -76,8 +85,9 @@ teststatic: allstatic | |||
76 | echo ' *** zlib test FAILED ***'; \ | 85 | echo ' *** zlib test FAILED ***'; \ |
77 | fi | 86 | fi |
78 | 87 | ||
79 | testshared: allshared | 88 | testshared: shared |
80 | @LD_LIBRARY_PATH=`pwd`:$(LD_LIBRARY_PATH) ; export LD_LIBRARY_PATH; \ | 89 | @LD_LIBRARY_PATH=`pwd`:$(LD_LIBRARY_PATH) ; export LD_LIBRARY_PATH; \ |
90 | LD_LIBRARYN32_PATH=`pwd`:$(LD_LIBRARYN32_PATH) ; export LD_LIBRARYN32_PATH; \ | ||
81 | DYLD_LIBRARY_PATH=`pwd`:$(DYLD_LIBRARY_PATH) ; export DYLD_LIBRARY_PATH; \ | 91 | DYLD_LIBRARY_PATH=`pwd`:$(DYLD_LIBRARY_PATH) ; export DYLD_LIBRARY_PATH; \ |
82 | SHLIB_PATH=`pwd`:$(SHLIB_PATH) ; export SHLIB_PATH; \ | 92 | SHLIB_PATH=`pwd`:$(SHLIB_PATH) ; export SHLIB_PATH; \ |
83 | echo hello world | ./minigzipsh | ./minigzipsh -d || \ | 93 | echo hello world | ./minigzipsh | ./minigzipsh -d || \ |
@@ -88,9 +98,14 @@ testshared: allshared | |||
88 | echo ' *** zlib shared test FAILED ***'; \ | 98 | echo ' *** zlib shared test FAILED ***'; \ |
89 | fi | 99 | fi |
90 | 100 | ||
91 | test: teststatic testshared | 101 | test64: all64 |
92 | 102 | @echo hello world | ./minigzip64 | ./minigzip64 -d || \ | |
93 | check: test | 103 | echo ' *** minigzip 64-bit test FAILED ***' ; \ |
104 | if ./example64; then \ | ||
105 | echo ' *** zlib 64-bit test OK ***'; \ | ||
106 | else \ | ||
107 | echo ' *** zlib 64-bit test FAILED ***'; \ | ||
108 | fi | ||
94 | 109 | ||
95 | libz.a: $(OBJS) | 110 | libz.a: $(OBJS) |
96 | $(AR) $@ $(OBJS) | 111 | $(AR) $@ $(OBJS) |
@@ -108,26 +123,43 @@ match.lo: match.S | |||
108 | mv _match.o match.lo | 123 | mv _match.o match.lo |
109 | rm -f _match.s | 124 | rm -f _match.s |
110 | 125 | ||
111 | %.lo: %.c | 126 | example64.o: example.c zlib.h zconf.h zlibdefs.h |
112 | $(CC) $(SFLAGS) -DPIC -c $< -o $@ | 127 | $(CC) $(CFLAGS) -D_FILE_OFFSET_BITS=64 -c -o $@ $< |
128 | |||
129 | minigzip64.o: minigzip.c zlib.h zconf.h zlibdefs.h | ||
130 | $(CC) $(CFLAGS) -D_FILE_OFFSET_BITS=64 -c -o $@ $< | ||
131 | |||
132 | .SUFFIXES: .lo | ||
133 | |||
134 | .c.lo: | ||
135 | -@if [ ! -d objs ]; then mkdir objs; fi | ||
136 | $(CC) $(SFLAGS) -DPIC -c -o objs/$*.o $< | ||
137 | -@mv objs/$*.o $@ | ||
113 | 138 | ||
114 | $(SHAREDLIBV): $(PIC_OBJS) | 139 | $(SHAREDLIBV): $(PIC_OBJS) |
115 | $(LDSHARED) -o $@ $(PIC_OBJS) -lc | 140 | $(LDSHARED) $(SFLAGS) -o $@ $(PIC_OBJS) -lc |
116 | rm -f $(SHAREDLIB) $(SHAREDLIBM) | 141 | rm -f $(SHAREDLIB) $(SHAREDLIBM) |
117 | ln -s $@ $(SHAREDLIB) | 142 | ln -s $@ $(SHAREDLIB) |
118 | ln -s $@ $(SHAREDLIBM) | 143 | ln -s $@ $(SHAREDLIBM) |
144 | -@rmdir objs | ||
119 | 145 | ||
120 | example$(EXE): example.o $(LIBS) | 146 | example$(EXE): example.o $(STATICLIB) |
121 | $(CC) $(CFLAGS) -o $@ example.o $(LDFLAGS) | 147 | $(CC) $(CFLAGS) -o $@ example.o $(LDFLAGS) |
122 | 148 | ||
123 | minigzip$(EXE): minigzip.o $(LIBS) | 149 | minigzip$(EXE): minigzip.o $(STATICLIB) |
124 | $(CC) $(CFLAGS) -o $@ minigzip.o $(LDFLAGS) | 150 | $(CC) $(CFLAGS) -o $@ minigzip.o $(LDFLAGS) |
125 | 151 | ||
126 | examplesh$(EXE): example.o $(LIBS) | 152 | examplesh$(EXE): example.o $(SHAREDLIBV) |
127 | $(CC) $(CFLAGS) -o $@ example.o -L. $(SHAREDLIB) | 153 | $(CC) $(CFLAGS) -o $@ example.o -L. $(SHAREDLIBV) |
154 | |||
155 | minigzipsh$(EXE): minigzip.o $(SHAREDLIBV) | ||
156 | $(CC) $(CFLAGS) -o $@ minigzip.o -L. $(SHAREDLIBV) | ||
157 | |||
158 | example64$(EXE): example64.o $(STATICLIB) | ||
159 | $(CC) $(CFLAGS) -o $@ example64.o $(LDFLAGS) | ||
128 | 160 | ||
129 | minigzipsh$(EXE): minigzip.o $(LIBS) | 161 | minigzip64$(EXE): minigzip64.o $(STATICLIB) |
130 | $(CC) $(CFLAGS) -o $@ minigzip.o -L. $(SHAREDLIB) | 162 | $(CC) $(CFLAGS) -o $@ minigzip64.o $(LDFLAGS) |
131 | 163 | ||
132 | install-libs: $(LIBS) | 164 | install-libs: $(LIBS) |
133 | -@if [ ! -d $(DESTDIR)$(exec_prefix) ]; then mkdir -p $(DESTDIR)$(exec_prefix); fi | 165 | -@if [ ! -d $(DESTDIR)$(exec_prefix) ]; then mkdir -p $(DESTDIR)$(exec_prefix); fi |
@@ -168,8 +200,10 @@ mostlyclean: clean | |||
168 | clean: | 200 | clean: |
169 | rm -f *.o *.lo *~ \ | 201 | rm -f *.o *.lo *~ \ |
170 | example$(EXE) minigzip$(EXE) examplesh$(EXE) minigzipsh$(EXE) \ | 202 | example$(EXE) minigzip$(EXE) examplesh$(EXE) minigzipsh$(EXE) \ |
203 | example64$(EXE) minigzip64$(EXE) \ | ||
171 | libz.* foo.gz so_locations \ | 204 | libz.* foo.gz so_locations \ |
172 | _match.s maketree contrib/infback9/*.o | 205 | _match.s maketree contrib/infback9/*.o |
206 | rm -rf objs | ||
173 | 207 | ||
174 | maintainer-clean: distclean | 208 | maintainer-clean: distclean |
175 | distclean: clean | 209 | distclean: clean |
@@ -186,30 +220,20 @@ depend: | |||
186 | 220 | ||
187 | # DO NOT DELETE THIS LINE -- make depend depends on it. | 221 | # DO NOT DELETE THIS LINE -- make depend depends on it. |
188 | 222 | ||
189 | adler32.o: zlib.h zconf.h zlibdefs.h | 223 | adler32.o gzio.o zutil.o: zutil.h zlib.h zconf.h zlibdefs.h |
190 | compress.o: zlib.h zconf.h zlibdefs.h | 224 | compress.o example.o minigzip.o uncompr.o: zlib.h zconf.h zlibdefs.h |
191 | crc32.o: crc32.h zlib.h zconf.h zlibdefs.h | 225 | crc32.o: zutil.h zlib.h zconf.h zlibdefs.h crc32.h |
192 | deflate.o: deflate.h zutil.h zlib.h zconf.h zlibdefs.h | 226 | deflate.o: deflate.h zutil.h zlib.h zconf.h zlibdefs.h |
193 | example.o: zlib.h zconf.h zlibdefs.h | 227 | infback.o inflate.o: zutil.h zlib.h zconf.h zlibdefs.h inftrees.h inflate.h inffast.h inffixed.h |
194 | gzio.o: zutil.h zlib.h zconf.h zlibdefs.h | ||
195 | inffast.o: zutil.h zlib.h zconf.h zlibdefs.h inftrees.h inflate.h inffast.h | 228 | inffast.o: zutil.h zlib.h zconf.h zlibdefs.h inftrees.h inflate.h inffast.h |
196 | inflate.o: zutil.h zlib.h zconf.h zlibdefs.h inftrees.h inflate.h inffast.h inffixed.h | ||
197 | infback.o: zutil.h zlib.h zconf.h zlibdefs.h inftrees.h inflate.h inffast.h inffixed.h | ||
198 | inftrees.o: zutil.h zlib.h zconf.h zlibdefs.h inftrees.h | 229 | inftrees.o: zutil.h zlib.h zconf.h zlibdefs.h inftrees.h |
199 | minigzip.o: zlib.h zconf.h zlibdefs.h | ||
200 | trees.o: deflate.h zutil.h zlib.h zconf.h zlibdefs.h trees.h | 230 | trees.o: deflate.h zutil.h zlib.h zconf.h zlibdefs.h trees.h |
201 | uncompr.o: zlib.h zconf.h zlibdefs.h | ||
202 | zutil.o: zutil.h zlib.h zconf.h zlibdefs.h | ||
203 | 231 | ||
204 | adler32.lo: zlib.h zconf.h zlibdefs.h | 232 | adler32.lo gzio.lo zutil.lo: zutil.h zlib.h zconf.h zlibdefs.h |
205 | compress.lo: zlib.h zconf.h zlibdefs.h | 233 | compress.lo example.lo minigzip.lo uncompr.lo: zlib.h zconf.h zlibdefs.h |
206 | crc32.lo: crc32.h zlib.h zconf.h zlibdefs.h | 234 | crc32.lo: zutil.h zlib.h zconf.h zlibdefs.h crc32.h |
207 | deflate.lo: deflate.h zutil.h zlib.h zconf.h zlibdefs.h | 235 | deflate.lo: deflate.h zutil.h zlib.h zconf.h zlibdefs.h |
208 | gzio.lo: zutil.h zlib.h zconf.h zlibdefs.h | 236 | infback.lo inflate.lo: zutil.h zlib.h zconf.h zlibdefs.h inftrees.h inflate.h inffast.h inffixed.h |
209 | inffast.lo: zutil.h zlib.h zconf.h zlibdefs.h inftrees.h inflate.h inffast.h | 237 | inffast.lo: zutil.h zlib.h zconf.h zlibdefs.h inftrees.h inflate.h inffast.h |
210 | inflate.lo: zutil.h zlib.h zconf.h zlibdefs.h inftrees.h inflate.h inffast.h inffixed.h | ||
211 | infback.lo: zutil.h zlib.h zconf.h zlibdefs.h inftrees.h inflate.h inffast.h inffixed.h | ||
212 | inftrees.lo: zutil.h zlib.h zconf.h zlibdefs.h inftrees.h | 238 | inftrees.lo: zutil.h zlib.h zconf.h zlibdefs.h inftrees.h |
213 | trees.lo: deflate.h zutil.h zlib.h zconf.h zlibdefs.h trees.h | 239 | trees.lo: deflate.h zutil.h zlib.h zconf.h zlibdefs.h trees.h |
214 | uncompr.lo: zlib.h zconf.h zlibdefs.h | ||
215 | zutil.lo: zutil.h zlib.h zconf.h zlibdefs.h | ||
@@ -1,6 +1,6 @@ | |||
1 | ZLIB DATA COMPRESSION LIBRARY | 1 | ZLIB DATA COMPRESSION LIBRARY |
2 | 2 | ||
3 | zlib 1.2.3.3 is a general purpose data compression library. All the code is | 3 | zlib 1.2.3.4 is a general purpose data compression library. All the code is |
4 | thread safe. The data format used by the zlib library is described by RFCs | 4 | thread safe. The data format used by the zlib library is described by RFCs |
5 | (Request for Comments) 1950 to 1952 in the files | 5 | (Request for Comments) 1950 to 1952 in the files |
6 | http://www.ietf.org/rfc/rfc1950.txt (zlib format), rfc1951.txt (deflate format) | 6 | http://www.ietf.org/rfc/rfc1950.txt (zlib format), rfc1951.txt (deflate format) |
@@ -33,7 +33,7 @@ Mark Nelson <markn@ieee.org> wrote an article about zlib for the Jan. 1997 | |||
33 | issue of Dr. Dobb's Journal; a copy of the article is available in | 33 | issue of Dr. Dobb's Journal; a copy of the article is available in |
34 | http://dogma.net/markn/articles/zlibtool/zlibtool.htm | 34 | http://dogma.net/markn/articles/zlibtool/zlibtool.htm |
35 | 35 | ||
36 | The changes made in version 1.2.3.3 are documented in the file ChangeLog. | 36 | The changes made in version 1.2.3.4 are documented in the file ChangeLog. |
37 | 37 | ||
38 | Unsupported third party contributions are provided in directory "contrib". | 38 | Unsupported third party contributions are provided in directory "contrib". |
39 | 39 | ||
@@ -1,21 +1,15 @@ | |||
1 | /* adler32.c -- compute the Adler-32 checksum of a data stream | 1 | /* adler32.c -- compute the Adler-32 checksum of a data stream |
2 | * Copyright (C) 1995-2006 Mark Adler | 2 | * Copyright (C) 1995-2007 Mark Adler |
3 | * For conditions of distribution and use, see copyright notice in zlib.h | 3 | * For conditions of distribution and use, see copyright notice in zlib.h |
4 | */ | 4 | */ |
5 | 5 | ||
6 | /* @(#) $Id$ */ | 6 | /* @(#) $Id$ */ |
7 | 7 | ||
8 | #define ZLIB_INTERNAL | 8 | #include "zutil.h" |
9 | #include "zlib.h" | ||
10 | 9 | ||
11 | #define local static | 10 | #define local static |
12 | 11 | ||
13 | #ifdef _LARGEFILE64_SOURCE | 12 | local uLong adler32_combine_(uLong adler1, uLong adler2, z_off64_t len2); |
14 | local uLong adler32_combine_(uLong adler1, uLong adler2, off64_t len2); | ||
15 | #else | ||
16 | local uLong adler32_combine_(uLong adler1, uLong adler2, z_off_t len2); | ||
17 | #endif | ||
18 | |||
19 | 13 | ||
20 | #define BASE 65521UL /* largest prime smaller than 65536 */ | 14 | #define BASE 65521UL /* largest prime smaller than 65536 */ |
21 | #define NMAX 5552 | 15 | #define NMAX 5552 |
@@ -137,11 +131,7 @@ uLong ZEXPORT adler32(adler, buf, len) | |||
137 | local uLong adler32_combine_(adler1, adler2, len2) | 131 | local uLong adler32_combine_(adler1, adler2, len2) |
138 | uLong adler1; | 132 | uLong adler1; |
139 | uLong adler2; | 133 | uLong adler2; |
140 | #ifdef _LARGEFILE64_SOURCE | 134 | z_off64_t len2; |
141 | off64_t len2; | ||
142 | #else | ||
143 | z_off_t len2; | ||
144 | #endif | ||
145 | { | 135 | { |
146 | unsigned long sum1; | 136 | unsigned long sum1; |
147 | unsigned long sum2; | 137 | unsigned long sum2; |
@@ -154,10 +144,10 @@ local uLong adler32_combine_(adler1, adler2, len2) | |||
154 | MOD(sum2); | 144 | MOD(sum2); |
155 | sum1 += (adler2 & 0xffff) + BASE - 1; | 145 | sum1 += (adler2 & 0xffff) + BASE - 1; |
156 | sum2 += ((adler1 >> 16) & 0xffff) + ((adler2 >> 16) & 0xffff) + BASE - rem; | 146 | sum2 += ((adler1 >> 16) & 0xffff) + ((adler2 >> 16) & 0xffff) + BASE - rem; |
157 | if (sum1 > BASE) sum1 -= BASE; | 147 | if (sum1 >= BASE) sum1 -= BASE; |
158 | if (sum1 > BASE) sum1 -= BASE; | 148 | if (sum1 >= BASE) sum1 -= BASE; |
159 | if (sum2 > (BASE << 1)) sum2 -= (BASE << 1); | 149 | if (sum2 >= (BASE << 1)) sum2 -= (BASE << 1); |
160 | if (sum2 > BASE) sum2 -= BASE; | 150 | if (sum2 >= BASE) sum2 -= BASE; |
161 | return sum1 | (sum2 << 16); | 151 | return sum1 | (sum2 << 16); |
162 | } | 152 | } |
163 | 153 | ||
@@ -170,20 +160,10 @@ uLong ZEXPORT adler32_combine(adler1, adler2, len2) | |||
170 | return adler32_combine_(adler1, adler2, len2); | 160 | return adler32_combine_(adler1, adler2, len2); |
171 | } | 161 | } |
172 | 162 | ||
173 | #ifdef _LARGEFILE64_SOURCE | ||
174 | uLong ZEXPORT adler32_combine64(adler1, adler2, len2) | 163 | uLong ZEXPORT adler32_combine64(adler1, adler2, len2) |
175 | uLong adler1; | 164 | uLong adler1; |
176 | uLong adler2; | 165 | uLong adler2; |
177 | off64_t len2; | 166 | z_off64_t len2; |
178 | { | 167 | { |
179 | return adler32_combine_(adler1, adler2, len2); | 168 | return adler32_combine_(adler1, adler2, len2); |
180 | } | 169 | } |
181 | #else | ||
182 | uLong ZEXPORT adler32_combine64(adler1, adler2, len2) | ||
183 | uLong adler1; | ||
184 | uLong adler2; | ||
185 | z_off_t len2; | ||
186 | { | ||
187 | return adler32_combine_(adler1, adler2, len2); | ||
188 | } | ||
189 | #endif | ||
diff --git a/as400/zlib.inc b/as400/zlib.inc index 4436477..9ef0b14 100644 --- a/as400/zlib.inc +++ b/as400/zlib.inc | |||
@@ -1,7 +1,7 @@ | |||
1 | * ZLIB.INC - Interface to the general purpose compression library | 1 | * ZLIB.INC - Interface to the general purpose compression library |
2 | * | 2 | * |
3 | * ILE RPG400 version by Patrick Monnerat, DATASPHERE. | 3 | * ILE RPG400 version by Patrick Monnerat, DATASPHERE. |
4 | * Version 1.2.3.3 | 4 | * Version 1.2.3.4 |
5 | * | 5 | * |
6 | * | 6 | * |
7 | * WARNING: | 7 | * WARNING: |
@@ -22,8 +22,8 @@ | |||
22 | * | 22 | * |
23 | * Versioning information. | 23 | * Versioning information. |
24 | * | 24 | * |
25 | D ZLIB_VERSION C '1.2.3.3' | 25 | D ZLIB_VERSION C '1.2.3.4' |
26 | D ZLIB_VERNUM C X'1233' | 26 | D ZLIB_VERNUM C X'1234' |
27 | * | 27 | * |
28 | * Other equates. | 28 | * Other equates. |
29 | * | 29 | * |
@@ -1,26 +1,22 @@ | |||
1 | #!/bin/sh | 1 | #!/bin/sh |
2 | # configure script for zlib. This script is needed only if | 2 | # configure script for zlib. |
3 | # you wish to build a shared library and your system supports them, | ||
4 | # of if you need special compiler, flags or install directory. | ||
5 | # Otherwise, you can just use directly "make test; make install" | ||
6 | # | 3 | # |
7 | # To create a shared library, use "configure --shared"; by default a static | 4 | # Normally configure builds both a static and a shared library. |
8 | # library is created. If the primitive shared library support provided here | 5 | # If you want to build just a static library, use: ./configure --static |
9 | # does not work, use ftp://prep.ai.mit.edu/pub/gnu/libtool-*.tar.gz | ||
10 | # | 6 | # |
11 | # To impose specific compiler or flags or install directory, use for example: | 7 | # To impose specific compiler or flags or install directory, use for example: |
12 | # prefix=$HOME CC=cc CFLAGS="-O4" ./configure | 8 | # prefix=$HOME CC=cc CFLAGS="-O4" ./configure |
13 | # or for csh/tcsh users: | 9 | # or for csh/tcsh users: |
14 | # (setenv prefix $HOME; setenv CC cc; setenv CFLAGS "-O4"; ./configure) | 10 | # (setenv prefix $HOME; setenv CC cc; setenv CFLAGS "-O4"; ./configure) |
15 | # LDSHARED is the command to be used to create a shared library | ||
16 | 11 | ||
17 | # Incorrect settings of CC or CFLAGS may prevent creating a shared library. | 12 | # Incorrect settings of CC or CFLAGS may prevent creating a shared library. |
18 | # If you have problems, try without defining CC and CFLAGS before reporting | 13 | # If you have problems, try without defining CC and CFLAGS before reporting |
19 | # an error. | 14 | # an error. |
20 | 15 | ||
21 | LIBS=libz.a | 16 | STATICLIB=libz.a |
22 | LDFLAGS="-L. ${LIBS}" | 17 | LDFLAGS="${LDFLAGS} -L. ${STATICLIB}" |
23 | VER=`sed -n -e '/VERSION "/s/.*"\(.*\)".*/\1/p' < zlib.h` | 18 | VER=`sed -n -e '/VERSION "/s/.*"\(.*\)".*/\1/p' < zlib.h` |
19 | VER3=`sed -n -e '/VERSION "/s/.*"\([0-9]*\\.[0-9]*\\.[0-9]*\)\\..*/\1/p' < zlib.h` | ||
24 | VER2=`sed -n -e '/VERSION "/s/.*"\([0-9]*\\.[0-9]*\)\\..*/\1/p' < zlib.h` | 20 | VER2=`sed -n -e '/VERSION "/s/.*"\([0-9]*\\.[0-9]*\)\\..*/\1/p' < zlib.h` |
25 | VER1=`sed -n -e '/VERSION "/s/.*"\([0-9]*\)\\..*/\1/p' < zlib.h` | 21 | VER1=`sed -n -e '/VERSION "/s/.*"\([0-9]*\)\\..*/\1/p' < zlib.h` |
26 | AR=${AR-"ar"} | 22 | AR=${AR-"ar"} |
@@ -45,22 +41,22 @@ case "$1" in | |||
45 | echo 'usage:' | 41 | echo 'usage:' |
46 | echo ' configure [--shared] [--prefix=PREFIX] [--exec_prefix=EXPREFIX]' | 42 | echo ' configure [--shared] [--prefix=PREFIX] [--exec_prefix=EXPREFIX]' |
47 | echo ' [--libdir=LIBDIR] [--includedir=INCLUDEDIR] [--zprefix]' | 43 | echo ' [--libdir=LIBDIR] [--includedir=INCLUDEDIR] [--zprefix]' |
48 | exit 0;; | 44 | exit 0 ;; |
49 | -p*=* | --prefix=*) prefix=`echo $1 | sed 's/[-a-z_]*=//'`; shift;; | 45 | -p*=* | --prefix=*) prefix=`echo $1 | sed 's/[-a-z_]*=//'`; shift ;; |
50 | -e*=* | --eprefix=*) exec_prefix=`echo $1 | sed 's/[-a-z_]*=//'`; shift;; | 46 | -e*=* | --eprefix=*) exec_prefix=`echo $1 | sed 's/[-a-z_]*=//'`; shift ;; |
51 | -l*=* | --libdir=*) libdir=`echo $1 | sed 's/[-a-z_]*=//'`; shift;; | 47 | -l*=* | --libdir=*) libdir=`echo $1 | sed 's/[-a-z_]*=//'`; shift ;; |
52 | -i*=* | --includedir=*) includedir=`echo $1 | sed 's/[-a-z_]*=//'`;shift;; | 48 | -i*=* | --includedir=*) includedir=`echo $1 | sed 's/[-a-z_]*=//'`;shift ;; |
53 | -u*=* | --uname=*) uname=`echo $1 | sed 's/[-a-z_]*=//'`;shift;; | 49 | -u*=* | --uname=*) uname=`echo $1 | sed 's/[-a-z_]*=//'`;shift ;; |
54 | -p* | --prefix) prefix="$2"; shift; shift;; | 50 | -p* | --prefix) prefix="$2"; shift; shift ;; |
55 | -e* | --eprefix) exec_prefix="$2"; shift; shift;; | 51 | -e* | --eprefix) exec_prefix="$2"; shift; shift ;; |
56 | -l* | --libdir) libdir="$2"; shift; shift;; | 52 | -l* | --libdir) libdir="$2"; shift; shift ;; |
57 | -i* | --includedir) includedir="$2"; shift; shift;; | 53 | -i* | --includedir) includedir="$2"; shift; shift ;; |
58 | -s* | --shared | --enable-shared) shared=1; shift;; | 54 | -s* | --shared | --enable-shared) shared=1; shift ;; |
59 | -t | --static) shared=0; shift;; | 55 | -t | --static) shared=0; shift ;; |
60 | -z* | --zprefix) zprefix=1; shift;; | 56 | -z* | --zprefix) zprefix=1; shift ;; |
61 | --sysconfdir=*) echo "ignored option: --sysconfdir"; shift;; | 57 | --sysconfdir=*) echo "ignored option: --sysconfdir"; shift ;; |
62 | --localstatedir=*) echo "ignored option: --localstatedir"; shift;; | 58 | --localstatedir=*) echo "ignored option: --localstatedir"; shift ;; |
63 | *) echo "unknown option: $1"; echo "$0 --help for help"; exit 1;; | 59 | *) echo "unknown option: $1"; echo "$0 --help for help"; exit 1 ;; |
64 | esac | 60 | esac |
65 | done | 61 | done |
66 | 62 | ||
@@ -75,44 +71,44 @@ cc=${CC-gcc} | |||
75 | cflags=${CFLAGS-"-O3"} | 71 | cflags=${CFLAGS-"-O3"} |
76 | # to force the asm version use: CFLAGS="-O3 -DASMV" ./configure | 72 | # to force the asm version use: CFLAGS="-O3 -DASMV" ./configure |
77 | case "$cc" in | 73 | case "$cc" in |
78 | *gcc*) gcc=1;; | 74 | *gcc*) gcc=1 ;; |
79 | esac | 75 | esac |
80 | 76 | ||
81 | if test "$gcc" -eq 1 && ($cc -c $cflags $test.c) 2>/dev/null; then | 77 | if test "$gcc" -eq 1 && ($cc -c $cflags $test.c) 2>/dev/null; then |
82 | CC="$cc" | 78 | CC="$cc" |
83 | SFLAGS="${CFLAGS-"-O3"} -fPIC" | 79 | SFLAGS="${CFLAGS-"-O3"} -fPIC" |
84 | CFLAGS="${CFLAGS-"-O3"}" | 80 | CFLAGS="${CFLAGS-"-O3"}" |
85 | if test -z $uname; then | 81 | if test -z "$uname"; then |
86 | uname=`(uname -s || echo unknown) 2>/dev/null` | 82 | uname=`(uname -s || echo unknown) 2>/dev/null` |
87 | fi | 83 | fi |
88 | case "$uname" in | 84 | case "$uname" in |
89 | Linux | linux | GNU | GNU/*) LDSHARED=${LDSHARED-"$cc -shared -Wl,-soname,libz.so.1,--version-script,zlib.map"};; | 85 | Linux | linux | GNU | GNU/*) LDSHARED=${LDSHARED-"$cc -shared -Wl,-soname,libz.so.1,--version-script,zlib.map"} ;; |
90 | CYGWIN* | Cygwin* | cygwin* | OS/2* ) | 86 | CYGWIN* | Cygwin* | cygwin* | OS/2* ) |
91 | EXE='.exe';; | 87 | EXE='.exe' ;; |
92 | QNX*) # This is for QNX6. I suppose that the QNX rule below is for QNX2,QNX4 | 88 | QNX*) # This is for QNX6. I suppose that the QNX rule below is for QNX2,QNX4 |
93 | # (alain.bonnefoy@icbt.com) | 89 | # (alain.bonnefoy@icbt.com) |
94 | LDSHARED=${LDSHARED-"$cc -shared -Wl,-hlibz.so.1"};; | 90 | LDSHARED=${LDSHARED-"$cc -shared -Wl,-hlibz.so.1"} ;; |
95 | HP-UX*) | 91 | HP-UX*) |
96 | LDSHARED=${LDSHARED-"$cc -shared $SFLAGS"} | 92 | LDSHARED=${LDSHARED-"$cc -shared $SFLAGS"} |
97 | case `(uname -m || echo unknown) 2>/dev/null` in | 93 | case `(uname -m || echo unknown) 2>/dev/null` in |
98 | ia64) | 94 | ia64) |
99 | shared_ext='.so' | 95 | shared_ext='.so' |
100 | SHAREDLIB='libz.so';; | 96 | SHAREDLIB='libz.so' ;; |
101 | *) | 97 | *) |
102 | shared_ext='.sl' | 98 | shared_ext='.sl' |
103 | SHAREDLIB='libz.sl';; | 99 | SHAREDLIB='libz.sl' ;; |
104 | esac;; | 100 | esac ;; |
105 | Darwin*) shared_ext='.dylib' | 101 | Darwin*) shared_ext='.dylib' |
106 | SHAREDLIB=libz$shared_ext | 102 | SHAREDLIB=libz$shared_ext |
107 | SHAREDLIBV=libz.$VER$shared_ext | 103 | SHAREDLIBV=libz.$VER$shared_ext |
108 | SHAREDLIBM=libz.$VER1$shared_ext | 104 | SHAREDLIBM=libz.$VER1$shared_ext |
109 | LDSHARED=${LDSHARED-"$cc -dynamiclib -install_name $libdir/$SHAREDLIBM -compatibility_version $VER1 -current_version $VER"};; | 105 | LDSHARED=${LDSHARED-"$cc -dynamiclib -install_name $libdir/$SHAREDLIBM -compatibility_version $VER1 -current_version $VER3"} ;; |
110 | *) LDSHARED=${LDSHARED-"$cc -shared"};; | 106 | *) LDSHARED=${LDSHARED-"$cc -shared"} ;; |
111 | esac | 107 | esac |
112 | else | 108 | else |
113 | # find system name and corresponding cc options | 109 | # find system name and corresponding cc options |
114 | CC=${CC-cc} | 110 | CC=${CC-cc} |
115 | if test -z $uname; then | 111 | if test -z "$uname"; then |
116 | uname=`(uname -sr || echo unknown) 2>/dev/null` | 112 | uname=`(uname -sr || echo unknown) 2>/dev/null` |
117 | fi | 113 | fi |
118 | case "$uname" in | 114 | case "$uname" in |
@@ -123,63 +119,64 @@ else | |||
123 | case `(uname -m || echo unknown) 2>/dev/null` in | 119 | case `(uname -m || echo unknown) 2>/dev/null` in |
124 | ia64) | 120 | ia64) |
125 | shared_ext='.so' | 121 | shared_ext='.so' |
126 | SHAREDLIB='libz.so';; | 122 | SHAREDLIB='libz.so' ;; |
127 | *) | 123 | *) |
128 | shared_ext='.sl' | 124 | shared_ext='.sl' |
129 | SHAREDLIB='libz.sl';; | 125 | SHAREDLIB='libz.sl' ;; |
130 | esac;; | 126 | esac ;; |
131 | IRIX*) SFLAGS=${CFLAGS-"-ansi -O2 -rpath ."} | 127 | IRIX*) SFLAGS=${CFLAGS-"-ansi -O2 -rpath ."} |
132 | CFLAGS=${CFLAGS-"-ansi -O2"} | 128 | CFLAGS=${CFLAGS-"-ansi -O2"} |
133 | LDSHARED=${LDSHARED-"cc -shared -Wl,-soname,libz.so.1"};; | 129 | LDSHARED=${LDSHARED-"cc -shared -Wl,-soname,libz.so.1"} ;; |
134 | OSF1\ V4*) SFLAGS=${CFLAGS-"-O -std1"} | 130 | OSF1\ V4*) SFLAGS=${CFLAGS-"-O -std1"} |
135 | CFLAGS=${CFLAGS-"-O -std1"} | 131 | CFLAGS=${CFLAGS-"-O -std1"} |
136 | LDSHARED=${LDSHARED-"cc -shared -Wl,-soname,libz.so -Wl,-msym -Wl,-rpath,$(libdir) -Wl,-set_version,${VER}:1.0"};; | 132 | LDFLAGS="${LDFLAGS} -Wl,-rpath,." |
133 | LDSHARED=${LDSHARED-"cc -shared -Wl,-soname,libz.so -Wl,-msym -Wl,-rpath,$(libdir) -Wl,-set_version,${VER}:1.0"} ;; | ||
137 | OSF1*) SFLAGS=${CFLAGS-"-O -std1"} | 134 | OSF1*) SFLAGS=${CFLAGS-"-O -std1"} |
138 | CFLAGS=${CFLAGS-"-O -std1"} | 135 | CFLAGS=${CFLAGS-"-O -std1"} |
139 | LDSHARED=${LDSHARED-"cc -shared -Wl,-soname,libz.so.1"};; | 136 | LDSHARED=${LDSHARED-"cc -shared -Wl,-soname,libz.so.1"} ;; |
140 | QNX*) SFLAGS=${CFLAGS-"-4 -O"} | 137 | QNX*) SFLAGS=${CFLAGS-"-4 -O"} |
141 | CFLAGS=${CFLAGS-"-4 -O"} | 138 | CFLAGS=${CFLAGS-"-4 -O"} |
142 | LDSHARED=${LDSHARED-"cc"} | 139 | LDSHARED=${LDSHARED-"cc"} |
143 | RANLIB=${RANLIB-"true"} | 140 | RANLIB=${RANLIB-"true"} |
144 | AR_RC="cc -A";; | 141 | AR_RC="cc -A" ;; |
145 | SCO_SV\ 3.2*) SFLAGS=${CFLAGS-"-O3 -dy -KPIC "} | 142 | SCO_SV\ 3.2*) SFLAGS=${CFLAGS-"-O3 -dy -KPIC "} |
146 | CFLAGS=${CFLAGS-"-O3"} | 143 | CFLAGS=${CFLAGS-"-O3"} |
147 | LDSHARED=${LDSHARED-"cc -dy -KPIC -G"};; | 144 | LDSHARED=${LDSHARED-"cc -dy -KPIC -G"} ;; |
148 | SunOS\ 5*) LDSHARED=${LDSHARED-"cc -G"} | 145 | SunOS\ 5*) LDSHARED=${LDSHARED-"cc -G"} |
149 | case `(uname -m || echo unknown) 2>/dev/null` in | 146 | case `(uname -m || echo unknown) 2>/dev/null` in |
150 | i86*) | 147 | i86*) |
151 | SFLAGS=${CFLAGS-"-xpentium -fast -KPIC -R."} | 148 | SFLAGS=${CFLAGS-"-xpentium -fast -KPIC -R."} |
152 | CFLAGS=${CFLAGS-"-xpentium -fast"};; | 149 | CFLAGS=${CFLAGS-"-xpentium -fast"} ;; |
153 | *) | 150 | *) |
154 | SFLAGS=${CFLAGS-"-fast -xcg92 -KPIC -R."} | 151 | SFLAGS=${CFLAGS-"-fast -xcg92 -KPIC -R."} |
155 | CFLAGS=${CFLAGS-"-fast -xcg92"};; | 152 | CFLAGS=${CFLAGS-"-fast -xcg92"} ;; |
156 | esac;; | 153 | esac ;; |
157 | SunOS\ 4*) SFLAGS=${CFLAGS-"-O2 -PIC"} | 154 | SunOS\ 4*) SFLAGS=${CFLAGS-"-O2 -PIC"} |
158 | CFLAGS=${CFLAGS-"-O2"} | 155 | CFLAGS=${CFLAGS-"-O2"} |
159 | LDSHARED=${LDSHARED-"ld"};; | 156 | LDSHARED=${LDSHARED-"ld"} ;; |
160 | SunStudio\ 9*) SFLAGS=${CFLAGS-"-DUSE_MMAP -fast -xcode=pic32 -xtarget=ultra3 -xarch=v9b"} | 157 | SunStudio\ 9*) SFLAGS=${CFLAGS-"-DUSE_MMAP -fast -xcode=pic32 -xtarget=ultra3 -xarch=v9b"} |
161 | CFLAGS=${CFLAGS-"-DUSE_MMAP -fast -xtarget=ultra3 -xarch=v9b"} | 158 | CFLAGS=${CFLAGS-"-DUSE_MMAP -fast -xtarget=ultra3 -xarch=v9b"} |
162 | LDSHARED=${LDSHARED-"cc -xarch=v9b"};; | 159 | LDSHARED=${LDSHARED-"cc -xarch=v9b"} ;; |
163 | UNIX_System_V\ 4.2.0) | 160 | UNIX_System_V\ 4.2.0) |
164 | SFLAGS=${CFLAGS-"-KPIC -O"} | 161 | SFLAGS=${CFLAGS-"-KPIC -O"} |
165 | CFLAGS=${CFLAGS-"-O"} | 162 | CFLAGS=${CFLAGS-"-O"} |
166 | LDSHARED=${LDSHARED-"cc -G"};; | 163 | LDSHARED=${LDSHARED-"cc -G"} ;; |
167 | UNIX_SV\ 4.2MP) | 164 | UNIX_SV\ 4.2MP) |
168 | SFLAGS=${CFLAGS-"-Kconform_pic -O"} | 165 | SFLAGS=${CFLAGS-"-Kconform_pic -O"} |
169 | CFLAGS=${CFLAGS-"-O"} | 166 | CFLAGS=${CFLAGS-"-O"} |
170 | LDSHARED=${LDSHARED-"cc -G"};; | 167 | LDSHARED=${LDSHARED-"cc -G"} ;; |
171 | OpenUNIX\ 5) | 168 | OpenUNIX\ 5) |
172 | SFLAGS=${CFLAGS-"-KPIC -O"} | 169 | SFLAGS=${CFLAGS-"-KPIC -O"} |
173 | CFLAGS=${CFLAGS-"-O"} | 170 | CFLAGS=${CFLAGS-"-O"} |
174 | LDSHARED=${LDSHARED-"cc -G"};; | 171 | LDSHARED=${LDSHARED-"cc -G"} ;; |
175 | AIX*) # Courtesy of dbakker@arrayasolutions.com | 172 | AIX*) # Courtesy of dbakker@arrayasolutions.com |
176 | SFLAGS=${CFLAGS-"-O -qmaxmem=8192"} | 173 | SFLAGS=${CFLAGS-"-O -qmaxmem=8192"} |
177 | CFLAGS=${CFLAGS-"-O -qmaxmem=8192"} | 174 | CFLAGS=${CFLAGS-"-O -qmaxmem=8192"} |
178 | LDSHARED=${LDSHARED-"xlc -G"};; | 175 | LDSHARED=${LDSHARED-"xlc -G"} ;; |
179 | # send working options for other systems to support@gzip.org | 176 | # send working options for other systems to support@gzip.org |
180 | *) SFLAGS=${CFLAGS-"-O"} | 177 | *) SFLAGS=${CFLAGS-"-O"} |
181 | CFLAGS=${CFLAGS-"-O"} | 178 | CFLAGS=${CFLAGS-"-O"} |
182 | LDSHARED=${LDSHARED-"cc -shared"};; | 179 | LDSHARED=${LDSHARED-"cc -shared"} ;; |
183 | esac | 180 | esac |
184 | fi | 181 | fi |
185 | 182 | ||
@@ -190,16 +187,15 @@ SHAREDLIBM=${SHAREDLIBM-"libz$shared_ext.$VER1"} | |||
190 | if test $shared -eq 1; then | 187 | if test $shared -eq 1; then |
191 | echo Checking for shared library support... | 188 | echo Checking for shared library support... |
192 | # we must test in two steps (cc then ld), required at least on SunOS 4.x | 189 | # we must test in two steps (cc then ld), required at least on SunOS 4.x |
193 | if test "`($CC -c $SFLAGS $test.c) 2>&1`" = "" && | 190 | if test "`($CC -w -c $SFLAGS $test.c) 2>&1`" = "" && |
194 | test "`($LDSHARED -o $test$shared_ext $test.o) 2>&1`" = ""; then | 191 | test "`($LDSHARED -o $test$shared_ext $test.o) 2>&1`" = ""; then |
195 | LIBS="$LIBS $SHAREDLIBV" | ||
196 | echo Building shared library $SHAREDLIBV with $CC. | 192 | echo Building shared library $SHAREDLIBV with $CC. |
197 | elif test -z "$old_cc" -a -z "$old_cflags"; then | 193 | elif test -z "$old_cc" -a -z "$old_cflags"; then |
198 | echo No shared library support. | 194 | echo No shared library support. |
199 | shared=0; | 195 | shared=0; |
200 | else | 196 | else |
201 | echo Tested $CC -c $SFLAGS $test.c | 197 | echo Tested $CC -w -c $SFLAGS $test.c |
202 | $CC -c $SFLAGS $test.c | 198 | $CC -w -c $SFLAGS $test.c |
203 | echo Tested $LDSHARED -o $test$shared_ext $test.o | 199 | echo Tested $LDSHARED -o $test$shared_ext $test.o |
204 | $LDSHARED -o $test$shared_ext $test.o | 200 | $LDSHARED -o $test$shared_ext $test.o |
205 | echo 'No shared library support; try without defining CC and CFLAGS' | 201 | echo 'No shared library support; try without defining CC and CFLAGS' |
@@ -208,12 +204,12 @@ if test $shared -eq 1; then | |||
208 | fi | 204 | fi |
209 | if test $shared -eq 0; then | 205 | if test $shared -eq 0; then |
210 | LDSHARED="$CC" | 206 | LDSHARED="$CC" |
211 | ALL="allstatic" | 207 | ALL="static" |
212 | TEST="teststatic" | 208 | TEST="all teststatic" |
213 | echo Building static library $LIBS version $VER with $CC. | 209 | echo Building static library $STATICLIB version $VER with $CC. |
214 | else | 210 | else |
215 | ALL="allstatic allshared" | 211 | ALL="static shared" |
216 | TEST="teststatic testshared" | 212 | TEST="all teststatic testshared" |
217 | fi | 213 | fi |
218 | 214 | ||
219 | cat > zlibdefs.h << EOF | 215 | cat > zlibdefs.h << EOF |
@@ -231,6 +227,8 @@ EOF | |||
231 | if test "`($CC -c $CFLAGS -D_LARGEFILE64_SOURCE=1 $test.c) 2>&1`" = ""; then | 227 | if test "`($CC -c $CFLAGS -D_LARGEFILE64_SOURCE=1 $test.c) 2>&1`" = ""; then |
232 | CFLAGS="${CFLAGS} -D_LARGEFILE64_SOURCE=1" | 228 | CFLAGS="${CFLAGS} -D_LARGEFILE64_SOURCE=1" |
233 | SFLAGS="${SFLAGS} -D_LARGEFILE64_SOURCE=1" | 229 | SFLAGS="${SFLAGS} -D_LARGEFILE64_SOURCE=1" |
230 | ALL="${ALL} all64" | ||
231 | TEST="${TEST} test64" | ||
234 | echo "Checking for off64_t... Yes." | 232 | echo "Checking for off64_t... Yes." |
235 | echo "Checking for fseeko... Yes." | 233 | echo "Checking for fseeko... Yes." |
236 | else | 234 | else |
@@ -345,6 +343,7 @@ EOF | |||
345 | echo "Checking for return value of vsnprintf()... Yes." | 343 | echo "Checking for return value of vsnprintf()... Yes." |
346 | else | 344 | else |
347 | CFLAGS="$CFLAGS -DHAS_vsnprintf_void" | 345 | CFLAGS="$CFLAGS -DHAS_vsnprintf_void" |
346 | SFLAGS="$SFLAGS -DHAS_vsnprintf_void" | ||
348 | echo "Checking for return value of vsnprintf()... No." | 347 | echo "Checking for return value of vsnprintf()... No." |
349 | echo " WARNING: apparently vsnprintf() does not return a value. zlib" | 348 | echo " WARNING: apparently vsnprintf() does not return a value. zlib" |
350 | echo " can build but will be open to possible string-format security" | 349 | echo " can build but will be open to possible string-format security" |
@@ -352,6 +351,7 @@ EOF | |||
352 | fi | 351 | fi |
353 | else | 352 | else |
354 | CFLAGS="$CFLAGS -DNO_vsnprintf" | 353 | CFLAGS="$CFLAGS -DNO_vsnprintf" |
354 | SFLAGS="$SFLAGS -DNO_vsnprintf" | ||
355 | echo "Checking for vsnprintf() in stdio.h... No." | 355 | echo "Checking for vsnprintf() in stdio.h... No." |
356 | echo " WARNING: vsnprintf() not found, falling back to vsprintf(). zlib" | 356 | echo " WARNING: vsnprintf() not found, falling back to vsprintf(). zlib" |
357 | echo " can build but will be open to possible buffer-overflow security" | 357 | echo " can build but will be open to possible buffer-overflow security" |
@@ -383,6 +383,7 @@ EOF | |||
383 | echo "Checking for return value of vsprintf()... Yes." | 383 | echo "Checking for return value of vsprintf()... Yes." |
384 | else | 384 | else |
385 | CFLAGS="$CFLAGS -DHAS_vsprintf_void" | 385 | CFLAGS="$CFLAGS -DHAS_vsprintf_void" |
386 | SFLAGS="$SFLAGS -DHAS_vsprintf_void" | ||
386 | echo "Checking for return value of vsprintf()... No." | 387 | echo "Checking for return value of vsprintf()... No." |
387 | echo " WARNING: apparently vsprintf() does not return a value. zlib" | 388 | echo " WARNING: apparently vsprintf() does not return a value. zlib" |
388 | echo " can build but will be open to possible string-format security" | 389 | echo " can build but will be open to possible string-format security" |
@@ -432,6 +433,7 @@ EOF | |||
432 | echo "Checking for return value of snprintf()... Yes." | 433 | echo "Checking for return value of snprintf()... Yes." |
433 | else | 434 | else |
434 | CFLAGS="$CFLAGS -DHAS_snprintf_void" | 435 | CFLAGS="$CFLAGS -DHAS_snprintf_void" |
436 | SFLAGS="$SFLAGS -DHAS_snprintf_void" | ||
435 | echo "Checking for return value of snprintf()... No." | 437 | echo "Checking for return value of snprintf()... No." |
436 | echo " WARNING: apparently snprintf() does not return a value. zlib" | 438 | echo " WARNING: apparently snprintf() does not return a value. zlib" |
437 | echo " can build but will be open to possible string-format security" | 439 | echo " can build but will be open to possible string-format security" |
@@ -439,6 +441,7 @@ EOF | |||
439 | fi | 441 | fi |
440 | else | 442 | else |
441 | CFLAGS="$CFLAGS -DNO_snprintf" | 443 | CFLAGS="$CFLAGS -DNO_snprintf" |
444 | SFLAGS="$SFLAGS -DNO_snprintf" | ||
442 | echo "Checking for snprintf() in stdio.h... No." | 445 | echo "Checking for snprintf() in stdio.h... No." |
443 | echo " WARNING: snprintf() not found, falling back to sprintf(). zlib" | 446 | echo " WARNING: snprintf() not found, falling back to sprintf(). zlib" |
444 | echo " can build but will be open to possible buffer-overflow security" | 447 | echo " can build but will be open to possible buffer-overflow security" |
@@ -464,6 +467,7 @@ EOF | |||
464 | echo "Checking for return value of sprintf()... Yes." | 467 | echo "Checking for return value of sprintf()... Yes." |
465 | else | 468 | else |
466 | CFLAGS="$CFLAGS -DHAS_sprintf_void" | 469 | CFLAGS="$CFLAGS -DHAS_sprintf_void" |
470 | SFLAGS="$SFLAGS -DHAS_sprintf_void" | ||
467 | echo "Checking for return value of sprintf()... No." | 471 | echo "Checking for return value of sprintf()... No." |
468 | echo " WARNING: apparently sprintf() does not return a value. zlib" | 472 | echo " WARNING: apparently sprintf() does not return a value. zlib" |
469 | echo " can build but will be open to possible string-format security" | 473 | echo " can build but will be open to possible string-format security" |
@@ -481,6 +485,7 @@ if test "`($CC -c $CFLAGS $test.c) 2>&1`" = ""; then | |||
481 | else | 485 | else |
482 | echo "Checking for errno.h... No." | 486 | echo "Checking for errno.h... No." |
483 | CFLAGS="$CFLAGS -DNO_ERRNO_H" | 487 | CFLAGS="$CFLAGS -DNO_ERRNO_H" |
488 | SFLAGS="$SFLAGS -DNO_ERRNO_H" | ||
484 | fi | 489 | fi |
485 | 490 | ||
486 | cat > $test.c <<EOF | 491 | cat > $test.c <<EOF |
@@ -493,6 +498,7 @@ caddr_t hello() { | |||
493 | EOF | 498 | EOF |
494 | if test "`($CC -c $CFLAGS $test.c) 2>&1`" = ""; then | 499 | if test "`($CC -c $CFLAGS $test.c) 2>&1`" = ""; then |
495 | CFLAGS="$CFLAGS -DUSE_MMAP" | 500 | CFLAGS="$CFLAGS -DUSE_MMAP" |
501 | SFLAGS="$SFLAGS -DUSE_MMAP" | ||
496 | echo Checking for mmap support... Yes. | 502 | echo Checking for mmap support... Yes. |
497 | else | 503 | else |
498 | echo Checking for mmap support... No. | 504 | echo Checking for mmap support... No. |
@@ -506,7 +512,7 @@ case $CFLAGS in | |||
506 | echo Checking for underline in external names... No. | 512 | echo Checking for underline in external names... No. |
507 | else | 513 | else |
508 | echo Checking for underline in external names... Yes. | 514 | echo Checking for underline in external names... Yes. |
509 | fi;; | 515 | fi ;; |
510 | esac | 516 | esac |
511 | 517 | ||
512 | rm -f $test.[co] $test $test$shared_ext | 518 | rm -f $test.[co] $test $test$shared_ext |
@@ -519,7 +525,7 @@ sed < Makefile.in " | |||
519 | /^LDFLAGS *=/s#=.*#=$LDFLAGS# | 525 | /^LDFLAGS *=/s#=.*#=$LDFLAGS# |
520 | /^LDSHARED *=/s#=.*#=$LDSHARED# | 526 | /^LDSHARED *=/s#=.*#=$LDSHARED# |
521 | /^CPP *=/s#=.*#=$CPP# | 527 | /^CPP *=/s#=.*#=$CPP# |
522 | /^LIBS *=/s#=.*#=$LIBS# | 528 | /^STATICLIB *=/s#=.*#=$STATICLIB# |
523 | /^SHAREDLIB *=/s#=.*#=$SHAREDLIB# | 529 | /^SHAREDLIB *=/s#=.*#=$SHAREDLIB# |
524 | /^SHAREDLIBV *=/s#=.*#=$SHAREDLIBV# | 530 | /^SHAREDLIBV *=/s#=.*#=$SHAREDLIBV# |
525 | /^SHAREDLIBM *=/s#=.*#=$SHAREDLIBM# | 531 | /^SHAREDLIBM *=/s#=.*#=$SHAREDLIBM# |
@@ -540,7 +546,7 @@ sed < zlib.pc.in " | |||
540 | /^CFLAGS *=/s#=.*#=$CFLAGS# | 546 | /^CFLAGS *=/s#=.*#=$CFLAGS# |
541 | /^CPP *=/s#=.*#=$CPP# | 547 | /^CPP *=/s#=.*#=$CPP# |
542 | /^LDSHARED *=/s#=.*#=$LDSHARED# | 548 | /^LDSHARED *=/s#=.*#=$LDSHARED# |
543 | /^LIBS *=/s#=.*#=$LIBS# | 549 | /^STATICLIB *=/s#=.*#=$STATICLIB# |
544 | /^SHAREDLIB *=/s#=.*#=$SHAREDLIB# | 550 | /^SHAREDLIB *=/s#=.*#=$SHAREDLIB# |
545 | /^SHAREDLIBV *=/s#=.*#=$SHAREDLIBV# | 551 | /^SHAREDLIBV *=/s#=.*#=$SHAREDLIBV# |
546 | /^SHAREDLIBM *=/s#=.*#=$SHAREDLIBM# | 552 | /^SHAREDLIBM *=/s#=.*#=$SHAREDLIBM# |
diff --git a/contrib/README.contrib b/contrib/README.contrib index 20afc62..f9c1665 100644 --- a/contrib/README.contrib +++ b/contrib/README.contrib | |||
@@ -8,6 +8,10 @@ ada/ by Dmitriy Anisimkov <anisimkov@yahoo.com> | |||
8 | Support for Ada | 8 | Support for Ada |
9 | See http://zlib-ada.sourceforge.net/ | 9 | See http://zlib-ada.sourceforge.net/ |
10 | 10 | ||
11 | amd64/ by Mikhail Teterin <mi@ALDAN.algebra.com> | ||
12 | asm code for AMD64 | ||
13 | See patch at http://www.freebsd.org/cgi/query-pr.cgi?pr=bin/96393 | ||
14 | |||
11 | asm586/ | 15 | asm586/ |
12 | asm686/ by Brian Raiter <breadbox@muppetlabs.com> | 16 | asm686/ by Brian Raiter <breadbox@muppetlabs.com> |
13 | asm code for Pentium and PPro/PII, using the AT&T (GNU as) syntax | 17 | asm code for Pentium and PPro/PII, using the AT&T (GNU as) syntax |
diff --git a/contrib/amd64/amd64-match.S b/contrib/amd64/amd64-match.S new file mode 100644 index 0000000..b3bf1ac --- /dev/null +++ b/contrib/amd64/amd64-match.S | |||
@@ -0,0 +1,357 @@ | |||
1 | /* | ||
2 | * match.S -- optimized version of longest_match() | ||
3 | * based on the similar work by Gilles Vollant, and Brian Raiter, written 1998 | ||
4 | * | ||
5 | * This is free software; you can redistribute it and/or modify it | ||
6 | * under the terms of the BSD License. Use by owners of Che Guevarra | ||
7 | * parafernalia is prohibited, where possible, and highly discouraged | ||
8 | * elsewhere. | ||
9 | */ | ||
10 | |||
11 | #ifndef NO_UNDERLINE | ||
12 | # define match_init _match_init | ||
13 | # define longest_match _longest_match | ||
14 | #endif | ||
15 | |||
16 | #define scanend ebx | ||
17 | #define scanendw bx | ||
18 | #define chainlenwmask edx /* high word: current chain len low word: s->wmask */ | ||
19 | #define curmatch rsi | ||
20 | #define curmatchd esi | ||
21 | #define windowbestlen r8 | ||
22 | #define scanalign r9 | ||
23 | #define scanalignd r9d | ||
24 | #define window r10 | ||
25 | #define bestlen r11 | ||
26 | #define bestlend r11d | ||
27 | #define scanstart r12d | ||
28 | #define scanstartw r12w | ||
29 | #define scan r13 | ||
30 | #define nicematch r14d | ||
31 | #define limit r15 | ||
32 | #define limitd r15d | ||
33 | #define prev rcx | ||
34 | |||
35 | /* | ||
36 | * The 258 is a "magic number, not a parameter -- changing it | ||
37 | * breaks the hell loose | ||
38 | */ | ||
39 | #define MAX_MATCH (258) | ||
40 | #define MIN_MATCH (3) | ||
41 | #define MIN_LOOKAHEAD (MAX_MATCH + MIN_MATCH + 1) | ||
42 | #define MAX_MATCH_8 ((MAX_MATCH + 7) & ~7) | ||
43 | |||
44 | /* stack frame offsets */ | ||
45 | #define LocalVarsSize (112) | ||
46 | #define _chainlenwmask ( 8-LocalVarsSize)(%rsp) | ||
47 | #define _windowbestlen (16-LocalVarsSize)(%rsp) | ||
48 | #define save_r14 (24-LocalVarsSize)(%rsp) | ||
49 | #define save_rsi (32-LocalVarsSize)(%rsp) | ||
50 | #define save_rbx (40-LocalVarsSize)(%rsp) | ||
51 | #define save_r12 (56-LocalVarsSize)(%rsp) | ||
52 | #define save_r13 (64-LocalVarsSize)(%rsp) | ||
53 | #define save_r15 (80-LocalVarsSize)(%rsp) | ||
54 | |||
55 | /* | ||
56 | * On AMD64 the first argument of a function (in our case -- the pointer to | ||
57 | * deflate_state structure) is passed in %rdi, hence our offsets below are | ||
58 | * all off of that. | ||
59 | */ | ||
60 | #ifndef STRUCT_OFFSET | ||
61 | # define STRUCT_OFFSET (0) | ||
62 | #endif | ||
63 | #define dsWSize ( 56 + STRUCT_OFFSET)(%rdi) | ||
64 | #define dsWMask ( 64 + STRUCT_OFFSET)(%rdi) | ||
65 | #define dsWindow ( 72 + STRUCT_OFFSET)(%rdi) | ||
66 | #define dsPrev ( 88 + STRUCT_OFFSET)(%rdi) | ||
67 | #define dsMatchLen (136 + STRUCT_OFFSET)(%rdi) | ||
68 | #define dsPrevMatch (140 + STRUCT_OFFSET)(%rdi) | ||
69 | #define dsStrStart (148 + STRUCT_OFFSET)(%rdi) | ||
70 | #define dsMatchStart (152 + STRUCT_OFFSET)(%rdi) | ||
71 | #define dsLookahead (156 + STRUCT_OFFSET)(%rdi) | ||
72 | #define dsPrevLen (160 + STRUCT_OFFSET)(%rdi) | ||
73 | #define dsMaxChainLen (164 + STRUCT_OFFSET)(%rdi) | ||
74 | #define dsGoodMatch (180 + STRUCT_OFFSET)(%rdi) | ||
75 | #define dsNiceMatch (184 + STRUCT_OFFSET)(%rdi) | ||
76 | |||
77 | .globl match_init, longest_match | ||
78 | |||
79 | .text | ||
80 | |||
81 | /* uInt longest_match(deflate_state *deflatestate, IPos curmatch) */ | ||
82 | |||
83 | longest_match: | ||
84 | /* | ||
85 | * Retrieve the function arguments. %curmatch will hold cur_match | ||
86 | * throughout the entire function (passed via rsi on amd64). | ||
87 | * rdi will hold the pointer to the deflate_state (first arg on amd64) | ||
88 | */ | ||
89 | mov %rsi, save_rsi | ||
90 | mov %rbx, save_rbx | ||
91 | mov %r12, save_r12 | ||
92 | mov %r13, save_r13 | ||
93 | mov %r14, save_r14 | ||
94 | mov %r15, save_r15 | ||
95 | |||
96 | /* uInt wmask = s->w_mask; */ | ||
97 | /* unsigned chain_length = s->max_chain_length; */ | ||
98 | /* if (s->prev_length >= s->good_match) { */ | ||
99 | /* chain_length >>= 2; */ | ||
100 | /* } */ | ||
101 | |||
102 | movl dsPrevLen, %eax | ||
103 | movl dsGoodMatch, %ebx | ||
104 | cmpl %ebx, %eax | ||
105 | movl dsWMask, %eax | ||
106 | movl dsMaxChainLen, %chainlenwmask | ||
107 | jl LastMatchGood | ||
108 | shrl $2, %chainlenwmask | ||
109 | LastMatchGood: | ||
110 | |||
111 | /* chainlen is decremented once beforehand so that the function can */ | ||
112 | /* use the sign flag instead of the zero flag for the exit test. */ | ||
113 | /* It is then shifted into the high word, to make room for the wmask */ | ||
114 | /* value, which it will always accompany. */ | ||
115 | |||
116 | decl %chainlenwmask | ||
117 | shll $16, %chainlenwmask | ||
118 | orl %eax, %chainlenwmask | ||
119 | |||
120 | /* if ((uInt)nice_match > s->lookahead) nice_match = s->lookahead; */ | ||
121 | |||
122 | movl dsNiceMatch, %eax | ||
123 | movl dsLookahead, %ebx | ||
124 | cmpl %eax, %ebx | ||
125 | jl LookaheadLess | ||
126 | movl %eax, %ebx | ||
127 | LookaheadLess: movl %ebx, %nicematch | ||
128 | |||
129 | /* register Bytef *scan = s->window + s->strstart; */ | ||
130 | |||
131 | mov dsWindow, %window | ||
132 | movl dsStrStart, %limitd | ||
133 | lea (%limit, %window), %scan | ||
134 | |||
135 | /* Determine how many bytes the scan ptr is off from being */ | ||
136 | /* dword-aligned. */ | ||
137 | |||
138 | mov %scan, %scanalign | ||
139 | negl %scanalignd | ||
140 | andl $3, %scanalignd | ||
141 | |||
142 | /* IPos limit = s->strstart > (IPos)MAX_DIST(s) ? */ | ||
143 | /* s->strstart - (IPos)MAX_DIST(s) : NIL; */ | ||
144 | |||
145 | movl dsWSize, %eax | ||
146 | subl $MIN_LOOKAHEAD, %eax | ||
147 | xorl %ecx, %ecx | ||
148 | subl %eax, %limitd | ||
149 | cmovng %ecx, %limitd | ||
150 | |||
151 | /* int best_len = s->prev_length; */ | ||
152 | |||
153 | movl dsPrevLen, %bestlend | ||
154 | |||
155 | /* Store the sum of s->window + best_len in %windowbestlen locally, and in memory. */ | ||
156 | |||
157 | lea (%window, %bestlen), %windowbestlen | ||
158 | mov %windowbestlen, _windowbestlen | ||
159 | |||
160 | /* register ush scan_start = *(ushf*)scan; */ | ||
161 | /* register ush scan_end = *(ushf*)(scan+best_len-1); */ | ||
162 | /* Posf *prev = s->prev; */ | ||
163 | |||
164 | movzwl (%scan), %scanstart | ||
165 | movzwl -1(%scan, %bestlen), %scanend | ||
166 | mov dsPrev, %prev | ||
167 | |||
168 | /* Jump into the main loop. */ | ||
169 | |||
170 | movl %chainlenwmask, _chainlenwmask | ||
171 | jmp LoopEntry | ||
172 | |||
173 | .balign 16 | ||
174 | |||
175 | /* do { | ||
176 | * match = s->window + cur_match; | ||
177 | * if (*(ushf*)(match+best_len-1) != scan_end || | ||
178 | * *(ushf*)match != scan_start) continue; | ||
179 | * [...] | ||
180 | * } while ((cur_match = prev[cur_match & wmask]) > limit | ||
181 | * && --chain_length != 0); | ||
182 | * | ||
183 | * Here is the inner loop of the function. The function will spend the | ||
184 | * majority of its time in this loop, and majority of that time will | ||
185 | * be spent in the first ten instructions. | ||
186 | */ | ||
187 | LookupLoop: | ||
188 | andl %chainlenwmask, %curmatchd | ||
189 | movzwl (%prev, %curmatch, 2), %curmatchd | ||
190 | cmpl %limitd, %curmatchd | ||
191 | jbe LeaveNow | ||
192 | subl $0x00010000, %chainlenwmask | ||
193 | js LeaveNow | ||
194 | LoopEntry: cmpw -1(%windowbestlen, %curmatch), %scanendw | ||
195 | jne LookupLoop | ||
196 | cmpw %scanstartw, (%window, %curmatch) | ||
197 | jne LookupLoop | ||
198 | |||
199 | /* Store the current value of chainlen. */ | ||
200 | movl %chainlenwmask, _chainlenwmask | ||
201 | |||
202 | /* %scan is the string under scrutiny, and %prev to the string we */ | ||
203 | /* are hoping to match it up with. In actuality, %esi and %edi are */ | ||
204 | /* both pointed (MAX_MATCH_8 - scanalign) bytes ahead, and %edx is */ | ||
205 | /* initialized to -(MAX_MATCH_8 - scanalign). */ | ||
206 | |||
207 | mov $(-MAX_MATCH_8), %rdx | ||
208 | lea (%curmatch, %window), %windowbestlen | ||
209 | lea MAX_MATCH_8(%windowbestlen, %scanalign), %windowbestlen | ||
210 | lea MAX_MATCH_8(%scan, %scanalign), %prev | ||
211 | |||
212 | /* the prefetching below makes very little difference... */ | ||
213 | prefetcht1 (%windowbestlen, %rdx) | ||
214 | prefetcht1 (%prev, %rdx) | ||
215 | |||
216 | /* | ||
217 | * Test the strings for equality, 8 bytes at a time. At the end, | ||
218 | * adjust %rdx so that it is offset to the exact byte that mismatched. | ||
219 | * | ||
220 | * It should be confessed that this loop usually does not represent | ||
221 | * much of the total running time. Replacing it with a more | ||
222 | * straightforward "rep cmpsb" would not drastically degrade | ||
223 | * performance -- unrolling it, for example, makes no difference. | ||
224 | */ | ||
225 | #undef USE_SSE /* works, but is 6-7% slower, than non-SSE... */ | ||
226 | LoopCmps: | ||
227 | #ifdef USE_SSE | ||
228 | /* Preload the SSE registers */ | ||
229 | movdqu (%windowbestlen, %rdx), %xmm1 | ||
230 | movdqu (%prev, %rdx), %xmm2 | ||
231 | pcmpeqb %xmm2, %xmm1 | ||
232 | movdqu 16(%windowbestlen, %rdx), %xmm3 | ||
233 | movdqu 16(%prev, %rdx), %xmm4 | ||
234 | pcmpeqb %xmm4, %xmm3 | ||
235 | movdqu 32(%windowbestlen, %rdx), %xmm5 | ||
236 | movdqu 32(%prev, %rdx), %xmm6 | ||
237 | pcmpeqb %xmm6, %xmm5 | ||
238 | movdqu 48(%windowbestlen, %rdx), %xmm7 | ||
239 | movdqu 48(%prev, %rdx), %xmm8 | ||
240 | pcmpeqb %xmm8, %xmm7 | ||
241 | |||
242 | /* Check the comparisions' results */ | ||
243 | pmovmskb %xmm1, %rax | ||
244 | notw %ax | ||
245 | bsfw %ax, %ax | ||
246 | jnz LeaveLoopCmps | ||
247 | add $16, %rdx | ||
248 | pmovmskb %xmm3, %rax | ||
249 | notw %ax | ||
250 | bsfw %ax, %ax | ||
251 | jnz LeaveLoopCmps | ||
252 | add $16, %rdx | ||
253 | pmovmskb %xmm5, %rax | ||
254 | notw %ax | ||
255 | bsfw %ax, %ax | ||
256 | jnz LeaveLoopCmps | ||
257 | add $16, %rdx | ||
258 | pmovmskb %xmm7, %rax | ||
259 | notw %ax | ||
260 | bsfw %ax, %ax | ||
261 | jnz LeaveLoopCmps | ||
262 | add $16, %rdx | ||
263 | jmp LoopCmps | ||
264 | LeaveLoopCmps: add %rax, %rdx | ||
265 | #else | ||
266 | mov (%windowbestlen, %rdx), %rax | ||
267 | xor (%prev, %rdx), %rax | ||
268 | jnz LeaveLoopCmps | ||
269 | add $8, %rdx | ||
270 | jnz LoopCmps | ||
271 | jmp LenMaximum | ||
272 | # if 0 | ||
273 | /* | ||
274 | * This three-liner is tantalizingly simple, but bsf is a slow instruction, | ||
275 | * and the complicated alternative down below is quite a bit faster. Sad... | ||
276 | */ | ||
277 | LeaveLoopCmps: bsf %rax, %rax /* find the first non-zero bit */ | ||
278 | shrl $3, %eax /* divide by 8 to get the byte */ | ||
279 | add %rax, %rdx | ||
280 | # else | ||
281 | LeaveLoopCmps: testl $0xFFFFFFFF, %eax /* Check the first 4 bytes */ | ||
282 | jnz Check16 | ||
283 | add $4, %rdx | ||
284 | shr $32, %rax | ||
285 | Check16: testw $0xFFFF, %ax | ||
286 | jnz LenLower | ||
287 | add $2, %rdx | ||
288 | shrl $16, %eax | ||
289 | LenLower: subb $1, %al | ||
290 | adc $0, %rdx | ||
291 | # endif | ||
292 | #endif | ||
293 | |||
294 | /* Calculate the length of the match. If it is longer than MAX_MATCH, */ | ||
295 | /* then automatically accept it as the best possible match and leave. */ | ||
296 | |||
297 | lea (%prev, %rdx), %rax | ||
298 | sub %scan, %rax | ||
299 | cmpl $MAX_MATCH, %eax | ||
300 | jge LenMaximum | ||
301 | |||
302 | /* If the length of the match is not longer than the best match we */ | ||
303 | /* have so far, then forget it and return to the lookup loop. */ | ||
304 | |||
305 | cmpl %bestlend, %eax | ||
306 | jg LongerMatch | ||
307 | mov _windowbestlen, %windowbestlen | ||
308 | mov dsPrev, %prev | ||
309 | movl _chainlenwmask, %edx | ||
310 | jmp LookupLoop | ||
311 | |||
312 | /* s->match_start = cur_match; */ | ||
313 | /* best_len = len; */ | ||
314 | /* if (len >= nice_match) break; */ | ||
315 | /* scan_end = *(ushf*)(scan+best_len-1); */ | ||
316 | |||
317 | LongerMatch: | ||
318 | movl %eax, %bestlend | ||
319 | movl %curmatchd, dsMatchStart | ||
320 | cmpl %nicematch, %eax | ||
321 | jge LeaveNow | ||
322 | |||
323 | lea (%window, %bestlen), %windowbestlen | ||
324 | mov %windowbestlen, _windowbestlen | ||
325 | |||
326 | movzwl -1(%scan, %rax), %scanend | ||
327 | mov dsPrev, %prev | ||
328 | movl _chainlenwmask, %chainlenwmask | ||
329 | jmp LookupLoop | ||
330 | |||
331 | /* Accept the current string, with the maximum possible length. */ | ||
332 | |||
333 | LenMaximum: | ||
334 | movl $MAX_MATCH, %bestlend | ||
335 | movl %curmatchd, dsMatchStart | ||
336 | |||
337 | /* if ((uInt)best_len <= s->lookahead) return (uInt)best_len; */ | ||
338 | /* return s->lookahead; */ | ||
339 | |||
340 | LeaveNow: | ||
341 | movl dsLookahead, %eax | ||
342 | cmpl %eax, %bestlend | ||
343 | cmovngl %bestlend, %eax | ||
344 | LookaheadRet: | ||
345 | |||
346 | /* Restore the registers and return from whence we came. */ | ||
347 | |||
348 | mov save_rsi, %rsi | ||
349 | mov save_rbx, %rbx | ||
350 | mov save_r12, %r12 | ||
351 | mov save_r13, %r13 | ||
352 | mov save_r14, %r14 | ||
353 | mov save_r15, %r15 | ||
354 | |||
355 | ret | ||
356 | |||
357 | match_init: ret | ||
diff --git a/contrib/infback9/infback9.c b/contrib/infback9/infback9.c index c5547ae..7bbe90c 100644 --- a/contrib/infback9/infback9.c +++ b/contrib/infback9/infback9.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* infback9.c -- inflate deflate64 data using a call-back interface | 1 | /* infback9.c -- inflate deflate64 data using a call-back interface |
2 | * Copyright (C) 1995-2006 Mark Adler | 2 | * Copyright (C) 1995-2008 Mark Adler |
3 | * For conditions of distribution and use, see copyright notice in zlib.h | 3 | * For conditions of distribution and use, see copyright notice in zlib.h |
4 | */ | 4 | */ |
5 | 5 | ||
@@ -433,7 +433,16 @@ void FAR *out_desc; | |||
433 | /* handle error breaks in while */ | 433 | /* handle error breaks in while */ |
434 | if (mode == BAD) break; | 434 | if (mode == BAD) break; |
435 | 435 | ||
436 | /* build code tables */ | 436 | /* check for end-of-block code (better have one) */ |
437 | if (state->lens[256] == 0) { | ||
438 | strm->msg = (char *)"invalid code -- missing end-of-block"; | ||
439 | mode = BAD; | ||
440 | break; | ||
441 | } | ||
442 | |||
443 | /* build code tables -- note: do not change the lenbits or distbits | ||
444 | values here (9 and 6) without reading the comments in inftree9.h | ||
445 | concerning the ENOUGH constants, which depend on those values */ | ||
437 | state->next = state->codes; | 446 | state->next = state->codes; |
438 | lencode = (code const FAR *)(state->next); | 447 | lencode = (code const FAR *)(state->next); |
439 | lenbits = 9; | 448 | lenbits = 9; |
diff --git a/contrib/infback9/inftree9.c b/contrib/infback9/inftree9.c index c24302b..18353cb 100644 --- a/contrib/infback9/inftree9.c +++ b/contrib/infback9/inftree9.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* inftree9.c -- generate Huffman trees for efficient decoding | 1 | /* inftree9.c -- generate Huffman trees for efficient decoding |
2 | * Copyright (C) 1995-2006 Mark Adler | 2 | * Copyright (C) 1995-2008 Mark Adler |
3 | * For conditions of distribution and use, see copyright notice in zlib.h | 3 | * For conditions of distribution and use, see copyright notice in zlib.h |
4 | */ | 4 | */ |
5 | 5 | ||
@@ -9,7 +9,7 @@ | |||
9 | #define MAXBITS 15 | 9 | #define MAXBITS 15 |
10 | 10 | ||
11 | const char inflate9_copyright[] = | 11 | const char inflate9_copyright[] = |
12 | " inflate9 1.2.3.3 Copyright 1995-2006 Mark Adler "; | 12 | " inflate9 1.2.3.4 Copyright 1995-2008 Mark Adler "; |
13 | /* | 13 | /* |
14 | If you use the zlib library in a product, an acknowledgment is welcome | 14 | If you use the zlib library in a product, an acknowledgment is welcome |
15 | in the documentation of your product. If for some reason you cannot | 15 | in the documentation of your product. If for some reason you cannot |
@@ -64,7 +64,7 @@ unsigned short FAR *work; | |||
64 | static const unsigned short lext[31] = { /* Length codes 257..285 extra */ | 64 | static const unsigned short lext[31] = { /* Length codes 257..285 extra */ |
65 | 128, 128, 128, 128, 128, 128, 128, 128, 129, 129, 129, 129, | 65 | 128, 128, 128, 128, 128, 128, 128, 128, 129, 129, 129, 129, |
66 | 130, 130, 130, 130, 131, 131, 131, 131, 132, 132, 132, 132, | 66 | 130, 130, 130, 130, 131, 131, 131, 131, 132, 132, 132, 132, |
67 | 133, 133, 133, 133, 144, 201, 203}; | 67 | 133, 133, 133, 133, 144, 72, 200}; |
68 | static const unsigned short dbase[32] = { /* Distance codes 0..31 base */ | 68 | static const unsigned short dbase[32] = { /* Distance codes 0..31 base */ |
69 | 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, | 69 | 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, |
70 | 65, 97, 129, 193, 257, 385, 513, 769, 1025, 1537, 2049, 3073, | 70 | 65, 97, 129, 193, 257, 385, 513, 769, 1025, 1537, 2049, 3073, |
@@ -160,11 +160,10 @@ unsigned short FAR *work; | |||
160 | entered in the tables. | 160 | entered in the tables. |
161 | 161 | ||
162 | used keeps track of how many table entries have been allocated from the | 162 | used keeps track of how many table entries have been allocated from the |
163 | provided *table space. It is checked when a LENS table is being made | 163 | provided *table space. It is checked for LENS and DIST tables against |
164 | against the space in *table, ENOUGH, minus the maximum space needed by | 164 | the constants ENOUGH_LENS and ENOUGH_DISTS to guard against changes in |
165 | the worst case distance code, MAXD. This should never happen, but the | 165 | the initial root table size constants. See the comments in inftree9.h |
166 | sufficiency of ENOUGH has not been proven exhaustively, hence the check. | 166 | for more information. |
167 | This assumes that when type == LENS, bits == 9. | ||
168 | 167 | ||
169 | sym increments through all symbols, and the loop terminates when | 168 | sym increments through all symbols, and the loop terminates when |
170 | all codes of length max, i.e. all codes, have been processed. This | 169 | all codes of length max, i.e. all codes, have been processed. This |
@@ -203,7 +202,8 @@ unsigned short FAR *work; | |||
203 | mask = used - 1; /* mask for comparing low */ | 202 | mask = used - 1; /* mask for comparing low */ |
204 | 203 | ||
205 | /* check available table space */ | 204 | /* check available table space */ |
206 | if (type == LENS && used >= ENOUGH - MAXD) | 205 | if ((type == LENS && used >= ENOUGH_LENS) || |
206 | (type == DISTS && used >= ENOUGH_DISTS)) | ||
207 | return 1; | 207 | return 1; |
208 | 208 | ||
209 | /* process all codes and make table entries */ | 209 | /* process all codes and make table entries */ |
@@ -270,7 +270,8 @@ unsigned short FAR *work; | |||
270 | 270 | ||
271 | /* check for enough space */ | 271 | /* check for enough space */ |
272 | used += 1U << curr; | 272 | used += 1U << curr; |
273 | if (type == LENS && used >= ENOUGH - MAXD) | 273 | if ((type == LENS && used >= ENOUGH_LENS) || |
274 | (type == DISTS && used >= ENOUGH_DISTS)) | ||
274 | return 1; | 275 | return 1; |
275 | 276 | ||
276 | /* point entry in root table to sub-table */ | 277 | /* point entry in root table to sub-table */ |
diff --git a/contrib/infback9/inftree9.h b/contrib/infback9/inftree9.h index a268084..5ab21f0 100644 --- a/contrib/infback9/inftree9.h +++ b/contrib/infback9/inftree9.h | |||
@@ -1,5 +1,5 @@ | |||
1 | /* inftree9.h -- header to use inftree9.c | 1 | /* inftree9.h -- header to use inftree9.c |
2 | * Copyright (C) 1995-2003 Mark Adler | 2 | * Copyright (C) 1995-2008 Mark Adler |
3 | * For conditions of distribution and use, see copyright notice in zlib.h | 3 | * For conditions of distribution and use, see copyright notice in zlib.h |
4 | */ | 4 | */ |
5 | 5 | ||
@@ -35,15 +35,21 @@ typedef struct { | |||
35 | 01000000 - invalid code | 35 | 01000000 - invalid code |
36 | */ | 36 | */ |
37 | 37 | ||
38 | /* Maximum size of dynamic tree. The maximum found in a long but non- | 38 | /* Maximum size of the dynamic table. The maximum number of code structures is |
39 | exhaustive search was 1444 code structures (852 for length/literals | 39 | 1446, which is the sum of 852 for literal/length codes and 594 for distance |
40 | and 592 for distances, the latter actually the result of an | 40 | codes. These values were found by exhaustive searches using the program |
41 | exhaustive search). The true maximum is not known, but the value | 41 | examples/enough.c found in the zlib distribtution. The arguments to that |
42 | below is more than safe. */ | 42 | program are the number of symbols, the initial root table size, and the |
43 | #define ENOUGH 2048 | 43 | maximum bit length of a code. "enough 286 9 15" for literal/length codes |
44 | #define MAXD 592 | 44 | returns returns 852, and "enough 32 6 15" for distance codes returns 594. |
45 | The initial root table size (9 or 6) is found in the fifth argument of the | ||
46 | inflate_table() calls in infback9.c. If the root table size is changed, | ||
47 | then these maximum sizes would be need to be recalculated and updated. */ | ||
48 | #define ENOUGH_LENS 852 | ||
49 | #define ENOUGH_DISTS 594 | ||
50 | #define ENOUGH (ENOUGH_LENS+ENOUGH_DISTS) | ||
45 | 51 | ||
46 | /* Type of code to build for inftable() */ | 52 | /* Type of code to build for inflate_table9() */ |
47 | typedef enum { | 53 | typedef enum { |
48 | CODES, | 54 | CODES, |
49 | LENS, | 55 | LENS, |
diff --git a/contrib/nintendods/Makefile b/contrib/nintendods/Makefile new file mode 100644 index 0000000..21337d0 --- /dev/null +++ b/contrib/nintendods/Makefile | |||
@@ -0,0 +1,126 @@ | |||
1 | #--------------------------------------------------------------------------------- | ||
2 | .SUFFIXES: | ||
3 | #--------------------------------------------------------------------------------- | ||
4 | |||
5 | ifeq ($(strip $(DEVKITARM)),) | ||
6 | $(error "Please set DEVKITARM in your environment. export DEVKITARM=<path to>devkitARM") | ||
7 | endif | ||
8 | |||
9 | include $(DEVKITARM)/ds_rules | ||
10 | |||
11 | #--------------------------------------------------------------------------------- | ||
12 | # TARGET is the name of the output | ||
13 | # BUILD is the directory where object files & intermediate files will be placed | ||
14 | # SOURCES is a list of directories containing source code | ||
15 | # DATA is a list of directories containing data files | ||
16 | # INCLUDES is a list of directories containing header files | ||
17 | #--------------------------------------------------------------------------------- | ||
18 | TARGET := $(shell basename $(CURDIR)) | ||
19 | BUILD := build | ||
20 | SOURCES := ../../ | ||
21 | DATA := data | ||
22 | INCLUDES := include | ||
23 | |||
24 | #--------------------------------------------------------------------------------- | ||
25 | # options for code generation | ||
26 | #--------------------------------------------------------------------------------- | ||
27 | ARCH := -mthumb -mthumb-interwork | ||
28 | |||
29 | CFLAGS := -Wall -O2\ | ||
30 | -march=armv5te -mtune=arm946e-s \ | ||
31 | -fomit-frame-pointer -ffast-math \ | ||
32 | $(ARCH) | ||
33 | |||
34 | CFLAGS += $(INCLUDE) -DARM9 | ||
35 | CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions | ||
36 | |||
37 | ASFLAGS := $(ARCH) -march=armv5te -mtune=arm946e-s | ||
38 | LDFLAGS = -specs=ds_arm9.specs -g $(ARCH) -Wl,-Map,$(notdir $*.map) | ||
39 | |||
40 | #--------------------------------------------------------------------------------- | ||
41 | # list of directories containing libraries, this must be the top level containing | ||
42 | # include and lib | ||
43 | #--------------------------------------------------------------------------------- | ||
44 | LIBDIRS := $(LIBNDS) | ||
45 | |||
46 | #--------------------------------------------------------------------------------- | ||
47 | # no real need to edit anything past this point unless you need to add additional | ||
48 | # rules for different file extensions | ||
49 | #--------------------------------------------------------------------------------- | ||
50 | ifneq ($(BUILD),$(notdir $(CURDIR))) | ||
51 | #--------------------------------------------------------------------------------- | ||
52 | |||
53 | export OUTPUT := $(CURDIR)/lib/libz.a | ||
54 | |||
55 | export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \ | ||
56 | $(foreach dir,$(DATA),$(CURDIR)/$(dir)) | ||
57 | |||
58 | export DEPSDIR := $(CURDIR)/$(BUILD) | ||
59 | |||
60 | CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c))) | ||
61 | CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp))) | ||
62 | SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s))) | ||
63 | BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*))) | ||
64 | |||
65 | #--------------------------------------------------------------------------------- | ||
66 | # use CXX for linking C++ projects, CC for standard C | ||
67 | #--------------------------------------------------------------------------------- | ||
68 | ifeq ($(strip $(CPPFILES)),) | ||
69 | #--------------------------------------------------------------------------------- | ||
70 | export LD := $(CC) | ||
71 | #--------------------------------------------------------------------------------- | ||
72 | else | ||
73 | #--------------------------------------------------------------------------------- | ||
74 | export LD := $(CXX) | ||
75 | #--------------------------------------------------------------------------------- | ||
76 | endif | ||
77 | #--------------------------------------------------------------------------------- | ||
78 | |||
79 | export OFILES := $(addsuffix .o,$(BINFILES)) \ | ||
80 | $(CPPFILES:.cpp=.o) $(CFILES:.c=.o) $(SFILES:.s=.o) | ||
81 | |||
82 | export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \ | ||
83 | $(foreach dir,$(LIBDIRS),-I$(dir)/include) \ | ||
84 | -I$(CURDIR)/$(BUILD) | ||
85 | |||
86 | .PHONY: $(BUILD) clean all | ||
87 | |||
88 | #--------------------------------------------------------------------------------- | ||
89 | all: $(BUILD) | ||
90 | @[ -d $@ ] || mkdir -p include | ||
91 | @cp ../../*.h include | ||
92 | |||
93 | lib: | ||
94 | @[ -d $@ ] || mkdir -p $@ | ||
95 | |||
96 | $(BUILD): lib | ||
97 | @[ -d $@ ] || mkdir -p $@ | ||
98 | @$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile | ||
99 | |||
100 | #--------------------------------------------------------------------------------- | ||
101 | clean: | ||
102 | @echo clean ... | ||
103 | @rm -fr $(BUILD) lib | ||
104 | |||
105 | #--------------------------------------------------------------------------------- | ||
106 | else | ||
107 | |||
108 | DEPENDS := $(OFILES:.o=.d) | ||
109 | |||
110 | #--------------------------------------------------------------------------------- | ||
111 | # main targets | ||
112 | #--------------------------------------------------------------------------------- | ||
113 | $(OUTPUT) : $(OFILES) | ||
114 | |||
115 | #--------------------------------------------------------------------------------- | ||
116 | %.bin.o : %.bin | ||
117 | #--------------------------------------------------------------------------------- | ||
118 | @echo $(notdir $<) | ||
119 | @$(bin2o) | ||
120 | |||
121 | |||
122 | -include $(DEPENDS) | ||
123 | |||
124 | #--------------------------------------------------------------------------------------- | ||
125 | endif | ||
126 | #--------------------------------------------------------------------------------------- | ||
diff --git a/contrib/nintendods/README b/contrib/nintendods/README new file mode 100644 index 0000000..ba7a37d --- /dev/null +++ b/contrib/nintendods/README | |||
@@ -0,0 +1,5 @@ | |||
1 | This Makefile requires devkitARM (http://www.devkitpro.org/category/devkitarm/) and works inside "contrib/nds". It is based on a devkitARM template. | ||
2 | |||
3 | Eduardo Costa <eduardo.m.costa@gmail.com> | ||
4 | January 3, 2009 | ||
5 | |||
diff --git a/contrib/puff/puff b/contrib/puff/puff new file mode 100755 index 0000000..bedac26 --- /dev/null +++ b/contrib/puff/puff | |||
Binary files differ | |||
diff --git a/contrib/puff/puff.c b/contrib/puff/puff.c index ce0cc40..df5b79f 100644 --- a/contrib/puff/puff.c +++ b/contrib/puff/puff.c | |||
@@ -1,8 +1,8 @@ | |||
1 | /* | 1 | /* |
2 | * puff.c | 2 | * puff.c |
3 | * Copyright (C) 2002-2004 Mark Adler | 3 | * Copyright (C) 2002-2008 Mark Adler |
4 | * For conditions of distribution and use, see copyright notice in puff.h | 4 | * For conditions of distribution and use, see copyright notice in puff.h |
5 | * version 1.8, 9 Jan 2004 | 5 | * version 2.0, 25 Jul 2008 |
6 | * | 6 | * |
7 | * puff.c is a simple inflate written to be an unambiguous way to specify the | 7 | * puff.c is a simple inflate written to be an unambiguous way to specify the |
8 | * deflate format. It is not written for speed but rather simplicity. As a | 8 | * deflate format. It is not written for speed but rather simplicity. As a |
@@ -61,6 +61,12 @@ | |||
61 | * 1.7 3 Mar 2003 - Added test code for distribution | 61 | * 1.7 3 Mar 2003 - Added test code for distribution |
62 | * - Added zlib-like license | 62 | * - Added zlib-like license |
63 | * 1.8 9 Jan 2004 - Added some comments on no distance codes case | 63 | * 1.8 9 Jan 2004 - Added some comments on no distance codes case |
64 | * 1.9 21 Feb 2008 - Fix bug on 16-bit integer architectures [Pohland] | ||
65 | * - Catch missing end-of-block symbol error | ||
66 | * 2.0 25 Jul 2008 - Add #define to permit distance too far back | ||
67 | * - Add option in TEST code for puff to write the data | ||
68 | * - Add option in TEST code to skip input bytes | ||
69 | * - Allow TEST code to read from piped stdin | ||
64 | */ | 70 | */ |
65 | 71 | ||
66 | #include <setjmp.h> /* for setjmp(), longjmp(), and jmp_buf */ | 72 | #include <setjmp.h> /* for setjmp(), longjmp(), and jmp_buf */ |
@@ -194,7 +200,7 @@ struct huffman { | |||
194 | * Decode a code from the stream s using huffman table h. Return the symbol or | 200 | * Decode a code from the stream s using huffman table h. Return the symbol or |
195 | * a negative value if there is an error. If all of the lengths are zero, i.e. | 201 | * a negative value if there is an error. If all of the lengths are zero, i.e. |
196 | * an empty code, or if the code is incomplete and an invalid code is received, | 202 | * an empty code, or if the code is incomplete and an invalid code is received, |
197 | * then -9 is returned after reading MAXBITS bits. | 203 | * then -10 is returned after reading MAXBITS bits. |
198 | * | 204 | * |
199 | * Format notes: | 205 | * Format notes: |
200 | * | 206 | * |
@@ -226,14 +232,14 @@ local int decode(struct state *s, struct huffman *h) | |||
226 | for (len = 1; len <= MAXBITS; len++) { | 232 | for (len = 1; len <= MAXBITS; len++) { |
227 | code |= bits(s, 1); /* get next bit */ | 233 | code |= bits(s, 1); /* get next bit */ |
228 | count = h->count[len]; | 234 | count = h->count[len]; |
229 | if (code < first + count) /* if length len, return symbol */ | 235 | if (code - count < first) /* if length len, return symbol */ |
230 | return h->symbol[index + (code - first)]; | 236 | return h->symbol[index + (code - first)]; |
231 | index += count; /* else update for next length */ | 237 | index += count; /* else update for next length */ |
232 | first += count; | 238 | first += count; |
233 | first <<= 1; | 239 | first <<= 1; |
234 | code <<= 1; | 240 | code <<= 1; |
235 | } | 241 | } |
236 | return -9; /* ran out of codes */ | 242 | return -10; /* ran out of codes */ |
237 | } | 243 | } |
238 | 244 | ||
239 | /* | 245 | /* |
@@ -263,7 +269,7 @@ local int decode(struct state *s, struct huffman *h) | |||
263 | code |= bitbuf & 1; | 269 | code |= bitbuf & 1; |
264 | bitbuf >>= 1; | 270 | bitbuf >>= 1; |
265 | count = *next++; | 271 | count = *next++; |
266 | if (code < first + count) { /* if length len, return symbol */ | 272 | if (code - count < first) { /* if length len, return symbol */ |
267 | s->bitbuf = bitbuf; | 273 | s->bitbuf = bitbuf; |
268 | s->bitcnt = (s->bitcnt - len) & 7; | 274 | s->bitcnt = (s->bitcnt - len) & 7; |
269 | return h->symbol[index + (code - first)]; | 275 | return h->symbol[index + (code - first)]; |
@@ -280,7 +286,7 @@ local int decode(struct state *s, struct huffman *h) | |||
280 | bitbuf = s->in[s->incnt++]; | 286 | bitbuf = s->in[s->incnt++]; |
281 | if (left > 8) left = 8; | 287 | if (left > 8) left = 8; |
282 | } | 288 | } |
283 | return -9; /* ran out of codes */ | 289 | return -10; /* ran out of codes */ |
284 | } | 290 | } |
285 | #endif /* SLOW */ | 291 | #endif /* SLOW */ |
286 | 292 | ||
@@ -448,21 +454,27 @@ local int codes(struct state *s, | |||
448 | else if (symbol > 256) { /* length */ | 454 | else if (symbol > 256) { /* length */ |
449 | /* get and compute length */ | 455 | /* get and compute length */ |
450 | symbol -= 257; | 456 | symbol -= 257; |
451 | if (symbol >= 29) return -9; /* invalid fixed code */ | 457 | if (symbol >= 29) return -10; /* invalid fixed code */ |
452 | len = lens[symbol] + bits(s, lext[symbol]); | 458 | len = lens[symbol] + bits(s, lext[symbol]); |
453 | 459 | ||
454 | /* get and check distance */ | 460 | /* get and check distance */ |
455 | symbol = decode(s, distcode); | 461 | symbol = decode(s, distcode); |
456 | if (symbol < 0) return symbol; /* invalid symbol */ | 462 | if (symbol < 0) return symbol; /* invalid symbol */ |
457 | dist = dists[symbol] + bits(s, dext[symbol]); | 463 | dist = dists[symbol] + bits(s, dext[symbol]); |
464 | #ifndef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR | ||
458 | if (dist > s->outcnt) | 465 | if (dist > s->outcnt) |
459 | return -10; /* distance too far back */ | 466 | return -11; /* distance too far back */ |
467 | #endif | ||
460 | 468 | ||
461 | /* copy length bytes from distance bytes back */ | 469 | /* copy length bytes from distance bytes back */ |
462 | if (s->out != NIL) { | 470 | if (s->out != NIL) { |
463 | if (s->outcnt + len > s->outlen) return 1; | 471 | if (s->outcnt + len > s->outlen) return 1; |
464 | while (len--) { | 472 | while (len--) { |
465 | s->out[s->outcnt] = s->out[s->outcnt - dist]; | 473 | s->out[s->outcnt] = |
474 | #ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR | ||
475 | dist > s->outcnt ? 0 : | ||
476 | #endif | ||
477 | s->out[s->outcnt - dist]; | ||
466 | s->outcnt++; | 478 | s->outcnt++; |
467 | } | 479 | } |
468 | } | 480 | } |
@@ -680,6 +692,10 @@ local int dynamic(struct state *s) | |||
680 | } | 692 | } |
681 | } | 693 | } |
682 | 694 | ||
695 | /* check for end-of-block code -- there better be one! */ | ||
696 | if (lengths[256] == 0) | ||
697 | return -9; | ||
698 | |||
683 | /* build huffman table for literal/length codes */ | 699 | /* build huffman table for literal/length codes */ |
684 | err = construct(&lencode, lengths, nlen); | 700 | err = construct(&lencode, lengths, nlen); |
685 | if (err < 0 || (err > 0 && nlen - lencode.count[0] != 1)) | 701 | if (err < 0 || (err > 0 && nlen - lencode.count[0] != 1)) |
@@ -724,8 +740,9 @@ local int dynamic(struct state *s) | |||
724 | * -6: dynamic block code description: repeat more than specified lengths | 740 | * -6: dynamic block code description: repeat more than specified lengths |
725 | * -7: dynamic block code description: invalid literal/length code lengths | 741 | * -7: dynamic block code description: invalid literal/length code lengths |
726 | * -8: dynamic block code description: invalid distance code lengths | 742 | * -8: dynamic block code description: invalid distance code lengths |
727 | * -9: invalid literal/length or distance code in fixed or dynamic block | 743 | * -9: dynamic block code description: missing end-of-block code |
728 | * -10: distance is too far back in fixed or dynamic block | 744 | * -10: invalid literal/length or distance code in fixed or dynamic block |
745 | * -11: distance is too far back in fixed or dynamic block | ||
729 | * | 746 | * |
730 | * Format notes: | 747 | * Format notes: |
731 | * | 748 | * |
@@ -783,54 +800,142 @@ int puff(unsigned char *dest, /* pointer to destination pointer */ | |||
783 | } | 800 | } |
784 | 801 | ||
785 | #ifdef TEST | 802 | #ifdef TEST |
786 | /* Example of how to use puff() */ | 803 | /* Examples of how to use puff(). |
804 | |||
805 | Usage: puff [-w] [-nnn] file | ||
806 | ... | puff [-w] [-nnn] | ||
807 | |||
808 | where file is the input file with deflate data, nnn is the number of bytes | ||
809 | of input to skip before inflating (e.g. to skip a zlib or gzip header), and | ||
810 | -w is used to write the decompressed data to stdout */ | ||
811 | |||
787 | #include <stdio.h> | 812 | #include <stdio.h> |
788 | #include <stdlib.h> | 813 | #include <stdlib.h> |
789 | #include <sys/types.h> | ||
790 | #include <sys/stat.h> | ||
791 | 814 | ||
792 | local unsigned char *yank(char *name, unsigned long *len) | 815 | /* Return size times approximately the cube root of 2, keeping the result as 1, |
816 | 3, or 5 times a power of 2 -- the result is always > size, until the result | ||
817 | is the maximum value of an unsigned long, where it remains. This is useful | ||
818 | to keep reallocations less than ~33% over the actual data. */ | ||
819 | local size_t bythirds(size_t size) | ||
793 | { | 820 | { |
794 | unsigned long size; | 821 | int n; |
795 | unsigned char *buf; | 822 | size_t m; |
823 | |||
824 | m = size; | ||
825 | for (n = 0; m; n++) | ||
826 | m >>= 1; | ||
827 | if (n < 3) | ||
828 | return size + 1; | ||
829 | n -= 3; | ||
830 | m = size >> n; | ||
831 | m += m == 6 ? 2 : 1; | ||
832 | m <<= n; | ||
833 | return m > size ? m : (size_t)(-1); | ||
834 | } | ||
835 | |||
836 | /* Read the input file *name, or stdin if name is NULL, into allocated memory. | ||
837 | Reallocate to larger buffers until the entire file is read in. Return a | ||
838 | pointer to the allocated data, or NULL if there was a memory allocation | ||
839 | failure. *len is the number of bytes of data read from the input file (even | ||
840 | if load() returns NULL). If the input file was empty or could not be opened | ||
841 | or read, *len is zero. */ | ||
842 | local void *load(char *name, size_t *len) | ||
843 | { | ||
844 | size_t size; | ||
845 | void *buf, *swap; | ||
796 | FILE *in; | 846 | FILE *in; |
797 | struct stat s; | ||
798 | 847 | ||
799 | *len = 0; | 848 | *len = 0; |
800 | if (stat(name, &s)) return NULL; | 849 | buf = malloc(size = 4096); |
801 | if ((s.st_mode & S_IFMT) != S_IFREG) return NULL; | 850 | if (buf == NULL) |
802 | size = (unsigned long)(s.st_size); | 851 | return NULL; |
803 | if (size == 0 || (off_t)size != s.st_size) return NULL; | 852 | in = name == NULL ? stdin : fopen(name, "rb"); |
804 | in = fopen(name, "r"); | 853 | if (in != NULL) { |
805 | if (in == NULL) return NULL; | 854 | for (;;) { |
806 | buf = malloc(size); | 855 | *len += fread((char *)buf + *len, 1, size - *len, in); |
807 | if (buf != NULL && fread(buf, 1, size, in) != size) { | 856 | if (*len < size) break; |
808 | free(buf); | 857 | size = bythirds(size); |
809 | buf = NULL; | 858 | if (size == *len || (swap = realloc(buf, size)) == NULL) { |
859 | free(buf); | ||
860 | buf = NULL; | ||
861 | break; | ||
862 | } | ||
863 | buf = swap; | ||
864 | } | ||
865 | fclose(in); | ||
810 | } | 866 | } |
811 | fclose(in); | ||
812 | *len = size; | ||
813 | return buf; | 867 | return buf; |
814 | } | 868 | } |
815 | 869 | ||
816 | int main(int argc, char **argv) | 870 | int main(int argc, char **argv) |
817 | { | 871 | { |
818 | int ret; | 872 | int ret, skip = 0, put = 0; |
819 | unsigned char *source; | 873 | char *arg, *name = NULL; |
820 | unsigned long len, sourcelen, destlen; | 874 | unsigned char *source = NULL, *dest; |
821 | 875 | size_t len = 0; | |
822 | if (argc < 2) return 2; | 876 | unsigned long sourcelen, destlen; |
823 | source = yank(argv[1], &len); | 877 | |
824 | if (source == NULL) return 2; | 878 | /* process arguments */ |
825 | sourcelen = len; | 879 | while (arg = *++argv, --argc) |
826 | ret = puff(NIL, &destlen, source, &sourcelen); | 880 | if (arg[0] == '-') { |
881 | if (arg[1] == 'w' && arg[2] == 0) | ||
882 | put = 1; | ||
883 | else if (arg[1] >= '0' && arg[1] <= '9') | ||
884 | skip = atoi(arg + 1); | ||
885 | else { | ||
886 | fprintf(stderr, "invalid option %s\n", arg); | ||
887 | return 3; | ||
888 | } | ||
889 | } | ||
890 | else if (name != NULL) { | ||
891 | fprintf(stderr, "only one file name allowed\n"); | ||
892 | return 3; | ||
893 | } | ||
894 | else | ||
895 | name = arg; | ||
896 | source = load(name, &len); | ||
897 | if (source == NULL) { | ||
898 | fprintf(stderr, "memory allocation failure\n"); | ||
899 | return 4; | ||
900 | } | ||
901 | if (len == 0) { | ||
902 | fprintf(stderr, "could not read %s, or it was empty\n", | ||
903 | name == NULL ? "<stdin>" : name); | ||
904 | free(source); | ||
905 | return 3; | ||
906 | } | ||
907 | if (skip >= len) { | ||
908 | fprintf(stderr, "skip request of %d leaves no input\n", skip); | ||
909 | free(source); | ||
910 | return 3; | ||
911 | } | ||
912 | |||
913 | /* test inflate data with offset skip */ | ||
914 | len -= skip; | ||
915 | sourcelen = (unsigned long)len; | ||
916 | ret = puff(NIL, &destlen, source + skip, &sourcelen); | ||
827 | if (ret) | 917 | if (ret) |
828 | printf("puff() failed with return code %d\n", ret); | 918 | fprintf(stderr, "puff() failed with return code %d\n", ret); |
829 | else { | 919 | else { |
830 | printf("puff() succeeded uncompressing %lu bytes\n", destlen); | 920 | fprintf(stderr, "puff() succeeded uncompressing %lu bytes\n", destlen); |
831 | if (sourcelen < len) printf("%lu compressed bytes unused\n", | 921 | if (sourcelen < len) fprintf(stderr, "%lu compressed bytes unused\n", |
832 | len - sourcelen); | 922 | len - sourcelen); |
833 | } | 923 | } |
924 | |||
925 | /* if requested, inflate again and write decompressd data to stdout */ | ||
926 | if (put) { | ||
927 | dest = malloc(destlen); | ||
928 | if (dest == NULL) { | ||
929 | fprintf(stderr, "memory allocation failure\n"); | ||
930 | free(source); | ||
931 | return 4; | ||
932 | } | ||
933 | puff(dest, &destlen, source + skip, &sourcelen); | ||
934 | fwrite(dest, 1, destlen, stdout); | ||
935 | free(dest); | ||
936 | } | ||
937 | |||
938 | /* clean up */ | ||
834 | free(source); | 939 | free(source); |
835 | return ret; | 940 | return ret; |
836 | } | 941 | } |
diff --git a/contrib/puff/puff.h b/contrib/puff/puff.h index ef61252..8d7f5f8 100644 --- a/contrib/puff/puff.h +++ b/contrib/puff/puff.h | |||
@@ -1,6 +1,6 @@ | |||
1 | /* puff.h | 1 | /* puff.h |
2 | Copyright (C) 2002, 2003 Mark Adler, all rights reserved | 2 | Copyright (C) 2002-2008 Mark Adler, all rights reserved |
3 | version 1.7, 3 Mar 2002 | 3 | version 1.9, 10 Jan 2008 |
4 | 4 | ||
5 | This software is provided 'as-is', without any express or implied | 5 | This software is provided 'as-is', without any express or implied |
6 | warranty. In no event will the author be held liable for any damages | 6 | warranty. In no event will the author be held liable for any damages |
diff --git a/contrib/vstudio/vc7/zlib.rc b/contrib/vstudio/vc7/zlib.rc index 39eca7e..98ca20b 100644 --- a/contrib/vstudio/vc7/zlib.rc +++ b/contrib/vstudio/vc7/zlib.rc | |||
@@ -2,8 +2,8 @@ | |||
2 | 2 | ||
3 | #define IDR_VERSION1 1 | 3 | #define IDR_VERSION1 1 |
4 | IDR_VERSION1 VERSIONINFO MOVEABLE IMPURE LOADONCALL DISCARDABLE | 4 | IDR_VERSION1 VERSIONINFO MOVEABLE IMPURE LOADONCALL DISCARDABLE |
5 | FILEVERSION 1,2,3,3 | 5 | FILEVERSION 1,2,3,4 |
6 | PRODUCTVERSION 1,2,3,3 | 6 | PRODUCTVERSION 1,2,3,4 |
7 | FILEFLAGSMASK VS_FFI_FILEFLAGSMASK | 7 | FILEFLAGSMASK VS_FFI_FILEFLAGSMASK |
8 | FILEFLAGS 0 | 8 | FILEFLAGS 0 |
9 | FILEOS VOS_DOS_WINDOWS32 | 9 | FILEOS VOS_DOS_WINDOWS32 |
@@ -17,7 +17,7 @@ BEGIN | |||
17 | 17 | ||
18 | BEGIN | 18 | BEGIN |
19 | VALUE "FileDescription", "zlib data compression library\0" | 19 | VALUE "FileDescription", "zlib data compression library\0" |
20 | VALUE "FileVersion", "1.2.3.3\0" | 20 | VALUE "FileVersion", "1.2.3.4\0" |
21 | VALUE "InternalName", "zlib\0" | 21 | VALUE "InternalName", "zlib\0" |
22 | VALUE "OriginalFilename", "zlib.dll\0" | 22 | VALUE "OriginalFilename", "zlib.dll\0" |
23 | VALUE "ProductName", "ZLib.DLL\0" | 23 | VALUE "ProductName", "ZLib.DLL\0" |
@@ -53,7 +53,7 @@ | |||
53 | 53 | ||
54 | /* Definitions for doing the crc four data bytes at a time. */ | 54 | /* Definitions for doing the crc four data bytes at a time. */ |
55 | #ifdef BYFOUR | 55 | #ifdef BYFOUR |
56 | # define REV(w) (((w)>>24)+(((w)>>8)&0xff00)+ \ | 56 | # define REV(w) ((((w)>>24)&0xff)+(((w)>>8)&0xff00)+ \ |
57 | (((w)&0xff00)<<8)+(((w)&0xff)<<24)) | 57 | (((w)&0xff00)<<8)+(((w)&0xff)<<24)) |
58 | local unsigned long crc32_little OF((unsigned long, | 58 | local unsigned long crc32_little OF((unsigned long, |
59 | const unsigned char FAR *, unsigned)); | 59 | const unsigned char FAR *, unsigned)); |
@@ -68,11 +68,7 @@ | |||
68 | local unsigned long gf2_matrix_times OF((unsigned long *mat, | 68 | local unsigned long gf2_matrix_times OF((unsigned long *mat, |
69 | unsigned long vec)); | 69 | unsigned long vec)); |
70 | local void gf2_matrix_square OF((unsigned long *square, unsigned long *mat)); | 70 | local void gf2_matrix_square OF((unsigned long *square, unsigned long *mat)); |
71 | #ifdef _LARGEFILE64_SOURCE | 71 | local uLong crc32_combine_(uLong crc1, uLong crc2, z_off64_t len2); |
72 | local uLong crc32_combine_(uLong crc1, uLong crc2, off64_t len2); | ||
73 | #else | ||
74 | local uLong crc32_combine_(uLong crc1, uLong crc2, z_off_t len2); | ||
75 | #endif | ||
76 | 72 | ||
77 | 73 | ||
78 | #ifdef DYNAMIC_CRC_TABLE | 74 | #ifdef DYNAMIC_CRC_TABLE |
@@ -376,23 +372,19 @@ local void gf2_matrix_square(square, mat) | |||
376 | local uLong crc32_combine_(crc1, crc2, len2) | 372 | local uLong crc32_combine_(crc1, crc2, len2) |
377 | uLong crc1; | 373 | uLong crc1; |
378 | uLong crc2; | 374 | uLong crc2; |
379 | #ifdef _LARGEFILE64_SOURCE | 375 | z_off64_t len2; |
380 | off64_t len2; | ||
381 | #else | ||
382 | z_off_t len2; | ||
383 | #endif | ||
384 | { | 376 | { |
385 | int n; | 377 | int n; |
386 | unsigned long row; | 378 | unsigned long row; |
387 | unsigned long even[GF2_DIM]; /* even-power-of-two zeros operator */ | 379 | unsigned long even[GF2_DIM]; /* even-power-of-two zeros operator */ |
388 | unsigned long odd[GF2_DIM]; /* odd-power-of-two zeros operator */ | 380 | unsigned long odd[GF2_DIM]; /* odd-power-of-two zeros operator */ |
389 | 381 | ||
390 | /* degenerate case */ | 382 | /* degenerate case (also disallow negative lengths) */ |
391 | if (len2 == 0) | 383 | if (len2 <= 0) |
392 | return crc1; | 384 | return crc1; |
393 | 385 | ||
394 | /* put operator for one zero bit in odd */ | 386 | /* put operator for one zero bit in odd */ |
395 | odd[0] = 0xedb88320L; /* CRC-32 polynomial */ | 387 | odd[0] = 0xedb88320UL; /* CRC-32 polynomial */ |
396 | row = 1; | 388 | row = 1; |
397 | for (n = 1; n < GF2_DIM; n++) { | 389 | for (n = 1; n < GF2_DIM; n++) { |
398 | odd[n] = row; | 390 | odd[n] = row; |
@@ -441,20 +433,10 @@ uLong ZEXPORT crc32_combine(crc1, crc2, len2) | |||
441 | return crc32_combine_(crc1, crc2, len2); | 433 | return crc32_combine_(crc1, crc2, len2); |
442 | } | 434 | } |
443 | 435 | ||
444 | #ifdef _LARGEFILE64_SOURCE | ||
445 | uLong ZEXPORT crc32_combine64(crc1, crc2, len2) | 436 | uLong ZEXPORT crc32_combine64(crc1, crc2, len2) |
446 | uLong crc1; | 437 | uLong crc1; |
447 | uLong crc2; | 438 | uLong crc2; |
448 | off64_t len2; | 439 | z_off64_t len2; |
449 | { | ||
450 | return crc32_combine_(crc1, crc2, len2); | ||
451 | } | ||
452 | #else | ||
453 | uLong ZEXPORT crc32_combine64(crc1, crc2, len2) | ||
454 | uLong crc1; | ||
455 | uLong crc2; | ||
456 | z_off_t len2; | ||
457 | { | 440 | { |
458 | return crc32_combine_(crc1, crc2, len2); | 441 | return crc32_combine_(crc1, crc2, len2); |
459 | } | 442 | } |
460 | #endif | ||
@@ -1,5 +1,5 @@ | |||
1 | /* deflate.c -- compress data using the deflation algorithm | 1 | /* deflate.c -- compress data using the deflation algorithm |
2 | * Copyright (C) 1995-2006 Jean-loup Gailly. | 2 | * Copyright (C) 1995-2009 Jean-loup Gailly. |
3 | * For conditions of distribution and use, see copyright notice in zlib.h | 3 | * For conditions of distribution and use, see copyright notice in zlib.h |
4 | */ | 4 | */ |
5 | 5 | ||
@@ -52,7 +52,7 @@ | |||
52 | #include "deflate.h" | 52 | #include "deflate.h" |
53 | 53 | ||
54 | const char deflate_copyright[] = | 54 | const char deflate_copyright[] = |
55 | " deflate 1.2.3.3 Copyright 1995-2006 Jean-loup Gailly "; | 55 | " deflate 1.2.3.4 Copyright 1995-2009 Jean-loup Gailly "; |
56 | /* | 56 | /* |
57 | If you use the zlib library in a product, an acknowledgment is welcome | 57 | If you use the zlib library in a product, an acknowledgment is welcome |
58 | in the documentation of your product. If for some reason you cannot | 58 | in the documentation of your product. If for some reason you cannot |
@@ -110,11 +110,6 @@ local void check_match OF((deflate_state *s, IPos start, IPos match, | |||
110 | #endif | 110 | #endif |
111 | /* Matches of length 3 are discarded if their distance exceeds TOO_FAR */ | 111 | /* Matches of length 3 are discarded if their distance exceeds TOO_FAR */ |
112 | 112 | ||
113 | #define MIN_LOOKAHEAD (MAX_MATCH+MIN_MATCH+1) | ||
114 | /* Minimum amount of lookahead, except at the end of the input file. | ||
115 | * See deflate.c for comments about the MIN_MATCH+1. | ||
116 | */ | ||
117 | |||
118 | /* Values for max_lazy_match, good_match and max_chain_length, depending on | 113 | /* Values for max_lazy_match, good_match and max_chain_length, depending on |
119 | * the desired pack level (0..9). The values given below have been tuned to | 114 | * the desired pack level (0..9). The values given below have been tuned to |
120 | * exclude worst case performance for pathological files. Better values may be | 115 | * exclude worst case performance for pathological files. Better values may be |
@@ -288,6 +283,8 @@ int ZEXPORT deflateInit2_(strm, level, method, windowBits, memLevel, strategy, | |||
288 | s->prev = (Posf *) ZALLOC(strm, s->w_size, sizeof(Pos)); | 283 | s->prev = (Posf *) ZALLOC(strm, s->w_size, sizeof(Pos)); |
289 | s->head = (Posf *) ZALLOC(strm, s->hash_size, sizeof(Pos)); | 284 | s->head = (Posf *) ZALLOC(strm, s->hash_size, sizeof(Pos)); |
290 | 285 | ||
286 | s->high_water = 0; /* nothing written to s->window yet */ | ||
287 | |||
291 | s->lit_bufsize = 1 << (memLevel + 6); /* 16K elements by default */ | 288 | s->lit_bufsize = 1 << (memLevel + 6); /* 16K elements by default */ |
292 | 289 | ||
293 | overlay = (ushf *) ZALLOC(strm, s->lit_bufsize, sizeof(ush)+2); | 290 | overlay = (ushf *) ZALLOC(strm, s->lit_bufsize, sizeof(ush)+2); |
@@ -332,8 +329,8 @@ int ZEXPORT deflateSetDictionary (strm, dictionary, dictLength) | |||
332 | strm->adler = adler32(strm->adler, dictionary, dictLength); | 329 | strm->adler = adler32(strm->adler, dictionary, dictLength); |
333 | 330 | ||
334 | if (length < MIN_MATCH) return Z_OK; | 331 | if (length < MIN_MATCH) return Z_OK; |
335 | if (length > MAX_DIST(s)) { | 332 | if (length > s->w_size) { |
336 | length = MAX_DIST(s); | 333 | length = s->w_size; |
337 | dictionary += dictLength - length; /* use the tail of the dictionary */ | 334 | dictionary += dictLength - length; /* use the tail of the dictionary */ |
338 | } | 335 | } |
339 | zmemcpy(s->window, dictionary, length); | 336 | zmemcpy(s->window, dictionary, length); |
@@ -513,16 +510,16 @@ uLong ZEXPORT deflateBound(strm, sourceLen) | |||
513 | break; | 510 | break; |
514 | case 2: /* gzip wrapper */ | 511 | case 2: /* gzip wrapper */ |
515 | wraplen = 18; | 512 | wraplen = 18; |
516 | if (s->gzhead != NULL) { /* user-supplied gzip header */ | 513 | if (s->gzhead != Z_NULL) { /* user-supplied gzip header */ |
517 | if (s->gzhead->extra != NULL) | 514 | if (s->gzhead->extra != Z_NULL) |
518 | wraplen += 2 + s->gzhead->extra_len; | 515 | wraplen += 2 + s->gzhead->extra_len; |
519 | str = s->gzhead->name; | 516 | str = s->gzhead->name; |
520 | if (str != NULL) | 517 | if (str != Z_NULL) |
521 | do { | 518 | do { |
522 | wraplen++; | 519 | wraplen++; |
523 | } while (*str++); | 520 | } while (*str++); |
524 | str = s->gzhead->comment; | 521 | str = s->gzhead->comment; |
525 | if (str != NULL) | 522 | if (str != Z_NULL) |
526 | do { | 523 | do { |
527 | wraplen++; | 524 | wraplen++; |
528 | } while (*str++); | 525 | } while (*str++); |
@@ -589,7 +586,7 @@ int ZEXPORT deflate (strm, flush) | |||
589 | deflate_state *s; | 586 | deflate_state *s; |
590 | 587 | ||
591 | if (strm == Z_NULL || strm->state == Z_NULL || | 588 | if (strm == Z_NULL || strm->state == Z_NULL || |
592 | flush > Z_FINISH || flush < 0) { | 589 | flush > Z_BLOCK || flush < 0) { |
593 | return Z_STREAM_ERROR; | 590 | return Z_STREAM_ERROR; |
594 | } | 591 | } |
595 | s = strm->state; | 592 | s = strm->state; |
@@ -613,7 +610,7 @@ int ZEXPORT deflate (strm, flush) | |||
613 | put_byte(s, 31); | 610 | put_byte(s, 31); |
614 | put_byte(s, 139); | 611 | put_byte(s, 139); |
615 | put_byte(s, 8); | 612 | put_byte(s, 8); |
616 | if (s->gzhead == NULL) { | 613 | if (s->gzhead == Z_NULL) { |
617 | put_byte(s, 0); | 614 | put_byte(s, 0); |
618 | put_byte(s, 0); | 615 | put_byte(s, 0); |
619 | put_byte(s, 0); | 616 | put_byte(s, 0); |
@@ -640,7 +637,7 @@ int ZEXPORT deflate (strm, flush) | |||
640 | (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2 ? | 637 | (s->strategy >= Z_HUFFMAN_ONLY || s->level < 2 ? |
641 | 4 : 0)); | 638 | 4 : 0)); |
642 | put_byte(s, s->gzhead->os & 0xff); | 639 | put_byte(s, s->gzhead->os & 0xff); |
643 | if (s->gzhead->extra != NULL) { | 640 | if (s->gzhead->extra != Z_NULL) { |
644 | put_byte(s, s->gzhead->extra_len & 0xff); | 641 | put_byte(s, s->gzhead->extra_len & 0xff); |
645 | put_byte(s, (s->gzhead->extra_len >> 8) & 0xff); | 642 | put_byte(s, (s->gzhead->extra_len >> 8) & 0xff); |
646 | } | 643 | } |
@@ -682,7 +679,7 @@ int ZEXPORT deflate (strm, flush) | |||
682 | } | 679 | } |
683 | #ifdef GZIP | 680 | #ifdef GZIP |
684 | if (s->status == EXTRA_STATE) { | 681 | if (s->status == EXTRA_STATE) { |
685 | if (s->gzhead->extra != NULL) { | 682 | if (s->gzhead->extra != Z_NULL) { |
686 | uInt beg = s->pending; /* start of bytes to update crc */ | 683 | uInt beg = s->pending; /* start of bytes to update crc */ |
687 | 684 | ||
688 | while (s->gzindex < (s->gzhead->extra_len & 0xffff)) { | 685 | while (s->gzindex < (s->gzhead->extra_len & 0xffff)) { |
@@ -710,7 +707,7 @@ int ZEXPORT deflate (strm, flush) | |||
710 | s->status = NAME_STATE; | 707 | s->status = NAME_STATE; |
711 | } | 708 | } |
712 | if (s->status == NAME_STATE) { | 709 | if (s->status == NAME_STATE) { |
713 | if (s->gzhead->name != NULL) { | 710 | if (s->gzhead->name != Z_NULL) { |
714 | uInt beg = s->pending; /* start of bytes to update crc */ | 711 | uInt beg = s->pending; /* start of bytes to update crc */ |
715 | int val; | 712 | int val; |
716 | 713 | ||
@@ -741,7 +738,7 @@ int ZEXPORT deflate (strm, flush) | |||
741 | s->status = COMMENT_STATE; | 738 | s->status = COMMENT_STATE; |
742 | } | 739 | } |
743 | if (s->status == COMMENT_STATE) { | 740 | if (s->status == COMMENT_STATE) { |
744 | if (s->gzhead->comment != NULL) { | 741 | if (s->gzhead->comment != Z_NULL) { |
745 | uInt beg = s->pending; /* start of bytes to update crc */ | 742 | uInt beg = s->pending; /* start of bytes to update crc */ |
746 | int val; | 743 | int val; |
747 | 744 | ||
@@ -840,13 +837,17 @@ int ZEXPORT deflate (strm, flush) | |||
840 | if (bstate == block_done) { | 837 | if (bstate == block_done) { |
841 | if (flush == Z_PARTIAL_FLUSH) { | 838 | if (flush == Z_PARTIAL_FLUSH) { |
842 | _tr_align(s); | 839 | _tr_align(s); |
843 | } else { /* FULL_FLUSH or SYNC_FLUSH */ | 840 | } else if (flush != Z_BLOCK) { /* FULL_FLUSH or SYNC_FLUSH */ |
844 | _tr_stored_block(s, (char*)0, 0L, 0); | 841 | _tr_stored_block(s, (char*)0, 0L, 0); |
845 | /* For a full flush, this empty block will be recognized | 842 | /* For a full flush, this empty block will be recognized |
846 | * as a special marker by inflate_sync(). | 843 | * as a special marker by inflate_sync(). |
847 | */ | 844 | */ |
848 | if (flush == Z_FULL_FLUSH) { | 845 | if (flush == Z_FULL_FLUSH) { |
849 | CLEAR_HASH(s); /* forget history */ | 846 | CLEAR_HASH(s); /* forget history */ |
847 | if (s->lookahead == 0) { | ||
848 | s->strstart = 0; | ||
849 | s->block_start = 0L; | ||
850 | } | ||
850 | } | 851 | } |
851 | } | 852 | } |
852 | flush_pending(strm); | 853 | flush_pending(strm); |
@@ -1387,6 +1388,40 @@ local void fill_window(s) | |||
1387 | */ | 1388 | */ |
1388 | 1389 | ||
1389 | } while (s->lookahead < MIN_LOOKAHEAD && s->strm->avail_in != 0); | 1390 | } while (s->lookahead < MIN_LOOKAHEAD && s->strm->avail_in != 0); |
1391 | |||
1392 | /* If the WIN_INIT bytes after the end of the current data have never been | ||
1393 | * written, then zero those bytes in order to avoid memory check reports of | ||
1394 | * the use of uninitialized (or uninitialised as Julian writes) bytes by | ||
1395 | * the longest match routines. Update the high water mark for the next | ||
1396 | * time through here. WIN_INIT is set to MAX_MATCH since the longest match | ||
1397 | * routines allow scanning to strstart + MAX_MATCH, ignoring lookahead. | ||
1398 | */ | ||
1399 | if (s->high_water < s->window_size) { | ||
1400 | ulg curr = s->strstart + (ulg)(s->lookahead); | ||
1401 | ulg init; | ||
1402 | |||
1403 | if (s->high_water < curr) { | ||
1404 | /* Previous high water mark below current data -- zero WIN_INIT | ||
1405 | * bytes or up to end of window, whichever is less. | ||
1406 | */ | ||
1407 | init = s->window_size - curr; | ||
1408 | if (init > WIN_INIT) | ||
1409 | init = WIN_INIT; | ||
1410 | zmemzero(s->window + curr, (unsigned)init); | ||
1411 | s->high_water = curr + init; | ||
1412 | } | ||
1413 | else if (s->high_water < (ulg)curr + WIN_INIT) { | ||
1414 | /* High water mark at or above current data, but below current data | ||
1415 | * plus WIN_INIT -- zero out to current data plus WIN_INIT, or up | ||
1416 | * to end of window, whichever is less. | ||
1417 | */ | ||
1418 | init = (ulg)curr + WIN_INIT - s->high_water; | ||
1419 | if (init > s->window_size - s->high_water) | ||
1420 | init = s->window_size - s->high_water; | ||
1421 | zmemzero(s->window + s->high_water, (unsigned)init); | ||
1422 | s->high_water += init; | ||
1423 | } | ||
1424 | } | ||
1390 | } | 1425 | } |
1391 | 1426 | ||
1392 | /* =========================================================================== | 1427 | /* =========================================================================== |
@@ -1,5 +1,5 @@ | |||
1 | /* deflate.h -- internal compression state | 1 | /* deflate.h -- internal compression state |
2 | * Copyright (C) 1995-2005 Jean-loup Gailly | 2 | * Copyright (C) 1995-2009 Jean-loup Gailly |
3 | * For conditions of distribution and use, see copyright notice in zlib.h | 3 | * For conditions of distribution and use, see copyright notice in zlib.h |
4 | */ | 4 | */ |
5 | 5 | ||
@@ -260,6 +260,13 @@ typedef struct internal_state { | |||
260 | * are always zero. | 260 | * are always zero. |
261 | */ | 261 | */ |
262 | 262 | ||
263 | ulg high_water; | ||
264 | /* High water mark offset in window for initialized bytes -- bytes above | ||
265 | * this are set to zero in order to avoid memory check warnings when | ||
266 | * longest match routines access bytes past the input. This is then | ||
267 | * updated to the new high water mark. | ||
268 | */ | ||
269 | |||
263 | } FAR deflate_state; | 270 | } FAR deflate_state; |
264 | 271 | ||
265 | /* Output a byte on the stream. | 272 | /* Output a byte on the stream. |
@@ -278,6 +285,10 @@ typedef struct internal_state { | |||
278 | * distances are limited to MAX_DIST instead of WSIZE. | 285 | * distances are limited to MAX_DIST instead of WSIZE. |
279 | */ | 286 | */ |
280 | 287 | ||
288 | #define WIN_INIT MAX_MATCH | ||
289 | /* Number of bytes after end of data in window to initialize in order to avoid | ||
290 | memory checker errors from longest match routines */ | ||
291 | |||
281 | /* in trees.c */ | 292 | /* in trees.c */ |
282 | void _tr_init OF((deflate_state *s)); | 293 | void _tr_init OF((deflate_state *s)); |
283 | int _tr_tally OF((deflate_state *s, unsigned dist, unsigned lc)); | 294 | int _tr_tally OF((deflate_state *s, unsigned dist, unsigned lc)); |
diff --git a/doc/algorithm.txt b/doc/algorithm.txt index b022dde..34960bd 100644 --- a/doc/algorithm.txt +++ b/doc/algorithm.txt | |||
@@ -121,7 +121,7 @@ At least for deflate's output that generates new trees every several 10's of | |||
121 | kbytes. You can imagine that filling in a 2^15 entry table for a 15-bit code | 121 | kbytes. You can imagine that filling in a 2^15 entry table for a 15-bit code |
122 | would take too long if you're only decoding several thousand symbols. At the | 122 | would take too long if you're only decoding several thousand symbols. At the |
123 | other extreme, you could make a new table for every bit in the code. In fact, | 123 | other extreme, you could make a new table for every bit in the code. In fact, |
124 | that's essentially a Huffman tree. But then you spend two much time | 124 | that's essentially a Huffman tree. But then you spend too much time |
125 | traversing the tree while decoding, even for short symbols. | 125 | traversing the tree while decoding, even for short symbols. |
126 | 126 | ||
127 | So the number of bits for the first lookup table is a trade of the time to | 127 | So the number of bits for the first lookup table is a trade of the time to |
diff --git a/examples/README.examples b/examples/README.examples index 5632d7a..146919c 100644 --- a/examples/README.examples +++ b/examples/README.examples | |||
@@ -1,4 +1,10 @@ | |||
1 | This directory contains examples of the use of zlib. | 1 | This directory contains examples of the use of zlib and other relevant |
2 | programs and documentation. | ||
3 | |||
4 | enough.c | ||
5 | calculation and justification of ENOUGH parameter in inftrees.h | ||
6 | - calculates the maximum table space used in inflate tree | ||
7 | construction over all possible Huffman codes | ||
2 | 8 | ||
3 | fitblk.c | 9 | fitblk.c |
4 | compress just enough input to nearly fill a requested output size | 10 | compress just enough input to nearly fill a requested output size |
@@ -23,9 +29,16 @@ gzjoin.c | |||
23 | 29 | ||
24 | gzlog.c | 30 | gzlog.c |
25 | gzlog.h | 31 | gzlog.h |
26 | efficiently maintain a message log file in gzip format | 32 | efficiently and robustly maintain a message log file in gzip format |
27 | - illustrates use of raw deflate and Z_SYNC_FLUSH | 33 | - illustrates use of raw deflate, Z_PARTIAL_FLUSH, deflatePrime(), |
28 | - illustrates use of gzip header extra field | 34 | and deflateSetDictionary() |
35 | - illustrates use of a gzip header extra field | ||
36 | |||
37 | pigz.c | ||
38 | parallel implementation of gzip compression | ||
39 | - uses pthreads to speed up compression on multiple core machines | ||
40 | - illustrates the use of deflateSetDictionary() with raw deflate | ||
41 | - illustrates the use of crc32_combine() | ||
29 | 42 | ||
30 | zlib_how.html | 43 | zlib_how.html |
31 | painfully comprehensive description of zpipe.c (see below) | 44 | painfully comprehensive description of zpipe.c (see below) |
diff --git a/examples/enough.c b/examples/enough.c new file mode 100644 index 0000000..b570707 --- /dev/null +++ b/examples/enough.c | |||
@@ -0,0 +1,569 @@ | |||
1 | /* enough.c -- determine the maximum size of inflate's Huffman code tables over | ||
2 | * all possible valid and complete Huffman codes, subject to a length limit. | ||
3 | * Copyright (C) 2007, 2008 Mark Adler | ||
4 | * Version 1.3 17 February 2008 Mark Adler | ||
5 | */ | ||
6 | |||
7 | /* Version history: | ||
8 | 1.0 3 Jan 2007 First version (derived from codecount.c version 1.4) | ||
9 | 1.1 4 Jan 2007 Use faster incremental table usage computation | ||
10 | Prune examine() search on previously visited states | ||
11 | 1.2 5 Jan 2007 Comments clean up | ||
12 | As inflate does, decrease root for short codes | ||
13 | Refuse cases where inflate would increase root | ||
14 | 1.3 17 Feb 2008 Add argument for initial root table size | ||
15 | Fix bug for initial root table size == max - 1 | ||
16 | Use a macro to compute the history index | ||
17 | */ | ||
18 | |||
19 | /* | ||
20 | Examine all possible Huffman codes for a given number of symbols and a | ||
21 | maximum code length in bits to determine the maximum table size for zilb's | ||
22 | inflate. Only complete Huffman codes are counted. | ||
23 | |||
24 | Two codes are considered distinct if the vectors of the number of codes per | ||
25 | length are not identical. So permutations of the symbol assignments result | ||
26 | in the same code for the counting, as do permutations of the assignments of | ||
27 | the bit values to the codes (i.e. only canonical codes are counted). | ||
28 | |||
29 | We build a code from shorter to longer lengths, determining how many symbols | ||
30 | are coded at each length. At each step, we have how many symbols remain to | ||
31 | be coded, what the last code length used was, and how many bit patterns of | ||
32 | that length remain unused. Then we add one to the code length and double the | ||
33 | number of unused patterns to graduate to the next code length. We then | ||
34 | assign all portions of the remaining symbols to that code length that | ||
35 | preserve the properties of a correct and eventually complete code. Those | ||
36 | properties are: we cannot use more bit patterns than are available; and when | ||
37 | all the symbols are used, there are exactly zero possible bit patterns | ||
38 | remaining. | ||
39 | |||
40 | The inflate Huffman decoding algorithm uses two-level lookup tables for | ||
41 | speed. There is a single first-level table to decode codes up to root bits | ||
42 | in length (root == 9 in the current inflate implementation). The table | ||
43 | has 1 << root entries and is indexed by the next root bits of input. Codes | ||
44 | shorter than root bits have replicated table entries, so that the correct | ||
45 | entry is pointed to regardless of the bits that follow the short code. If | ||
46 | the code is longer than root bits, then the table entry points to a second- | ||
47 | level table. The size of that table is determined by the longest code with | ||
48 | that root-bit prefix. If that longest code has length len, then the table | ||
49 | has size 1 << (len - root), to index the remaining bits in that set of | ||
50 | codes. Each subsequent root-bit prefix then has its own sub-table. The | ||
51 | total number of table entries required by the code is calculated | ||
52 | incrementally as the number of codes at each bit length is populated. When | ||
53 | all of the codes are shorter than root bits, then root is reduced to the | ||
54 | longest code length, resulting in a single, smaller, one-level table. | ||
55 | |||
56 | The inflate algorithm also provides for small values of root (relative to | ||
57 | the log2 of the number of symbols), where the shortest code has more bits | ||
58 | than root. In that case, root is increased to the length of the shortest | ||
59 | code. This program, by design, does not handle that case, so it is verified | ||
60 | that the number of symbols is less than 2^(root + 1). | ||
61 | |||
62 | In order to speed up the examination (by about ten orders of magnitude for | ||
63 | the default arguments), the intermediate states in the build-up of a code | ||
64 | are remembered and previously visited branches are pruned. The memory | ||
65 | required for this will increase rapidly with the total number of symbols and | ||
66 | the maximum code length in bits. However this is a very small price to pay | ||
67 | for the vast speedup. | ||
68 | |||
69 | First, all of the possible Huffman codes are counted, and reachable | ||
70 | intermediate states are noted by a non-zero count in a saved-results array. | ||
71 | Second, the intermediate states that lead to (root + 1) bit or longer codes | ||
72 | are used to look at all sub-codes from those junctures for their inflate | ||
73 | memory usage. (The amount of memory used is not affected by the number of | ||
74 | codes of root bits or less in length.) Third, the visited states in the | ||
75 | construction of those sub-codes and the associated calculation of the table | ||
76 | size is recalled in order to avoid recalculating from the same juncture. | ||
77 | Beginning the code examination at (root + 1) bit codes, which is enabled by | ||
78 | identifying the reachable nodes, accounts for about six of the orders of | ||
79 | magnitude of improvement for the default arguments. About another four | ||
80 | orders of magnitude come from not revisiting previous states. Out of | ||
81 | approximately 2x10^16 possible Huffman codes, only about 2x10^6 sub-codes | ||
82 | need to be examined to cover all of the possible table memory usage cases | ||
83 | for the default arguments of 286 symbols limited to 15-bit codes. | ||
84 | |||
85 | Note that an unsigned long long type is used for counting. It is quite easy | ||
86 | to exceed the capacity of an eight-byte integer with a large number of | ||
87 | symbols and a large maximum code length, so multiple-precision arithmetic | ||
88 | would need to replace the unsigned long long arithmetic in that case. This | ||
89 | program will abort if an overflow occurs. The big_t type identifies where | ||
90 | the counting takes place. | ||
91 | |||
92 | An unsigned long long type is also used for calculating the number of | ||
93 | possible codes remaining at the maximum length. This limits the maximum | ||
94 | code length to the number of bits in a long long minus the number of bits | ||
95 | needed to represent the symbols in a flat code. The code_t type identifies | ||
96 | where the bit pattern counting takes place. | ||
97 | */ | ||
98 | |||
99 | #include <stdio.h> | ||
100 | #include <stdlib.h> | ||
101 | #include <string.h> | ||
102 | #include <assert.h> | ||
103 | |||
104 | #define local static | ||
105 | |||
106 | /* special data types */ | ||
107 | typedef unsigned long long big_t; /* type for code counting */ | ||
108 | typedef unsigned long long code_t; /* type for bit pattern counting */ | ||
109 | struct tab { /* type for been here check */ | ||
110 | size_t len; /* length of bit vector in char's */ | ||
111 | char *vec; /* allocated bit vector */ | ||
112 | }; | ||
113 | |||
114 | /* The array for saving results, num[], is indexed with this triplet: | ||
115 | |||
116 | syms: number of symbols remaining to code | ||
117 | left: number of available bit patterns at length len | ||
118 | len: number of bits in the codes currently being assigned | ||
119 | |||
120 | Those indices are constrained thusly when saving results: | ||
121 | |||
122 | syms: 3..totsym (totsym == total symbols to code) | ||
123 | left: 2..syms - 1, but only the evens (so syms == 8 -> 2, 4, 6) | ||
124 | len: 1..max - 1 (max == maximum code length in bits) | ||
125 | |||
126 | syms == 2 is not saved since that immediately leads to a single code. left | ||
127 | must be even, since it represents the number of available bit patterns at | ||
128 | the current length, which is double the number at the previous length. | ||
129 | left ends at syms-1 since left == syms immediately results in a single code. | ||
130 | (left > sym is not allowed since that would result in an incomplete code.) | ||
131 | len is less than max, since the code completes immediately when len == max. | ||
132 | |||
133 | The offset into the array is calculated for the three indices with the | ||
134 | first one (syms) being outermost, and the last one (len) being innermost. | ||
135 | We build the array with length max-1 lists for the len index, with syms-3 | ||
136 | of those for each symbol. There are totsym-2 of those, with each one | ||
137 | varying in length as a function of sym. See the calculation of index in | ||
138 | count() for the index, and the calculation of size in main() for the size | ||
139 | of the array. | ||
140 | |||
141 | For the deflate example of 286 symbols limited to 15-bit codes, the array | ||
142 | has 284,284 entries, taking up 2.17 MB for an 8-byte big_t. More than | ||
143 | half of the space allocated for saved results is actually used -- not all | ||
144 | possible triplets are reached in the generation of valid Huffman codes. | ||
145 | */ | ||
146 | |||
147 | /* The array for tracking visited states, done[], is itself indexed identically | ||
148 | to the num[] array as described above for the (syms, left, len) triplet. | ||
149 | Each element in the array is further indexed by the (mem, rem) doublet, | ||
150 | where mem is the amount of inflate table space used so far, and rem is the | ||
151 | remaining unused entries in the current inflate sub-table. Each indexed | ||
152 | element is simply one bit indicating whether the state has been visited or | ||
153 | not. Since the ranges for mem and rem are not known a priori, each bit | ||
154 | vector is of a variable size, and grows as needed to accommodate the visited | ||
155 | states. mem and rem are used to calculate a single index in a triangular | ||
156 | array. Since the range of mem is expected in the default case to be about | ||
157 | ten times larger than the range of rem, the array is skewed to reduce the | ||
158 | memory usage, with eight times the range for mem than for rem. See the | ||
159 | calculations for offset and bit in beenhere() for the details. | ||
160 | |||
161 | For the deflate example of 286 symbols limited to 15-bit codes, the bit | ||
162 | vectors grow to total approximately 21 MB, in addition to the 4.3 MB done[] | ||
163 | array itself. | ||
164 | */ | ||
165 | |||
166 | /* Globals to avoid propagating constants or constant pointers recursively */ | ||
167 | local int max; /* maximum allowed bit length for the codes */ | ||
168 | local int root; /* size of base code table in bits */ | ||
169 | local int large; /* largest code table so far */ | ||
170 | local size_t size; /* number of elements in num and done */ | ||
171 | local int *code; /* number of symbols assigned to each bit length */ | ||
172 | local big_t *num; /* saved results array for code counting */ | ||
173 | local struct tab *done; /* states already evaluated array */ | ||
174 | |||
175 | /* Index function for num[] and done[] */ | ||
176 | #define INDEX(i,j,k) (((size_t)((i-1)>>1)*((i-2)>>1)+(j>>1)-1)*(max-1)+k-1) | ||
177 | |||
178 | /* Free allocated space. Uses globals code, num, and done. */ | ||
179 | local void cleanup(void) | ||
180 | { | ||
181 | size_t n; | ||
182 | |||
183 | if (done != NULL) { | ||
184 | for (n = 0; n < size; n++) | ||
185 | if (done[n].len) | ||
186 | free(done[n].vec); | ||
187 | free(done); | ||
188 | } | ||
189 | if (num != NULL) | ||
190 | free(num); | ||
191 | if (code != NULL) | ||
192 | free(code); | ||
193 | } | ||
194 | |||
195 | /* Return the number of possible Huffman codes using bit patterns of lengths | ||
196 | len through max inclusive, coding syms symbols, with left bit patterns of | ||
197 | length len unused -- return -1 if there is an overflow in the counting. | ||
198 | Keep a record of previous results in num to prevent repeating the same | ||
199 | calculation. Uses the globals max and num. */ | ||
200 | local big_t count(int syms, int len, int left) | ||
201 | { | ||
202 | big_t sum; /* number of possible codes from this juncture */ | ||
203 | big_t got; /* value returned from count() */ | ||
204 | int least; /* least number of syms to use at this juncture */ | ||
205 | int most; /* most number of syms to use at this juncture */ | ||
206 | int use; /* number of bit patterns to use in next call */ | ||
207 | size_t index; /* index of this case in *num */ | ||
208 | |||
209 | /* see if only one possible code */ | ||
210 | if (syms == left) | ||
211 | return 1; | ||
212 | |||
213 | /* note and verify the expected state */ | ||
214 | assert(syms > left && left > 0 && len < max); | ||
215 | |||
216 | /* see if we've done this one already */ | ||
217 | index = INDEX(syms, left, len); | ||
218 | got = num[index]; | ||
219 | if (got) | ||
220 | return got; /* we have -- return the saved result */ | ||
221 | |||
222 | /* we need to use at least this many bit patterns so that the code won't be | ||
223 | incomplete at the next length (more bit patterns than symbols) */ | ||
224 | least = (left << 1) - syms; | ||
225 | if (least < 0) | ||
226 | least = 0; | ||
227 | |||
228 | /* we can use at most this many bit patterns, lest there not be enough | ||
229 | available for the remaining symbols at the maximum length (if there were | ||
230 | no limit to the code length, this would become: most = left - 1) */ | ||
231 | most = (((code_t)left << (max - len)) - syms) / | ||
232 | (((code_t)1 << (max - len)) - 1); | ||
233 | |||
234 | /* count all possible codes from this juncture and add them up */ | ||
235 | sum = 0; | ||
236 | for (use = least; use <= most; use++) { | ||
237 | got = count(syms - use, len + 1, (left - use) << 1); | ||
238 | sum += got; | ||
239 | if (got == -1 || sum < got) /* overflow */ | ||
240 | return -1; | ||
241 | } | ||
242 | |||
243 | /* verify that all recursive calls are productive */ | ||
244 | assert(sum != 0); | ||
245 | |||
246 | /* save the result and return it */ | ||
247 | num[index] = sum; | ||
248 | return sum; | ||
249 | } | ||
250 | |||
251 | /* Return true if we've been here before, set to true if not. Set a bit in a | ||
252 | bit vector to indicate visiting this state. Each (syms,len,left) state | ||
253 | has a variable size bit vector indexed by (mem,rem). The bit vector is | ||
254 | lengthened if needed to allow setting the (mem,rem) bit. */ | ||
255 | local int beenhere(int syms, int len, int left, int mem, int rem) | ||
256 | { | ||
257 | size_t index; /* index for this state's bit vector */ | ||
258 | size_t offset; /* offset in this state's bit vector */ | ||
259 | int bit; /* mask for this state's bit */ | ||
260 | size_t length; /* length of the bit vector in bytes */ | ||
261 | char *vector; /* new or enlarged bit vector */ | ||
262 | |||
263 | /* point to vector for (syms,left,len), bit in vector for (mem,rem) */ | ||
264 | index = INDEX(syms, left, len); | ||
265 | mem -= 1 << root; | ||
266 | offset = (mem >> 3) + rem; | ||
267 | offset = ((offset * (offset + 1)) >> 1) + rem; | ||
268 | bit = 1 << (mem & 7); | ||
269 | |||
270 | /* see if we've been here */ | ||
271 | length = done[index].len; | ||
272 | if (offset < length && (done[index].vec[offset] & bit) != 0) | ||
273 | return 1; /* done this! */ | ||
274 | |||
275 | /* we haven't been here before -- set the bit to show we have now */ | ||
276 | |||
277 | /* see if we need to lengthen the vector in order to set the bit */ | ||
278 | if (length <= offset) { | ||
279 | /* if we have one already, enlarge it, zero out the appended space */ | ||
280 | if (length) { | ||
281 | do { | ||
282 | length <<= 1; | ||
283 | } while (length <= offset); | ||
284 | vector = realloc(done[index].vec, length); | ||
285 | if (vector != NULL) | ||
286 | memset(vector + done[index].len, 0, length - done[index].len); | ||
287 | } | ||
288 | |||
289 | /* otherwise we need to make a new vector and zero it out */ | ||
290 | else { | ||
291 | length = 1 << (len - root); | ||
292 | while (length <= offset) | ||
293 | length <<= 1; | ||
294 | vector = calloc(length, sizeof(char)); | ||
295 | } | ||
296 | |||
297 | /* in either case, bail if we can't get the memory */ | ||
298 | if (vector == NULL) { | ||
299 | fputs("abort: unable to allocate enough memory\n", stderr); | ||
300 | cleanup(); | ||
301 | exit(1); | ||
302 | } | ||
303 | |||
304 | /* install the new vector */ | ||
305 | done[index].len = length; | ||
306 | done[index].vec = vector; | ||
307 | } | ||
308 | |||
309 | /* set the bit */ | ||
310 | done[index].vec[offset] |= bit; | ||
311 | return 0; | ||
312 | } | ||
313 | |||
314 | /* Examine all possible codes from the given node (syms, len, left). Compute | ||
315 | the amount of memory required to build inflate's decoding tables, where the | ||
316 | number of code structures used so far is mem, and the number remaining in | ||
317 | the current sub-table is rem. Uses the globals max, code, root, large, and | ||
318 | done. */ | ||
319 | local void examine(int syms, int len, int left, int mem, int rem) | ||
320 | { | ||
321 | int least; /* least number of syms to use at this juncture */ | ||
322 | int most; /* most number of syms to use at this juncture */ | ||
323 | int use; /* number of bit patterns to use in next call */ | ||
324 | |||
325 | /* see if we have a complete code */ | ||
326 | if (syms == left) { | ||
327 | /* set the last code entry */ | ||
328 | code[len] = left; | ||
329 | |||
330 | /* complete computation of memory used by this code */ | ||
331 | while (rem < left) { | ||
332 | left -= rem; | ||
333 | rem = 1 << (len - root); | ||
334 | mem += rem; | ||
335 | } | ||
336 | assert(rem == left); | ||
337 | |||
338 | /* if this is a new maximum, show the entries used and the sub-code */ | ||
339 | if (mem > large) { | ||
340 | large = mem; | ||
341 | printf("max %d: ", mem); | ||
342 | for (use = root + 1; use <= max; use++) | ||
343 | if (code[use]) | ||
344 | printf("%d[%d] ", code[use], use); | ||
345 | putchar('\n'); | ||
346 | fflush(stdout); | ||
347 | } | ||
348 | |||
349 | /* remove entries as we drop back down in the recursion */ | ||
350 | code[len] = 0; | ||
351 | return; | ||
352 | } | ||
353 | |||
354 | /* prune the tree if we can */ | ||
355 | if (beenhere(syms, len, left, mem, rem)) | ||
356 | return; | ||
357 | |||
358 | /* we need to use at least this many bit patterns so that the code won't be | ||
359 | incomplete at the next length (more bit patterns than symbols) */ | ||
360 | least = (left << 1) - syms; | ||
361 | if (least < 0) | ||
362 | least = 0; | ||
363 | |||
364 | /* we can use at most this many bit patterns, lest there not be enough | ||
365 | available for the remaining symbols at the maximum length (if there were | ||
366 | no limit to the code length, this would become: most = left - 1) */ | ||
367 | most = (((code_t)left << (max - len)) - syms) / | ||
368 | (((code_t)1 << (max - len)) - 1); | ||
369 | |||
370 | /* occupy least table spaces, creating new sub-tables as needed */ | ||
371 | use = least; | ||
372 | while (rem < use) { | ||
373 | use -= rem; | ||
374 | rem = 1 << (len - root); | ||
375 | mem += rem; | ||
376 | } | ||
377 | rem -= use; | ||
378 | |||
379 | /* examine codes from here, updating table space as we go */ | ||
380 | for (use = least; use <= most; use++) { | ||
381 | code[len] = use; | ||
382 | examine(syms - use, len + 1, (left - use) << 1, | ||
383 | mem + (rem ? 1 << (len - root) : 0), rem << 1); | ||
384 | if (rem == 0) { | ||
385 | rem = 1 << (len - root); | ||
386 | mem += rem; | ||
387 | } | ||
388 | rem--; | ||
389 | } | ||
390 | |||
391 | /* remove entries as we drop back down in the recursion */ | ||
392 | code[len] = 0; | ||
393 | } | ||
394 | |||
395 | /* Look at all sub-codes starting with root + 1 bits. Look at only the valid | ||
396 | intermediate code states (syms, left, len). For each completed code, | ||
397 | calculate the amount of memory required by inflate to build the decoding | ||
398 | tables. Find the maximum amount of memory required and show the code that | ||
399 | requires that maximum. Uses the globals max, root, and num. */ | ||
400 | local void enough(int syms) | ||
401 | { | ||
402 | int n; /* number of remaing symbols for this node */ | ||
403 | int left; /* number of unused bit patterns at this length */ | ||
404 | size_t index; /* index of this case in *num */ | ||
405 | |||
406 | /* clear code */ | ||
407 | for (n = 0; n <= max; n++) | ||
408 | code[n] = 0; | ||
409 | |||
410 | /* look at all (root + 1) bit and longer codes */ | ||
411 | large = 1 << root; /* base table */ | ||
412 | if (root < max) /* otherwise, there's only a base table */ | ||
413 | for (n = 3; n <= syms; n++) | ||
414 | for (left = 2; left < n; left += 2) | ||
415 | { | ||
416 | /* look at all reachable (root + 1) bit nodes, and the | ||
417 | resulting codes (complete at root + 2 or more) */ | ||
418 | index = INDEX(n, left, root + 1); | ||
419 | if (root + 1 < max && num[index]) /* reachable node */ | ||
420 | examine(n, root + 1, left, 1 << root, 0); | ||
421 | |||
422 | /* also look at root bit codes with completions at root + 1 | ||
423 | bits (not saved in num, since complete), just in case */ | ||
424 | if (num[index - 1] && n <= left << 1) | ||
425 | examine((n - left) << 1, root + 1, (n - left) << 1, | ||
426 | 1 << root, 0); | ||
427 | } | ||
428 | |||
429 | /* done */ | ||
430 | printf("done: maximum of %d table entries\n", large); | ||
431 | } | ||
432 | |||
433 | /* | ||
434 | Examine and show the total number of possible Huffman codes for a given | ||
435 | maximum number of symbols, initial root table size, and maximum code length | ||
436 | in bits -- those are the command arguments in that order. The default | ||
437 | values are 286, 9, and 15 respectively, for the deflate literal/length code. | ||
438 | The possible codes are counted for each number of coded symbols from two to | ||
439 | the maximum. The counts for each of those and the total number of codes are | ||
440 | shown. The maximum number of inflate table entires is then calculated | ||
441 | across all possible codes. Each new maximum number of table entries and the | ||
442 | associated sub-code (starting at root + 1 == 10 bits) is shown. | ||
443 | |||
444 | To count and examine Huffman codes that are not length-limited, provide a | ||
445 | maximum length equal to the number of symbols minus one. | ||
446 | |||
447 | For the deflate literal/length code, use "enough". For the deflate distance | ||
448 | code, use "enough 30 6". | ||
449 | |||
450 | This uses the %llu printf format to print big_t numbers, which assumes that | ||
451 | big_t is an unsigned long long. If the big_t type is changed (for example | ||
452 | to a multiple precision type), the method of printing will also need to be | ||
453 | updated. | ||
454 | */ | ||
455 | int main(int argc, char **argv) | ||
456 | { | ||
457 | int syms; /* total number of symbols to code */ | ||
458 | int n; /* number of symbols to code for this run */ | ||
459 | big_t got; /* return value of count() */ | ||
460 | big_t sum; /* accumulated number of codes over n */ | ||
461 | |||
462 | /* set up globals for cleanup() */ | ||
463 | code = NULL; | ||
464 | num = NULL; | ||
465 | done = NULL; | ||
466 | |||
467 | /* get arguments -- default to the deflate literal/length code */ | ||
468 | syms = 286; | ||
469 | root = 9; | ||
470 | max = 15; | ||
471 | if (argc > 1) { | ||
472 | syms = atoi(argv[1]); | ||
473 | if (argc > 2) { | ||
474 | root = atoi(argv[2]); | ||
475 | if (argc > 3) | ||
476 | max = atoi(argv[3]); | ||
477 | } | ||
478 | } | ||
479 | if (argc > 4 || syms < 2 || root < 1 || max < 1) { | ||
480 | fputs("invalid arguments, need: [sym >= 2 [root >= 1 [max >= 1]]]\n", | ||
481 | stderr); | ||
482 | return 1; | ||
483 | } | ||
484 | |||
485 | /* if not restricting the code length, the longest is syms - 1 */ | ||
486 | if (max > syms - 1) | ||
487 | max = syms - 1; | ||
488 | |||
489 | /* determine the number of bits in a code_t */ | ||
490 | n = 0; | ||
491 | while (((code_t)1 << n) != 0) | ||
492 | n++; | ||
493 | |||
494 | /* make sure that the calculation of most will not overflow */ | ||
495 | if (max > n || syms - 2 >= (((code_t)0 - 1) >> (max - 1))) { | ||
496 | fputs("abort: code length too long for internal types\n", stderr); | ||
497 | return 1; | ||
498 | } | ||
499 | |||
500 | /* reject impossible code requests */ | ||
501 | if (syms - 1 > ((code_t)1 << max) - 1) { | ||
502 | fprintf(stderr, "%d symbols cannot be coded in %d bits\n", | ||
503 | syms, max); | ||
504 | return 1; | ||
505 | } | ||
506 | |||
507 | /* allocate code vector */ | ||
508 | code = calloc(max + 1, sizeof(int)); | ||
509 | if (code == NULL) { | ||
510 | fputs("abort: unable to allocate enough memory\n", stderr); | ||
511 | return 1; | ||
512 | } | ||
513 | |||
514 | /* determine size of saved results array, checking for overflows, | ||
515 | allocate and clear the array (set all to zero with calloc()) */ | ||
516 | if (syms == 2) /* iff max == 1 */ | ||
517 | num = NULL; /* won't be saving any results */ | ||
518 | else { | ||
519 | size = syms >> 1; | ||
520 | if (size > ((size_t)0 - 1) / (n = (syms - 1) >> 1) || | ||
521 | (size *= n, size > ((size_t)0 - 1) / (n = max - 1)) || | ||
522 | (size *= n, size > ((size_t)0 - 1) / sizeof(big_t)) || | ||
523 | (num = calloc(size, sizeof(big_t))) == NULL) { | ||
524 | fputs("abort: unable to allocate enough memory\n", stderr); | ||
525 | cleanup(); | ||
526 | return 1; | ||
527 | } | ||
528 | } | ||
529 | |||
530 | /* count possible codes for all numbers of symbols, add up counts */ | ||
531 | sum = 0; | ||
532 | for (n = 2; n <= syms; n++) { | ||
533 | got = count(n, 1, 2); | ||
534 | sum += got; | ||
535 | if (got == -1 || sum < got) { /* overflow */ | ||
536 | fputs("abort: can't count that high!\n", stderr); | ||
537 | cleanup(); | ||
538 | return 1; | ||
539 | } | ||
540 | printf("%llu %d-codes\n", got, n); | ||
541 | } | ||
542 | printf("%llu total codes for 2 to %d symbols", sum, syms); | ||
543 | if (max < syms - 1) | ||
544 | printf(" (%d-bit length limit)\n", max); | ||
545 | else | ||
546 | puts(" (no length limit)"); | ||
547 | |||
548 | /* allocate and clear done array for beenhere() */ | ||
549 | if (syms == 2) | ||
550 | done = NULL; | ||
551 | else if (size > ((size_t)0 - 1) / sizeof(struct tab) || | ||
552 | (done = calloc(size, sizeof(struct tab))) == NULL) { | ||
553 | fputs("abort: unable to allocate enough memory\n", stderr); | ||
554 | cleanup(); | ||
555 | return 1; | ||
556 | } | ||
557 | |||
558 | /* find and show maximum inflate table usage */ | ||
559 | if (root > max) /* reduce root to max length */ | ||
560 | root = max; | ||
561 | if (syms < ((code_t)1 << (root + 1))) | ||
562 | enough(syms); | ||
563 | else | ||
564 | puts("cannot handle minimum code lengths > root"); | ||
565 | |||
566 | /* done */ | ||
567 | cleanup(); | ||
568 | return 0; | ||
569 | } | ||
diff --git a/examples/gzlog.c b/examples/gzlog.c index b6acdef..4daf1c2 100644 --- a/examples/gzlog.c +++ b/examples/gzlog.c | |||
@@ -1,413 +1,1058 @@ | |||
1 | /* | 1 | /* |
2 | * gzlog.c | 2 | * gzlog.c |
3 | * Copyright (C) 2004 Mark Adler | 3 | * Copyright (C) 2004, 2008 Mark Adler, all rights reserved |
4 | * For conditions of distribution and use, see copyright notice in gzlog.h | 4 | * For conditions of distribution and use, see copyright notice in gzlog.h |
5 | * version 1.0, 26 Nov 2004 | 5 | * version 2.0, 25 Apr 2008 |
6 | * | ||
7 | */ | 6 | */ |
8 | 7 | ||
9 | #include <string.h> /* memcmp() */ | 8 | /* |
10 | #include <stdlib.h> /* malloc(), free(), NULL */ | 9 | gzlog provides a mechanism for frequently appending short strings to a gzip |
11 | #include <sys/types.h> /* size_t, off_t */ | 10 | file that is efficient both in execution time and compression ratio. The |
12 | #include <unistd.h> /* read(), close(), sleep(), ftruncate(), */ | 11 | strategy is to write the short strings in an uncompressed form to the end of |
13 | /* lseek() */ | 12 | the gzip file, only compressing when the amount of uncompressed data has |
14 | #include <fcntl.h> /* open() */ | 13 | reached a given threshold. |
15 | #include <sys/file.h> /* flock() */ | 14 | |
16 | #include "zlib.h" /* deflateInit2(), deflate(), deflateEnd() */ | 15 | gzlog also provides protection against interruptions in the process due to |
16 | system crashes. The status of the operation is recorded in an extra field | ||
17 | in the gzip file, and is only updated once the gzip file is brought to a | ||
18 | valid state. The last data to be appended or compressed is saved in an | ||
19 | auxiliary file, so that if the operation is interrupted, it can be completed | ||
20 | the next time an append operation is attempted. | ||
21 | |||
22 | gzlog maintains another auxiliary file with the last 32K of data from the | ||
23 | compressed portion, which is preloaded for the compression of the subsequent | ||
24 | data. This minimizes the impact to the compression ratio of appending. | ||
25 | */ | ||
26 | |||
27 | /* | ||
28 | Operations Concept: | ||
29 | |||
30 | Files (log name "foo"): | ||
31 | foo.gz -- gzip file with the complete log | ||
32 | foo.add -- last message to append or last data to compress | ||
33 | foo.dict -- dictionary of the last 32K of data for next compression | ||
34 | foo.temp -- temporary dictionary file for compression after this one | ||
35 | foo.lock -- lock file for reading and writing the other files | ||
36 | foo.repairs -- log file for log file recovery operations (not compressed) | ||
37 | |||
38 | gzip file structure: | ||
39 | - fixed-length (no file name) header with extra field (see below) | ||
40 | - compressed data ending initially with empty stored block | ||
41 | - uncompressed data filling out originally empty stored block and | ||
42 | subsequent stored blocks as needed (16K max each) | ||
43 | - gzip trailer | ||
44 | - no junk at end (no other gzip streams) | ||
45 | |||
46 | When appending data, the information in the first three items above plus the | ||
47 | foo.add file are sufficient to recover an interrupted append operation. The | ||
48 | extra field has the necessary information to restore the start of the last | ||
49 | stored block and determine where to append the data in the foo.add file, as | ||
50 | well as the crc and length of the gzip data before the append operation. | ||
51 | |||
52 | The foo.add file is created before the gzip file is marked for append, and | ||
53 | deleted after the gzip file is marked as complete. So if the append | ||
54 | operation is interrupted, the data to add will still be there. If due to | ||
55 | some external force, the foo.add file gets deleted between when the append | ||
56 | operation was interrupted and when recovery is attempted, the gzip file will | ||
57 | still be restored, but without the appended data. | ||
58 | |||
59 | When compressing data, the information in the first two items above plus the | ||
60 | foo.add file are sufficient to recover an interrupted compress operation. | ||
61 | The extra field has the necessary information to find the end of the | ||
62 | compressed data, and contains both the crc and length of just the compressed | ||
63 | data and of the complete set of data including the contents of the foo.add | ||
64 | file. | ||
65 | |||
66 | Again, the foo.add file is maintained during the compress operation in case | ||
67 | of an interruption. If in the unlikely event the foo.add file with the data | ||
68 | to be compressed is missing due to some external force, a gzip file with | ||
69 | just the previous compressed data will be reconstructed. In this case, all | ||
70 | of the data that was to be compressed is lost (approximately one megabyte). | ||
71 | This will not occur if all that happened was an interruption of the compress | ||
72 | operation. | ||
73 | |||
74 | The third state that is marked is the replacement of the old dictionary with | ||
75 | the new dictionary after a compress operation. Once compression is | ||
76 | complete, the gzip file is marked as being in the replace state. This | ||
77 | completes the gzip file, so an interrupt after being so marked does not | ||
78 | result in recompression. Then the dictionary file is replaced, and the gzip | ||
79 | file is marked as completed. This state prevents the possibility of | ||
80 | restarting compression with the wrong dictionary file. | ||
81 | |||
82 | All three operations are wrapped by a lock/unlock procedure. In order to | ||
83 | gain exclusive access to the log files, first a foo.lock file must be | ||
84 | exclusively created. When all operations are complete, the lock is | ||
85 | released by deleting the foo.lock file. If when attempting to create the | ||
86 | lock file, it already exists and the modify time of the lock file is more | ||
87 | than five minutes old (set by the PATIENCE define below), then the old | ||
88 | lock file is considered stale and deleted, and the exclusive creation of | ||
89 | the lock file is retried. To assure that there are no false assessments | ||
90 | of the staleness of the lock file, the operations periodically touch the | ||
91 | lock file to update the modified date. | ||
92 | |||
93 | Following is the definition of the extra field with all of the information | ||
94 | required to enable the above append and compress operations and their | ||
95 | recovery if interrupted. Multi-byte values are stored little endian | ||
96 | (consistent with the gzip format). File pointers are eight bytes long. | ||
97 | The crc's and lengths for the gzip trailer are four bytes long. (Note that | ||
98 | the length at the end of a gzip file is used for error checking only, and | ||
99 | for large files is actually the length modulo 2^32.) The stored block | ||
100 | length is two bytes long. The gzip extra field two-byte identification is | ||
101 | "ap" for append. It is assumed that writing the extra field to the file is | ||
102 | an "atomic" operation. That is, either all of the extra field is written | ||
103 | to the file, or none of it is, if the operation is interrupted right at the | ||
104 | point of updating the extra field. This is a reasonable assumption, since | ||
105 | the extra field is within the first 52 bytes of the file, which is smaller | ||
106 | than any expected block size for a mass storage device (usually 512 bytes or | ||
107 | larger). | ||
108 | |||
109 | Extra field (35 bytes): | ||
110 | - Pointer to first stored block length -- this points to the two-byte length | ||
111 | of the first stored block, which is followed by the two-byte, one's | ||
112 | complement of that length. The stored block length is preceded by the | ||
113 | three-bit header of the stored block, which is the actual start of the | ||
114 | stored block in the deflate format. See the bit offset field below. | ||
115 | - Pointer to the last stored block length. This is the same as above, but | ||
116 | for the last stored block of the uncompressed data in the gzip file. | ||
117 | Initially this is the same as the first stored block length pointer. | ||
118 | When the stored block gets to 16K (see the MAX_STORE define), then a new | ||
119 | stored block as added, at which point the last stored block length pointer | ||
120 | is different from the first stored block length pointer. When they are | ||
121 | different, the first bit of the last stored block header is eight bits, or | ||
122 | one byte back from the block length. | ||
123 | - Compressed data crc and length. This is the crc and length of the data | ||
124 | that is in the compressed portion of the deflate stream. These are used | ||
125 | only in the event that the foo.add file containing the data to compress is | ||
126 | lost after a compress operation is interrupted. | ||
127 | - Total data crc and length. This is the crc and length of all of the data | ||
128 | stored in the gzip file, compressed and uncompressed. It is used to | ||
129 | reconstruct the gzip trailer when compressing, as well as when recovering | ||
130 | interrupted operations. | ||
131 | - Final stored block length. This is used to quickly find where to append, | ||
132 | and allows the restoration of the original final stored block state when | ||
133 | an append operation is interrupted. | ||
134 | - First stored block start as the number of bits back from the final stored | ||
135 | block first length byte. This value is in the range of 3..10, and is | ||
136 | stored as the low three bits of the final byte of the extra field after | ||
137 | subtracting three (0..7). This allows the last-block bit of the stored | ||
138 | block header to be updated when a new stored block is added, for the case | ||
139 | when the first stored block and the last stored block are the same. (When | ||
140 | they are different, the numbers of bits back is known to be eight.) This | ||
141 | also allows for new compressed data to be appended to the old compressed | ||
142 | data in the compress operation, overwriting the previous first stored | ||
143 | block, or for the compressed data to be terminated and a valid gzip file | ||
144 | reconstructed on the off chance that a compression operation was | ||
145 | interrupted and the data to compress in the foo.add file was deleted. | ||
146 | - The operation in process. This is the next two bits in the last byte (the | ||
147 | bits under the mask 0x18). The are interpreted as 0: nothing in process, | ||
148 | 1: append in process, 2: compress in process, 3: replace in process. | ||
149 | - The top three bits of the last byte in the extra field are reserved and | ||
150 | are currently set to zero. | ||
151 | |||
152 | Main procedure: | ||
153 | - Exclusively create the foo.lock file using the O_CREAT and O_EXCL modes of | ||
154 | the system open() call. If the modify time of an existing lock file is | ||
155 | more than PATIENCE seconds old, then the lock file is deleted and the | ||
156 | exclusive create is retried. | ||
157 | - Load the extra field from the foo.gz file, and see if an operation was in | ||
158 | progress but not completed. If so, apply the recovery procedure below. | ||
159 | - Perform the append procedure with the provided data. | ||
160 | - If the uncompressed data in the foo.gz file is 1MB or more, apply the | ||
161 | compress procedure. | ||
162 | - Delete the foo.lock file. | ||
163 | |||
164 | Append procedure: | ||
165 | - Put what to append in the foo.add file so that the operation can be | ||
166 | restarted if this procedure is interrupted. | ||
167 | - Mark the foo.gz extra field with the append operation in progress. | ||
168 | + Restore the original last-block bit and stored block length of the last | ||
169 | stored block from the information in the extra field, in case a previous | ||
170 | append operation was interrupted. | ||
171 | - Append the provided data to the last stored block, creating new stored | ||
172 | blocks as needed and updating the stored blocks last-block bits and | ||
173 | lengths. | ||
174 | - Update the crc and length with the new data, and write the gzip trailer. | ||
175 | - Write over the extra field (with a single write operation) with the new | ||
176 | pointers, lengths, and crc's, and mark the gzip file as not in process. | ||
177 | Though there is still a foo.add file, it will be ignored since nothing | ||
178 | is in process. If a foo.add file is leftover from a previously | ||
179 | completed operation, it is truncated when writing new data to it. | ||
180 | - Delete the foo.add file. | ||
181 | |||
182 | Compress and replace procedures: | ||
183 | - Read all of the uncompressed data in the stored blocks in foo.gz and write | ||
184 | it to foo.add. Also write foo.temp with the last 32K of that data to | ||
185 | provide a dictionary for the next invocation of this procedure. | ||
186 | - Rewrite the extra field marking foo.gz with a compression in process. | ||
187 | * If there is no data provided to compress (due to a missing foo.add file | ||
188 | when recovering), reconstruct and truncate the foo.gz file to contain | ||
189 | only the previous compressed data and proceed to the step after the next | ||
190 | one. Otherwise ... | ||
191 | - Compress the data with the dictionary in foo.dict, and write to the | ||
192 | foo.gz file starting at the bit immediately following the last previously | ||
193 | compressed block. If there is no foo.dict, proceed anyway with the | ||
194 | compression at slightly reduced efficiency. (For the foo.dict file to be | ||
195 | missing requires some external failure beyond simply the interruption of | ||
196 | a compress operation.) During this process, the foo.lock file is | ||
197 | periodically touched to assure that that file is not considered stale by | ||
198 | another process before we're done. The deflation is terminated with a | ||
199 | non-last empty static block (10 bits long), that is then located and | ||
200 | written over by a last-bit-set empty stored block. | ||
201 | - Append the crc and length of the data in the gzip file (previously | ||
202 | calculated during the append operations). | ||
203 | - Write over the extra field with the updated stored block offsets, bits | ||
204 | back, crc's, and lengths, and mark foo.gz as in process for a replacement | ||
205 | of the dictionary. | ||
206 | @ Delete the foo.add file. | ||
207 | - Replace foo.dict with foo.temp. | ||
208 | - Write over the extra field, marking foo.gz as complete. | ||
209 | |||
210 | Recovery procedure: | ||
211 | - If not a replace recovery, read in the foo.add file, and provide that data | ||
212 | to the appropriate recovery below. If there is no foo.add file, provide | ||
213 | a zero data length to the recovery. In that case, the append recovery | ||
214 | restores the foo.gz to the previous compressed + uncompressed data state. | ||
215 | For the the compress recovery, a missing foo.add file results in foo.gz | ||
216 | being restored to the previous compressed-only data state. | ||
217 | - Append recovery: | ||
218 | - Pick up append at + step above | ||
219 | - Compress recovery: | ||
220 | - Pick up compress at * step above | ||
221 | - Replace recovery: | ||
222 | - Pick up compress at @ step above | ||
223 | - Log the repair with a date stamp in foo.repairs | ||
224 | */ | ||
225 | |||
226 | #include <sys/types.h> | ||
227 | #include <stdio.h> /* rename, fopen, fprintf, fclose */ | ||
228 | #include <stdlib.h> /* malloc, free */ | ||
229 | #include <string.h> /* strlen, strrchr, strcpy, strncpy, strcmp */ | ||
230 | #include <fcntl.h> /* open */ | ||
231 | #include <unistd.h> /* lseek, read, write, close, unlink, sleep, */ | ||
232 | /* ftruncate, fsync */ | ||
233 | #include <errno.h> /* errno */ | ||
234 | #include <time.h> /* time, ctime */ | ||
235 | #include <sys/stat.h> /* stat */ | ||
236 | #include <sys/time.h> /* utimes */ | ||
237 | #include "zlib.h" /* crc32 */ | ||
238 | |||
239 | #include "gzlog.h" /* header for external access */ | ||
17 | 240 | ||
18 | #include "gzlog.h" /* interface */ | ||
19 | #define local static | 241 | #define local static |
242 | typedef unsigned int uint; | ||
243 | typedef unsigned long ulong; | ||
244 | |||
245 | /* Macro for debugging to deterministically force recovery operations */ | ||
246 | #ifdef DEBUG | ||
247 | #include <setjmp.h> /* longjmp */ | ||
248 | jmp_buf gzlog_jump; /* where to go back to */ | ||
249 | int gzlog_bail = 0; /* which point to bail at (1..8) */ | ||
250 | int gzlog_count = -1; /* number of times through to wait */ | ||
251 | # define BAIL(n) do { if (n == gzlog_bail && gzlog_count-- == 0) \ | ||
252 | longjmp(gzlog_jump, gzlog_bail); } while (0) | ||
253 | #else | ||
254 | # define BAIL(n) | ||
255 | #endif | ||
256 | |||
257 | /* how old the lock file can be in seconds before considering it stale */ | ||
258 | #define PATIENCE 300 | ||
259 | |||
260 | /* maximum stored block size in Kbytes -- must be in 1..63 */ | ||
261 | #define MAX_STORE 16 | ||
20 | 262 | ||
21 | /* log object structure */ | 263 | /* number of stored Kbytes to trigger compression (must be >= 32 to allow |
22 | typedef struct { | 264 | dictionary construction, and <= 204 * MAX_STORE, in order for >> 10 to |
23 | int id; /* object identifier */ | 265 | discard the stored block headers contribution of five bytes each) */ |
24 | int fd; /* log file descriptor */ | 266 | #define TRIGGER 1024 |
25 | off_t extra; /* offset of extra "ap" subfield */ | 267 | |
26 | off_t mark_off; /* offset of marked data */ | 268 | /* size of a deflate dictionary (this cannot be changed) */ |
27 | off_t last_off; /* offset of last block */ | 269 | #define DICT 32768U |
28 | unsigned long crc; /* uncompressed crc */ | 270 | |
29 | unsigned long len; /* uncompressed length (modulo 2^32) */ | 271 | /* values for the operation (2 bits) */ |
30 | unsigned stored; /* length of current stored block */ | 272 | #define NO_OP 0 |
31 | } gz_log; | 273 | #define APPEND_OP 1 |
32 | 274 | #define COMPRESS_OP 2 | |
33 | #define GZLOGID 19334 /* gz_log object identifier */ | 275 | #define REPLACE_OP 3 |
34 | 276 | ||
35 | #define LOCK_RETRY 1 /* retry lock once a second */ | 277 | /* macros to extract little-endian integers from an unsigned byte buffer */ |
36 | #define LOCK_PATIENCE 1200 /* try about twenty minutes before forcing */ | 278 | #define PULL2(p) ((p)[0]+((uint)((p)[1])<<8)) |
37 | 279 | #define PULL4(p) (PULL2(p)+((ulong)PULL2(p+2)<<16)) | |
38 | /* acquire a lock on a file */ | 280 | #define PULL8(p) (PULL4(p)+((off_t)PULL4(p+4)<<32)) |
39 | local int lock(int fd) | 281 | |
282 | /* macros to store integers into a byte buffer in little-endian order */ | ||
283 | #define PUT2(p,a) do {(p)[0]=a;(p)[1]=(a)>>8;} while(0) | ||
284 | #define PUT4(p,a) do {PUT2(p,a);PUT2(p+2,a>>16);} while(0) | ||
285 | #define PUT8(p,a) do {PUT4(p,a);PUT4(p+4,a>>32);} while(0) | ||
286 | |||
287 | /* internal structure for log information */ | ||
288 | #define LOGID "\106\035\172" /* should be three non-zero characters */ | ||
289 | struct log { | ||
290 | char id[4]; /* contains LOGID to detect inadvertent overwrites */ | ||
291 | int fd; /* file descriptor for .gz file, opened read/write */ | ||
292 | char *path; /* allocated path, e.g. "/var/log/foo" or "foo" */ | ||
293 | char *end; /* end of path, for appending suffices such as ".gz" */ | ||
294 | off_t first; /* offset of first stored block first length byte */ | ||
295 | int back; /* location of first block id in bits back from first */ | ||
296 | uint stored; /* bytes currently in last stored block */ | ||
297 | off_t last; /* offset of last stored block first length byte */ | ||
298 | ulong ccrc; /* crc of compressed data */ | ||
299 | ulong clen; /* length (modulo 2^32) of compressed data */ | ||
300 | ulong tcrc; /* crc of total data */ | ||
301 | ulong tlen; /* length (modulo 2^32) of total data */ | ||
302 | time_t lock; /* last modify time of our lock file */ | ||
303 | }; | ||
304 | |||
305 | /* gzip header for gzlog */ | ||
306 | local unsigned char log_gzhead[] = { | ||
307 | 0x1f, 0x8b, /* magic gzip id */ | ||
308 | 8, /* compression method is deflate */ | ||
309 | 4, /* there is an extra field (no file name) */ | ||
310 | 0, 0, 0, 0, /* no modification time provided */ | ||
311 | 0, 0xff, /* no extra flags, no OS specified */ | ||
312 | 39, 0, 'a', 'p', 35, 0 /* extra field with "ap" subfield */ | ||
313 | /* 35 is EXTRA, 39 is EXTRA + 4 */ | ||
314 | }; | ||
315 | |||
316 | #define HEAD sizeof(log_gzhead) /* should be 16 */ | ||
317 | |||
318 | /* initial gzip extra field content (52 == HEAD + EXTRA + 1) */ | ||
319 | local unsigned char log_gzext[] = { | ||
320 | 52, 0, 0, 0, 0, 0, 0, 0, /* offset of first stored block length */ | ||
321 | 52, 0, 0, 0, 0, 0, 0, 0, /* offset of last stored block length */ | ||
322 | 0, 0, 0, 0, 0, 0, 0, 0, /* compressed data crc and length */ | ||
323 | 0, 0, 0, 0, 0, 0, 0, 0, /* total data crc and length */ | ||
324 | 0, 0, /* final stored block data length */ | ||
325 | 5 /* op is NO_OP, last bit 8 bits back */ | ||
326 | }; | ||
327 | |||
328 | #define EXTRA sizeof(log_gzext) /* should be 35 */ | ||
329 | |||
330 | /* initial gzip data and trailer */ | ||
331 | local unsigned char log_gzbody[] = { | ||
332 | 1, 0, 0, 0xff, 0xff, /* empty stored block (last) */ | ||
333 | 0, 0, 0, 0, /* crc */ | ||
334 | 0, 0, 0, 0 /* uncompressed length */ | ||
335 | }; | ||
336 | |||
337 | #define BODY sizeof(log_gzbody) | ||
338 | |||
339 | /* Exclusively create foo.lock in order to negotiate exclusive access to the | ||
340 | foo.* files. If the modify time of an existing lock file is greater than | ||
341 | PATIENCE seconds in the past, then consider the lock file to have been | ||
342 | abandoned, delete it, and try the exclusive create again. Save the lock | ||
343 | file modify time for verification of ownership. Return 0 on success, or -1 | ||
344 | on failure, usually due to an access restriction or invalid path. Note that | ||
345 | if stat() or unlink() fails, it may be due to another process noticing the | ||
346 | abandoned lock file a smidge sooner and deleting it, so those are not | ||
347 | flagged as an error. */ | ||
348 | local int log_lock(struct log *log) | ||
40 | { | 349 | { |
41 | int patience; | 350 | int fd; |
351 | struct stat st; | ||
42 | 352 | ||
43 | /* try to lock every LOCK_RETRY seconds for LOCK_PATIENCE seconds */ | 353 | strcpy(log->end, ".lock"); |
44 | patience = LOCK_PATIENCE; | 354 | while ((fd = open(log->path, O_CREAT | O_EXCL, 0644)) < 0) { |
45 | do { | 355 | if (errno != EEXIST) |
46 | if (flock(fd, LOCK_EX + LOCK_NB) == 0) | 356 | return -1; |
47 | return 0; | 357 | if (stat(log->path, &st) == 0 && time(NULL) - st.st_mtime > PATIENCE) { |
48 | (void)sleep(LOCK_RETRY); | 358 | unlink(log->path); |
49 | patience -= LOCK_RETRY; | 359 | continue; |
50 | } while (patience > 0); | 360 | } |
361 | sleep(2); /* relinquish the CPU for two seconds while waiting */ | ||
362 | } | ||
363 | close(fd); | ||
364 | if (stat(log->path, &st) == 0) | ||
365 | log->lock = st.st_mtime; | ||
366 | return 0; | ||
367 | } | ||
51 | 368 | ||
52 | /* we've run out of patience -- give up */ | 369 | /* Update the modify time of the lock file to now, in order to prevent another |
53 | return -1; | 370 | task from thinking that the lock is stale. Save the lock file modify time |
371 | for verification of ownership. */ | ||
372 | local void log_touch(struct log *log) | ||
373 | { | ||
374 | struct stat st; | ||
375 | |||
376 | strcpy(log->end, ".lock"); | ||
377 | utimes(log->path, NULL); | ||
378 | if (stat(log->path, &st) == 0) | ||
379 | log->lock = st.st_mtime; | ||
54 | } | 380 | } |
55 | 381 | ||
56 | /* release lock */ | 382 | /* Check the log file modify time against what is expected. Return true if |
57 | local void unlock(int fd) | 383 | this is not our lock. If it is our lock, touch it to keep it. */ |
384 | local int log_check(struct log *log) | ||
58 | { | 385 | { |
59 | (void)flock(fd, LOCK_UN); | 386 | struct stat st; |
387 | |||
388 | strcpy(log->end, ".lock"); | ||
389 | if (stat(log->path, &st) || st.st_mtime != log->lock) | ||
390 | return 1; | ||
391 | log_touch(log); | ||
392 | return 0; | ||
60 | } | 393 | } |
61 | 394 | ||
62 | /* release a log object */ | 395 | /* Unlock a previously acquired lock, but only if it's ours. */ |
63 | local void log_clean(gz_log *log) | 396 | local void log_unlock(struct log *log) |
64 | { | 397 | { |
65 | unlock(log->fd); | 398 | if (log_check(log)) |
66 | (void)close(log->fd); | 399 | return; |
67 | free(log); | 400 | strcpy(log->end, ".lock"); |
401 | unlink(log->path); | ||
402 | log->lock = 0; | ||
68 | } | 403 | } |
69 | 404 | ||
70 | /* read an unsigned long from a byte buffer little-endian */ | 405 | /* Check the gzip header and read in the extra field, filling in the values in |
71 | local unsigned long make_ulg(unsigned char *buf) | 406 | the log structure. Return op on success or -1 if the gzip header was not as |
407 | expected. op is the current operation in progress last written to the extra | ||
408 | field. This assumes that the gzip file has already been opened, with the | ||
409 | file descriptor log->fd. */ | ||
410 | local int log_head(struct log *log) | ||
72 | { | 411 | { |
73 | int n; | 412 | int op; |
74 | unsigned long val; | 413 | unsigned char buf[HEAD + EXTRA]; |
75 | 414 | ||
76 | val = (unsigned long)(*buf++); | 415 | if (lseek(log->fd, 0, SEEK_SET) < 0 || |
77 | for (n = 8; n < 32; n += 8) | 416 | read(log->fd, buf, HEAD + EXTRA) != HEAD + EXTRA || |
78 | val += (unsigned long)(*buf++) << n; | 417 | memcmp(buf, log_gzhead, HEAD)) { |
79 | return val; | 418 | return -1; |
419 | } | ||
420 | log->first = PULL8(buf + HEAD); | ||
421 | log->last = PULL8(buf + HEAD + 8); | ||
422 | log->ccrc = PULL4(buf + HEAD + 16); | ||
423 | log->clen = PULL4(buf + HEAD + 20); | ||
424 | log->tcrc = PULL4(buf + HEAD + 24); | ||
425 | log->tlen = PULL4(buf + HEAD + 28); | ||
426 | log->stored = PULL2(buf + HEAD + 32); | ||
427 | log->back = 3 + (buf[HEAD + 34] & 7); | ||
428 | op = (buf[HEAD + 34] >> 3) & 3; | ||
429 | return op; | ||
80 | } | 430 | } |
81 | 431 | ||
82 | /* read an off_t from a byte buffer little-endian */ | 432 | /* Write over the extra field contents, marking the operation as op. Use fsync |
83 | local off_t make_off(unsigned char *buf) | 433 | to assure that the device is written to, and in the requested order. This |
434 | operation, and only this operation, is assumed to be atomic in order to | ||
435 | assure that the log is recoverable in the event of an interruption at any | ||
436 | point in the process. Return -1 if the write to foo.gz failed. */ | ||
437 | local int log_mark(struct log *log, int op) | ||
84 | { | 438 | { |
85 | int n; | 439 | int ret; |
86 | off_t val; | 440 | unsigned char ext[EXTRA]; |
87 | 441 | ||
88 | val = (off_t)(*buf++); | 442 | PUT8(ext, log->first); |
89 | for (n = 8; n < 64; n += 8) | 443 | PUT8(ext + 8, log->last); |
90 | val += (off_t)(*buf++) << n; | 444 | PUT4(ext + 16, log->ccrc); |
91 | return val; | 445 | PUT4(ext + 20, log->clen); |
446 | PUT4(ext + 24, log->tcrc); | ||
447 | PUT4(ext + 28, log->tlen); | ||
448 | PUT2(ext + 32, log->stored); | ||
449 | ext[34] = log->back - 3 + (op << 3); | ||
450 | fsync(log->fd); | ||
451 | ret = lseek(log->fd, HEAD, SEEK_SET) < 0 || | ||
452 | write(log->fd, ext, EXTRA) != EXTRA ? -1 : 0; | ||
453 | fsync(log->fd); | ||
454 | return ret; | ||
92 | } | 455 | } |
93 | 456 | ||
94 | /* write an unsigned long little-endian to byte buffer */ | 457 | /* Rewrite the last block header bits and subsequent zero bits to get to a byte |
95 | local void dice_ulg(unsigned long val, unsigned char *buf) | 458 | boundary, setting the last block bit if last is true, and then write the |
459 | remainder of the stored block header (length and one's complement). Leave | ||
460 | the file pointer after the end of the last stored block data. Return -1 if | ||
461 | there is a read or write failure on the foo.gz file */ | ||
462 | local int log_last(struct log *log, int last) | ||
96 | { | 463 | { |
97 | int n; | 464 | int back, len, mask; |
465 | unsigned char buf[6]; | ||
466 | |||
467 | /* determine the locations of the bytes and bits to modify */ | ||
468 | back = log->last == log->first ? log->back : 8; | ||
469 | len = back > 8 ? 2 : 1; /* bytes back from log->last */ | ||
470 | mask = 0x80 >> ((back - 1) & 7); /* mask for block last-bit */ | ||
471 | |||
472 | /* get the byte to modify (one or two back) into buf[0] -- don't need to | ||
473 | read the byte if the last-bit is eight bits back, since in that case | ||
474 | the entire byte will be modified */ | ||
475 | buf[0] = 0; | ||
476 | if (back != 8 && (lseek(log->fd, log->last - len, SEEK_SET) < 0 || | ||
477 | read(log->fd, buf, 1) != 1)) | ||
478 | return -1; | ||
479 | |||
480 | /* change the last-bit of the last stored block as requested -- note | ||
481 | that all bits above the last-bit are set to zero, per the type bits | ||
482 | of a stored block being 00 and per the convention that the bits to | ||
483 | bring the stream to a byte boundary are also zeros */ | ||
484 | buf[1] = 0; | ||
485 | buf[2 - len] = (*buf & (mask - 1)) + (last ? mask : 0); | ||
98 | 486 | ||
99 | for (n = 0; n < 4; n++) { | 487 | /* write the modified stored block header and lengths, move the file |
100 | *buf++ = val & 0xff; | 488 | pointer to after the last stored block data */ |
101 | val >>= 8; | 489 | PUT2(buf + 2, log->stored); |
490 | PUT2(buf + 4, log->stored ^ 0xffff); | ||
491 | return lseek(log->fd, log->last - len, SEEK_SET) < 0 || | ||
492 | write(log->fd, buf + 2 - len, len + 4) != len + 4 || | ||
493 | lseek(log->fd, log->stored, SEEK_CUR) < 0 ? -1 : 0; | ||
494 | } | ||
495 | |||
496 | /* Append len bytes from data to the locked and open log file. len may be zero | ||
497 | if recovering and no .add file was found. In that case, the previous state | ||
498 | of the foo.gz file is restored. The data is appended uncompressed in | ||
499 | deflate stored blocks. Return -1 if there was an error reading or writing | ||
500 | the foo.gz file. */ | ||
501 | local int log_append(struct log *log, unsigned char *data, size_t len) | ||
502 | { | ||
503 | uint put; | ||
504 | off_t end; | ||
505 | unsigned char buf[8]; | ||
506 | |||
507 | /* set the last block last-bit and length, in case recovering an | ||
508 | interrupted append, then position the file pointer to append to the | ||
509 | block */ | ||
510 | if (log_last(log, 1)) | ||
511 | return -1; | ||
512 | |||
513 | /* append, adding stored blocks and updating the offset of the last stored | ||
514 | block as needed, and update the total crc and length */ | ||
515 | while (len) { | ||
516 | /* append as much as we can to the last block */ | ||
517 | put = (MAX_STORE << 10) - log->stored; | ||
518 | if (put > len) | ||
519 | put = (uint)len; | ||
520 | if (put) { | ||
521 | if (write(log->fd, data, put) != put) | ||
522 | return -1; | ||
523 | BAIL(1); | ||
524 | log->tcrc = crc32(log->tcrc, data, put); | ||
525 | log->tlen += put; | ||
526 | log->stored += put; | ||
527 | data += put; | ||
528 | len -= put; | ||
529 | } | ||
530 | |||
531 | /* if we need to, add a new empty stored block */ | ||
532 | if (len) { | ||
533 | /* mark current block as not last */ | ||
534 | if (log_last(log, 0)) | ||
535 | return -1; | ||
536 | |||
537 | /* point to new, empty stored block */ | ||
538 | log->last += 4 + log->stored + 1; | ||
539 | log->stored = 0; | ||
540 | } | ||
541 | |||
542 | /* mark last block as last, update its length */ | ||
543 | if (log_last(log, 1)) | ||
544 | return -1; | ||
545 | BAIL(2); | ||
102 | } | 546 | } |
547 | |||
548 | /* write the new crc and length trailer, and truncate just in case (could | ||
549 | be recovering from partial append with a missing foo.add file) */ | ||
550 | PUT4(buf, log->tcrc); | ||
551 | PUT4(buf + 4, log->tlen); | ||
552 | if (write(log->fd, buf, 8) != 8 || | ||
553 | (end = lseek(log->fd, 0, SEEK_CUR)) < 0 || ftruncate(log->fd, end)) | ||
554 | return -1; | ||
555 | |||
556 | /* write the extra field, marking the log file as done, delete .add file */ | ||
557 | if (log_mark(log, NO_OP)) | ||
558 | return -1; | ||
559 | strcpy(log->end, ".add"); | ||
560 | unlink(log->path); /* ignore error, since may not exist */ | ||
561 | return 0; | ||
103 | } | 562 | } |
104 | 563 | ||
105 | /* write an off_t little-endian to byte buffer */ | 564 | /* Replace the foo.dict file with the foo.temp file. Also delete the foo.add |
106 | local void dice_off(off_t val, unsigned char *buf) | 565 | file, since the compress operation may have been interrupted before that was |
566 | done. Returns 1 if memory could not be allocated, or -1 if reading or | ||
567 | writing foo.gz fails, or if the rename fails for some reason other than | ||
568 | foo.temp not existing. foo.temp not existing is a permitted error, since | ||
569 | the replace operation may have been interrupted after the rename is done, | ||
570 | but before foo.gz is marked as complete. */ | ||
571 | local int log_replace(struct log *log) | ||
107 | { | 572 | { |
108 | int n; | 573 | int ret; |
574 | char *dest; | ||
575 | |||
576 | /* delete foo.add file */ | ||
577 | strcpy(log->end, ".add"); | ||
578 | unlink(log->path); /* ignore error, since may not exist */ | ||
579 | BAIL(3); | ||
580 | |||
581 | /* rename foo.name to foo.dict, replacing foo.dict if it exists */ | ||
582 | strcpy(log->end, ".dict"); | ||
583 | dest = malloc(strlen(log->path) + 1); | ||
584 | if (dest == NULL) | ||
585 | return -2; | ||
586 | strcpy(dest, log->path); | ||
587 | strcpy(log->end, ".temp"); | ||
588 | ret = rename(log->path, dest); | ||
589 | free(dest); | ||
590 | if (ret && errno != ENOENT) | ||
591 | return -1; | ||
592 | BAIL(4); | ||
109 | 593 | ||
110 | for (n = 0; n < 8; n++) { | 594 | /* mark the foo.gz file as done */ |
111 | *buf++ = val & 0xff; | 595 | return log_mark(log, NO_OP); |
112 | val >>= 8; | 596 | } |
597 | |||
598 | /* Compress the len bytes at data and append the compressed data to the | ||
599 | foo.gz deflate data immediately after the previous compressed data. This | ||
600 | overwrites the previous uncompressed data, which was stored in foo.add | ||
601 | and is the data provided in data[0..len-1]. If this operation is | ||
602 | interrupted, it picks up at the start of this routine, with the foo.add | ||
603 | file read in again. If there is no data to compress (len == 0), then we | ||
604 | simply terminate the foo.gz file after the previously compressed data, | ||
605 | appending a final empty stored block and the gzip trailer. Return -1 if | ||
606 | reading or writing the log.gz file failed, or -2 if there was a memory | ||
607 | allocation failure. */ | ||
608 | local int log_compress(struct log *log, unsigned char *data, size_t len) | ||
609 | { | ||
610 | int fd; | ||
611 | uint got, max; | ||
612 | ssize_t dict; | ||
613 | off_t end; | ||
614 | z_stream strm; | ||
615 | unsigned char buf[DICT]; | ||
616 | |||
617 | /* compress and append compressed data */ | ||
618 | if (len) { | ||
619 | /* set up for deflate, allocating memory */ | ||
620 | strm.zalloc = Z_NULL; | ||
621 | strm.zfree = Z_NULL; | ||
622 | strm.opaque = Z_NULL; | ||
623 | if (deflateInit2(&strm, Z_DEFAULT_COMPRESSION, Z_DEFLATED, -15, 8, | ||
624 | Z_DEFAULT_STRATEGY) != Z_OK) | ||
625 | return -2; | ||
626 | |||
627 | /* read in dictionary (last 32K of data that was compressed) */ | ||
628 | strcpy(log->end, ".dict"); | ||
629 | fd = open(log->path, O_RDONLY, 0); | ||
630 | if (fd >= 0) { | ||
631 | dict = read(fd, buf, DICT); | ||
632 | close(fd); | ||
633 | if (dict < 0) { | ||
634 | deflateEnd(&strm); | ||
635 | return -1; | ||
636 | } | ||
637 | if (dict) | ||
638 | deflateSetDictionary(&strm, buf, (uint)dict); | ||
639 | } | ||
640 | log_touch(log); | ||
641 | |||
642 | /* prime deflate with last bits of previous block, position write | ||
643 | pointer to write those bits and overwrite what follows */ | ||
644 | if (lseek(log->fd, log->first - (log->back > 8 ? 2 : 1), | ||
645 | SEEK_SET) < 0 || | ||
646 | read(log->fd, buf, 1) != 1 || lseek(log->fd, -1, SEEK_CUR) < 0) { | ||
647 | deflateEnd(&strm); | ||
648 | return -1; | ||
649 | } | ||
650 | deflatePrime(&strm, (8 - log->back) & 7, *buf); | ||
651 | |||
652 | /* compress, finishing with a partial non-last empty static block */ | ||
653 | strm.next_in = data; | ||
654 | max = (((uint)0 - 1) >> 1) + 1; /* in case int smaller than size_t */ | ||
655 | do { | ||
656 | strm.avail_in = len > max ? max : (uint)len; | ||
657 | len -= strm.avail_in; | ||
658 | do { | ||
659 | strm.avail_out = DICT; | ||
660 | strm.next_out = buf; | ||
661 | deflate(&strm, len ? Z_NO_FLUSH : Z_PARTIAL_FLUSH); | ||
662 | got = DICT - strm.avail_out; | ||
663 | if (got && write(log->fd, buf, got) != got) { | ||
664 | deflateEnd(&strm); | ||
665 | return -1; | ||
666 | } | ||
667 | log_touch(log); | ||
668 | } while (strm.avail_out == 0); | ||
669 | } while (len); | ||
670 | deflateEnd(&strm); | ||
671 | BAIL(5); | ||
672 | |||
673 | /* find start of empty static block -- scanning backwards the first one | ||
674 | bit is the second bit of the block, if the last byte is zero, then | ||
675 | we know the byte before that has a one in the top bit, since an | ||
676 | empty static block is ten bits long */ | ||
677 | if ((log->first = lseek(log->fd, -1, SEEK_CUR)) < 0 || | ||
678 | read(log->fd, buf, 1) != 1) | ||
679 | return -1; | ||
680 | log->first++; | ||
681 | if (*buf) { | ||
682 | log->back = 1; | ||
683 | while ((*buf & ((uint)1 << (8 - log->back++))) == 0) | ||
684 | ; /* guaranteed to terminate, since *buf != 0 */ | ||
685 | } | ||
686 | else | ||
687 | log->back = 10; | ||
688 | |||
689 | /* update compressed crc and length */ | ||
690 | log->ccrc = log->tcrc; | ||
691 | log->clen = log->tlen; | ||
692 | } | ||
693 | else { | ||
694 | /* no data to compress -- fix up existing gzip stream */ | ||
695 | log->tcrc = log->ccrc; | ||
696 | log->tlen = log->clen; | ||
113 | } | 697 | } |
698 | |||
699 | /* complete and truncate gzip stream */ | ||
700 | log->last = log->first; | ||
701 | log->stored = 0; | ||
702 | PUT4(buf, log->tcrc); | ||
703 | PUT4(buf + 4, log->tlen); | ||
704 | if (log_last(log, 1) || write(log->fd, buf, 8) != 8 || | ||
705 | (end = lseek(log->fd, 0, SEEK_CUR)) < 0 || ftruncate(log->fd, end)) | ||
706 | return -1; | ||
707 | BAIL(6); | ||
708 | |||
709 | /* mark as being in the replace operation */ | ||
710 | if (log_mark(log, REPLACE_OP)) | ||
711 | return -1; | ||
712 | |||
713 | /* execute the replace operation and mark the file as done */ | ||
714 | return log_replace(log); | ||
114 | } | 715 | } |
115 | 716 | ||
116 | /* initial, empty gzip file for appending */ | 717 | /* log a repair record to the .repairs file */ |
117 | local char empty_gz[] = { | 718 | local void log_log(struct log *log, int op, char *record) |
118 | 0x1f, 0x8b, /* magic gzip id */ | 719 | { |
119 | 8, /* compression method is deflate */ | 720 | time_t now; |
120 | 4, /* there is an extra field */ | 721 | FILE *rec; |
121 | 0, 0, 0, 0, /* no modification time provided */ | ||
122 | 0, 0xff, /* no extra flags, no OS */ | ||
123 | 20, 0, 'a', 'p', 16, 0, /* extra field with "ap" subfield */ | ||
124 | 32, 0, 0, 0, 0, 0, 0, 0, /* offset of uncompressed data */ | ||
125 | 32, 0, 0, 0, 0, 0, 0, 0, /* offset of last block */ | ||
126 | 1, 0, 0, 0xff, 0xff, /* empty stored block (last) */ | ||
127 | 0, 0, 0, 0, /* crc */ | ||
128 | 0, 0, 0, 0 /* uncompressed length */ | ||
129 | }; | ||
130 | 722 | ||
131 | /* initialize a log object with locking */ | 723 | now = time(NULL); |
132 | void *gzlog_open(char *path) | 724 | strcpy(log->end, ".repairs"); |
725 | rec = fopen(log->path, "a"); | ||
726 | if (rec == NULL) | ||
727 | return; | ||
728 | fprintf(rec, "%.24s %s recovery: %s\n", ctime(&now), op == APPEND_OP ? | ||
729 | "append" : (op == COMPRESS_OP ? "compress" : "replace"), record); | ||
730 | fclose(rec); | ||
731 | return; | ||
732 | } | ||
733 | |||
734 | /* Recover the interrupted operation op. First read foo.add for recovering an | ||
735 | append or compress operation. Return -1 if there was an error reading or | ||
736 | writing foo.gz or reading an existing foo.add, or -2 if there was a memory | ||
737 | allocation failure. */ | ||
738 | local int log_recover(struct log *log, int op) | ||
133 | { | 739 | { |
134 | unsigned xlen; | 740 | int fd, ret = 0; |
135 | unsigned char temp[20]; | 741 | unsigned char *data = NULL; |
136 | unsigned sub_len; | 742 | size_t len = 0; |
137 | int good; | 743 | struct stat st; |
138 | gz_log *log; | ||
139 | |||
140 | /* allocate log structure */ | ||
141 | log = malloc(sizeof(gz_log)); | ||
142 | if (log == NULL) | ||
143 | return NULL; | ||
144 | log->id = GZLOGID; | ||
145 | 744 | ||
146 | /* open file, creating it if necessary, and locking it */ | 745 | /* log recovery */ |
147 | log->fd = open(path, O_RDWR | O_CREAT, 0600); | 746 | log_log(log, op, "start"); |
148 | if (log->fd < 0) { | 747 | |
149 | free(log); | 748 | /* load foo.add file if expected and present */ |
150 | return NULL; | 749 | if (op == APPEND_OP || op == COMPRESS_OP) { |
750 | strcpy(log->end, ".add"); | ||
751 | if (stat(log->path, &st) == 0 && st.st_size) { | ||
752 | len = (size_t)(st.st_size); | ||
753 | if (len != st.st_size || (data = malloc(st.st_size)) == NULL) { | ||
754 | log_log(log, op, "allocation failure"); | ||
755 | return -2; | ||
756 | } | ||
757 | if ((fd = open(log->path, O_RDONLY, 0)) < 0) { | ||
758 | log_log(log, op, ".add file read failure"); | ||
759 | return -1; | ||
760 | } | ||
761 | ret = read(fd, data, len) != len; | ||
762 | close(fd); | ||
763 | if (ret) { | ||
764 | log_log(log, op, ".add file read failure"); | ||
765 | return -1; | ||
766 | } | ||
767 | log_log(log, op, "loaded .add file"); | ||
768 | } | ||
769 | else | ||
770 | log_log(log, op, "missing .add file!"); | ||
771 | } | ||
772 | |||
773 | /* recover the interrupted operation */ | ||
774 | switch (op) { | ||
775 | case APPEND_OP: | ||
776 | ret = log_append(log, data, len); | ||
777 | break; | ||
778 | case COMPRESS_OP: | ||
779 | ret = log_compress(log, data, len); | ||
780 | break; | ||
781 | case REPLACE_OP: | ||
782 | ret = log_replace(log); | ||
151 | } | 783 | } |
152 | if (lock(log->fd)) { | 784 | |
785 | /* log status */ | ||
786 | log_log(log, op, ret ? "failure" : "complete"); | ||
787 | |||
788 | /* clean up */ | ||
789 | if (data != NULL) | ||
790 | free(data); | ||
791 | return ret; | ||
792 | } | ||
793 | |||
794 | /* Close the foo.gz file (if open) and release the lock. */ | ||
795 | local void log_close(struct log *log) | ||
796 | { | ||
797 | if (log->fd >= 0) | ||
153 | close(log->fd); | 798 | close(log->fd); |
154 | free(log); | 799 | log->fd = -1; |
155 | return NULL; | 800 | log_unlock(log); |
801 | } | ||
802 | |||
803 | /* Open foo.gz, verify the header, and load the extra field contents, after | ||
804 | first creating the foo.lock file to gain exclusive access to the foo.* | ||
805 | files. If foo.gz does not exist or is empty, then write the initial header, | ||
806 | extra, and body content of an empty foo.gz log file. If there is an error | ||
807 | creating the lock file due to access restrictions, or an error reading or | ||
808 | writing the foo.gz file, or if the foo.gz file is not a proper log file for | ||
809 | this object (e.g. not a gzip file or does not contain the expected extra | ||
810 | field), then return true. If there is an error, the lock is released. | ||
811 | Otherwise, the lock is left in place. */ | ||
812 | local int log_open(struct log *log) | ||
813 | { | ||
814 | int op; | ||
815 | |||
816 | /* release open file resource if left over -- can occur if lock lost | ||
817 | between gzlog_open() and gzlog_write() */ | ||
818 | if (log->fd >= 0) | ||
819 | close(log->fd); | ||
820 | log->fd = -1; | ||
821 | |||
822 | /* negotiate exclusive access */ | ||
823 | if (log_lock(log) < 0) | ||
824 | return -1; | ||
825 | |||
826 | /* open the log file, foo.gz */ | ||
827 | strcpy(log->end, ".gz"); | ||
828 | log->fd = open(log->path, O_RDWR | O_CREAT, 0644); | ||
829 | if (log->fd < 0) { | ||
830 | log_close(log); | ||
831 | return -1; | ||
156 | } | 832 | } |
157 | 833 | ||
158 | /* if file is empty, write new gzip stream */ | 834 | /* if new, initialize foo.gz with an empty log, delete old dictionary */ |
159 | if (lseek(log->fd, 0, SEEK_END) == 0) { | 835 | if (lseek(log->fd, 0, SEEK_END) == 0) { |
160 | if (write(log->fd, empty_gz, sizeof(empty_gz)) != sizeof(empty_gz)) { | 836 | if (write(log->fd, log_gzhead, HEAD) != HEAD || |
161 | log_clean(log); | 837 | write(log->fd, log_gzext, EXTRA) != EXTRA || |
162 | return NULL; | 838 | write(log->fd, log_gzbody, BODY) != BODY) { |
839 | log_close(log); | ||
840 | return -1; | ||
163 | } | 841 | } |
842 | strcpy(log->end, ".dict"); | ||
843 | unlink(log->path); | ||
164 | } | 844 | } |
165 | 845 | ||
166 | /* check gzip header */ | 846 | /* verify log file and load extra field information */ |
167 | (void)lseek(log->fd, 0, SEEK_SET); | 847 | if ((op = log_head(log)) < 0) { |
168 | if (read(log->fd, temp, 12) != 12 || temp[0] != 0x1f || | 848 | log_close(log); |
169 | temp[1] != 0x8b || temp[2] != 8 || (temp[3] & 4) == 0) { | 849 | return -1; |
170 | log_clean(log); | ||
171 | return NULL; | ||
172 | } | 850 | } |
173 | 851 | ||
174 | /* process extra field to find "ap" sub-field */ | 852 | /* check for interrupted process and if so, recover */ |
175 | xlen = temp[10] + (temp[11] << 8); | 853 | if (op != NO_OP && log_recover(log, op)) { |
176 | good = 0; | 854 | log_close(log); |
177 | while (xlen) { | 855 | return -1; |
178 | if (xlen < 4 || read(log->fd, temp, 4) != 4) | ||
179 | break; | ||
180 | sub_len = temp[2]; | ||
181 | sub_len += temp[3] << 8; | ||
182 | xlen -= 4; | ||
183 | if (memcmp(temp, "ap", 2) == 0 && sub_len == 16) { | ||
184 | good = 1; | ||
185 | break; | ||
186 | } | ||
187 | if (xlen < sub_len) | ||
188 | break; | ||
189 | (void)lseek(log->fd, sub_len, SEEK_CUR); | ||
190 | xlen -= sub_len; | ||
191 | } | 856 | } |
192 | if (!good) { | 857 | |
193 | log_clean(log); | 858 | /* touch the lock file to prevent another process from grabbing it */ |
859 | log_touch(log); | ||
860 | return 0; | ||
861 | } | ||
862 | |||
863 | /* See gzlog.h for the description of the external methods below */ | ||
864 | gzlog *gzlog_open(char *path) | ||
865 | { | ||
866 | size_t n; | ||
867 | struct log *log; | ||
868 | |||
869 | /* check arguments */ | ||
870 | if (path == NULL || *path == 0) | ||
194 | return NULL; | 871 | return NULL; |
195 | } | ||
196 | 872 | ||
197 | /* read in "ap" sub-field */ | 873 | /* allocate and initialize log structure */ |
198 | log->extra = lseek(log->fd, 0, SEEK_CUR); | 874 | log = malloc(sizeof(struct log)); |
199 | if (read(log->fd, temp, 16) != 16) { | 875 | if (log == NULL) |
200 | log_clean(log); | 876 | return NULL; |
877 | strcpy(log->id, LOGID); | ||
878 | log->fd = -1; | ||
879 | |||
880 | /* save path and end of path for name construction */ | ||
881 | n = strlen(path); | ||
882 | log->path = malloc(n + 9); /* allow for ".repairs" */ | ||
883 | if (log->path == NULL) { | ||
884 | free(log); | ||
201 | return NULL; | 885 | return NULL; |
202 | } | 886 | } |
203 | log->mark_off = make_off(temp); | 887 | strcpy(log->path, path); |
204 | log->last_off = make_off(temp + 8); | 888 | log->end = log->path + n; |
205 | 889 | ||
206 | /* get crc, length of gzip file */ | 890 | /* gain exclusive access and verify log file -- may perform a |
207 | (void)lseek(log->fd, log->last_off, SEEK_SET); | 891 | recovery operation if needed */ |
208 | if (read(log->fd, temp, 13) != 13 || | 892 | if (log_open(log)) { |
209 | memcmp(temp, "\001\000\000\377\377", 5) != 0) { | 893 | free(log->path); |
210 | log_clean(log); | 894 | free(log); |
211 | return NULL; | 895 | return NULL; |
212 | } | 896 | } |
213 | log->crc = make_ulg(temp + 5); | ||
214 | log->len = make_ulg(temp + 9); | ||
215 | 897 | ||
216 | /* set up to write over empty last block */ | 898 | /* return pointer to log structure */ |
217 | (void)lseek(log->fd, log->last_off + 5, SEEK_SET); | 899 | return log; |
218 | log->stored = 0; | ||
219 | return (void *)log; | ||
220 | } | 900 | } |
221 | 901 | ||
222 | /* maximum amount to put in a stored block before starting a new one */ | 902 | /* gzlog_compress() return values: |
223 | #define MAX_BLOCK 16384 | 903 | 0: all good |
224 | 904 | -1: file i/o error (usually access issue) | |
225 | /* write a block to a log object */ | 905 | -2: memory allocation failure |
226 | int gzlog_write(void *obj, char *data, size_t len) | 906 | -3: invalid log pointer argument */ |
907 | int gzlog_compress(gzlog *logd) | ||
227 | { | 908 | { |
228 | size_t some; | 909 | int fd, ret; |
229 | unsigned char temp[5]; | 910 | uint block; |
230 | gz_log *log; | 911 | size_t len, next; |
912 | unsigned char *data, buf[5]; | ||
913 | struct log *log = logd; | ||
231 | 914 | ||
232 | /* check object */ | 915 | /* check arguments */ |
233 | log = (gz_log *)obj; | 916 | if (log == NULL || strcmp(log->id, LOGID) || len < 0) |
234 | if (log == NULL || log->id != GZLOGID) | 917 | return -3; |
235 | return 1; | ||
236 | 918 | ||
237 | /* write stored blocks until all of the input is written */ | 919 | /* see if we lost the lock -- if so get it again and reload the extra |
238 | do { | 920 | field information (it probably changed), recover last operation if |
239 | some = MAX_BLOCK - log->stored; | 921 | necessary */ |
240 | if (some > len) | 922 | if (log_check(log) && log_open(log)) |
241 | some = len; | 923 | return -1; |
242 | if (write(log->fd, data, some) != some) | ||
243 | return 1; | ||
244 | log->crc = crc32(log->crc, (unsigned char *)data, some); | ||
245 | log->len += some; | ||
246 | len -= some; | ||
247 | data += some; | ||
248 | log->stored += some; | ||
249 | |||
250 | /* if the stored block is full, end it and start another */ | ||
251 | if (log->stored == MAX_BLOCK) { | ||
252 | (void)lseek(log->fd, log->last_off, SEEK_SET); | ||
253 | temp[0] = 0; | ||
254 | dice_ulg(log->stored + ((unsigned long)(~log->stored) << 16), | ||
255 | temp + 1); | ||
256 | if (write(log->fd, temp, 5) != 5) | ||
257 | return 1; | ||
258 | log->last_off = lseek(log->fd, log->stored, SEEK_CUR); | ||
259 | (void)lseek(log->fd, 5, SEEK_CUR); | ||
260 | log->stored = 0; | ||
261 | } | ||
262 | } while (len); | ||
263 | return 0; | ||
264 | } | ||
265 | 924 | ||
266 | /* recompress the remaining stored deflate data in place */ | 925 | /* create space for uncompressed data */ |
267 | local int recomp(gz_log *log) | 926 | len = ((size_t)(log->last - log->first) & ~(((size_t)1 << 10) - 1)) + |
268 | { | 927 | log->stored; |
269 | z_stream strm; | 928 | if ((data = malloc(len)) == NULL) |
270 | size_t len, max; | 929 | return -2; |
271 | unsigned char *in; | ||
272 | unsigned char *out; | ||
273 | unsigned char temp[16]; | ||
274 | |||
275 | /* allocate space and read it all in (it's around 1 MB) */ | ||
276 | len = log->last_off - log->mark_off; | ||
277 | max = len + (len >> 12) + (len >> 14) + 11; | ||
278 | out = malloc(max); | ||
279 | if (out == NULL) | ||
280 | return 1; | ||
281 | in = malloc(len); | ||
282 | if (in == NULL) { | ||
283 | free(out); | ||
284 | return 1; | ||
285 | } | ||
286 | (void)lseek(log->fd, log->mark_off, SEEK_SET); | ||
287 | if (read(log->fd, in, len) != len) { | ||
288 | free(in); | ||
289 | free(out); | ||
290 | return 1; | ||
291 | } | ||
292 | 930 | ||
293 | /* recompress in memory, decoding stored data as we go */ | 931 | /* do statement here is just a cheap trick for error handling */ |
294 | /* note: this assumes that unsigned is four bytes or more */ | 932 | do { |
295 | /* consider not making that assumption */ | 933 | /* read in the uncompressed data */ |
296 | strm.zalloc = Z_NULL; | 934 | if (lseek(log->fd, log->first - 1, SEEK_SET) < 0) |
297 | strm.zfree = Z_NULL; | ||
298 | strm.opaque = Z_NULL; | ||
299 | if (deflateInit2(&strm, Z_BEST_COMPRESSION, Z_DEFLATED, -15, 8, | ||
300 | Z_DEFAULT_STRATEGY) != Z_OK) { | ||
301 | free(in); | ||
302 | free(out); | ||
303 | return 1; | ||
304 | } | ||
305 | strm.next_in = in; | ||
306 | strm.avail_out = max; | ||
307 | strm.next_out = out; | ||
308 | while (len >= 5) { | ||
309 | if (strm.next_in[0] != 0) | ||
310 | break; | 935 | break; |
311 | strm.avail_in = strm.next_in[1] + (strm.next_in[2] << 8); | 936 | next = 0; |
312 | strm.next_in += 5; | 937 | while (next < len) { |
313 | len -= 5; | 938 | if (read(log->fd, buf, 5) != 5) |
314 | if (strm.avail_in != 0) { | ||
315 | if (len < strm.avail_in) | ||
316 | break; | 939 | break; |
317 | len -= strm.avail_in; | 940 | block = PULL2(buf + 1); |
318 | (void)deflate(&strm, Z_NO_FLUSH); | 941 | if (next + block > len || |
319 | if (strm.avail_in != 0 || strm.avail_out == 0) | 942 | read(log->fd, (char *)data + next, block) != block) |
320 | break; | 943 | break; |
944 | next += block; | ||
321 | } | 945 | } |
322 | } | 946 | if (lseek(log->fd, 0, SEEK_CUR) != log->last + 4 + log->stored) |
323 | (void)deflate(&strm, Z_SYNC_FLUSH); | 947 | break; |
324 | (void)deflateEnd(&strm); | 948 | log_touch(log); |
325 | free(in); | ||
326 | if (len != 0 || strm.avail_out == 0) { | ||
327 | free(out); | ||
328 | return 1; | ||
329 | } | ||
330 | 949 | ||
331 | /* overwrite stored data with compressed data */ | 950 | /* write the uncompressed data to the .add file */ |
332 | (void)lseek(log->fd, log->mark_off, SEEK_SET); | 951 | strcpy(log->end, ".add"); |
333 | len = max - strm.avail_out; | 952 | fd = open(log->path, O_WRONLY | O_CREAT | O_TRUNC, 0644); |
334 | if (write(log->fd, out, len) != len) { | 953 | if (fd < 0) |
335 | free(out); | 954 | break; |
336 | return 1; | 955 | ret = write(fd, data, len) != len; |
337 | } | 956 | if (ret | close(fd)) |
338 | free(out); | 957 | break; |
339 | 958 | log_touch(log); | |
340 | /* write last empty block, crc, and length */ | ||
341 | log->mark_off = log->last_off = lseek(log->fd, 0, SEEK_CUR); | ||
342 | temp[0] = 1; | ||
343 | dice_ulg(0xffffL << 16, temp + 1); | ||
344 | dice_ulg(log->crc, temp + 5); | ||
345 | dice_ulg(log->len, temp + 9); | ||
346 | if (write(log->fd, temp, 13) != 13) | ||
347 | return 1; | ||
348 | 959 | ||
349 | /* truncate file to discard remaining stored data and old trailer */ | 960 | /* write the dictionary for the next compress to the .temp file */ |
350 | ftruncate(log->fd, lseek(log->fd, 0, SEEK_CUR)); | 961 | strcpy(log->end, ".temp"); |
962 | fd = open(log->path, O_WRONLY | O_CREAT | O_TRUNC, 0644); | ||
963 | if (fd < 0) | ||
964 | break; | ||
965 | next = DICT > len ? len : DICT; | ||
966 | ret = write(fd, (char *)data + len - next, next) != next; | ||
967 | if (ret | close(fd)) | ||
968 | break; | ||
969 | log_touch(log); | ||
351 | 970 | ||
352 | /* update extra field to point to new last empty block */ | 971 | /* roll back to compressed data, mark the compress in progress */ |
353 | (void)lseek(log->fd, log->extra, SEEK_SET); | 972 | log->last = log->first; |
354 | dice_off(log->mark_off, temp); | 973 | log->stored = 0; |
355 | dice_off(log->last_off, temp + 8); | 974 | if (log_mark(log, COMPRESS_OP)) |
356 | if (write(log->fd, temp, 16) != 16) | 975 | break; |
357 | return 1; | 976 | BAIL(7); |
358 | return 0; | 977 | |
359 | } | 978 | /* compress and append the data (clears mark) */ |
979 | ret = log_compress(log, data, len); | ||
980 | free(data); | ||
981 | return ret; | ||
982 | } while (0); | ||
360 | 983 | ||
361 | /* maximum accumulation of stored blocks before compressing */ | 984 | /* broke out of do above on i/o error */ |
362 | #define MAX_STORED 1048576 | 985 | free(data); |
986 | return -1; | ||
987 | } | ||
363 | 988 | ||
364 | /* close log object */ | 989 | /* gzlog_write() return values: |
365 | int gzlog_close(void *obj) | 990 | 0: all good |
991 | -1: file i/o error (usually access issue) | ||
992 | -2: memory allocation failure | ||
993 | -3: invalid log pointer argument */ | ||
994 | int gzlog_write(gzlog *logd, void *data, size_t len) | ||
366 | { | 995 | { |
367 | unsigned char temp[8]; | 996 | int fd, ret; |
368 | gz_log *log; | 997 | struct log *log = logd; |
369 | 998 | ||
370 | /* check object */ | 999 | /* check arguments */ |
371 | log = (gz_log *)obj; | 1000 | if (log == NULL || strcmp(log->id, LOGID) || len < 0) |
372 | if (log == NULL || log->id != GZLOGID) | 1001 | return -3; |
373 | return 1; | 1002 | if (data == NULL || len == 0) |
1003 | return 0; | ||
374 | 1004 | ||
375 | /* go to start of most recent block being written */ | 1005 | /* see if we lost the lock -- if so get it again and reload the extra |
376 | (void)lseek(log->fd, log->last_off, SEEK_SET); | 1006 | field information (it probably changed), recover last operation if |
377 | 1007 | necessary */ | |
378 | /* if some stuff was put there, update block */ | 1008 | if (log_check(log) && log_open(log)) |
379 | if (log->stored) { | 1009 | return -1; |
380 | temp[0] = 0; | ||
381 | dice_ulg(log->stored + ((unsigned long)(~log->stored) << 16), | ||
382 | temp + 1); | ||
383 | if (write(log->fd, temp, 5) != 5) | ||
384 | return 1; | ||
385 | log->last_off = lseek(log->fd, log->stored, SEEK_CUR); | ||
386 | } | ||
387 | 1010 | ||
388 | /* write last block (empty) */ | 1011 | /* create and write .add file */ |
389 | if (write(log->fd, "\001\000\000\377\377", 5) != 5) | 1012 | strcpy(log->end, ".add"); |
390 | return 1; | 1013 | fd = open(log->path, O_WRONLY | O_CREAT | O_TRUNC, 0644); |
1014 | if (fd < 0) | ||
1015 | return -1; | ||
1016 | ret = write(fd, data, len) != len; | ||
1017 | if (ret | close(fd)) | ||
1018 | return -1; | ||
1019 | log_touch(log); | ||
391 | 1020 | ||
392 | /* write updated crc and uncompressed length */ | 1021 | /* mark log file with append in progress */ |
393 | dice_ulg(log->crc, temp); | 1022 | if (log_mark(log, APPEND_OP)) |
394 | dice_ulg(log->len, temp + 4); | 1023 | return -1; |
395 | if (write(log->fd, temp, 8) != 8) | 1024 | BAIL(8); |
396 | return 1; | ||
397 | 1025 | ||
398 | /* put offset of that last block in gzip extra block */ | 1026 | /* append data (clears mark) */ |
399 | (void)lseek(log->fd, log->extra + 8, SEEK_SET); | 1027 | if (log_append(log, data, len)) |
400 | dice_off(log->last_off, temp); | 1028 | return -1; |
401 | if (write(log->fd, temp, 8) != 8) | ||
402 | return 1; | ||
403 | 1029 | ||
404 | /* if more than 1 MB stored, then time to compress it */ | 1030 | /* check to see if it's time to compress -- if not, then done */ |
405 | if (log->last_off - log->mark_off > MAX_STORED) { | 1031 | if (((log->last - log->first) >> 10) + (log->stored >> 10) < TRIGGER) |
406 | if (recomp(log)) | 1032 | return 0; |
407 | return 1; | 1033 | |
408 | } | 1034 | /* time to compress */ |
1035 | return gzlog_compress(log); | ||
1036 | } | ||
1037 | |||
1038 | /* gzlog_close() return values: | ||
1039 | 0: ok | ||
1040 | -3: invalid log pointer argument */ | ||
1041 | int gzlog_close(gzlog *logd) | ||
1042 | { | ||
1043 | struct log *log = logd; | ||
409 | 1044 | ||
410 | /* unlock and close file */ | 1045 | /* check arguments */ |
411 | log_clean(log); | 1046 | if (log == NULL || strcmp(log->id, LOGID)) |
1047 | return -3; | ||
1048 | |||
1049 | /* close the log file and release the lock */ | ||
1050 | log_close(log); | ||
1051 | |||
1052 | /* free structure and return */ | ||
1053 | if (log->path != NULL) | ||
1054 | free(log->path); | ||
1055 | strcpy(log->id, "bad"); | ||
1056 | free(log); | ||
412 | return 0; | 1057 | return 0; |
413 | } | 1058 | } |
diff --git a/examples/gzlog.h b/examples/gzlog.h index a800bd5..c461426 100644 --- a/examples/gzlog.h +++ b/examples/gzlog.h | |||
@@ -1,6 +1,6 @@ | |||
1 | /* gzlog.h | 1 | /* gzlog.h |
2 | Copyright (C) 2004 Mark Adler, all rights reserved | 2 | Copyright (C) 2004, 2008 Mark Adler, all rights reserved |
3 | version 1.0, 26 Nov 2004 | 3 | version 2.0, 25 Apr 2008 |
4 | 4 | ||
5 | This software is provided 'as-is', without any express or implied | 5 | This software is provided 'as-is', without any express or implied |
6 | warranty. In no event will the author be held liable for any damages | 6 | warranty. In no event will the author be held liable for any damages |
@@ -21,38 +21,69 @@ | |||
21 | Mark Adler madler@alumni.caltech.edu | 21 | Mark Adler madler@alumni.caltech.edu |
22 | */ | 22 | */ |
23 | 23 | ||
24 | /* Version History: | ||
25 | 1.0 26 Nov 2004 First version | ||
26 | 2.0 25 Apr 2008 Complete redesign for recovery of interrupted operations | ||
27 | Interface changed slightly in that now path is a prefix | ||
28 | Compression now occurs as needed during gzlog_write() | ||
29 | gzlog_write() now always leaves the log file as valid gzip | ||
30 | */ | ||
31 | |||
24 | /* | 32 | /* |
25 | The gzlog object allows writing short messages to a gzipped log file, | 33 | The gzlog object allows writing short messages to a gzipped log file, |
26 | opening the log file locked for small bursts, and then closing it. The log | 34 | opening the log file locked for small bursts, and then closing it. The log |
27 | object works by appending stored data to the gzip file until 1 MB has been | 35 | object works by appending stored (uncompressed) data to the gzip file until |
28 | accumulated. At that time, the stored data is compressed, and replaces the | 36 | 1 MB has been accumulated. At that time, the stored data is compressed, and |
29 | uncompressed data in the file. The log file is truncated to its new size at | 37 | replaces the uncompressed data in the file. The log file is truncated to |
30 | that time. After closing, the log file is always valid gzip file that can | 38 | its new size at that time. After each write operation, the log file is a |
31 | decompressed to recover what was written. | 39 | valid gzip file that can decompressed to recover what was written. |
32 | 40 | ||
33 | A gzip header "extra" field contains two file offsets for appending. The | 41 | The gzlog operations can be interupted at any point due to an application or |
34 | first points to just after the last compressed data. The second points to | 42 | system crash, and the log file will be recovered the next time the log is |
35 | the last stored block in the deflate stream, which is empty. All of the | 43 | opened with gzlog_open(). |
36 | data between those pointers is uncompressed. | ||
37 | */ | 44 | */ |
38 | 45 | ||
46 | #ifndef GZLOG_H | ||
47 | #define GZLOG_H | ||
48 | |||
49 | /* gzlog object type */ | ||
50 | typedef void gzlog; | ||
51 | |||
39 | /* Open a gzlog object, creating the log file if it does not exist. Return | 52 | /* Open a gzlog object, creating the log file if it does not exist. Return |
40 | NULL on error. Note that gzlog_open() could take a long time to return if | 53 | NULL on error. Note that gzlog_open() could take a while to complete if it |
41 | there is difficulty in locking the file. */ | 54 | has to wait to verify that a lock is stale (possibly for five minutes), or |
42 | void *gzlog_open(char *path); | 55 | if there is significant contention with other instantiations of this object |
43 | 56 | when locking the resource. path is the prefix of the file names created by | |
44 | /* Write to a gzlog object. Return non-zero on error. This function will | 57 | this object. If path is "foo", then the log file will be "foo.gz", and |
45 | simply write data to the file uncompressed. Compression of the data | 58 | other auxiliary files will be created and destroyed during the process: |
46 | will not occur until gzlog_close() is called. It is expected that | 59 | "foo.dict" for a compression dictionary, "foo.temp" for a temporary (next) |
47 | gzlog_write() is used for a short message, and then gzlog_close() is | 60 | dictionary, "foo.add" for data being added or compressed, "foo.lock" for the |
48 | called. If a large amount of data is to be written, then the application | 61 | lock file, and "foo.repairs" to log recovery operations performed due to |
49 | should write no more than 1 MB at a time with gzlog_write() before | 62 | interrupted gzlog operations. A gzlog_open() followed by a gzlog_close() |
50 | calling gzlog_close() and then gzlog_open() again. */ | 63 | will recover a previously interrupted operation, if any. */ |
51 | int gzlog_write(void *log, char *data, size_t len); | 64 | gzlog *gzlog_open(char *path); |
52 | 65 | ||
53 | /* Close a gzlog object. Return non-zero on error. The log file is locked | 66 | /* Write to a gzlog object. Return zero on success, -1 if there is a file i/o |
54 | until this function is called. This function will compress stored data | 67 | error on any of the gzlog files (this should not happen if gzlog_open() |
55 | at the end of the gzip file if at least 1 MB has been accumulated. Note | 68 | succeeded, unless the device has run out of space or leftover auxiliary |
56 | that the file will not be a valid gzip file until this function completes. | 69 | files have permissions or ownership that prevent their use), -2 if there is |
57 | */ | 70 | a memory allocation failure, or -3 if the log argument is invalid (e.g. if |
58 | int gzlog_close(void *log); | 71 | it was not created by gzlog_open()). This function will write data to the |
72 | file uncompressed, until 1 MB has been accumulated, at which time that data | ||
73 | will be compressed. The log file will be a valid gzip file upon successful | ||
74 | return. */ | ||
75 | int gzlog_write(gzlog *log, void *data, size_t len); | ||
76 | |||
77 | /* Force compression of any uncompressed data in the log. This should be used | ||
78 | sparingly, if at all. The main application would be when a log file will | ||
79 | not be appended to again. If this is used to compress frequently while | ||
80 | appending, it will both significantly increase the execution time and | ||
81 | reduce the compression ratio. The return codes are the same as for | ||
82 | gzlog_write(). */ | ||
83 | int gzlog_compress(gzlog *log); | ||
84 | |||
85 | /* Close a gzlog object. Return zero on success, -3 if the log argument is | ||
86 | invalid. The log object is freed, and so cannot be referenced again. */ | ||
87 | int gzlog_close(gzlog *log); | ||
88 | |||
89 | #endif | ||
diff --git a/examples/pigz.c b/examples/pigz.c new file mode 100644 index 0000000..42794d0 --- /dev/null +++ b/examples/pigz.c | |||
@@ -0,0 +1,452 @@ | |||
1 | /* pigz.c -- parallel implementation of gzip | ||
2 | * Copyright (C) 2007 Mark Adler | ||
3 | * Version 1.1 28 January 2007 Mark Adler | ||
4 | */ | ||
5 | |||
6 | /* Version history: | ||
7 | 1.0 17 Jan 2007 First version | ||
8 | 1.1 28 Jan 2007 Avoid void * arithmetic (some compilers don't get that) | ||
9 | Add note about requiring zlib 1.2.3 | ||
10 | Allow compression level 0 (no compression) | ||
11 | Completely rewrite parallelism -- add a write thread | ||
12 | Use deflateSetDictionary() to make use of history | ||
13 | Tune argument defaults to best performance on four cores | ||
14 | */ | ||
15 | |||
16 | /* | ||
17 | pigz compresses from stdin to stdout using threads to make use of multiple | ||
18 | processors and cores. The input is broken up into 128 KB chunks, and each | ||
19 | is compressed separately. The CRC for each chunk is also calculated | ||
20 | separately. The compressed chunks are written in order to the output, | ||
21 | and the overall CRC is calculated from the CRC's of the chunks. | ||
22 | |||
23 | The compressed data format generated is the gzip format using the deflate | ||
24 | compression method. First a gzip header is written, followed by raw deflate | ||
25 | partial streams. They are partial, in that they do not have a terminating | ||
26 | block. At the end, the deflate stream is terminated with a final empty | ||
27 | static block, and lastly a gzip trailer is written with the CRC and the | ||
28 | number of input bytes. | ||
29 | |||
30 | Each raw deflate partial stream is terminated by an empty stored block | ||
31 | (using the Z_SYNC_FLUSH option of zlib), in order to end that partial | ||
32 | bit stream at a byte boundary. That allows the partial streams to be | ||
33 | concantenated simply as sequences of bytes. This adds a very small four | ||
34 | or five byte overhead to the output for each input chunk. | ||
35 | |||
36 | zlib's crc32_combine() routine allows the calcuation of the CRC of the | ||
37 | entire input using the independent CRC's of the chunks. pigz requires zlib | ||
38 | version 1.2.3 or later, since that is the first version that provides the | ||
39 | crc32_combine() function. | ||
40 | |||
41 | pigz uses the POSIX pthread library for thread control and communication. | ||
42 | */ | ||
43 | |||
44 | #include <stdio.h> | ||
45 | #include <stdlib.h> | ||
46 | #include <string.h> | ||
47 | #include <pthread.h> | ||
48 | #include <sys/types.h> | ||
49 | #include <sys/uio.h> | ||
50 | #include <unistd.h> | ||
51 | #include "zlib.h" | ||
52 | |||
53 | #define local static | ||
54 | |||
55 | /* exit with error */ | ||
56 | local void bail(char *msg) | ||
57 | { | ||
58 | fprintf(stderr, "pigz abort: %s\n", msg); | ||
59 | exit(1); | ||
60 | } | ||
61 | |||
62 | /* read up to len bytes into buf, repeating read() calls as needed */ | ||
63 | local size_t readn(int desc, unsigned char *buf, size_t len) | ||
64 | { | ||
65 | ssize_t ret; | ||
66 | size_t got; | ||
67 | |||
68 | got = 0; | ||
69 | while (len) { | ||
70 | ret = read(desc, buf, len); | ||
71 | if (ret < 0) | ||
72 | bail("read error"); | ||
73 | if (ret == 0) | ||
74 | break; | ||
75 | buf += ret; | ||
76 | len -= ret; | ||
77 | got += ret; | ||
78 | } | ||
79 | return got; | ||
80 | } | ||
81 | |||
82 | /* write len bytes, repeating write() calls as needed */ | ||
83 | local void writen(int desc, unsigned char *buf, size_t len) | ||
84 | { | ||
85 | ssize_t ret; | ||
86 | |||
87 | while (len) { | ||
88 | ret = write(desc, buf, len); | ||
89 | if (ret < 1) | ||
90 | bail("write error"); | ||
91 | buf += ret; | ||
92 | len -= ret; | ||
93 | } | ||
94 | } | ||
95 | |||
96 | /* a flag variable for communication between two threads */ | ||
97 | struct flag { | ||
98 | int value; /* value of flag */ | ||
99 | pthread_mutex_t lock; /* lock for checking and changing flag */ | ||
100 | pthread_cond_t cond; /* condition for signaling on flag change */ | ||
101 | }; | ||
102 | |||
103 | /* initialize a flag for use, starting with value val */ | ||
104 | local void flag_init(struct flag *me, int val) | ||
105 | { | ||
106 | me->value = val; | ||
107 | pthread_mutex_init(&(me->lock), NULL); | ||
108 | pthread_cond_init(&(me->cond), NULL); | ||
109 | } | ||
110 | |||
111 | /* set the flag to val, signal another process that may be waiting for it */ | ||
112 | local void flag_set(struct flag *me, int val) | ||
113 | { | ||
114 | pthread_mutex_lock(&(me->lock)); | ||
115 | me->value = val; | ||
116 | pthread_cond_signal(&(me->cond)); | ||
117 | pthread_mutex_unlock(&(me->lock)); | ||
118 | } | ||
119 | |||
120 | /* if it isn't already, wait for some other thread to set the flag to val */ | ||
121 | local void flag_wait(struct flag *me, int val) | ||
122 | { | ||
123 | pthread_mutex_lock(&(me->lock)); | ||
124 | while (me->value != val) | ||
125 | pthread_cond_wait(&(me->cond), &(me->lock)); | ||
126 | pthread_mutex_unlock(&(me->lock)); | ||
127 | } | ||
128 | |||
129 | /* if flag is equal to val, wait for some other thread to change it */ | ||
130 | local void flag_wait_not(struct flag *me, int val) | ||
131 | { | ||
132 | pthread_mutex_lock(&(me->lock)); | ||
133 | while (me->value == val) | ||
134 | pthread_cond_wait(&(me->cond), &(me->lock)); | ||
135 | pthread_mutex_unlock(&(me->lock)); | ||
136 | } | ||
137 | |||
138 | /* clean up the flag when done with it */ | ||
139 | local void flag_done(struct flag *me) | ||
140 | { | ||
141 | pthread_cond_destroy(&(me->cond)); | ||
142 | pthread_mutex_destroy(&(me->lock)); | ||
143 | } | ||
144 | |||
145 | /* a unit of work to feed to compress_thread() -- it is assumed that the out | ||
146 | buffer is large enough to hold the maximum size len bytes could deflate to, | ||
147 | plus five bytes for the final sync marker */ | ||
148 | struct work { | ||
149 | size_t len; /* length of input */ | ||
150 | unsigned long crc; /* crc of input */ | ||
151 | unsigned char *buf; /* input */ | ||
152 | unsigned char *out; /* space for output (guaranteed big enough) */ | ||
153 | z_stream strm; /* pre-initialized z_stream */ | ||
154 | struct flag busy; /* busy flag indicating work unit in use */ | ||
155 | pthread_t comp; /* this compression thread */ | ||
156 | }; | ||
157 | |||
158 | /* busy flag values */ | ||
159 | #define IDLE 0 /* compress and writing done -- can start compress */ | ||
160 | #define COMP 1 /* compress -- input and output buffers in use */ | ||
161 | #define WRITE 2 /* compress done, writing output -- can read input */ | ||
162 | |||
163 | /* read-only globals (set by main/read thread before others started) */ | ||
164 | local int ind; /* input file descriptor */ | ||
165 | local int outd; /* output file descriptor */ | ||
166 | local int level; /* compression level */ | ||
167 | local int procs; /* number of compression threads (>= 2) */ | ||
168 | local size_t size; /* uncompressed input size per thread (>= 32K) */ | ||
169 | local struct work *jobs; /* work units: jobs[0..procs-1] */ | ||
170 | |||
171 | /* next and previous jobs[] indices */ | ||
172 | #define NEXT(n) ((n) == procs - 1 ? 0 : (n) + 1) | ||
173 | #define PREV(n) ((n) == 0 ? procs - 1 : (n) - 1) | ||
174 | |||
175 | /* sliding dictionary size for deflate */ | ||
176 | #define DICT 32768U | ||
177 | |||
178 | /* largest power of 2 that fits in an unsigned int -- used to limit requests | ||
179 | to zlib functions that use unsigned int lengths */ | ||
180 | #define MAX ((((unsigned)-1) >> 1) + 1) | ||
181 | |||
182 | /* compress thread: compress the input in the provided work unit and compute | ||
183 | its crc -- assume that the amount of space at job->out is guaranteed to be | ||
184 | enough for the compressed output, as determined by the maximum expansion | ||
185 | of deflate compression -- use the input in the previous work unit (if there | ||
186 | is one) to set the deflate dictionary for better compression */ | ||
187 | local void *compress_thread(void *arg) | ||
188 | { | ||
189 | size_t len; /* input length for this work unit */ | ||
190 | unsigned long crc; /* crc of input data */ | ||
191 | struct work *prev; /* previous work unit */ | ||
192 | struct work *job = arg; /* work unit for this thread */ | ||
193 | z_stream *strm = &(job->strm); /* zlib stream for this work unit */ | ||
194 | |||
195 | /* reset state for a new compressed stream */ | ||
196 | (void)deflateReset(strm); | ||
197 | |||
198 | /* initialize input, output, and crc */ | ||
199 | strm->next_in = job->buf; | ||
200 | strm->next_out = job->out; | ||
201 | len = job->len; | ||
202 | crc = crc32(0L, Z_NULL, 0); | ||
203 | |||
204 | /* set dictionary if this isn't the first work unit, and if we will be | ||
205 | compressing something (the read thread assures that the dictionary | ||
206 | data in the previous work unit is still there) */ | ||
207 | prev = jobs + PREV(job - jobs); | ||
208 | if (prev->buf != NULL && len != 0) | ||
209 | deflateSetDictionary(strm, prev->buf + (size - DICT), DICT); | ||
210 | |||
211 | /* run MAX-sized amounts of input through deflate and crc32 -- this loop | ||
212 | is needed for those cases where the integer type is smaller than the | ||
213 | size_t type, or when len is close to the limit of the size_t type */ | ||
214 | while (len > MAX) { | ||
215 | strm->avail_in = MAX; | ||
216 | strm->avail_out = (unsigned)-1; | ||
217 | crc = crc32(crc, strm->next_in, strm->avail_in); | ||
218 | (void)deflate(strm, Z_NO_FLUSH); | ||
219 | len -= MAX; | ||
220 | } | ||
221 | |||
222 | /* run last piece through deflate and crc32, follow with a sync marker */ | ||
223 | if (len) { | ||
224 | strm->avail_in = len; | ||
225 | strm->avail_out = (unsigned)-1; | ||
226 | crc = crc32(crc, strm->next_in, strm->avail_in); | ||
227 | (void)deflate(strm, Z_SYNC_FLUSH); | ||
228 | } | ||
229 | |||
230 | /* don't need to Z_FINISH, since we'd delete the last two bytes anyway */ | ||
231 | |||
232 | /* return result */ | ||
233 | job->crc = crc; | ||
234 | return NULL; | ||
235 | } | ||
236 | |||
237 | /* put a 4-byte integer into a byte array in LSB order */ | ||
238 | #define PUT4(a,b) (*(a)=(b),(a)[1]=(b)>>8,(a)[2]=(b)>>16,(a)[3]=(b)>>24) | ||
239 | |||
240 | /* write thread: wait for compression threads to complete, write output in | ||
241 | order, also write gzip header and trailer around the compressed data */ | ||
242 | local void *write_thread(void *arg) | ||
243 | { | ||
244 | int n; /* compress thread index */ | ||
245 | size_t len; /* length of input processed */ | ||
246 | unsigned long tot; /* total uncompressed size (overflow ok) */ | ||
247 | unsigned long crc; /* CRC-32 of uncompressed data */ | ||
248 | unsigned char wrap[10]; /* gzip header or trailer */ | ||
249 | |||
250 | /* write simple gzip header */ | ||
251 | memcpy(wrap, "\037\213\10\0\0\0\0\0\0\3", 10); | ||
252 | wrap[8] = level == 9 ? 2 : (level == 1 ? 4 : 0); | ||
253 | writen(outd, wrap, 10); | ||
254 | |||
255 | /* process output of compress threads until end of input */ | ||
256 | tot = 0; | ||
257 | crc = crc32(0L, Z_NULL, 0); | ||
258 | n = 0; | ||
259 | do { | ||
260 | /* wait for compress thread to start, then wait to complete */ | ||
261 | flag_wait(&(jobs[n].busy), COMP); | ||
262 | pthread_join(jobs[n].comp, NULL); | ||
263 | |||
264 | /* now that compress is done, allow read thread to use input buffer */ | ||
265 | flag_set(&(jobs[n].busy), WRITE); | ||
266 | |||
267 | /* write compressed data and update length and crc */ | ||
268 | writen(outd, jobs[n].out, jobs[n].strm.next_out - jobs[n].out); | ||
269 | len = jobs[n].len; | ||
270 | tot += len; | ||
271 | crc = crc32_combine(crc, jobs[n].crc, len); | ||
272 | |||
273 | /* release this work unit and go to the next work unit */ | ||
274 | flag_set(&(jobs[n].busy), IDLE); | ||
275 | n = NEXT(n); | ||
276 | |||
277 | /* an input buffer less than size in length indicates end of input */ | ||
278 | } while (len == size); | ||
279 | |||
280 | /* write final static block and gzip trailer (crc and len mod 2^32) */ | ||
281 | wrap[0] = 3; wrap[1] = 0; | ||
282 | PUT4(wrap + 2, crc); | ||
283 | PUT4(wrap + 6, tot); | ||
284 | writen(outd, wrap, 10); | ||
285 | return NULL; | ||
286 | } | ||
287 | |||
288 | /* one-time initialization of a work unit -- this is where we set the deflate | ||
289 | compression level and request raw deflate, and also where we set the size | ||
290 | of the output buffer to guarantee enough space for a worst-case deflate | ||
291 | ending with a Z_SYNC_FLUSH */ | ||
292 | local void job_init(struct work *job) | ||
293 | { | ||
294 | int ret; /* deflateInit2() return value */ | ||
295 | |||
296 | job->buf = malloc(size); | ||
297 | job->out = malloc(size + (size >> 11) + 10); | ||
298 | job->strm.zfree = Z_NULL; | ||
299 | job->strm.zalloc = Z_NULL; | ||
300 | job->strm.opaque = Z_NULL; | ||
301 | ret = deflateInit2(&(job->strm), level, Z_DEFLATED, -15, 8, | ||
302 | Z_DEFAULT_STRATEGY); | ||
303 | if (job->buf == NULL || job->out == NULL || ret != Z_OK) | ||
304 | bail("not enough memory"); | ||
305 | } | ||
306 | |||
307 | /* compress ind to outd in the gzip format, using multiple threads for the | ||
308 | compression and crc calculation and another thread for writing the output -- | ||
309 | the read thread is the main thread */ | ||
310 | local void read_thread(void) | ||
311 | { | ||
312 | int n; /* general index */ | ||
313 | size_t got; /* amount read */ | ||
314 | pthread_attr_t attr; /* thread attributes (left at defaults) */ | ||
315 | pthread_t write; /* write thread */ | ||
316 | |||
317 | /* set defaults (not all pthread implementations default to joinable) */ | ||
318 | pthread_attr_init(&attr); | ||
319 | pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); | ||
320 | |||
321 | /* allocate and set up work list (individual work units will be initialized | ||
322 | as needed, in case the input is short), assure that allocation size | ||
323 | arithmetic does not overflow */ | ||
324 | if (size + (size >> 11) + 10 < (size >> 11) + 10 || | ||
325 | (ssize_t)(size + (size >> 11) + 10) < 0 || | ||
326 | ((size_t)0 - 1) / procs <= sizeof(struct work) || | ||
327 | (jobs = malloc(procs * sizeof(struct work))) == NULL) | ||
328 | bail("not enough memory"); | ||
329 | for (n = 0; n < procs; n++) { | ||
330 | jobs[n].buf = NULL; | ||
331 | flag_init(&(jobs[n].busy), IDLE); | ||
332 | } | ||
333 | |||
334 | /* start write thread */ | ||
335 | pthread_create(&write, &attr, write_thread, NULL); | ||
336 | |||
337 | /* read from input and start compress threads (write thread will pick up | ||
338 | the output of the compress threads) */ | ||
339 | n = 0; | ||
340 | do { | ||
341 | /* initialize this work unit if it's the first time it's used */ | ||
342 | if (jobs[n].buf == NULL) | ||
343 | job_init(jobs + n); | ||
344 | |||
345 | /* read input data, but wait for last compress on this work unit to be | ||
346 | done, and wait for the dictionary to be used by the last compress on | ||
347 | the next work unit */ | ||
348 | flag_wait_not(&(jobs[n].busy), COMP); | ||
349 | flag_wait_not(&(jobs[NEXT(n)].busy), COMP); | ||
350 | got = readn(ind, jobs[n].buf, size); | ||
351 | |||
352 | /* start compress thread, but wait for write to be done first */ | ||
353 | flag_wait(&(jobs[n].busy), IDLE); | ||
354 | jobs[n].len = got; | ||
355 | pthread_create(&(jobs[n].comp), &attr, compress_thread, jobs + n); | ||
356 | |||
357 | /* mark work unit so write thread knows compress was started */ | ||
358 | flag_set(&(jobs[n].busy), COMP); | ||
359 | |||
360 | /* go to the next work unit */ | ||
361 | n = NEXT(n); | ||
362 | |||
363 | /* do until end of input, indicated by a read less than size */ | ||
364 | } while (got == size); | ||
365 | |||
366 | /* wait for the write thread to complete -- the write thread will join with | ||
367 | all of the compress threads, so this waits for all of the threads to | ||
368 | complete */ | ||
369 | pthread_join(write, NULL); | ||
370 | |||
371 | /* free up all requested resources and return */ | ||
372 | for (n = procs - 1; n >= 0; n--) { | ||
373 | flag_done(&(jobs[n].busy)); | ||
374 | (void)deflateEnd(&(jobs[n].strm)); | ||
375 | free(jobs[n].out); | ||
376 | free(jobs[n].buf); | ||
377 | } | ||
378 | free(jobs); | ||
379 | pthread_attr_destroy(&attr); | ||
380 | } | ||
381 | |||
382 | /* Process arguments for level, size, and procs, compress from stdin to | ||
383 | stdout in the gzip format. Note that procs must be at least two in | ||
384 | order to provide a dictionary in one work unit for the other work | ||
385 | unit, and that size must be at least 32K to store a full dictionary. */ | ||
386 | int main(int argc, char **argv) | ||
387 | { | ||
388 | int n; /* general index */ | ||
389 | int get; /* command line parameters to get */ | ||
390 | char *arg; /* command line argument */ | ||
391 | |||
392 | /* set defaults -- 32 processes and 128K buffers was found to provide | ||
393 | good utilization of four cores (about 97%) and balanced the overall | ||
394 | execution time impact of more threads against more dictionary | ||
395 | processing for a fixed amount of memory -- the memory usage for these | ||
396 | settings and full use of all work units (at least 4 MB of input) is | ||
397 | 16.2 MB | ||
398 | */ | ||
399 | level = Z_DEFAULT_COMPRESSION; | ||
400 | procs = 32; | ||
401 | size = 131072UL; | ||
402 | |||
403 | /* process command-line arguments */ | ||
404 | get = 0; | ||
405 | for (n = 1; n < argc; n++) { | ||
406 | arg = argv[n]; | ||
407 | if (*arg == '-') { | ||
408 | while (*++arg) | ||
409 | if (*arg >= '0' && *arg <= '9') /* compression level */ | ||
410 | level = *arg - '0'; | ||
411 | else if (*arg == 'b') /* chunk size in K */ | ||
412 | get |= 1; | ||
413 | else if (*arg == 'p') /* number of processes */ | ||
414 | get |= 2; | ||
415 | else if (*arg == 'h') { /* help */ | ||
416 | fputs("usage: pigz [-0..9] [-b blocksizeinK]", stderr); | ||
417 | fputs(" [-p processes] < foo > foo.gz\n", stderr); | ||
418 | return 0; | ||
419 | } | ||
420 | else | ||
421 | bail("invalid option"); | ||
422 | } | ||
423 | else if (get & 1) { | ||
424 | if (get & 2) | ||
425 | bail("you need to separate the -b and -p options"); | ||
426 | size = (size_t)(atol(arg)) << 10; /* chunk size */ | ||
427 | if (size < DICT) | ||
428 | bail("invalid option"); | ||
429 | get = 0; | ||
430 | } | ||
431 | else if (get & 2) { | ||
432 | procs = atoi(arg); /* processes */ | ||
433 | if (procs < 2) | ||
434 | bail("invalid option"); | ||
435 | get = 0; | ||
436 | } | ||
437 | else | ||
438 | bail("invalid option (you need to pipe input and output)"); | ||
439 | } | ||
440 | if (get) | ||
441 | bail("missing option argument"); | ||
442 | |||
443 | /* do parallel compression from stdin to stdout (the read thread starts up | ||
444 | the write thread and the compression threads, and they all join before | ||
445 | the read thread returns) */ | ||
446 | ind = 0; | ||
447 | outd = 1; | ||
448 | read_thread(); | ||
449 | |||
450 | /* done */ | ||
451 | return 0; | ||
452 | } | ||
@@ -1,5 +1,5 @@ | |||
1 | /* gzio.c -- IO on .gz files | 1 | /* gzio.c -- IO on .gz files |
2 | * Copyright (C) 1995-2006 Jean-loup Gailly. | 2 | * Copyright (C) 1995-2009 Jean-loup Gailly. |
3 | * For conditions of distribution and use, see copyright notice in zlib.h | 3 | * For conditions of distribution and use, see copyright notice in zlib.h |
4 | * | 4 | * |
5 | * Compile this file with -DNO_GZCOMPRESS to avoid the compression code. | 5 | * Compile this file with -DNO_GZCOMPRESS to avoid the compression code. |
@@ -71,43 +71,32 @@ static int const gz_magic[2] = {0x1f, 0x8b}; /* gzip magic header */ | |||
71 | 71 | ||
72 | typedef struct gz_stream { | 72 | typedef struct gz_stream { |
73 | z_stream stream; | 73 | z_stream stream; |
74 | int z_err; /* error code for last stream operation */ | 74 | int z_err; /* error code for last stream operation */ |
75 | int z_eof; /* set if end of input file */ | 75 | int z_eof; /* set if end of input file */ |
76 | FILE *file; /* .gz file */ | 76 | FILE *file; /* .gz file */ |
77 | Byte *inbuf; /* input buffer */ | 77 | Byte *inbuf; /* input buffer */ |
78 | Byte *outbuf; /* output buffer */ | 78 | Byte *outbuf; /* output buffer */ |
79 | uLong crc; /* crc32 of uncompressed data */ | 79 | uLong crc; /* crc32 of uncompressed data */ |
80 | char *msg; /* error message */ | 80 | char *msg; /* error message */ |
81 | char *path; /* path name for debugging only */ | 81 | char *path; /* path name for debugging only */ |
82 | int transparent; /* 1 if input file is not a .gz file */ | 82 | int transparent; /* 1 if input file is not a .gz file */ |
83 | char mode; /* 'w' or 'r' */ | 83 | char mode; /* 'w' or 'r' */ |
84 | #ifdef _LARGEFILE64_SOURCE | 84 | z_off64_t start; /* start of compressed data in file */ |
85 | off64_t start; /* start of compressed data in file (header skipped) */ | 85 | z_off64_t in; /* bytes into deflate or inflate */ |
86 | off64_t in; /* bytes into deflate or inflate */ | 86 | z_off64_t out; /* bytes out of deflate or inflate */ |
87 | off64_t out; /* bytes out of deflate or inflate */ | 87 | int back; /* one character push-back */ |
88 | #else | 88 | int last; /* true if push-back is last character */ |
89 | z_off_t start; /* start of compressed data in file (header skipped) */ | ||
90 | z_off_t in; /* bytes into deflate or inflate */ | ||
91 | z_off_t out; /* bytes out of deflate or inflate */ | ||
92 | #endif | ||
93 | int back; /* one character push-back */ | ||
94 | int last; /* true if push-back is last character */ | ||
95 | } gz_stream; | 89 | } gz_stream; |
96 | 90 | ||
97 | 91 | ||
98 | local gzFile gz_open OF((const char *path, const char *mode, int fd, | 92 | local gzFile gz_open OF((const char *, const char *, int, int)); |
99 | int use64)); | 93 | local z_off64_t gz_seek OF((gzFile, z_off64_t, int, int)); |
100 | #ifdef _LARGEFILE64_SOURCE | 94 | local int do_flush OF((gzFile, int)); |
101 | local off64_t gz_seek OF((gzFile file, off64_t offset, int whence, int use64)); | 95 | local int get_byte OF((gz_stream *)); |
102 | #else | 96 | local void check_header OF((gz_stream *)); |
103 | local z_off_t gz_seek OF((gzFile file, z_off_t offset, int whence, int use64)); | 97 | local int destroy OF((gz_stream *)); |
104 | #endif | 98 | local void putLong OF((FILE *, uLong)); |
105 | local int do_flush OF((gzFile file, int flush)); | 99 | local uLong getLong OF((gz_stream *)); |
106 | local int get_byte OF((gz_stream *s)); | ||
107 | local void check_header OF((gz_stream *s)); | ||
108 | local int destroy OF((gz_stream *s)); | ||
109 | local void putLong OF((FILE *file, uLong x)); | ||
110 | local uLong getLong OF((gz_stream *s)); | ||
111 | 100 | ||
112 | /* =========================================================================== | 101 | /* =========================================================================== |
113 | Opens a gzip (.gz) file for reading or writing. The mode parameter | 102 | Opens a gzip (.gz) file for reading or writing. The mode parameter |
@@ -143,6 +132,7 @@ local gzFile gz_open (path, mode, fd, use64) | |||
143 | s->stream.next_in = s->inbuf = Z_NULL; | 132 | s->stream.next_in = s->inbuf = Z_NULL; |
144 | s->stream.next_out = s->outbuf = Z_NULL; | 133 | s->stream.next_out = s->outbuf = Z_NULL; |
145 | s->stream.avail_in = s->stream.avail_out = 0; | 134 | s->stream.avail_in = s->stream.avail_out = 0; |
135 | s->stream.state = Z_NULL; | ||
146 | s->file = NULL; | 136 | s->file = NULL; |
147 | s->z_err = Z_OK; | 137 | s->z_err = Z_OK; |
148 | s->z_eof = 0; | 138 | s->z_eof = 0; |
@@ -442,7 +432,7 @@ int ZEXPORT gzread (file, buf, len) | |||
442 | if (s == NULL || s->mode != 'r') return Z_STREAM_ERROR; | 432 | if (s == NULL || s->mode != 'r') return Z_STREAM_ERROR; |
443 | 433 | ||
444 | if (s->z_err == Z_DATA_ERROR || s->z_err == Z_ERRNO) return -1; | 434 | if (s->z_err == Z_DATA_ERROR || s->z_err == Z_ERRNO) return -1; |
445 | if (s->z_err == Z_STREAM_END) return 0; /* EOF */ | 435 | if (s->z_err == Z_STREAM_END || s->z_eof) return 0; /* EOF */ |
446 | 436 | ||
447 | next_out = (Byte*)buf; | 437 | next_out = (Byte*)buf; |
448 | s->stream.next_out = (Bytef*)buf; | 438 | s->stream.next_out = (Bytef*)buf; |
@@ -482,7 +472,7 @@ int ZEXPORT gzread (file, buf, len) | |||
482 | len -= s->stream.avail_out; | 472 | len -= s->stream.avail_out; |
483 | s->in += len; | 473 | s->in += len; |
484 | s->out += len; | 474 | s->out += len; |
485 | if (len == 0) s->z_eof = 1; | 475 | if (feof(s->file)) s->z_eof = 1; |
486 | return (int)len; | 476 | return (int)len; |
487 | } | 477 | } |
488 | if (s->stream.avail_in == 0 && !s->z_eof) { | 478 | if (s->stream.avail_in == 0 && !s->z_eof) { |
@@ -803,15 +793,9 @@ int ZEXPORT gzflush (file, flush) | |||
803 | SEEK_END is not implemented, returns error. | 793 | SEEK_END is not implemented, returns error. |
804 | In this version of the library, gzseek can be extremely slow. | 794 | In this version of the library, gzseek can be extremely slow. |
805 | */ | 795 | */ |
806 | #ifdef _LARGEFILE64_SOURCE | 796 | local z_off64_t gz_seek (file, offset, whence, use64) |
807 | local off64_t gz_seek (file, offset, whence, use64) | ||
808 | gzFile file; | ||
809 | off64_t offset; | ||
810 | #else | ||
811 | local z_off_t gz_seek (file, offset, whence, use64) | ||
812 | gzFile file; | 797 | gzFile file; |
813 | z_off_t offset; | 798 | z_off64_t offset; |
814 | #endif | ||
815 | int whence; | 799 | int whence; |
816 | int use64; | 800 | int use64; |
817 | { | 801 | { |
@@ -914,23 +898,17 @@ z_off_t ZEXPORT gzseek (file, offset, whence) | |||
914 | return (z_off_t)gz_seek(file, offset, whence, 0); | 898 | return (z_off_t)gz_seek(file, offset, whence, 0); |
915 | } | 899 | } |
916 | 900 | ||
917 | #ifdef _LARGEFILE64_SOURCE | 901 | z_off64_t ZEXPORT gzseek64 (file, offset, whence) |
918 | off64_t ZEXPORT gzseek64 (file, offset, whence) | ||
919 | gzFile file; | 902 | gzFile file; |
920 | off64_t offset; | 903 | z_off64_t offset; |
921 | int whence; | 904 | int whence; |
922 | { | 905 | { |
906 | #ifdef _LARGEFILE64_SOURCE | ||
923 | return gz_seek(file, offset, whence, 1); | 907 | return gz_seek(file, offset, whence, 1); |
924 | } | ||
925 | #else | 908 | #else |
926 | z_off_t ZEXPORT gzseek64 (file, offset, whence) | ||
927 | gzFile file; | ||
928 | z_off_t offset; | ||
929 | int whence; | ||
930 | { | ||
931 | return gz_seek(file, offset, whence, 0); | 909 | return gz_seek(file, offset, whence, 0); |
932 | } | ||
933 | #endif | 910 | #endif |
911 | } | ||
934 | 912 | ||
935 | /* =========================================================================== | 913 | /* =========================================================================== |
936 | Rewinds input file. | 914 | Rewinds input file. |
@@ -968,11 +946,7 @@ z_off_t ZEXPORT gztell (file) | |||
968 | /* =========================================================================== | 946 | /* =========================================================================== |
969 | 64-bit version | 947 | 64-bit version |
970 | */ | 948 | */ |
971 | #ifdef _LARGEFILE64_SOURCE | 949 | z_off64_t ZEXPORT gztell64 (file) |
972 | off64_t ZEXPORT gztell64 (file) | ||
973 | #else | ||
974 | z_off_t ZEXPORT gztell64 (file) | ||
975 | #endif | ||
976 | gzFile file; | 950 | gzFile file; |
977 | { | 951 | { |
978 | return gzseek64(file, 0L, SEEK_CUR); | 952 | return gzseek64(file, 0L, SEEK_CUR); |
@@ -1,5 +1,5 @@ | |||
1 | /* infback.c -- inflate using a call-back interface | 1 | /* infback.c -- inflate using a call-back interface |
2 | * Copyright (C) 1995-2006 Mark Adler | 2 | * Copyright (C) 1995-2008 Mark Adler |
3 | * For conditions of distribution and use, see copyright notice in zlib.h | 3 | * For conditions of distribution and use, see copyright notice in zlib.h |
4 | */ | 4 | */ |
5 | 5 | ||
@@ -438,7 +438,16 @@ void FAR *out_desc; | |||
438 | /* handle error breaks in while */ | 438 | /* handle error breaks in while */ |
439 | if (state->mode == BAD) break; | 439 | if (state->mode == BAD) break; |
440 | 440 | ||
441 | /* build code tables */ | 441 | /* check for end-of-block code (better have one) */ |
442 | if (state->lens[256] == 0) { | ||
443 | strm->msg = (char *)"invalid code -- missing end-of-block"; | ||
444 | state->mode = BAD; | ||
445 | break; | ||
446 | } | ||
447 | |||
448 | /* build code tables -- note: do not change the lenbits or distbits | ||
449 | values here (9 and 6) without reading the comments in inftrees.h | ||
450 | concerning the ENOUGH constants, which depend on those values */ | ||
442 | state->next = state->codes; | 451 | state->next = state->codes; |
443 | state->lencode = (code const FAR *)(state->next); | 452 | state->lencode = (code const FAR *)(state->next); |
444 | state->lenbits = 9; | 453 | state->lenbits = 9; |
@@ -1,5 +1,5 @@ | |||
1 | /* inffast.c -- fast decoding | 1 | /* inffast.c -- fast decoding |
2 | * Copyright (C) 1995-2006 Mark Adler | 2 | * Copyright (C) 1995-2008 Mark Adler |
3 | * For conditions of distribution and use, see copyright notice in zlib.h | 3 | * For conditions of distribution and use, see copyright notice in zlib.h |
4 | */ | 4 | */ |
5 | 5 | ||
@@ -188,7 +188,8 @@ unsigned start; /* inflate()'s starting value for strm->avail_out */ | |||
188 | op = dist - op; /* distance back in window */ | 188 | op = dist - op; /* distance back in window */ |
189 | if (op > whave) { | 189 | if (op > whave) { |
190 | if (state->sane) { | 190 | if (state->sane) { |
191 | strm->msg = (char *)"invalid distance too far back"; | 191 | strm->msg = |
192 | (char *)"invalid distance too far back"; | ||
192 | state->mode = BAD; | 193 | state->mode = BAD; |
193 | break; | 194 | break; |
194 | } | 195 | } |
@@ -1,5 +1,5 @@ | |||
1 | /* inflate.c -- zlib decompression | 1 | /* inflate.c -- zlib decompression |
2 | * Copyright (C) 1995-2006 Mark Adler | 2 | * Copyright (C) 1995-2009 Mark Adler |
3 | * For conditions of distribution and use, see copyright notice in zlib.h | 3 | * For conditions of distribution and use, see copyright notice in zlib.h |
4 | */ | 4 | */ |
5 | 5 | ||
@@ -122,24 +122,47 @@ z_streamp strm; | |||
122 | state->bits = 0; | 122 | state->bits = 0; |
123 | state->lencode = state->distcode = state->next = state->codes; | 123 | state->lencode = state->distcode = state->next = state->codes; |
124 | state->sane = 1; | 124 | state->sane = 1; |
125 | state->back = -1; | ||
125 | Tracev((stderr, "inflate: reset\n")); | 126 | Tracev((stderr, "inflate: reset\n")); |
126 | return Z_OK; | 127 | return Z_OK; |
127 | } | 128 | } |
128 | 129 | ||
129 | int ZEXPORT inflatePrime(strm, bits, value) | 130 | int ZEXPORT inflateReset2(strm, windowBits) |
130 | z_streamp strm; | 131 | z_streamp strm; |
131 | int bits; | 132 | int windowBits; |
132 | int value; | ||
133 | { | 133 | { |
134 | int wrap; | ||
134 | struct inflate_state FAR *state; | 135 | struct inflate_state FAR *state; |
135 | 136 | ||
137 | /* get the state */ | ||
136 | if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; | 138 | if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; |
137 | state = (struct inflate_state FAR *)strm->state; | 139 | state = (struct inflate_state FAR *)strm->state; |
138 | if (bits > 16 || state->bits + bits > 32) return Z_STREAM_ERROR; | 140 | |
139 | value &= (1L << bits) - 1; | 141 | /* extract wrap request from windowBits parameter */ |
140 | state->hold += value << state->bits; | 142 | if (windowBits < 0) { |
141 | state->bits += bits; | 143 | wrap = 0; |
142 | return Z_OK; | 144 | windowBits = -windowBits; |
145 | } | ||
146 | else { | ||
147 | wrap = (windowBits >> 4) + 1; | ||
148 | #ifdef GUNZIP | ||
149 | if (windowBits < 48) | ||
150 | windowBits &= 15; | ||
151 | #endif | ||
152 | } | ||
153 | |||
154 | /* set number of window bits, free window if different */ | ||
155 | if (windowBits < 8 || windowBits > 15) | ||
156 | return Z_STREAM_ERROR; | ||
157 | if (state->wbits != windowBits && state->window != Z_NULL) { | ||
158 | ZFREE(strm, state->window); | ||
159 | state->window = Z_NULL; | ||
160 | } | ||
161 | |||
162 | /* update state and reset the rest of it */ | ||
163 | state->wrap = wrap; | ||
164 | state->wbits = (unsigned)windowBits; | ||
165 | return inflateReset(strm); | ||
143 | } | 166 | } |
144 | 167 | ||
145 | int ZEXPORT inflateInit2_(strm, windowBits, version, stream_size) | 168 | int ZEXPORT inflateInit2_(strm, windowBits, version, stream_size) |
@@ -148,6 +171,7 @@ int windowBits; | |||
148 | const char *version; | 171 | const char *version; |
149 | int stream_size; | 172 | int stream_size; |
150 | { | 173 | { |
174 | int ret; | ||
151 | struct inflate_state FAR *state; | 175 | struct inflate_state FAR *state; |
152 | 176 | ||
153 | if (version == Z_NULL || version[0] != ZLIB_VERSION[0] || | 177 | if (version == Z_NULL || version[0] != ZLIB_VERSION[0] || |
@@ -165,24 +189,13 @@ int stream_size; | |||
165 | if (state == Z_NULL) return Z_MEM_ERROR; | 189 | if (state == Z_NULL) return Z_MEM_ERROR; |
166 | Tracev((stderr, "inflate: allocated\n")); | 190 | Tracev((stderr, "inflate: allocated\n")); |
167 | strm->state = (struct internal_state FAR *)state; | 191 | strm->state = (struct internal_state FAR *)state; |
168 | if (windowBits < 0) { | 192 | state->window = Z_NULL; |
169 | state->wrap = 0; | 193 | ret = inflateReset2(strm, windowBits); |
170 | windowBits = -windowBits; | 194 | if (ret != Z_OK) { |
171 | } | ||
172 | else { | ||
173 | state->wrap = (windowBits >> 4) + 1; | ||
174 | #ifdef GUNZIP | ||
175 | if (windowBits < 48) windowBits &= 15; | ||
176 | #endif | ||
177 | } | ||
178 | if (windowBits < 8 || windowBits > 15) { | ||
179 | ZFREE(strm, state); | 195 | ZFREE(strm, state); |
180 | strm->state = Z_NULL; | 196 | strm->state = Z_NULL; |
181 | return Z_STREAM_ERROR; | ||
182 | } | 197 | } |
183 | state->wbits = (unsigned)windowBits; | 198 | return ret; |
184 | state->window = Z_NULL; | ||
185 | return inflateReset(strm); | ||
186 | } | 199 | } |
187 | 200 | ||
188 | int ZEXPORT inflateInit_(strm, version, stream_size) | 201 | int ZEXPORT inflateInit_(strm, version, stream_size) |
@@ -193,6 +206,27 @@ int stream_size; | |||
193 | return inflateInit2_(strm, DEF_WBITS, version, stream_size); | 206 | return inflateInit2_(strm, DEF_WBITS, version, stream_size); |
194 | } | 207 | } |
195 | 208 | ||
209 | int ZEXPORT inflatePrime(strm, bits, value) | ||
210 | z_streamp strm; | ||
211 | int bits; | ||
212 | int value; | ||
213 | { | ||
214 | struct inflate_state FAR *state; | ||
215 | |||
216 | if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; | ||
217 | state = (struct inflate_state FAR *)strm->state; | ||
218 | if (bits < 0) { | ||
219 | state->hold = 0; | ||
220 | state->bits = 0; | ||
221 | return Z_OK; | ||
222 | } | ||
223 | if (bits > 16 || state->bits + bits > 32) return Z_STREAM_ERROR; | ||
224 | value &= (1L << bits) - 1; | ||
225 | state->hold += value << state->bits; | ||
226 | state->bits += bits; | ||
227 | return Z_OK; | ||
228 | } | ||
229 | |||
196 | /* | 230 | /* |
197 | Return state with length and distance decoding tables and index sizes set to | 231 | Return state with length and distance decoding tables and index sizes set to |
198 | fixed code decoding. Normally this returns fixed tables from inffixed.h. | 232 | fixed code decoding. Normally this returns fixed tables from inffixed.h. |
@@ -772,7 +806,7 @@ int flush; | |||
772 | strm->adler = state->check = adler32(0L, Z_NULL, 0); | 806 | strm->adler = state->check = adler32(0L, Z_NULL, 0); |
773 | state->mode = TYPE; | 807 | state->mode = TYPE; |
774 | case TYPE: | 808 | case TYPE: |
775 | if (flush == Z_BLOCK) goto inf_leave; | 809 | if (flush == Z_BLOCK || flush == Z_TREES) goto inf_leave; |
776 | case TYPEDO: | 810 | case TYPEDO: |
777 | if (state->last) { | 811 | if (state->last) { |
778 | BYTEBITS(); | 812 | BYTEBITS(); |
@@ -792,7 +826,11 @@ int flush; | |||
792 | fixedtables(state); | 826 | fixedtables(state); |
793 | Tracev((stderr, "inflate: fixed codes block%s\n", | 827 | Tracev((stderr, "inflate: fixed codes block%s\n", |
794 | state->last ? " (last)" : "")); | 828 | state->last ? " (last)" : "")); |
795 | state->mode = LEN; /* decode codes */ | 829 | state->mode = LEN_; /* decode codes */ |
830 | if (flush == Z_TREES) { | ||
831 | DROPBITS(2); | ||
832 | goto inf_leave; | ||
833 | } | ||
796 | break; | 834 | break; |
797 | case 2: /* dynamic block */ | 835 | case 2: /* dynamic block */ |
798 | Tracev((stderr, "inflate: dynamic codes block%s\n", | 836 | Tracev((stderr, "inflate: dynamic codes block%s\n", |
@@ -817,6 +855,9 @@ int flush; | |||
817 | Tracev((stderr, "inflate: stored length %u\n", | 855 | Tracev((stderr, "inflate: stored length %u\n", |
818 | state->length)); | 856 | state->length)); |
819 | INITBITS(); | 857 | INITBITS(); |
858 | state->mode = COPY_; | ||
859 | if (flush == Z_TREES) goto inf_leave; | ||
860 | case COPY_: | ||
820 | state->mode = COPY; | 861 | state->mode = COPY; |
821 | case COPY: | 862 | case COPY: |
822 | copy = state->length; | 863 | copy = state->length; |
@@ -926,7 +967,16 @@ int flush; | |||
926 | /* handle error breaks in while */ | 967 | /* handle error breaks in while */ |
927 | if (state->mode == BAD) break; | 968 | if (state->mode == BAD) break; |
928 | 969 | ||
929 | /* build code tables */ | 970 | /* check for end-of-block code (better have one) */ |
971 | if (state->lens[256] == 0) { | ||
972 | strm->msg = (char *)"invalid code -- missing end-of-block"; | ||
973 | state->mode = BAD; | ||
974 | break; | ||
975 | } | ||
976 | |||
977 | /* build code tables -- note: do not change the lenbits or distbits | ||
978 | values here (9 and 6) without reading the comments in inftrees.h | ||
979 | concerning the ENOUGH constants, which depend on those values */ | ||
930 | state->next = state->codes; | 980 | state->next = state->codes; |
931 | state->lencode = (code const FAR *)(state->next); | 981 | state->lencode = (code const FAR *)(state->next); |
932 | state->lenbits = 9; | 982 | state->lenbits = 9; |
@@ -947,14 +997,20 @@ int flush; | |||
947 | break; | 997 | break; |
948 | } | 998 | } |
949 | Tracev((stderr, "inflate: codes ok\n")); | 999 | Tracev((stderr, "inflate: codes ok\n")); |
1000 | state->mode = LEN_; | ||
1001 | if (flush == Z_TREES) goto inf_leave; | ||
1002 | case LEN_: | ||
950 | state->mode = LEN; | 1003 | state->mode = LEN; |
951 | case LEN: | 1004 | case LEN: |
952 | if (have >= 6 && left >= 258) { | 1005 | if (have >= 6 && left >= 258) { |
953 | RESTORE(); | 1006 | RESTORE(); |
954 | inflate_fast(strm, out); | 1007 | inflate_fast(strm, out); |
955 | LOAD(); | 1008 | LOAD(); |
1009 | if (state->mode == TYPE) | ||
1010 | state->back = -1; | ||
956 | break; | 1011 | break; |
957 | } | 1012 | } |
1013 | state->back = 0; | ||
958 | for (;;) { | 1014 | for (;;) { |
959 | here = state->lencode[BITS(state->lenbits)]; | 1015 | here = state->lencode[BITS(state->lenbits)]; |
960 | if ((unsigned)(here.bits) <= bits) break; | 1016 | if ((unsigned)(here.bits) <= bits) break; |
@@ -969,8 +1025,10 @@ int flush; | |||
969 | PULLBYTE(); | 1025 | PULLBYTE(); |
970 | } | 1026 | } |
971 | DROPBITS(last.bits); | 1027 | DROPBITS(last.bits); |
1028 | state->back += last.bits; | ||
972 | } | 1029 | } |
973 | DROPBITS(here.bits); | 1030 | DROPBITS(here.bits); |
1031 | state->back += here.bits; | ||
974 | state->length = (unsigned)here.val; | 1032 | state->length = (unsigned)here.val; |
975 | if ((int)(here.op) == 0) { | 1033 | if ((int)(here.op) == 0) { |
976 | Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ? | 1034 | Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ? |
@@ -981,6 +1039,7 @@ int flush; | |||
981 | } | 1039 | } |
982 | if (here.op & 32) { | 1040 | if (here.op & 32) { |
983 | Tracevv((stderr, "inflate: end of block\n")); | 1041 | Tracevv((stderr, "inflate: end of block\n")); |
1042 | state->back = -1; | ||
984 | state->mode = TYPE; | 1043 | state->mode = TYPE; |
985 | break; | 1044 | break; |
986 | } | 1045 | } |
@@ -996,8 +1055,10 @@ int flush; | |||
996 | NEEDBITS(state->extra); | 1055 | NEEDBITS(state->extra); |
997 | state->length += BITS(state->extra); | 1056 | state->length += BITS(state->extra); |
998 | DROPBITS(state->extra); | 1057 | DROPBITS(state->extra); |
1058 | state->back += state->extra; | ||
999 | } | 1059 | } |
1000 | Tracevv((stderr, "inflate: length %u\n", state->length)); | 1060 | Tracevv((stderr, "inflate: length %u\n", state->length)); |
1061 | state->was = state->length; | ||
1001 | state->mode = DIST; | 1062 | state->mode = DIST; |
1002 | case DIST: | 1063 | case DIST: |
1003 | for (;;) { | 1064 | for (;;) { |
@@ -1014,8 +1075,10 @@ int flush; | |||
1014 | PULLBYTE(); | 1075 | PULLBYTE(); |
1015 | } | 1076 | } |
1016 | DROPBITS(last.bits); | 1077 | DROPBITS(last.bits); |
1078 | state->back += last.bits; | ||
1017 | } | 1079 | } |
1018 | DROPBITS(here.bits); | 1080 | DROPBITS(here.bits); |
1081 | state->back += here.bits; | ||
1019 | if (here.op & 64) { | 1082 | if (here.op & 64) { |
1020 | strm->msg = (char *)"invalid distance code"; | 1083 | strm->msg = (char *)"invalid distance code"; |
1021 | state->mode = BAD; | 1084 | state->mode = BAD; |
@@ -1029,6 +1092,7 @@ int flush; | |||
1029 | NEEDBITS(state->extra); | 1092 | NEEDBITS(state->extra); |
1030 | state->offset += BITS(state->extra); | 1093 | state->offset += BITS(state->extra); |
1031 | DROPBITS(state->extra); | 1094 | DROPBITS(state->extra); |
1095 | state->back += state->extra; | ||
1032 | } | 1096 | } |
1033 | #ifdef INFLATE_STRICT | 1097 | #ifdef INFLATE_STRICT |
1034 | if (state->offset > state->dmax) { | 1098 | if (state->offset > state->dmax) { |
@@ -1066,6 +1130,9 @@ int flush; | |||
1066 | } | 1130 | } |
1067 | if (copy > state->write) { | 1131 | if (copy > state->write) { |
1068 | copy -= state->write; | 1132 | copy -= state->write; |
1133 | /* %% problem here if copy > state->wsize -- avoid? */ | ||
1134 | /* %% or can (state->window + state->wsize) - copy */ | ||
1135 | /* %% but really should detect and reject this case */ | ||
1069 | from = state->window + (state->wsize - copy); | 1136 | from = state->window + (state->wsize - copy); |
1070 | } | 1137 | } |
1071 | else | 1138 | else |
@@ -1162,7 +1229,8 @@ int flush; | |||
1162 | strm->adler = state->check = | 1229 | strm->adler = state->check = |
1163 | UPDATE(state->check, strm->next_out - out, out); | 1230 | UPDATE(state->check, strm->next_out - out, out); |
1164 | strm->data_type = state->bits + (state->last ? 64 : 0) + | 1231 | strm->data_type = state->bits + (state->last ? 64 : 0) + |
1165 | (state->mode == TYPE ? 128 : 0); | 1232 | (state->mode == TYPE ? 128 : 0) + |
1233 | (state->mode == LEN_ || state->mode == COPY_ ? 256 : 0); | ||
1166 | if (((in == 0 && out == 0) || flush == Z_FINISH) && ret == Z_OK) | 1234 | if (((in == 0 && out == 0) || flush == Z_FINISH) && ret == Z_OK) |
1167 | ret = Z_BUF_ERROR; | 1235 | ret = Z_BUF_ERROR; |
1168 | return ret; | 1236 | return ret; |
@@ -1399,3 +1467,15 @@ int subvert; | |||
1399 | return Z_DATA_ERROR; | 1467 | return Z_DATA_ERROR; |
1400 | #endif | 1468 | #endif |
1401 | } | 1469 | } |
1470 | |||
1471 | long ZEXPORT inflateMark(strm) | ||
1472 | z_streamp strm; | ||
1473 | { | ||
1474 | struct inflate_state FAR *state; | ||
1475 | |||
1476 | if (strm == Z_NULL || strm->state == Z_NULL) return -1L << 16; | ||
1477 | state = (struct inflate_state FAR *)strm->state; | ||
1478 | return ((long)(state->back) << 16) + | ||
1479 | (state->mode == COPY ? state->length : | ||
1480 | (state->mode == MATCH ? state->was - state->length : 0)); | ||
1481 | } | ||
@@ -1,5 +1,5 @@ | |||
1 | /* inflate.h -- internal inflate state definition | 1 | /* inflate.h -- internal inflate state definition |
2 | * Copyright (C) 1995-2006 Mark Adler | 2 | * Copyright (C) 1995-2009 Mark Adler |
3 | * For conditions of distribution and use, see copyright notice in zlib.h | 3 | * For conditions of distribution and use, see copyright notice in zlib.h |
4 | */ | 4 | */ |
5 | 5 | ||
@@ -32,11 +32,13 @@ typedef enum { | |||
32 | TYPE, /* i: waiting for type bits, including last-flag bit */ | 32 | TYPE, /* i: waiting for type bits, including last-flag bit */ |
33 | TYPEDO, /* i: same, but skip check to exit inflate on new block */ | 33 | TYPEDO, /* i: same, but skip check to exit inflate on new block */ |
34 | STORED, /* i: waiting for stored size (length and complement) */ | 34 | STORED, /* i: waiting for stored size (length and complement) */ |
35 | COPY_, /* i/o: same as COPY below, but only first time in */ | ||
35 | COPY, /* i/o: waiting for input or output to copy stored block */ | 36 | COPY, /* i/o: waiting for input or output to copy stored block */ |
36 | TABLE, /* i: waiting for dynamic block table lengths */ | 37 | TABLE, /* i: waiting for dynamic block table lengths */ |
37 | LENLENS, /* i: waiting for code length code lengths */ | 38 | LENLENS, /* i: waiting for code length code lengths */ |
38 | CODELENS, /* i: waiting for length/lit and distance code lengths */ | 39 | CODELENS, /* i: waiting for length/lit and distance code lengths */ |
39 | LEN, /* i: waiting for length/lit code */ | 40 | LEN_, /* i: same as LEN below, but only first time in */ |
41 | LEN, /* i: waiting for length/lit/eob code */ | ||
40 | LENEXT, /* i: waiting for length extra bits */ | 42 | LENEXT, /* i: waiting for length extra bits */ |
41 | DIST, /* i: waiting for distance code */ | 43 | DIST, /* i: waiting for distance code */ |
42 | DISTEXT, /* i: waiting for distance extra bits */ | 44 | DISTEXT, /* i: waiting for distance extra bits */ |
@@ -53,19 +55,21 @@ typedef enum { | |||
53 | /* | 55 | /* |
54 | State transitions between above modes - | 56 | State transitions between above modes - |
55 | 57 | ||
56 | (most modes can go to the BAD or MEM mode -- not shown for clarity) | 58 | (most modes can go to BAD or MEM on error -- not shown for clarity) |
57 | 59 | ||
58 | Process header: | 60 | Process header: |
59 | HEAD -> (gzip) or (zlib) | 61 | HEAD -> (gzip) or (zlib) or (raw) |
60 | (gzip) -> FLAGS -> TIME -> OS -> EXLEN -> EXTRA -> NAME | 62 | (gzip) -> FLAGS -> TIME -> OS -> EXLEN -> EXTRA -> NAME -> COMMENT -> |
61 | NAME -> COMMENT -> HCRC -> TYPE | 63 | HCRC -> TYPE |
62 | (zlib) -> DICTID or TYPE | 64 | (zlib) -> DICTID or TYPE |
63 | DICTID -> DICT -> TYPE | 65 | DICTID -> DICT -> TYPE |
66 | (raw) -> TYPEDO | ||
64 | Read deflate blocks: | 67 | Read deflate blocks: |
65 | TYPE -> STORED or TABLE or LEN or CHECK | 68 | TYPE -> TYPEDO -> STORED or TABLE or LEN_ or CHECK |
66 | STORED -> COPY -> TYPE | 69 | STORED -> COPY_ -> COPY -> TYPE |
67 | TABLE -> LENLENS -> CODELENS -> LEN | 70 | TABLE -> LENLENS -> CODELENS -> LEN_ |
68 | Read deflate codes: | 71 | LEN_ -> LEN |
72 | Read deflate codes in fixed or dynamic block: | ||
69 | LEN -> LENEXT or LIT or TYPE | 73 | LEN -> LENEXT or LIT or TYPE |
70 | LENEXT -> DIST -> DISTEXT -> MATCH -> LEN | 74 | LENEXT -> DIST -> DISTEXT -> MATCH -> LEN |
71 | LIT -> LEN | 75 | LIT -> LEN |
@@ -113,4 +117,6 @@ struct inflate_state { | |||
113 | unsigned short work[288]; /* work area for code table building */ | 117 | unsigned short work[288]; /* work area for code table building */ |
114 | code codes[ENOUGH]; /* space for code tables */ | 118 | code codes[ENOUGH]; /* space for code tables */ |
115 | int sane; /* if false, allow invalid distance too far */ | 119 | int sane; /* if false, allow invalid distance too far */ |
120 | int back; /* bits back of last unprocessed length/lit */ | ||
121 | unsigned was; /* initial length of match */ | ||
116 | }; | 122 | }; |
@@ -1,5 +1,5 @@ | |||
1 | /* inftrees.c -- generate Huffman trees for efficient decoding | 1 | /* inftrees.c -- generate Huffman trees for efficient decoding |
2 | * Copyright (C) 1995-2006 Mark Adler | 2 | * Copyright (C) 1995-2009 Mark Adler |
3 | * For conditions of distribution and use, see copyright notice in zlib.h | 3 | * For conditions of distribution and use, see copyright notice in zlib.h |
4 | */ | 4 | */ |
5 | 5 | ||
@@ -9,7 +9,7 @@ | |||
9 | #define MAXBITS 15 | 9 | #define MAXBITS 15 |
10 | 10 | ||
11 | const char inflate_copyright[] = | 11 | const char inflate_copyright[] = |
12 | " inflate 1.2.3.3 Copyright 1995-2006 Mark Adler "; | 12 | " inflate 1.2.3.4 Copyright 1995-2008 Mark Adler "; |
13 | /* | 13 | /* |
14 | If you use the zlib library in a product, an acknowledgment is welcome | 14 | If you use the zlib library in a product, an acknowledgment is welcome |
15 | in the documentation of your product. If for some reason you cannot | 15 | in the documentation of your product. If for some reason you cannot |
@@ -62,7 +62,7 @@ unsigned short FAR *work; | |||
62 | 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0}; | 62 | 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0}; |
63 | static const unsigned short lext[31] = { /* Length codes 257..285 extra */ | 63 | static const unsigned short lext[31] = { /* Length codes 257..285 extra */ |
64 | 16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 18, 18, 18, 18, | 64 | 16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 18, 18, 18, 18, |
65 | 19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 16, 201, 203}; | 65 | 19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 16, 72, 200}; |
66 | static const unsigned short dbase[32] = { /* Distance codes 0..29 base */ | 66 | static const unsigned short dbase[32] = { /* Distance codes 0..29 base */ |
67 | 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, | 67 | 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, |
68 | 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, | 68 | 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, |
@@ -123,7 +123,7 @@ unsigned short FAR *work; | |||
123 | *bits = 1; | 123 | *bits = 1; |
124 | return 0; /* no symbols, but wait for decoding to report error */ | 124 | return 0; /* no symbols, but wait for decoding to report error */ |
125 | } | 125 | } |
126 | for (min = 1; min <= MAXBITS; min++) | 126 | for (min = 1; min < max; min++) |
127 | if (count[min] != 0) break; | 127 | if (count[min] != 0) break; |
128 | if (root < min) root = min; | 128 | if (root < min) root = min; |
129 | 129 | ||
@@ -166,11 +166,10 @@ unsigned short FAR *work; | |||
166 | entered in the tables. | 166 | entered in the tables. |
167 | 167 | ||
168 | used keeps track of how many table entries have been allocated from the | 168 | used keeps track of how many table entries have been allocated from the |
169 | provided *table space. It is checked when a LENS table is being made | 169 | provided *table space. It is checked for LENS and DIST tables against |
170 | against the space in *table, ENOUGH, minus the maximum space needed by | 170 | the constants ENOUGH_LENS and ENOUGH_DISTS to guard against changes in |
171 | the worst case distance code, MAXD. This should never happen, but the | 171 | the initial root table size constants. See the comments in inftrees.h |
172 | sufficiency of ENOUGH has not been proven exhaustively, hence the check. | 172 | for more information. |
173 | This assumes that when type == LENS, bits == 9. | ||
174 | 173 | ||
175 | sym increments through all symbols, and the loop terminates when | 174 | sym increments through all symbols, and the loop terminates when |
176 | all codes of length max, i.e. all codes, have been processed. This | 175 | all codes of length max, i.e. all codes, have been processed. This |
@@ -209,7 +208,8 @@ unsigned short FAR *work; | |||
209 | mask = used - 1; /* mask for comparing low */ | 208 | mask = used - 1; /* mask for comparing low */ |
210 | 209 | ||
211 | /* check available table space */ | 210 | /* check available table space */ |
212 | if (type == LENS && used >= ENOUGH - MAXD) | 211 | if ((type == LENS && used >= ENOUGH_LENS) || |
212 | (type == DISTS && used >= ENOUGH_DISTS)) | ||
213 | return 1; | 213 | return 1; |
214 | 214 | ||
215 | /* process all codes and make table entries */ | 215 | /* process all codes and make table entries */ |
@@ -277,7 +277,8 @@ unsigned short FAR *work; | |||
277 | 277 | ||
278 | /* check for enough space */ | 278 | /* check for enough space */ |
279 | used += 1U << curr; | 279 | used += 1U << curr; |
280 | if (type == LENS && used >= ENOUGH - MAXD) | 280 | if ((type == LENS && used >= ENOUGH_LENS) || |
281 | (type == DISTS && used >= ENOUGH_DISTS)) | ||
281 | return 1; | 282 | return 1; |
282 | 283 | ||
283 | /* point entry in root table to sub-table */ | 284 | /* point entry in root table to sub-table */ |
@@ -35,15 +35,22 @@ typedef struct { | |||
35 | 01000000 - invalid code | 35 | 01000000 - invalid code |
36 | */ | 36 | */ |
37 | 37 | ||
38 | /* Maximum size of dynamic tree. The maximum found in a long but non- | 38 | /* Maximum size of the dynamic table. The maximum number of code structures is |
39 | exhaustive search was 1444 code structures (852 for length/literals | 39 | 1444, which is the sum of 852 for literal/length codes and 592 for distance |
40 | and 592 for distances, the latter actually the result of an | 40 | codes. These values were found by exhaustive searches using the program |
41 | exhaustive search). The true maximum is not known, but the value | 41 | examples/enough.c found in the zlib distribtution. The arguments to that |
42 | below is more than safe. */ | 42 | program are the number of symbols, the initial root table size, and the |
43 | #define ENOUGH 2048 | 43 | maximum bit length of a code. "enough 286 9 15" for literal/length codes |
44 | #define MAXD 592 | 44 | returns returns 852, and "enough 30 6 15" for distance codes returns 592. |
45 | The initial root table size (9 or 6) is found in the fifth argument of the | ||
46 | inflate_table() calls in inflate.c and infback.c. If the root table size is | ||
47 | changed, then these maximum sizes would be need to be recalculated and | ||
48 | updated. */ | ||
49 | #define ENOUGH_LENS 852 | ||
50 | #define ENOUGH_DISTS 592 | ||
51 | #define ENOUGH (ENOUGH_LENS+ENOUGH_DISTS) | ||
45 | 52 | ||
46 | /* Type of code to build for inftable() */ | 53 | /* Type of code to build for inflate_table() */ |
47 | typedef enum { | 54 | typedef enum { |
48 | CODES, | 55 | CODES, |
49 | LENS, | 56 | LENS, |
diff --git a/make_vms.com b/make_vms.com index c8fa6a5..87c480a 100644 --- a/make_vms.com +++ b/make_vms.com | |||
@@ -10,6 +10,7 @@ $! | |||
10 | $!------------------------------------------------------------------------------ | 10 | $!------------------------------------------------------------------------------ |
11 | $! Version history | 11 | $! Version history |
12 | $! 0.01 20060120 First version to receive a number | 12 | $! 0.01 20060120 First version to receive a number |
13 | $! 0.02 20061008 Adapt to new Makefile.in | ||
13 | $! | 14 | $! |
14 | $ on error then goto err_exit | 15 | $ on error then goto err_exit |
15 | $! | 16 | $! |
@@ -353,7 +354,7 @@ $! | |||
353 | $CREA_OLIST: | 354 | $CREA_OLIST: |
354 | $ open/read min makefile.in | 355 | $ open/read min makefile.in |
355 | $ open/write mod modules.opt | 356 | $ open/write mod modules.opt |
356 | $ src_check = "OBJS =" | 357 | $ src_check = "OBJC =" |
357 | $MRLOOP: | 358 | $MRLOOP: |
358 | $ read/end=mrdone min rec | 359 | $ read/end=mrdone min rec |
359 | $ if (f$extract(0,6,rec) .nes. src_check) then goto mrloop | 360 | $ if (f$extract(0,6,rec) .nes. src_check) then goto mrloop |
diff --git a/qnx/package.qpg b/qnx/package.qpg index be5d5c1..c37e91b 100644 --- a/qnx/package.qpg +++ b/qnx/package.qpg | |||
@@ -25,10 +25,10 @@ | |||
25 | <QPG:Files> | 25 | <QPG:Files> |
26 | <QPG:Add file="../zconf.h" install="/opt/include/" user="root:sys" permission="644"/> | 26 | <QPG:Add file="../zconf.h" install="/opt/include/" user="root:sys" permission="644"/> |
27 | <QPG:Add file="../zlib.h" install="/opt/include/" user="root:sys" permission="644"/> | 27 | <QPG:Add file="../zlib.h" install="/opt/include/" user="root:sys" permission="644"/> |
28 | <QPG:Add file="../libz.so.1.2.3.3" install="/opt/lib/" user="root:bin" permission="644"/> | 28 | <QPG:Add file="../libz.so.1.2.3.4" install="/opt/lib/" user="root:bin" permission="644"/> |
29 | <QPG:Add file="libz.so" install="/opt/lib/" component="dev" filetype="symlink" linkto="libz.so.1.2.3.3"/> | 29 | <QPG:Add file="libz.so" install="/opt/lib/" component="dev" filetype="symlink" linkto="libz.so.1.2.3.4"/> |
30 | <QPG:Add file="libz.so.1" install="/opt/lib/" filetype="symlink" linkto="libz.so.1.2.3.3"/> | 30 | <QPG:Add file="libz.so.1" install="/opt/lib/" filetype="symlink" linkto="libz.so.1.2.3.4"/> |
31 | <QPG:Add file="../libz.so.1.2.3.3" install="/opt/lib/" component="slib"/> | 31 | <QPG:Add file="../libz.so.1.2.3.4" install="/opt/lib/" component="slib"/> |
32 | </QPG:Files> | 32 | </QPG:Files> |
33 | 33 | ||
34 | <QPG:PackageFilter> | 34 | <QPG:PackageFilter> |
@@ -63,7 +63,7 @@ | |||
63 | </QPM:ProductDescription> | 63 | </QPM:ProductDescription> |
64 | 64 | ||
65 | <QPM:ReleaseDescription> | 65 | <QPM:ReleaseDescription> |
66 | <QPM:ReleaseVersion>1.2.3.3</QPM:ReleaseVersion> | 66 | <QPM:ReleaseVersion>1.2.3.4</QPM:ReleaseVersion> |
67 | <QPM:ReleaseUrgency>Medium</QPM:ReleaseUrgency> | 67 | <QPM:ReleaseUrgency>Medium</QPM:ReleaseUrgency> |
68 | <QPM:ReleaseStability>Stable</QPM:ReleaseStability> | 68 | <QPM:ReleaseStability>Stable</QPM:ReleaseStability> |
69 | <QPM:ReleaseNoteMinor></QPM:ReleaseNoteMinor> | 69 | <QPM:ReleaseNoteMinor></QPM:ReleaseNoteMinor> |
@@ -1,5 +1,5 @@ | |||
1 | /* trees.c -- output deflated data using Huffman coding | 1 | /* trees.c -- output deflated data using Huffman coding |
2 | * Copyright (C) 1995-2006 Jean-loup Gailly | 2 | * Copyright (C) 1995-2009 Jean-loup Gailly |
3 | * detect_data_type() function provided freely by Cosmin Truta, 2006 | 3 | * detect_data_type() function provided freely by Cosmin Truta, 2006 |
4 | * For conditions of distribution and use, see copyright notice in zlib.h | 4 | * For conditions of distribution and use, see copyright notice in zlib.h |
5 | */ | 5 | */ |
@@ -204,12 +204,12 @@ local void send_bits(s, value, length) | |||
204 | * unused bits in value. | 204 | * unused bits in value. |
205 | */ | 205 | */ |
206 | if (s->bi_valid > (int)Buf_size - length) { | 206 | if (s->bi_valid > (int)Buf_size - length) { |
207 | s->bi_buf |= (value << s->bi_valid); | 207 | s->bi_buf |= (ush)value << s->bi_valid; |
208 | put_short(s, s->bi_buf); | 208 | put_short(s, s->bi_buf); |
209 | s->bi_buf = (ush)value >> (Buf_size - s->bi_valid); | 209 | s->bi_buf = (ush)value >> (Buf_size - s->bi_valid); |
210 | s->bi_valid += length - Buf_size; | 210 | s->bi_valid += length - Buf_size; |
211 | } else { | 211 | } else { |
212 | s->bi_buf |= value << s->bi_valid; | 212 | s->bi_buf |= (ush)value << s->bi_valid; |
213 | s->bi_valid += length; | 213 | s->bi_valid += length; |
214 | } | 214 | } |
215 | } | 215 | } |
@@ -219,12 +219,12 @@ local void send_bits(s, value, length) | |||
219 | { int len = length;\ | 219 | { int len = length;\ |
220 | if (s->bi_valid > (int)Buf_size - len) {\ | 220 | if (s->bi_valid > (int)Buf_size - len) {\ |
221 | int val = value;\ | 221 | int val = value;\ |
222 | s->bi_buf |= (val << s->bi_valid);\ | 222 | s->bi_buf |= (ush)val << s->bi_valid;\ |
223 | put_short(s, s->bi_buf);\ | 223 | put_short(s, s->bi_buf);\ |
224 | s->bi_buf = (ush)val >> (Buf_size - s->bi_valid);\ | 224 | s->bi_buf = (ush)val >> (Buf_size - s->bi_valid);\ |
225 | s->bi_valid += len - Buf_size;\ | 225 | s->bi_valid += len - Buf_size;\ |
226 | } else {\ | 226 | } else {\ |
227 | s->bi_buf |= (value) << s->bi_valid;\ | 227 | s->bi_buf |= (ush)(value) << s->bi_valid;\ |
228 | s->bi_valid += len;\ | 228 | s->bi_valid += len;\ |
229 | }\ | 229 | }\ |
230 | } | 230 | } |
diff --git a/win32/zlib.def b/win32/zlib.def index dbea9c5..c148ecb 100644 --- a/win32/zlib.def +++ b/win32/zlib.def | |||
@@ -13,12 +13,18 @@ EXPORTS | |||
13 | deflateCopy | 13 | deflateCopy |
14 | deflateReset | 14 | deflateReset |
15 | deflateParams | 15 | deflateParams |
16 | deflateTune | ||
16 | deflateBound | 17 | deflateBound |
17 | deflatePrime | 18 | deflatePrime |
19 | deflateSetHeader | ||
18 | inflateSetDictionary | 20 | inflateSetDictionary |
19 | inflateSync | 21 | inflateSync |
20 | inflateCopy | 22 | inflateCopy |
21 | inflateReset | 23 | inflateReset |
24 | inflateReset2 | ||
25 | inflatePrime | ||
26 | inflateMark | ||
27 | inflateGetHeader | ||
22 | inflateBack | 28 | inflateBack |
23 | inflateBackEnd | 29 | inflateBackEnd |
24 | zlibCompileFlags | 30 | zlibCompileFlags |
@@ -49,8 +55,8 @@ EXPORTS | |||
49 | gzclearerr | 55 | gzclearerr |
50 | ; checksum functions | 56 | ; checksum functions |
51 | adler32 | 57 | adler32 |
52 | adler32_combine | ||
53 | crc32 | 58 | crc32 |
59 | adler32_combine | ||
54 | crc32_combine | 60 | crc32_combine |
55 | ; various hacks, don't look :) | 61 | ; various hacks, don't look :) |
56 | deflateInit_ | 62 | deflateInit_ |
@@ -58,6 +64,12 @@ EXPORTS | |||
58 | inflateInit_ | 64 | inflateInit_ |
59 | inflateInit2_ | 65 | inflateInit2_ |
60 | inflateBackInit_ | 66 | inflateBackInit_ |
67 | gzopen64 | ||
68 | gzseek64 | ||
69 | gztell64 | ||
70 | adler32_combine64 | ||
71 | crc32_combine64 | ||
72 | zError | ||
61 | inflateSyncPoint | 73 | inflateSyncPoint |
62 | get_crc_table | 74 | get_crc_table |
63 | zError | 75 | inflateUndermine |
@@ -1,5 +1,5 @@ | |||
1 | /* zconf.h -- configuration of the zlib compression library | 1 | /* zconf.h -- configuration of the zlib compression library |
2 | * Copyright (C) 1995-2006 Jean-loup Gailly. | 2 | * Copyright (C) 1995-2007 Jean-loup Gailly. |
3 | * For conditions of distribution and use, see copyright notice in zlib.h | 3 | * For conditions of distribution and use, see copyright notice in zlib.h |
4 | */ | 4 | */ |
5 | 5 | ||
@@ -353,6 +353,10 @@ typedef uLong FAR uLongf; | |||
353 | 353 | ||
354 | #include "zlibdefs.h" /* created by configure */ | 354 | #include "zlibdefs.h" /* created by configure */ |
355 | 355 | ||
356 | #ifdef _LARGEFILE64_SOURCE | ||
357 | # include <sys/types.h> | ||
358 | #endif | ||
359 | |||
356 | #ifndef SEEK_SET | 360 | #ifndef SEEK_SET |
357 | # define SEEK_SET 0 /* Seek from beginning of file. */ | 361 | # define SEEK_SET 0 /* Seek from beginning of file. */ |
358 | # define SEEK_CUR 1 /* Seek from current position. */ | 362 | # define SEEK_CUR 1 /* Seek from current position. */ |
@@ -1,4 +1,4 @@ | |||
1 | .TH ZLIB 3 "2 October 2006" | 1 | .TH ZLIB 3 "21 December 2009" |
2 | .SH NAME | 2 | .SH NAME |
3 | zlib \- compression/decompression library | 3 | zlib \- compression/decompression library |
4 | .SH SYNOPSIS | 4 | .SH SYNOPSIS |
@@ -133,7 +133,7 @@ before asking for help. | |||
133 | Send questions and/or comments to zlib@gzip.org, | 133 | Send questions and/or comments to zlib@gzip.org, |
134 | or (for the Windows DLL version) to Gilles Vollant (info@winimage.com). | 134 | or (for the Windows DLL version) to Gilles Vollant (info@winimage.com). |
135 | .SH AUTHORS | 135 | .SH AUTHORS |
136 | Version 1.2.3.3 | 136 | Version 1.2.3.4 |
137 | Copyright (C) 1995-2006 Jean-loup Gailly (jloup@gzip.org) | 137 | Copyright (C) 1995-2006 Jean-loup Gailly (jloup@gzip.org) |
138 | and Mark Adler (madler@alumni.caltech.edu). | 138 | and Mark Adler (madler@alumni.caltech.edu). |
139 | .LP | 139 | .LP |
@@ -1,7 +1,7 @@ | |||
1 | /* zlib.h -- interface of the 'zlib' general purpose compression library | 1 | /* zlib.h -- interface of the 'zlib' general purpose compression library |
2 | version 1.2.3.3, October 2nd, 2006 | 2 | version 1.2.3.4, December 21st, 2009 |
3 | 3 | ||
4 | Copyright (C) 1995-2006 Jean-loup Gailly and Mark Adler | 4 | Copyright (C) 1995-2009 Jean-loup Gailly and Mark Adler |
5 | 5 | ||
6 | This software is provided 'as-is', without any express or implied | 6 | This software is provided 'as-is', without any express or implied |
7 | warranty. In no event will the authors be held liable for any damages | 7 | warranty. In no event will the authors be held liable for any damages |
@@ -37,8 +37,8 @@ | |||
37 | extern "C" { | 37 | extern "C" { |
38 | #endif | 38 | #endif |
39 | 39 | ||
40 | #define ZLIB_VERSION "1.2.3.3" | 40 | #define ZLIB_VERSION "1.2.3.4" |
41 | #define ZLIB_VERNUM 0x1233 | 41 | #define ZLIB_VERNUM 0x1234 |
42 | #define ZLIB_VER_MAJOR 1 | 42 | #define ZLIB_VER_MAJOR 1 |
43 | #define ZLIB_VER_MINOR 2 | 43 | #define ZLIB_VER_MINOR 2 |
44 | #define ZLIB_VER_REVISION 3 | 44 | #define ZLIB_VER_REVISION 3 |
@@ -163,11 +163,12 @@ typedef gz_header FAR *gz_headerp; | |||
163 | /* constants */ | 163 | /* constants */ |
164 | 164 | ||
165 | #define Z_NO_FLUSH 0 | 165 | #define Z_NO_FLUSH 0 |
166 | #define Z_PARTIAL_FLUSH 1 /* will be removed, use Z_SYNC_FLUSH instead */ | 166 | #define Z_PARTIAL_FLUSH 1 |
167 | #define Z_SYNC_FLUSH 2 | 167 | #define Z_SYNC_FLUSH 2 |
168 | #define Z_FULL_FLUSH 3 | 168 | #define Z_FULL_FLUSH 3 |
169 | #define Z_FINISH 4 | 169 | #define Z_FINISH 4 |
170 | #define Z_BLOCK 5 | 170 | #define Z_BLOCK 5 |
171 | #define Z_TREES 6 | ||
171 | /* Allowed flush values; see deflate() and inflate() below for details */ | 172 | /* Allowed flush values; see deflate() and inflate() below for details */ |
172 | 173 | ||
173 | #define Z_OK 0 | 174 | #define Z_OK 0 |
@@ -273,7 +274,7 @@ ZEXTERN int ZEXPORT deflate OF((z_streamp strm, int flush)); | |||
273 | output buffer because there might be more output pending. | 274 | output buffer because there might be more output pending. |
274 | 275 | ||
275 | Normally the parameter flush is set to Z_NO_FLUSH, which allows deflate to | 276 | Normally the parameter flush is set to Z_NO_FLUSH, which allows deflate to |
276 | decide how much data to accumualte before producing output, in order to | 277 | decide how much data to accumulate before producing output, in order to |
277 | maximize compression. | 278 | maximize compression. |
278 | 279 | ||
279 | If the parameter flush is set to Z_SYNC_FLUSH, all pending output is | 280 | If the parameter flush is set to Z_SYNC_FLUSH, all pending output is |
@@ -281,7 +282,26 @@ ZEXTERN int ZEXPORT deflate OF((z_streamp strm, int flush)); | |||
281 | that the decompressor can get all input data available so far. (In particular | 282 | that the decompressor can get all input data available so far. (In particular |
282 | avail_in is zero after the call if enough output space has been provided | 283 | avail_in is zero after the call if enough output space has been provided |
283 | before the call.) Flushing may degrade compression for some compression | 284 | before the call.) Flushing may degrade compression for some compression |
284 | algorithms and so it should be used only when necessary. | 285 | algorithms and so it should be used only when necessary. This completes the |
286 | current deflate block and follows it with an empty stored block that is three | ||
287 | bits plus filler bits to the next byte, followed by four bytes (00 00 ff ff). | ||
288 | |||
289 | If flush is set to Z_PARTIAL_FLUSH, all pending output is flushed to the | ||
290 | output buffer, but the output is not aligned to a byte boundary. All of the | ||
291 | input data so far will be available to the decompressor, as for Z_SYNC_FLUSH. | ||
292 | This completes the current deflate block and follows it with an empty fixed | ||
293 | codes block that is 10 bits long. This assures that enough bytes are output | ||
294 | in order for the decompressor to finish the block before the empty fixed code | ||
295 | block. | ||
296 | |||
297 | If flush is set to Z_BLOCK, a deflate block is completed and emitted, as | ||
298 | for Z_SYNC_FLUSH, but the output is not aligned on a byte boundary, and up to | ||
299 | seven bits of the current block are held to be written as the next byte after | ||
300 | the next deflate block is completed. In this case, the decompressor may not | ||
301 | be provided enough bits at this point in order to complete decompression of | ||
302 | the data provided so far to the compressor. It may need to wait for the next | ||
303 | block to be emitted. This is for advanced applications that need to control | ||
304 | the emission of deflate blocks. | ||
285 | 305 | ||
286 | If flush is set to Z_FULL_FLUSH, all output is flushed as with | 306 | If flush is set to Z_FULL_FLUSH, all output is flushed as with |
287 | Z_SYNC_FLUSH, and the compression state is reset so that decompression can | 307 | Z_SYNC_FLUSH, and the compression state is reset so that decompression can |
@@ -321,7 +341,7 @@ ZEXTERN int ZEXPORT deflate OF((z_streamp strm, int flush)); | |||
321 | processed or more output produced), Z_STREAM_END if all input has been | 341 | processed or more output produced), Z_STREAM_END if all input has been |
322 | consumed and all output has been produced (only when flush is set to | 342 | consumed and all output has been produced (only when flush is set to |
323 | Z_FINISH), Z_STREAM_ERROR if the stream state was inconsistent (for example | 343 | Z_FINISH), Z_STREAM_ERROR if the stream state was inconsistent (for example |
324 | if next_in or next_out was NULL), Z_BUF_ERROR if no progress is possible | 344 | if next_in or next_out was Z_NULL), Z_BUF_ERROR if no progress is possible |
325 | (for example avail_in or avail_out was zero). Note that Z_BUF_ERROR is not | 345 | (for example avail_in or avail_out was zero). Note that Z_BUF_ERROR is not |
326 | fatal, and deflate() can be called again with more input and more output | 346 | fatal, and deflate() can be called again with more input and more output |
327 | space to continue compressing. | 347 | space to continue compressing. |
@@ -396,8 +416,8 @@ ZEXTERN int ZEXPORT inflate OF((z_streamp strm, int flush)); | |||
396 | must be called again after making room in the output buffer because there | 416 | must be called again after making room in the output buffer because there |
397 | might be more output pending. | 417 | might be more output pending. |
398 | 418 | ||
399 | The flush parameter of inflate() can be Z_NO_FLUSH, Z_SYNC_FLUSH, | 419 | The flush parameter of inflate() can be Z_NO_FLUSH, Z_SYNC_FLUSH, Z_FINISH, |
400 | Z_FINISH, or Z_BLOCK. Z_SYNC_FLUSH requests that inflate() flush as much | 420 | Z_BLOCK, or Z_TREES. Z_SYNC_FLUSH requests that inflate() flush as much |
401 | output as possible to the output buffer. Z_BLOCK requests that inflate() stop | 421 | output as possible to the output buffer. Z_BLOCK requests that inflate() stop |
402 | if and when it gets to the next deflate block boundary. When decoding the | 422 | if and when it gets to the next deflate block boundary. When decoding the |
403 | zlib or gzip format, this will cause inflate() to return immediately after | 423 | zlib or gzip format, this will cause inflate() to return immediately after |
@@ -415,7 +435,16 @@ ZEXTERN int ZEXPORT inflate OF((z_streamp strm, int flush)); | |||
415 | uncompressed data from that block has been written to strm->next_out. The | 435 | uncompressed data from that block has been written to strm->next_out. The |
416 | number of unused bits may in general be greater than seven, except when | 436 | number of unused bits may in general be greater than seven, except when |
417 | bit 7 of data_type is set, in which case the number of unused bits will be | 437 | bit 7 of data_type is set, in which case the number of unused bits will be |
418 | less than eight. | 438 | less than eight. data_type is set as noted here every time inflate() |
439 | returns for all flush options, and so can be used to determine the amount | ||
440 | of currently consumed input in bits. | ||
441 | |||
442 | The Z_TREES option behaves as Z_BLOCK does, but it also returns when the | ||
443 | end of each deflate block header is reached, before any actual data in that | ||
444 | block is decoded. This allows the caller to determine the length of the | ||
445 | deflate block header for later use in random access within a deflate block. | ||
446 | 256 is added to the value of strm->data_type when inflate() returns | ||
447 | immediately after reaching the end of the deflate block header. | ||
419 | 448 | ||
420 | inflate() should normally be called until it returns Z_STREAM_END or an | 449 | inflate() should normally be called until it returns Z_STREAM_END or an |
421 | error. However if all decompression is to be performed in a single step | 450 | error. However if all decompression is to be performed in a single step |
@@ -432,7 +461,7 @@ ZEXTERN int ZEXPORT inflate OF((z_streamp strm, int flush)); | |||
432 | possible to the output buffer, and always uses the faster approach on the | 461 | possible to the output buffer, and always uses the faster approach on the |
433 | first call. So the only effect of the flush parameter in this implementation | 462 | first call. So the only effect of the flush parameter in this implementation |
434 | is on the return value of inflate(), as noted below, or when it returns early | 463 | is on the return value of inflate(), as noted below, or when it returns early |
435 | because Z_BLOCK is used. | 464 | because Z_BLOCK or Z_TREES is used. |
436 | 465 | ||
437 | If a preset dictionary is needed after this call (see inflateSetDictionary | 466 | If a preset dictionary is needed after this call (see inflateSetDictionary |
438 | below), inflate sets strm->adler to the adler32 checksum of the dictionary | 467 | below), inflate sets strm->adler to the adler32 checksum of the dictionary |
@@ -443,12 +472,12 @@ ZEXTERN int ZEXPORT inflate OF((z_streamp strm, int flush)); | |||
443 | checksum is equal to that saved by the compressor and returns Z_STREAM_END | 472 | checksum is equal to that saved by the compressor and returns Z_STREAM_END |
444 | only if the checksum is correct. | 473 | only if the checksum is correct. |
445 | 474 | ||
446 | inflate() will decompress and check either zlib-wrapped or gzip-wrapped | 475 | inflate() can decompress and check either zlib-wrapped or gzip-wrapped |
447 | deflate data. The header type is detected automatically. Any information | 476 | deflate data. The header type is detected automatically, if requested when |
448 | contained in the gzip header is not retained, so applications that need that | 477 | initializing with inflateInit2(). Any information contained in the gzip |
449 | information should instead use raw inflate, see inflateInit2() below, or | 478 | header is not retained, so applications that need that information should |
450 | inflateBack() and perform their own processing of the gzip header and | 479 | instead use raw inflate, see inflateInit2() below, or inflateBack() and |
451 | trailer. | 480 | perform their own processing of the gzip header and trailer. |
452 | 481 | ||
453 | inflate() returns Z_OK if some progress has been made (more input processed | 482 | inflate() returns Z_OK if some progress has been made (more input processed |
454 | or more output produced), Z_STREAM_END if the end of the compressed data has | 483 | or more output produced), Z_STREAM_END if the end of the compressed data has |
@@ -456,7 +485,7 @@ ZEXTERN int ZEXPORT inflate OF((z_streamp strm, int flush)); | |||
456 | preset dictionary is needed at this point, Z_DATA_ERROR if the input data was | 485 | preset dictionary is needed at this point, Z_DATA_ERROR if the input data was |
457 | corrupted (input stream not conforming to the zlib format or incorrect check | 486 | corrupted (input stream not conforming to the zlib format or incorrect check |
458 | value), Z_STREAM_ERROR if the stream structure was inconsistent (for example | 487 | value), Z_STREAM_ERROR if the stream structure was inconsistent (for example |
459 | if next_in or next_out was NULL), Z_MEM_ERROR if there was not enough memory, | 488 | next_in or next_out was Z_NULL), Z_MEM_ERROR if there was not enough memory, |
460 | Z_BUF_ERROR if no progress is possible or if there was not enough room in the | 489 | Z_BUF_ERROR if no progress is possible or if there was not enough room in the |
461 | output buffer when Z_FINISH is used. Note that Z_BUF_ERROR is not fatal, and | 490 | output buffer when Z_FINISH is used. Note that Z_BUF_ERROR is not fatal, and |
462 | inflate() can be called again with more input and more output space to | 491 | inflate() can be called again with more input and more output space to |
@@ -529,12 +558,12 @@ ZEXTERN int ZEXPORT deflateInit2 OF((z_streamp strm, | |||
529 | random distribution. In this case, the compression algorithm is tuned to | 558 | random distribution. In this case, the compression algorithm is tuned to |
530 | compress them better. The effect of Z_FILTERED is to force more Huffman | 559 | compress them better. The effect of Z_FILTERED is to force more Huffman |
531 | coding and less string matching; it is somewhat intermediate between | 560 | coding and less string matching; it is somewhat intermediate between |
532 | Z_DEFAULT and Z_HUFFMAN_ONLY. Z_RLE is designed to be almost as fast as | 561 | Z_DEFAULT_STRATEGY and Z_HUFFMAN_ONLY. Z_RLE is designed to be almost as |
533 | Z_HUFFMAN_ONLY, but give better compression for PNG image data. The strategy | 562 | fast as Z_HUFFMAN_ONLY, but give better compression for PNG image data. The |
534 | parameter only affects the compression ratio but not the correctness of the | 563 | strategy parameter only affects the compression ratio but not the |
535 | compressed output even if it is not set appropriately. Z_FIXED prevents the | 564 | correctness of the compressed output even if it is not set appropriately. |
536 | use of dynamic Huffman codes, allowing for a simpler decoder for special | 565 | Z_FIXED prevents the use of dynamic Huffman codes, allowing for a simpler |
537 | applications. | 566 | decoder for special applications. |
538 | 567 | ||
539 | deflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough | 568 | deflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough |
540 | memory, Z_STREAM_ERROR if a parameter is invalid (such as an invalid | 569 | memory, Z_STREAM_ERROR if a parameter is invalid (such as an invalid |
@@ -561,11 +590,11 @@ ZEXTERN int ZEXPORT deflateSetDictionary OF((z_streamp strm, | |||
561 | 590 | ||
562 | Depending on the size of the compression data structures selected by | 591 | Depending on the size of the compression data structures selected by |
563 | deflateInit or deflateInit2, a part of the dictionary may in effect be | 592 | deflateInit or deflateInit2, a part of the dictionary may in effect be |
564 | discarded, for example if the dictionary is larger than the window size in | 593 | discarded, for example if the dictionary is larger than the window size |
565 | deflate or deflate2. Thus the strings most likely to be useful should be | 594 | provided in deflateInit or deflateInit2. Thus the strings most likely to be |
566 | put at the end of the dictionary, not at the front. In addition, the | 595 | useful should be put at the end of the dictionary, not at the front. In |
567 | current implementation of deflate will use at most the window size minus | 596 | addition, the current implementation of deflate will use at most the window |
568 | 262 bytes of the provided dictionary. | 597 | size minus 262 bytes of the provided dictionary. |
569 | 598 | ||
570 | Upon return of this function, strm->adler is set to the adler32 value | 599 | Upon return of this function, strm->adler is set to the adler32 value |
571 | of the dictionary; the decompressor may later use this value to determine | 600 | of the dictionary; the decompressor may later use this value to determine |
@@ -575,7 +604,7 @@ ZEXTERN int ZEXPORT deflateSetDictionary OF((z_streamp strm, | |||
575 | adler32 value is not computed and strm->adler is not set. | 604 | adler32 value is not computed and strm->adler is not set. |
576 | 605 | ||
577 | deflateSetDictionary returns Z_OK if success, or Z_STREAM_ERROR if a | 606 | deflateSetDictionary returns Z_OK if success, or Z_STREAM_ERROR if a |
578 | parameter is invalid (such as NULL dictionary) or the stream state is | 607 | parameter is invalid (e.g. dictionary being Z_NULL) or the stream state is |
579 | inconsistent (for example if deflate has already been called for this stream | 608 | inconsistent (for example if deflate has already been called for this stream |
580 | or if the compression method is bsort). deflateSetDictionary does not | 609 | or if the compression method is bsort). deflateSetDictionary does not |
581 | perform any compression: this will be done by deflate(). | 610 | perform any compression: this will be done by deflate(). |
@@ -595,7 +624,7 @@ ZEXTERN int ZEXPORT deflateCopy OF((z_streamp dest, | |||
595 | 624 | ||
596 | deflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not | 625 | deflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not |
597 | enough memory, Z_STREAM_ERROR if the source stream state was inconsistent | 626 | enough memory, Z_STREAM_ERROR if the source stream state was inconsistent |
598 | (such as zalloc being NULL). msg is left unchanged in both source and | 627 | (such as zalloc being Z_NULL). msg is left unchanged in both source and |
599 | destination. | 628 | destination. |
600 | */ | 629 | */ |
601 | 630 | ||
@@ -607,7 +636,7 @@ ZEXTERN int ZEXPORT deflateReset OF((z_streamp strm)); | |||
607 | that may have been set by deflateInit2. | 636 | that may have been set by deflateInit2. |
608 | 637 | ||
609 | deflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source | 638 | deflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source |
610 | stream state was inconsistent (such as zalloc or state being NULL). | 639 | stream state was inconsistent (such as zalloc or state being Z_NULL). |
611 | */ | 640 | */ |
612 | 641 | ||
613 | ZEXTERN int ZEXPORT deflateParams OF((z_streamp strm, | 642 | ZEXTERN int ZEXPORT deflateParams OF((z_streamp strm, |
@@ -760,7 +789,7 @@ ZEXTERN int ZEXPORT inflateSetDictionary OF((z_streamp strm, | |||
760 | dictionary that was used for compression is provided. | 789 | dictionary that was used for compression is provided. |
761 | 790 | ||
762 | inflateSetDictionary returns Z_OK if success, Z_STREAM_ERROR if a | 791 | inflateSetDictionary returns Z_OK if success, Z_STREAM_ERROR if a |
763 | parameter is invalid (such as NULL dictionary) or the stream state is | 792 | parameter is invalid (e.g. dictionary being Z_NULL) or the stream state is |
764 | inconsistent, Z_DATA_ERROR if the given dictionary doesn't match the | 793 | inconsistent, Z_DATA_ERROR if the given dictionary doesn't match the |
765 | expected one (incorrect adler32 value). inflateSetDictionary does not | 794 | expected one (incorrect adler32 value). inflateSetDictionary does not |
766 | perform any decompression: this will be done by subsequent calls of | 795 | perform any decompression: this will be done by subsequent calls of |
@@ -794,7 +823,7 @@ ZEXTERN int ZEXPORT inflateCopy OF((z_streamp dest, | |||
794 | 823 | ||
795 | inflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not | 824 | inflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not |
796 | enough memory, Z_STREAM_ERROR if the source stream state was inconsistent | 825 | enough memory, Z_STREAM_ERROR if the source stream state was inconsistent |
797 | (such as zalloc being NULL). msg is left unchanged in both source and | 826 | (such as zalloc being Z_NULL). msg is left unchanged in both source and |
798 | destination. | 827 | destination. |
799 | */ | 828 | */ |
800 | 829 | ||
@@ -805,7 +834,19 @@ ZEXTERN int ZEXPORT inflateReset OF((z_streamp strm)); | |||
805 | The stream will keep attributes that may have been set by inflateInit2. | 834 | The stream will keep attributes that may have been set by inflateInit2. |
806 | 835 | ||
807 | inflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source | 836 | inflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source |
808 | stream state was inconsistent (such as zalloc or state being NULL). | 837 | stream state was inconsistent (such as zalloc or state being Z_NULL). |
838 | */ | ||
839 | |||
840 | ZEXTERN int ZEXPORT inflateReset2 OF((z_streamp strm, | ||
841 | int windowBits)); | ||
842 | /* | ||
843 | This function is the same as inflateReset, but it also permits changing | ||
844 | the wrap and window size requests. The windowBits parameter is | ||
845 | interpreted the same as it is for inflateInit2. | ||
846 | |||
847 | inflateReset2 returns Z_OK if success, or Z_STREAM_ERROR if the source | ||
848 | stream state was inconsistent (such as zalloc or state being Z_NULL), or if | ||
849 | the windowBits parameter is invalid. | ||
809 | */ | 850 | */ |
810 | 851 | ||
811 | ZEXTERN int ZEXPORT inflatePrime OF((z_streamp strm, | 852 | ZEXTERN int ZEXPORT inflatePrime OF((z_streamp strm, |
@@ -820,10 +861,43 @@ ZEXTERN int ZEXPORT inflatePrime OF((z_streamp strm, | |||
820 | inflateReset(). bits must be less than or equal to 16, and that many of the | 861 | inflateReset(). bits must be less than or equal to 16, and that many of the |
821 | least significant bits of value will be inserted in the input. | 862 | least significant bits of value will be inserted in the input. |
822 | 863 | ||
864 | If bits is negative, then the input stream bit buffer is emptied. Then | ||
865 | inflatePrime() can be called again to put bits in the buffer. This is used | ||
866 | to clear out bits leftover after feeding inflate a block description prior | ||
867 | to feeding inflate codes. | ||
868 | |||
823 | inflatePrime returns Z_OK if success, or Z_STREAM_ERROR if the source | 869 | inflatePrime returns Z_OK if success, or Z_STREAM_ERROR if the source |
824 | stream state was inconsistent. | 870 | stream state was inconsistent. |
825 | */ | 871 | */ |
826 | 872 | ||
873 | ZEXTERN long ZEXPORT inflateMark OF((z_streamp strm)); | ||
874 | /* | ||
875 | This function returns two values, one in the lower 16 bits of the return | ||
876 | value, and the other in the remaining upper bits, obtained by shifting the | ||
877 | return value down 16 bits. If the upper value is -1 and the lower value is | ||
878 | zero, then inflate() is currently decoding information outside of a block. | ||
879 | If the upper value is -1 and the lower value is non-zero, then inflate is in | ||
880 | the middle of a stored block, with the lower value equaling the number of | ||
881 | bytes from the input remaining to copy. If the upper value is not -1, then | ||
882 | it is the number of bits back from the current bit position in the input of | ||
883 | the code (literal or length/distance pair) currently being processed. In | ||
884 | that case the lower value is the number of bytes already emitted for that | ||
885 | code. | ||
886 | |||
887 | A code is being processed if inflate is waiting for more input to complete | ||
888 | decoding of the code, or if it has completed decoding but is waiting for | ||
889 | more output space to write the literal or match data. | ||
890 | |||
891 | inflateMark() is used to mark locations in the input data for random | ||
892 | access, which may be at bit positions, and to note those cases where the | ||
893 | output of a code may span boundaries of random access blocks. The current | ||
894 | location in the input stream can be determined from avail_in and data_type | ||
895 | as noted in the description for the Z_BLOCK flush parameter for inflate. | ||
896 | |||
897 | inflateMark returns the value noted above or -1 << 16 if the provided | ||
898 | source stream state was inconsistent. | ||
899 | */ | ||
900 | |||
827 | ZEXTERN int ZEXPORT inflateGetHeader OF((z_streamp strm, | 901 | ZEXTERN int ZEXPORT inflateGetHeader OF((z_streamp strm, |
828 | gz_headerp head)); | 902 | gz_headerp head)); |
829 | /* | 903 | /* |
@@ -833,9 +907,9 @@ ZEXTERN int ZEXPORT inflateGetHeader OF((z_streamp strm, | |||
833 | As inflate() processes the gzip stream, head->done is zero until the header | 907 | As inflate() processes the gzip stream, head->done is zero until the header |
834 | is completed, at which time head->done is set to one. If a zlib stream is | 908 | is completed, at which time head->done is set to one. If a zlib stream is |
835 | being decoded, then head->done is set to -1 to indicate that there will be | 909 | being decoded, then head->done is set to -1 to indicate that there will be |
836 | no gzip header information forthcoming. Note that Z_BLOCK can be used to | 910 | no gzip header information forthcoming. Note that Z_BLOCK or Z_TREES can be |
837 | force inflate() to return immediately after header processing is complete | 911 | used to force inflate() to return immediately after header processing is |
838 | and before any actual data is decompressed. | 912 | complete and before any actual data is decompressed. |
839 | 913 | ||
840 | The text, time, xflags, and os fields are filled in with the gzip header | 914 | The text, time, xflags, and os fields are filled in with the gzip header |
841 | contents. hcrc is set to true if there is a header CRC. (The header CRC | 915 | contents. hcrc is set to true if there is a header CRC. (The header CRC |
@@ -952,7 +1026,7 @@ ZEXTERN int ZEXPORT inflateBack OF((z_streamp strm, | |||
952 | nature of the error), or Z_STREAM_ERROR if the stream was not properly | 1026 | nature of the error), or Z_STREAM_ERROR if the stream was not properly |
953 | initialized. In the case of Z_BUF_ERROR, an input or output error can be | 1027 | initialized. In the case of Z_BUF_ERROR, an input or output error can be |
954 | distinguished using strm->next_in which will be Z_NULL only if in() returned | 1028 | distinguished using strm->next_in which will be Z_NULL only if in() returned |
955 | an error. If strm->next is not Z_NULL, then the Z_BUF_ERROR was due to | 1029 | an error. If strm->next_in is not Z_NULL, then the Z_BUF_ERROR was due to |
956 | out() returning non-zero. (in() will always be called before out(), so | 1030 | out() returning non-zero. (in() will always be called before out(), so |
957 | strm->next_in is assured to be defined if out() returns non-zero.) Note | 1031 | strm->next_in is assured to be defined if out() returns non-zero.) Note |
958 | that inflateBack() cannot return Z_OK. | 1032 | that inflateBack() cannot return Z_OK. |
@@ -1065,7 +1139,7 @@ ZEXTERN int ZEXPORT uncompress OF((Bytef *dest, uLongf *destLen, | |||
1065 | entire uncompressed data. (The size of the uncompressed data must have | 1139 | entire uncompressed data. (The size of the uncompressed data must have |
1066 | been saved previously by the compressor and transmitted to the decompressor | 1140 | been saved previously by the compressor and transmitted to the decompressor |
1067 | by some mechanism outside the scope of this compression library.) | 1141 | by some mechanism outside the scope of this compression library.) |
1068 | Upon exit, destLen is the actual size of the compressed buffer. | 1142 | Upon exit, destLen is the actual size of the uncompressed buffer. |
1069 | This function can be used to decompress a whole file at once if the | 1143 | This function can be used to decompress a whole file at once if the |
1070 | input file is mmap'ed. | 1144 | input file is mmap'ed. |
1071 | 1145 | ||
@@ -1279,7 +1353,7 @@ ZEXTERN void ZEXPORT gzclearerr OF((gzFile file)); | |||
1279 | ZEXTERN uLong ZEXPORT adler32 OF((uLong adler, const Bytef *buf, uInt len)); | 1353 | ZEXTERN uLong ZEXPORT adler32 OF((uLong adler, const Bytef *buf, uInt len)); |
1280 | /* | 1354 | /* |
1281 | Update a running Adler-32 checksum with the bytes buf[0..len-1] and | 1355 | Update a running Adler-32 checksum with the bytes buf[0..len-1] and |
1282 | return the updated checksum. If buf is NULL, this function returns | 1356 | return the updated checksum. If buf is Z_NULL, this function returns |
1283 | the required initial value for the checksum. | 1357 | the required initial value for the checksum. |
1284 | An Adler-32 checksum is almost as reliable as a CRC32 but can be computed | 1358 | An Adler-32 checksum is almost as reliable as a CRC32 but can be computed |
1285 | much faster. Usage example: | 1359 | much faster. Usage example: |
@@ -1305,7 +1379,7 @@ ZEXTERN uLong ZEXPORT adler32_combine OF((uLong adler1, uLong adler2, | |||
1305 | ZEXTERN uLong ZEXPORT crc32 OF((uLong crc, const Bytef *buf, uInt len)); | 1379 | ZEXTERN uLong ZEXPORT crc32 OF((uLong crc, const Bytef *buf, uInt len)); |
1306 | /* | 1380 | /* |
1307 | Update a running CRC-32 with the bytes buf[0..len-1] and return the | 1381 | Update a running CRC-32 with the bytes buf[0..len-1] and return the |
1308 | updated CRC-32. If buf is NULL, this function returns the required initial | 1382 | updated CRC-32. If buf is Z_NULL, this function returns the required initial |
1309 | value for the for the crc. Pre- and post-conditioning (one's complement) is | 1383 | value for the for the crc. Pre- and post-conditioning (one's complement) is |
1310 | performed within this function so it shouldn't be done by the application. | 1384 | performed within this function so it shouldn't be done by the application. |
1311 | Usage example: | 1385 | Usage example: |
@@ -1369,12 +1443,19 @@ ZEXTERN int ZEXPORT inflateBackInit_ OF((z_streamp strm, int windowBits, | |||
1369 | ZEXTERN uLong ZEXPORT crc32_combine64 OF((uLong, uLong, off64_t)); | 1443 | ZEXTERN uLong ZEXPORT crc32_combine64 OF((uLong, uLong, off64_t)); |
1370 | #endif | 1444 | #endif |
1371 | 1445 | ||
1372 | #if _FILE_OFFSET_BITS == 64 | 1446 | #if !defined(ZLIB_INTERNAL) && _FILE_OFFSET_BITS == 64 |
1373 | # define gzopen gzopen64 | 1447 | # define gzopen gzopen64 |
1374 | # define gzseek gzseek64 | 1448 | # define gzseek gzseek64 |
1375 | # define gztell gztell64 | 1449 | # define gztell gztell64 |
1376 | # define adler32_combine adler32_combine64 | 1450 | # define adler32_combine adler32_combine64 |
1377 | # define crc32_combine crc32_combine64 | 1451 | # define crc32_combine crc32_combine64 |
1452 | # ifndef _LARGEFILE64_SOURCE | ||
1453 | ZEXTERN gzFile ZEXPORT gzopen64 OF((const char *, const char *)); | ||
1454 | ZEXTERN off_t ZEXPORT gzseek64 OF((gzFile, off_t, int)); | ||
1455 | ZEXTERN off_t ZEXPORT gztell64 OF((gzFile)); | ||
1456 | ZEXTERN uLong ZEXPORT adler32_combine64 OF((uLong, uLong, off_t)); | ||
1457 | ZEXTERN uLong ZEXPORT crc32_combine64 OF((uLong, uLong, off_t)); | ||
1458 | # endif | ||
1378 | #else | 1459 | #else |
1379 | ZEXTERN gzFile ZEXPORT gzopen OF((const char *, const char *)); | 1460 | ZEXTERN gzFile ZEXPORT gzopen OF((const char *, const char *)); |
1380 | ZEXTERN z_off_t ZEXPORT gzseek OF((gzFile, z_off_t, int)); | 1461 | ZEXTERN z_off_t ZEXPORT gzseek OF((gzFile, z_off_t, int)); |
@@ -42,3 +42,12 @@ ZLIB_1.2.2.3 { | |||
42 | ZLIB_1.2.2.4 { | 42 | ZLIB_1.2.2.4 { |
43 | inflatePrime; | 43 | inflatePrime; |
44 | } ZLIB_1.2.2.3; | 44 | } ZLIB_1.2.2.3; |
45 | |||
46 | ZLIB_1.2.3.3 { | ||
47 | inflateUndermine; | ||
48 | } ZLIB_1.2.2.4; | ||
49 | |||
50 | ZLIB_1.2.3.4 { | ||
51 | inflateReset2; | ||
52 | inflateMark; | ||
53 | } ZLIB_1.2.3.3; | ||
diff --git a/zlib2ansi b/zlib2ansi new file mode 100755 index 0000000..0695f6b --- /dev/null +++ b/zlib2ansi | |||
@@ -0,0 +1,152 @@ | |||
1 | #!/usr/bin/perl | ||
2 | |||
3 | # Transform K&R C function definitions into ANSI equivalent. | ||
4 | # | ||
5 | # Author: Paul Marquess | ||
6 | # Version: 1.0 | ||
7 | # Date: 3 October 2006 | ||
8 | |||
9 | # TODO | ||
10 | # | ||
11 | # Asumes no function pointer parameters. unless they are typedefed. | ||
12 | # Assumes no literal strings that look like function definitions | ||
13 | # Assumes functions start at the beginning of a line | ||
14 | |||
15 | use strict; | ||
16 | use warnings; | ||
17 | |||
18 | local $/; | ||
19 | $_ = <>; | ||
20 | |||
21 | my $sp = qr{ \s* (?: /\* .*? \*/ )? \s* }x; # assume no nested comments | ||
22 | |||
23 | my $d1 = qr{ $sp (?: [\w\*\s]+ $sp)* $sp \w+ $sp [\[\]\s]* $sp }x ; | ||
24 | my $decl = qr{ $sp (?: \w+ $sp )+ $d1 }xo ; | ||
25 | my $dList = qr{ $sp $decl (?: $sp , $d1 )* $sp ; $sp }xo ; | ||
26 | |||
27 | |||
28 | while (s/^ | ||
29 | ( # Start $1 | ||
30 | ( # Start $2 | ||
31 | .*? # Minimal eat content | ||
32 | ( ^ \w [\w\s\*]+ ) # $3 -- function name | ||
33 | \s* # optional whitespace | ||
34 | ) # $2 - Matched up to before parameter list | ||
35 | |||
36 | \( \s* # Literal "(" + optional whitespace | ||
37 | ( [^\)]+ ) # $4 - one or more anythings except ")" | ||
38 | \s* \) # optional whitespace surrounding a Literal ")" | ||
39 | |||
40 | ( (?: $dList )+ ) # $5 | ||
41 | |||
42 | $sp ^ { # literal "{" at start of line | ||
43 | ) # Remember to $1 | ||
44 | //xsom | ||
45 | ) | ||
46 | { | ||
47 | my $all = $1 ; | ||
48 | my $prefix = $2; | ||
49 | my $param_list = $4 ; | ||
50 | my $params = $5; | ||
51 | |||
52 | StripComments($params); | ||
53 | StripComments($param_list); | ||
54 | $param_list =~ s/^\s+//; | ||
55 | $param_list =~ s/\s+$//; | ||
56 | |||
57 | my $i = 0 ; | ||
58 | my %pList = map { $_ => $i++ } | ||
59 | split /\s*,\s*/, $param_list; | ||
60 | my $pMatch = '(\b' . join('|', keys %pList) . '\b)\W*$' ; | ||
61 | |||
62 | my @params = split /\s*;\s*/, $params; | ||
63 | my @outParams = (); | ||
64 | foreach my $p (@params) | ||
65 | { | ||
66 | if ($p =~ /,/) | ||
67 | { | ||
68 | my @bits = split /\s*,\s*/, $p; | ||
69 | my $first = shift @bits; | ||
70 | $first =~ s/^\s*//; | ||
71 | push @outParams, $first; | ||
72 | $first =~ /^(\w+\s*)/; | ||
73 | my $type = $1 ; | ||
74 | push @outParams, map { $type . $_ } @bits; | ||
75 | } | ||
76 | else | ||
77 | { | ||
78 | $p =~ s/^\s+//; | ||
79 | push @outParams, $p; | ||
80 | } | ||
81 | } | ||
82 | |||
83 | |||
84 | my %tmp = map { /$pMatch/; $_ => $pList{$1} } | ||
85 | @outParams ; | ||
86 | |||
87 | @outParams = map { " $_" } | ||
88 | sort { $tmp{$a} <=> $tmp{$b} } | ||
89 | @outParams ; | ||
90 | |||
91 | print $prefix ; | ||
92 | print "(\n" . join(",\n", @outParams) . ")\n"; | ||
93 | print "{" ; | ||
94 | |||
95 | } | ||
96 | |||
97 | # Output any trailing code. | ||
98 | print ; | ||
99 | exit 0; | ||
100 | |||
101 | |||
102 | sub StripComments | ||
103 | { | ||
104 | |||
105 | no warnings; | ||
106 | |||
107 | # Strip C & C++ coments | ||
108 | # From the perlfaq | ||
109 | $_[0] =~ | ||
110 | |||
111 | s{ | ||
112 | /\* ## Start of /* ... */ comment | ||
113 | [^*]*\*+ ## Non-* followed by 1-or-more *'s | ||
114 | ( | ||
115 | [^/*][^*]*\*+ | ||
116 | )* ## 0-or-more things which don't start with / | ||
117 | ## but do end with '*' | ||
118 | / ## End of /* ... */ comment | ||
119 | |||
120 | | ## OR C++ Comment | ||
121 | // ## Start of C++ comment // | ||
122 | [^\n]* ## followed by 0-or-more non end of line characters | ||
123 | |||
124 | | ## OR various things which aren't comments: | ||
125 | |||
126 | ( | ||
127 | " ## Start of " ... " string | ||
128 | ( | ||
129 | \\. ## Escaped char | ||
130 | | ## OR | ||
131 | [^"\\] ## Non "\ | ||
132 | )* | ||
133 | " ## End of " ... " string | ||
134 | |||
135 | | ## OR | ||
136 | |||
137 | ' ## Start of ' ... ' string | ||
138 | ( | ||
139 | \\. ## Escaped char | ||
140 | | ## OR | ||
141 | [^'\\] ## Non '\ | ||
142 | )* | ||
143 | ' ## End of ' ... ' string | ||
144 | |||
145 | | ## OR | ||
146 | |||
147 | . ## Anything other char | ||
148 | [^/"'\\]* ## Chars which doesn't start a comment, string or escape | ||
149 | ) | ||
150 | }{$2}gxs; | ||
151 | |||
152 | } | ||
@@ -167,6 +167,12 @@ extern const char * const z_errmsg[10]; /* indexed by 2-zlib_error */ | |||
167 | #pragma warn -8066 | 167 | #pragma warn -8066 |
168 | #endif | 168 | #endif |
169 | 169 | ||
170 | #ifdef _LARGEFILE64_SOURCE | ||
171 | # define z_off64_t off64_t | ||
172 | #else | ||
173 | # define z_off64_t z_off_t | ||
174 | #endif | ||
175 | |||
170 | /* common defaults */ | 176 | /* common defaults */ |
171 | 177 | ||
172 | #ifndef OS_CODE | 178 | #ifndef OS_CODE |