3rdparty/zlib: Update to 1.3

This commit is contained in:
Stenzek 2023-10-02 15:34:09 +10:00 committed by Connor McLaughlin
parent fe0d31ae94
commit 828c0bcb99
39 changed files with 11884 additions and 7342 deletions

View File

@ -1,6 +1,99 @@
ChangeLog file for zlib ChangeLog file for zlib
Changes in 1.3 (18 Aug 2023)
- Remove K&R function definitions and zlib2ansi
- Fix bug in deflateBound() for level 0 and memLevel 9
- Fix bug when gzungetc() is used immediately after gzopen()
- Fix bug when using gzflush() with a very small buffer
- Fix crash when gzsetparams() attempted for transparent write
- Fix test/example.c to work with FORCE_STORED
- Rewrite of zran in examples (see zran.c version history)
- Fix minizip to allow it to open an empty zip file
- Fix reading disk number start on zip64 files in minizip
- Fix logic error in minizip argument processing
- Add minizip testing to Makefile
- Read multiple bytes instead of byte-by-byte in minizip unzip.c
- Add memory sanitizer to configure (--memory)
- Various portability improvements
- Various documentation improvements
- Various spelling and typo corrections
Changes in 1.2.13 (13 Oct 2022)
- Fix configure issue that discarded provided CC definition
- Correct incorrect inputs provided to the CRC functions
- Repair prototypes and exporting of new CRC functions
- Fix inflateBack to detect invalid input with distances too far
- Have infback() deliver all of the available output up to any error
- Fix a bug when getting a gzip header extra field with inflate()
- Fix bug in block type selection when Z_FIXED used
- Tighten deflateBound bounds
- Remove deleted assembler code references
- Various portability and appearance improvements
Changes in 1.2.12 (27 Mar 2022)
- Cygwin does not have _wopen(), so do not create gzopen_w() there
- Permit a deflateParams() parameter change as soon as possible
- Limit hash table inserts after switch from stored deflate
- Fix bug when window full in deflate_stored()
- Fix CLEAR_HASH macro to be usable as a single statement
- Avoid a conversion error in gzseek when off_t type too small
- Have Makefile return non-zero error code on test failure
- Avoid some conversion warnings in gzread.c and gzwrite.c
- Update use of errno for newer Windows CE versions
- Small speedup to inflate [psumbera]
- Return an error if the gzputs string length can't fit in an int
- Add address checking in clang to -w option of configure
- Don't compute check value for raw inflate if asked to validate
- Handle case where inflateSync used when header never processed
- Avoid the use of ptrdiff_t
- Avoid an undefined behavior of memcpy() in gzappend()
- Avoid undefined behaviors of memcpy() in gz*printf()
- Avoid an undefined behavior of memcpy() in _tr_stored_block()
- Make the names in functions declarations identical to definitions
- Remove old assembler code in which bugs have manifested
- Fix deflateEnd() to not report an error at start of raw deflate
- Add legal disclaimer to README
- Emphasize the need to continue decompressing gzip members
- Correct the initialization requirements for deflateInit2()
- Fix a bug that can crash deflate on some input when using Z_FIXED
- Assure that the number of bits for deflatePrime() is valid
- Use a structure to make globals in enough.c evident
- Use a macro for the printf format of big_t in enough.c
- Clean up code style in enough.c, update version
- Use inline function instead of macro for index in enough.c
- Clarify that prefix codes are counted in enough.c
- Show all the codes for the maximum tables size in enough.c
- Add gznorm.c example, which normalizes gzip files
- Fix the zran.c example to work on a multiple-member gzip file
- Add tables for crc32_combine(), to speed it up by a factor of 200
- Add crc32_combine_gen() and crc32_combine_op() for fast combines
- Speed up software CRC-32 computation by a factor of 1.5 to 3
- Use atomic test and set, if available, for dynamic CRC tables
- Don't bother computing check value after successful inflateSync()
- Correct comment in crc32.c
- Add use of the ARMv8 crc32 instructions when requested
- Use ARM crc32 instructions if the ARM architecture has them
- Explicitly note that the 32-bit check values are 32 bits
- Avoid adding empty gzip member after gzflush with Z_FINISH
- Fix memory leak on error in gzlog.c
- Fix error in comment on the polynomial representation of a byte
- Clarify gz* function interfaces, referring to parameter names
- Change macro name in inflate.c to avoid collision in VxWorks
- Correct typo in blast.c
- Improve portability of contrib/minizip
- Fix indentation in minizip's zip.c
- Replace black/white with allow/block. (theresa-m)
- minizip warning fix if MAXU32 already defined. (gvollant)
- Fix unztell64() in minizip to work past 4GB. (Daniël Hörchner)
- Clean up minizip to reduce warnings for testing
- Add fallthrough comments for gcc
- Eliminate use of ULL constants
- Separate out address sanitizing from warnings in configure
- Remove destructive aspects of make distclean
- Check for cc masquerading as gcc or clang in configure
- Fix crc32.c to compile local functions only if used
Changes in 1.2.11 (15 Jan 2017) Changes in 1.2.11 (15 Jan 2017)
- Fix deflate stored bug when pulling last block from window - Fix deflate stored bug when pulling last block from window
- Permit immediate deflateParams changes before any deflate input - Permit immediate deflateParams changes before any deflate input
@ -96,7 +189,7 @@ Changes in 1.2.7.1 (24 Mar 2013)
- Fix types in contrib/minizip to match result of get_crc_table() - Fix types in contrib/minizip to match result of get_crc_table()
- Simplify contrib/vstudio/vc10 with 'd' suffix - Simplify contrib/vstudio/vc10 with 'd' suffix
- Add TOP support to win32/Makefile.msc - Add TOP support to win32/Makefile.msc
- Suport i686 and amd64 assembler builds in CMakeLists.txt - Support i686 and amd64 assembler builds in CMakeLists.txt
- Fix typos in the use of _LARGEFILE64_SOURCE in zconf.h - Fix typos in the use of _LARGEFILE64_SOURCE in zconf.h
- Add vc11 and vc12 build files to contrib/vstudio - Add vc11 and vc12 build files to contrib/vstudio
- Add gzvprintf() as an undocumented function in zlib - Add gzvprintf() as an undocumented function in zlib
@ -296,14 +389,14 @@ Changes in 1.2.5.1 (10 Sep 2011)
- Use u4 type for crc_table to avoid conversion warnings - Use u4 type for crc_table to avoid conversion warnings
- Apply casts in zlib.h to avoid conversion warnings - Apply casts in zlib.h to avoid conversion warnings
- Add OF to prototypes for adler32_combine_ and crc32_combine_ [Miller] - Add OF to prototypes for adler32_combine_ and crc32_combine_ [Miller]
- Improve inflateSync() documentation to note indeterminancy - Improve inflateSync() documentation to note indeterminacy
- Add deflatePending() function to return the amount of pending output - Add deflatePending() function to return the amount of pending output
- Correct the spelling of "specification" in FAQ [Randers-Pehrson] - Correct the spelling of "specification" in FAQ [Randers-Pehrson]
- Add a check in configure for stdarg.h, use for gzprintf() - Add a check in configure for stdarg.h, use for gzprintf()
- Check that pointers fit in ints when gzprint() compiled old style - Check that pointers fit in ints when gzprint() compiled old style
- Add dummy name before $(SHAREDLIBV) in Makefile [Bar-Lev, Bowler] - Add dummy name before $(SHAREDLIBV) in Makefile [Bar-Lev, Bowler]
- Delete line in configure that adds -L. libz.a to LDFLAGS [Weigelt] - Delete line in configure that adds -L. libz.a to LDFLAGS [Weigelt]
- Add debug records in assmebler code [Londer] - Add debug records in assembler code [Londer]
- Update RFC references to use http://tools.ietf.org/html/... [Li] - Update RFC references to use http://tools.ietf.org/html/... [Li]
- Add --archs option, use of libtool to configure for Mac OS X [Borstel] - Add --archs option, use of libtool to configure for Mac OS X [Borstel]
@ -511,7 +604,7 @@ Changes in 1.2.3.5 (8 Jan 2010)
- Don't use _vsnprintf on later versions of MSVC [Lowman] - Don't use _vsnprintf on later versions of MSVC [Lowman]
- Add CMake build script and input file [Lowman] - Add CMake build script and input file [Lowman]
- Update contrib/minizip to 1.1 [Svensson, Vollant] - Update contrib/minizip to 1.1 [Svensson, Vollant]
- Moved nintendods directory from contrib to . - Moved nintendods directory from contrib to root
- Replace gzio.c with a new set of routines with the same functionality - Replace gzio.c with a new set of routines with the same functionality
- Add gzbuffer(), gzoffset(), gzclose_r(), gzclose_w() as part of above - Add gzbuffer(), gzoffset(), gzclose_r(), gzclose_w() as part of above
- Update contrib/minizip to 1.1b - Update contrib/minizip to 1.1b
@ -685,7 +778,7 @@ Changes in 1.2.2.4 (11 July 2005)
- Be more strict on incomplete code sets in inflate_table() and increase - Be more strict on incomplete code sets in inflate_table() and increase
ENOUGH and MAXD -- this repairs a possible security vulnerability for ENOUGH and MAXD -- this repairs a possible security vulnerability for
invalid inflate input. Thanks to Tavis Ormandy and Markus Oberhumer for invalid inflate input. Thanks to Tavis Ormandy and Markus Oberhumer for
discovering the vulnerability and providing test cases. discovering the vulnerability and providing test cases
- Add ia64 support to configure for HP-UX [Smith] - Add ia64 support to configure for HP-UX [Smith]
- Add error return to gzread() for format or i/o error [Levin] - Add error return to gzread() for format or i/o error [Levin]
- Use malloc.h for OS/2 [Necasek] - Use malloc.h for OS/2 [Necasek]
@ -721,7 +814,7 @@ Changes in 1.2.2.2 (30 December 2004)
- Add Z_FIXED strategy option to deflateInit2() to force fixed trees - Add Z_FIXED strategy option to deflateInit2() to force fixed trees
- Add updated make_vms.com [Coghlan], update README - Add updated make_vms.com [Coghlan], update README
- Create a new "examples" directory, move gzappend.c there, add zpipe.c, - Create a new "examples" directory, move gzappend.c there, add zpipe.c,
fitblk.c, gzlog.[ch], gzjoin.c, and zlib_how.html. fitblk.c, gzlog.[ch], gzjoin.c, and zlib_how.html
- Add FAQ entry and comments in deflate.c on uninitialized memory access - Add FAQ entry and comments in deflate.c on uninitialized memory access
- Add Solaris 9 make options in configure [Gilbert] - Add Solaris 9 make options in configure [Gilbert]
- Allow strerror() usage in gzio.c for STDC - Allow strerror() usage in gzio.c for STDC
@ -792,7 +885,7 @@ Changes in 1.2.1.1 (9 January 2004)
- Fix a big fat bug in inftrees.c that prevented decoding valid - Fix a big fat bug in inftrees.c that prevented decoding valid
dynamic blocks with only literals and no distance codes -- dynamic blocks with only literals and no distance codes --
Thanks to "Hot Emu" for the bug report and sample file Thanks to "Hot Emu" for the bug report and sample file
- Add a note to puff.c on no distance codes case. - Add a note to puff.c on no distance codes case
Changes in 1.2.1 (17 November 2003) Changes in 1.2.1 (17 November 2003)
- Remove a tab in contrib/gzappend/gzappend.c - Remove a tab in contrib/gzappend/gzappend.c
@ -970,7 +1063,7 @@ Changes in 1.2.0.1 (17 March 2003)
- Include additional header file on VMS for off_t typedef - Include additional header file on VMS for off_t typedef
- Try to use _vsnprintf where it supplants vsprintf [Vollant] - Try to use _vsnprintf where it supplants vsprintf [Vollant]
- Add some casts in inffast.c - Add some casts in inffast.c
- Enchance comments in zlib.h on what happens if gzprintf() tries to - Enhance comments in zlib.h on what happens if gzprintf() tries to
write more than 4095 bytes before compression write more than 4095 bytes before compression
- Remove unused state from inflateBackEnd() - Remove unused state from inflateBackEnd()
- Remove exit(0) from minigzip.c, example.c - Remove exit(0) from minigzip.c, example.c
@ -1036,14 +1129,14 @@ Changes in 1.2.0 (9 March 2003)
- Add contrib/puff/ simple inflate for deflate format description - Add contrib/puff/ simple inflate for deflate format description
Changes in 1.1.4 (11 March 2002) Changes in 1.1.4 (11 March 2002)
- ZFREE was repeated on same allocation on some error conditions. - ZFREE was repeated on same allocation on some error conditions
This creates a security problem described in This creates a security problem described in
http://www.zlib.org/advisory-2002-03-11.txt http://www.zlib.org/advisory-2002-03-11.txt
- Returned incorrect error (Z_MEM_ERROR) on some invalid data - Returned incorrect error (Z_MEM_ERROR) on some invalid data
- Avoid accesses before window for invalid distances with inflate window - Avoid accesses before window for invalid distances with inflate window
less than 32K. less than 32K
- force windowBits > 8 to avoid a bug in the encoder for a window size - force windowBits > 8 to avoid a bug in the encoder for a window size
of 256 bytes. (A complete fix will be available in 1.1.5). of 256 bytes. (A complete fix will be available in 1.1.5)
Changes in 1.1.3 (9 July 1998) Changes in 1.1.3 (9 July 1998)
- fix "an inflate input buffer bug that shows up on rare but persistent - fix "an inflate input buffer bug that shows up on rare but persistent
@ -1117,7 +1210,7 @@ Changes in 1.1.1 (27 Feb 98)
- remove block truncation heuristic which had very marginal effect for zlib - remove block truncation heuristic which had very marginal effect for zlib
(smaller lit_bufsize than in gzip 1.2.4) and degraded a little the (smaller lit_bufsize than in gzip 1.2.4) and degraded a little the
compression ratio on some files. This also allows inlining _tr_tally for compression ratio on some files. This also allows inlining _tr_tally for
matches in deflate_slow. matches in deflate_slow
- added msdos/Makefile.w32 for WIN32 Microsoft Visual C++ (Bob Frazier) - added msdos/Makefile.w32 for WIN32 Microsoft Visual C++ (Bob Frazier)
Changes in 1.1.0 (24 Feb 98) Changes in 1.1.0 (24 Feb 98)
@ -1148,7 +1241,7 @@ Changes in 1.0.9 (17 Feb 1998)
- Avoid gcc 2.8.0 comparison bug a little differently than zlib 1.0.8 - Avoid gcc 2.8.0 comparison bug a little differently than zlib 1.0.8
- in inftrees.c, avoid cc -O bug on HP (Farshid Elahi) - in inftrees.c, avoid cc -O bug on HP (Farshid Elahi)
- in zconf.h move the ZLIB_DLL stuff earlier to avoid problems with - in zconf.h move the ZLIB_DLL stuff earlier to avoid problems with
the declaration of FAR (Gilles VOllant) the declaration of FAR (Gilles Vollant)
- install libz.so* with mode 755 (executable) instead of 644 (Marc Lehmann) - install libz.so* with mode 755 (executable) instead of 644 (Marc Lehmann)
- read_buf buf parameter of type Bytef* instead of charf* - read_buf buf parameter of type Bytef* instead of charf*
- zmemcpy parameters are of type Bytef*, not charf* (Joseph Strout) - zmemcpy parameters are of type Bytef*, not charf* (Joseph Strout)
@ -1162,7 +1255,7 @@ Changes in 1.0.8 (27 Jan 1998)
- include sys/types.h to get off_t on some systems (Marc Lehmann & QingLong) - include sys/types.h to get off_t on some systems (Marc Lehmann & QingLong)
- use constant arrays for the static trees in trees.c instead of computing - use constant arrays for the static trees in trees.c instead of computing
them at run time (thanks to Ken Raeburn for this suggestion). To create them at run time (thanks to Ken Raeburn for this suggestion). To create
trees.h, compile with GEN_TREES_H and run "make test". trees.h, compile with GEN_TREES_H and run "make test"
- check return code of example in "make test" and display result - check return code of example in "make test" and display result
- pass minigzip command line options to file_compress - pass minigzip command line options to file_compress
- simplifying code of inflateSync to avoid gcc 2.8 bug - simplifying code of inflateSync to avoid gcc 2.8 bug
@ -1201,12 +1294,12 @@ Changes in 1.0.6 (19 Jan 1998)
- add functions gzprintf, gzputc, gzgetc, gztell, gzeof, gzseek, gzrewind and - add functions gzprintf, gzputc, gzgetc, gztell, gzeof, gzseek, gzrewind and
gzsetparams (thanks to Roland Giersig and Kevin Ruland for some of this code) gzsetparams (thanks to Roland Giersig and Kevin Ruland for some of this code)
- Fix a deflate bug occurring only with compression level 0 (thanks to - Fix a deflate bug occurring only with compression level 0 (thanks to
Andy Buckler for finding this one). Andy Buckler for finding this one)
- In minigzip, pass transparently also the first byte for .Z files. - In minigzip, pass transparently also the first byte for .Z files
- return Z_BUF_ERROR instead of Z_OK if output buffer full in uncompress() - return Z_BUF_ERROR instead of Z_OK if output buffer full in uncompress()
- check Z_FINISH in inflate (thanks to Marc Schluper) - check Z_FINISH in inflate (thanks to Marc Schluper)
- Implement deflateCopy (thanks to Adam Costello) - Implement deflateCopy (thanks to Adam Costello)
- make static libraries by default in configure, add --shared option. - make static libraries by default in configure, add --shared option
- move MSDOS or Windows specific files to directory msdos - move MSDOS or Windows specific files to directory msdos
- suppress the notion of partial flush to simplify the interface - suppress the notion of partial flush to simplify the interface
(but the symbol Z_PARTIAL_FLUSH is kept for compatibility with 1.0.4) (but the symbol Z_PARTIAL_FLUSH is kept for compatibility with 1.0.4)
@ -1218,7 +1311,7 @@ Changes in 1.0.6 (19 Jan 1998)
- added Makefile.nt (thanks to Stephen Williams) - added Makefile.nt (thanks to Stephen Williams)
- added the unsupported "contrib" directory: - added the unsupported "contrib" directory:
contrib/asm386/ by Gilles Vollant <info@winimage.com> contrib/asm386/ by Gilles Vollant <info@winimage.com>
386 asm code replacing longest_match(). 386 asm code replacing longest_match()
contrib/iostream/ by Kevin Ruland <kevin@rodin.wustl.edu> contrib/iostream/ by Kevin Ruland <kevin@rodin.wustl.edu>
A C++ I/O streams interface to the zlib gz* functions A C++ I/O streams interface to the zlib gz* functions
contrib/iostream2/ by Tyge Løvset <Tyge.Lovset@cmr.no> contrib/iostream2/ by Tyge Løvset <Tyge.Lovset@cmr.no>
@ -1226,7 +1319,7 @@ Changes in 1.0.6 (19 Jan 1998)
contrib/untgz/ by "Pedro A. Aranda Guti\irrez" <paag@tid.es> contrib/untgz/ by "Pedro A. Aranda Guti\irrez" <paag@tid.es>
A very simple tar.gz file extractor using zlib A very simple tar.gz file extractor using zlib
contrib/visual-basic.txt by Carlos Rios <c_rios@sonda.cl> contrib/visual-basic.txt by Carlos Rios <c_rios@sonda.cl>
How to use compress(), uncompress() and the gz* functions from VB. How to use compress(), uncompress() and the gz* functions from VB
- pass params -f (filtered data), -h (huffman only), -1 to -9 (compression - pass params -f (filtered data), -h (huffman only), -1 to -9 (compression
level) in minigzip (thanks to Tom Lane) level) in minigzip (thanks to Tom Lane)
@ -1235,8 +1328,8 @@ Changes in 1.0.6 (19 Jan 1998)
- add undocumented function inflateSyncPoint() (hack for Paul Mackerras) - add undocumented function inflateSyncPoint() (hack for Paul Mackerras)
- add undocumented function zError to convert error code to string - add undocumented function zError to convert error code to string
(for Tim Smithers) (for Tim Smithers)
- Allow compilation of gzio with -DNO_DEFLATE to avoid the compression code. - Allow compilation of gzio with -DNO_DEFLATE to avoid the compression code
- Use default memcpy for Symantec MSDOS compiler. - Use default memcpy for Symantec MSDOS compiler
- Add EXPORT keyword for check_func (needed for Windows DLL) - Add EXPORT keyword for check_func (needed for Windows DLL)
- add current directory to LD_LIBRARY_PATH for "make test" - add current directory to LD_LIBRARY_PATH for "make test"
- create also a link for libz.so.1 - create also a link for libz.so.1
@ -1249,7 +1342,7 @@ Changes in 1.0.6 (19 Jan 1998)
- allow compilation with ANSI keywords only enabled for TurboC in large model - allow compilation with ANSI keywords only enabled for TurboC in large model
- avoid "versionString"[0] (Borland bug) - avoid "versionString"[0] (Borland bug)
- add NEED_DUMMY_RETURN for Borland - add NEED_DUMMY_RETURN for Borland
- use variable z_verbose for tracing in debug mode (L. Peter Deutsch). - use variable z_verbose for tracing in debug mode (L. Peter Deutsch)
- allow compilation with CC - allow compilation with CC
- defined STDC for OS/2 (David Charlap) - defined STDC for OS/2 (David Charlap)
- limit external names to 8 chars for MVS (Thomas Lund) - limit external names to 8 chars for MVS (Thomas Lund)
@ -1259,7 +1352,7 @@ Changes in 1.0.6 (19 Jan 1998)
- use _fdopen instead of fdopen for MSC >= 6.0 (Thomas Fanslau) - use _fdopen instead of fdopen for MSC >= 6.0 (Thomas Fanslau)
- added makelcc.bat for lcc-win32 (Tom St Denis) - added makelcc.bat for lcc-win32 (Tom St Denis)
- in Makefile.dj2, use copy and del instead of install and rm (Frank Donahoe) - in Makefile.dj2, use copy and del instead of install and rm (Frank Donahoe)
- Avoid expanded $Id$. Use "rcs -kb" or "cvs admin -kb" to avoid Id expansion. - Avoid expanded $Id$. Use "rcs -kb" or "cvs admin -kb" to avoid Id expansion
- check for unistd.h in configure (for off_t) - check for unistd.h in configure (for off_t)
- remove useless check parameter in inflate_blocks_free - remove useless check parameter in inflate_blocks_free
- avoid useless assignment of s->check to itself in inflate_blocks_new - avoid useless assignment of s->check to itself in inflate_blocks_new
@ -1280,7 +1373,7 @@ Changes in 1.0.5 (3 Jan 98)
Changes in 1.0.4 (24 Jul 96) Changes in 1.0.4 (24 Jul 96)
- In very rare conditions, deflate(s, Z_FINISH) could fail to produce an EOF - In very rare conditions, deflate(s, Z_FINISH) could fail to produce an EOF
bit, so the decompressor could decompress all the correct data but went bit, so the decompressor could decompress all the correct data but went
on to attempt decompressing extra garbage data. This affected minigzip too. on to attempt decompressing extra garbage data. This affected minigzip too
- zlibVersion and gzerror return const char* (needed for DLL) - zlibVersion and gzerror return const char* (needed for DLL)
- port to RISCOS (no fdopen, no multiple dots, no unlink, no fileno) - port to RISCOS (no fdopen, no multiple dots, no unlink, no fileno)
- use z_error only for DEBUG (avoid problem with DLLs) - use z_error only for DEBUG (avoid problem with DLLs)
@ -1310,7 +1403,7 @@ Changes in 1.0.1 (20 May 96) [1.0 skipped to avoid confusion]
- fix array overlay in deflate.c which sometimes caused bad compressed data - fix array overlay in deflate.c which sometimes caused bad compressed data
- fix inflate bug with empty stored block - fix inflate bug with empty stored block
- fix MSDOS medium model which was broken in 0.99 - fix MSDOS medium model which was broken in 0.99
- fix deflateParams() which could generate bad compressed data. - fix deflateParams() which could generate bad compressed data
- Bytef is define'd instead of typedef'ed (work around Borland bug) - Bytef is define'd instead of typedef'ed (work around Borland bug)
- added an INDEX file - added an INDEX file
- new makefiles for DJGPP (Makefile.dj2), 32-bit Borland (Makefile.b32), - new makefiles for DJGPP (Makefile.dj2), 32-bit Borland (Makefile.b32),
@ -1331,7 +1424,7 @@ Changes in 0.99 (27 Jan 96)
- allow preset dictionary shared between compressor and decompressor - allow preset dictionary shared between compressor and decompressor
- allow compression level 0 (no compression) - allow compression level 0 (no compression)
- add deflateParams in zlib.h: allow dynamic change of compression level - add deflateParams in zlib.h: allow dynamic change of compression level
and compression strategy. and compression strategy
- test large buffers and deflateParams in example.c - test large buffers and deflateParams in example.c
- add optional "configure" to build zlib as a shared library - add optional "configure" to build zlib as a shared library
- suppress Makefile.qnx, use configure instead - suppress Makefile.qnx, use configure instead
@ -1370,33 +1463,33 @@ Changes in 0.99 (27 Jan 96)
- fix typo in Make_vms.com (f$trnlnm -> f$getsyi) - fix typo in Make_vms.com (f$trnlnm -> f$getsyi)
- in fcalloc, normalize pointer if size > 65520 bytes - in fcalloc, normalize pointer if size > 65520 bytes
- don't use special fcalloc for 32 bit Borland C++ - don't use special fcalloc for 32 bit Borland C++
- use STDC instead of __GO32__ to avoid redeclaring exit, calloc, etc... - use STDC instead of __GO32__ to avoid redeclaring exit, calloc, etc.
- use Z_BINARY instead of BINARY - use Z_BINARY instead of BINARY
- document that gzclose after gzdopen will close the file - document that gzclose after gzdopen will close the file
- allow "a" as mode in gzopen. - allow "a" as mode in gzopen
- fix error checking in gzread - fix error checking in gzread
- allow skipping .gz extra-field on pipes - allow skipping .gz extra-field on pipes
- added reference to Perl interface in README - added reference to Perl interface in README
- put the crc table in FAR data (I dislike more and more the medium model :) - put the crc table in FAR data (I dislike more and more the medium model :)
- added get_crc_table - added get_crc_table
- added a dimension to all arrays (Borland C can't count). - added a dimension to all arrays (Borland C can't count)
- workaround Borland C bug in declaration of inflate_codes_new & inflate_fast - workaround Borland C bug in declaration of inflate_codes_new & inflate_fast
- guard against multiple inclusion of *.h (for precompiled header on Mac) - guard against multiple inclusion of *.h (for precompiled header on Mac)
- Watcom C pretends to be Microsoft C small model even in 32 bit mode. - Watcom C pretends to be Microsoft C small model even in 32 bit mode
- don't use unsized arrays to avoid silly warnings by Visual C++: - don't use unsized arrays to avoid silly warnings by Visual C++:
warning C4746: 'inflate_mask' : unsized array treated as '__far' warning C4746: 'inflate_mask' : unsized array treated as '__far'
(what's wrong with far data in far model?). (what's wrong with far data in far model?)
- define enum out of inflate_blocks_state to allow compilation with C++ - define enum out of inflate_blocks_state to allow compilation with C++
Changes in 0.95 (16 Aug 95) Changes in 0.95 (16 Aug 95)
- fix MSDOS small and medium model (now easier to adapt to any compiler) - fix MSDOS small and medium model (now easier to adapt to any compiler)
- inlined send_bits - inlined send_bits
- fix the final (:-) bug for deflate with flush (output was correct but - fix the final (:-) bug for deflate with flush (output was correct but
not completely flushed in rare occasions). not completely flushed in rare occasions)
- default window size is same for compression and decompression - default window size is same for compression and decompression
(it's now sufficient to set MAX_WBITS in zconf.h). (it's now sufficient to set MAX_WBITS in zconf.h)
- voidp -> voidpf and voidnp -> voidp (for consistency with other - voidp -> voidpf and voidnp -> voidp (for consistency with other
typedefs and because voidnp was not near in large model). typedefs and because voidnp was not near in large model)
Changes in 0.94 (13 Aug 95) Changes in 0.94 (13 Aug 95)
- support MSDOS medium model - support MSDOS medium model
@ -1405,12 +1498,12 @@ Changes in 0.94 (13 Aug 95)
- added support for VMS - added support for VMS
- allow a compression level in gzopen() - allow a compression level in gzopen()
- gzflush now calls fflush - gzflush now calls fflush
- For deflate with flush, flush even if no more input is provided. - For deflate with flush, flush even if no more input is provided
- rename libgz.a as libz.a - rename libgz.a as libz.a
- avoid complex expression in infcodes.c triggering Turbo C bug - avoid complex expression in infcodes.c triggering Turbo C bug
- work around a problem with gcc on Alpha (in INSERT_STRING) - work around a problem with gcc on Alpha (in INSERT_STRING)
- don't use inline functions (problem with some gcc versions) - don't use inline functions (problem with some gcc versions)
- allow renaming of Byte, uInt, etc... with #define. - allow renaming of Byte, uInt, etc... with #define
- avoid warning about (unused) pointer before start of array in deflate.c - avoid warning about (unused) pointer before start of array in deflate.c
- avoid various warnings in gzio.c, example.c, infblock.c, adler32.c, zutil.c - avoid various warnings in gzio.c, example.c, infblock.c, adler32.c, zutil.c
- avoid reserved word 'new' in trees.c - avoid reserved word 'new' in trees.c
@ -1429,7 +1522,7 @@ Changes in 0.92 (3 May 95)
- no memcpy on Pyramid - no memcpy on Pyramid
- suppressed inftest.c - suppressed inftest.c
- optimized fill_window, put longest_match inline for gcc - optimized fill_window, put longest_match inline for gcc
- optimized inflate on stored blocks. - optimized inflate on stored blocks
- untabify all sources to simplify patches - untabify all sources to simplify patches
Changes in 0.91 (2 May 95) Changes in 0.91 (2 May 95)
@ -1447,7 +1540,7 @@ Changes in 0.9 (1 May 95)
- let again gzread copy uncompressed data unchanged (was working in 0.71) - let again gzread copy uncompressed data unchanged (was working in 0.71)
- deflate(Z_FULL_FLUSH), inflateReset and inflateSync are now fully implemented - deflate(Z_FULL_FLUSH), inflateReset and inflateSync are now fully implemented
- added a test of inflateSync in example.c - added a test of inflateSync in example.c
- moved MAX_WBITS to zconf.h because users might want to change that. - moved MAX_WBITS to zconf.h because users might want to change that
- document explicitly that zalloc(64K) on MSDOS must return a normalized - document explicitly that zalloc(64K) on MSDOS must return a normalized
pointer (zero offset) pointer (zero offset)
- added Makefiles for Microsoft C, Turbo C, Borland C++ - added Makefiles for Microsoft C, Turbo C, Borland C++
@ -1456,7 +1549,7 @@ Changes in 0.9 (1 May 95)
Changes in 0.8 (29 April 95) Changes in 0.8 (29 April 95)
- added fast inflate (inffast.c) - added fast inflate (inffast.c)
- deflate(Z_FINISH) now returns Z_STREAM_END when done. Warning: this - deflate(Z_FINISH) now returns Z_STREAM_END when done. Warning: this
is incompatible with previous versions of zlib which returned Z_OK. is incompatible with previous versions of zlib which returned Z_OK
- work around a TurboC compiler bug (bad code for b << 0, see infutil.h) - work around a TurboC compiler bug (bad code for b << 0, see infutil.h)
(actually that was not a compiler bug, see 0.81 above) (actually that was not a compiler bug, see 0.81 above)
- gzread no longer reads one extra byte in certain cases - gzread no longer reads one extra byte in certain cases
@ -1466,50 +1559,50 @@ Changes in 0.8 (29 April 95)
Changes in 0.71 (14 April 95) Changes in 0.71 (14 April 95)
- Fixed more MSDOS compilation problems :( There is still a bug with - Fixed more MSDOS compilation problems :( There is still a bug with
TurboC large model. TurboC large model
Changes in 0.7 (14 April 95) Changes in 0.7 (14 April 95)
- Added full inflate support. - Added full inflate support
- Simplified the crc32() interface. The pre- and post-conditioning - Simplified the crc32() interface. The pre- and post-conditioning
(one's complement) is now done inside crc32(). WARNING: this is (one's complement) is now done inside crc32(). WARNING: this is
incompatible with previous versions; see zlib.h for the new usage. incompatible with previous versions; see zlib.h for the new usage
Changes in 0.61 (12 April 95) Changes in 0.61 (12 April 95)
- workaround for a bug in TurboC. example and minigzip now work on MSDOS. - workaround for a bug in TurboC. example and minigzip now work on MSDOS
Changes in 0.6 (11 April 95) Changes in 0.6 (11 April 95)
- added minigzip.c - added minigzip.c
- added gzdopen to reopen a file descriptor as gzFile - added gzdopen to reopen a file descriptor as gzFile
- added transparent reading of non-gziped files in gzread. - added transparent reading of non-gziped files in gzread
- fixed bug in gzread (don't read crc as data) - fixed bug in gzread (don't read crc as data)
- fixed bug in destroy (gzio.c) (don't return Z_STREAM_END for gzclose). - fixed bug in destroy (gzio.c) (don't return Z_STREAM_END for gzclose)
- don't allocate big arrays in the stack (for MSDOS) - don't allocate big arrays in the stack (for MSDOS)
- fix some MSDOS compilation problems - fix some MSDOS compilation problems
Changes in 0.5: Changes in 0.5:
- do real compression in deflate.c. Z_PARTIAL_FLUSH is supported but - do real compression in deflate.c. Z_PARTIAL_FLUSH is supported but
not yet Z_FULL_FLUSH. not yet Z_FULL_FLUSH
- support decompression but only in a single step (forced Z_FINISH) - support decompression but only in a single step (forced Z_FINISH)
- added opaque object for zalloc and zfree. - added opaque object for zalloc and zfree
- added deflateReset and inflateReset - added deflateReset and inflateReset
- added a variable zlib_version for consistency checking. - added a variable zlib_version for consistency checking
- renamed the 'filter' parameter of deflateInit2 as 'strategy'. - renamed the 'filter' parameter of deflateInit2 as 'strategy'
Added Z_FILTERED and Z_HUFFMAN_ONLY constants. Added Z_FILTERED and Z_HUFFMAN_ONLY constants
Changes in 0.4: Changes in 0.4:
- avoid "zip" everywhere, use zlib instead of ziplib. - avoid "zip" everywhere, use zlib instead of ziplib
- suppress Z_BLOCK_FLUSH, interpret Z_PARTIAL_FLUSH as block flush - suppress Z_BLOCK_FLUSH, interpret Z_PARTIAL_FLUSH as block flush
if compression method == 8. if compression method == 8
- added adler32 and crc32 - added adler32 and crc32
- renamed deflateOptions as deflateInit2, call one or the other but not both - renamed deflateOptions as deflateInit2, call one or the other but not both
- added the method parameter for deflateInit2. - added the method parameter for deflateInit2
- added inflateInit2 - added inflateInit2
- simplied considerably deflateInit and inflateInit by not supporting - simplified considerably deflateInit and inflateInit by not supporting
user-provided history buffer. This is supported only in deflateInit2 user-provided history buffer. This is supported only in deflateInit2
and inflateInit2. and inflateInit2
Changes in 0.3: Changes in 0.3:
- prefix all macro names with Z_ - prefix all macro names with Z_
- use Z_FINISH instead of deflateEnd to finish compression. - use Z_FINISH instead of deflateEnd to finish compression
- added Z_HUFFMAN_ONLY - added Z_HUFFMAN_ONLY
- added gzerror() - added gzerror()

2
3rdparty/zlib/FAQ vendored
View File

@ -4,7 +4,7 @@
If your question is not there, please check the zlib home page If your question is not there, please check the zlib home page
http://zlib.net/ which may have more recent information. http://zlib.net/ which may have more recent information.
The lastest zlib FAQ is at http://zlib.net/zlib_faq.html The latest zlib FAQ is at http://zlib.net/zlib_faq.html
1. Is zlib Y2K-compliant? 1. Is zlib Y2K-compliant?

22
3rdparty/zlib/LICENSE vendored Normal file
View File

@ -0,0 +1,22 @@
Copyright notice:
(C) 1995-2022 Jean-loup Gailly and Mark Adler
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
Jean-loup Gailly Mark Adler
jloup@gzip.org madler@alumni.caltech.edu

24
3rdparty/zlib/README vendored
View File

@ -1,6 +1,6 @@
ZLIB DATA COMPRESSION LIBRARY ZLIB DATA COMPRESSION LIBRARY
zlib 1.2.11 is a general purpose data compression library. All the code is zlib 1.3 is a general purpose data compression library. All the code is
thread safe. The data format used by the zlib library is described by RFCs thread safe. The data format used by the zlib library is described by RFCs
(Request for Comments) 1950 to 1952 in the files (Request for Comments) 1950 to 1952 in the files
http://tools.ietf.org/html/rfc1950 (zlib format), rfc1951 (deflate format) and http://tools.ietf.org/html/rfc1950 (zlib format), rfc1951 (deflate format) and
@ -29,18 +29,17 @@ PLEASE read the zlib FAQ http://zlib.net/zlib_faq.html before asking for help.
Mark Nelson <markn@ieee.org> wrote an article about zlib for the Jan. 1997 Mark Nelson <markn@ieee.org> wrote an article about zlib for the Jan. 1997
issue of Dr. Dobb's Journal; a copy of the article is available at issue of Dr. Dobb's Journal; a copy of the article is available at
http://marknelson.us/1997/01/01/zlib-engine/ . https://marknelson.us/posts/1997/01/01/zlib-engine.html .
The changes made in version 1.2.11 are documented in the file ChangeLog. The changes made in version 1.3 are documented in the file ChangeLog.
Unsupported third party contributions are provided in directory contrib/ . Unsupported third party contributions are provided in directory contrib/ .
zlib is available in Java using the java.util.zip package, documented at zlib is available in Java using the java.util.zip package. Follow the API
http://java.sun.com/developer/technicalArticles/Programming/compression/ . Documentation link at: https://docs.oracle.com/search/?q=java.util.zip .
A Perl interface to zlib written by Paul Marquess <pmqs@cpan.org> is available A Perl interface to zlib and bzip2 written by Paul Marquess <pmqs@cpan.org>
at CPAN (Comprehensive Perl Archive Network) sites, including can be found at https://github.com/pmqs/IO-Compress .
http://search.cpan.org/~pmqs/IO-Compress-Zlib/ .
A Python interface to zlib written by A.M. Kuchling <amk@amk.ca> is A Python interface to zlib written by A.M. Kuchling <amk@amk.ca> is
available in Python 1.5 and later versions, see available in Python 1.5 and later versions, see
@ -64,7 +63,7 @@ Notes for some targets:
- zlib doesn't work with gcc 2.6.3 on a DEC 3000/300LX under OSF/1 2.1 it works - zlib doesn't work with gcc 2.6.3 on a DEC 3000/300LX under OSF/1 2.1 it works
when compiled with cc. when compiled with cc.
- On Digital Unix 4.0D (formely OSF/1) on AlphaServer, the cc option -std1 is - On Digital Unix 4.0D (formerly OSF/1) on AlphaServer, the cc option -std1 is
necessary to get gzprintf working correctly. This is done by configure. necessary to get gzprintf working correctly. This is done by configure.
- zlib doesn't work on HP-UX 9.05 with some versions of /bin/cc. It works with - zlib doesn't work on HP-UX 9.05 with some versions of /bin/cc. It works with
@ -84,7 +83,7 @@ Acknowledgments:
Copyright notice: Copyright notice:
(C) 1995-2017 Jean-loup Gailly and Mark Adler (C) 1995-2023 Jean-loup Gailly and Mark Adler
This software is provided 'as-is', without any express or implied This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages warranty. In no event will the authors be held liable for any damages
@ -108,7 +107,10 @@ Copyright notice:
If you use the zlib library in a product, we would appreciate *not* receiving If you use the zlib library in a product, we would appreciate *not* receiving
lengthy legal documents to sign. The sources are provided for free but without lengthy legal documents to sign. The sources are provided for free but without
warranty of any kind. The library has been entirely written by Jean-loup warranty of any kind. The library has been entirely written by Jean-loup
Gailly and Mark Adler; it does not include third-party code. Gailly and Mark Adler; it does not include third-party code. We make all
contributions to and distributions of this project solely in our personal
capacity, and are not conveying any rights to any intellectual property of
any third parties.
If you redistribute modified sources, we would appreciate that you include in If you redistribute modified sources, we would appreciate that you include in
the file ChangeLog history information documenting your changes. Please read the file ChangeLog history information documenting your changes. Please read

View File

@ -7,8 +7,6 @@
#include "zutil.h" #include "zutil.h"
local uLong adler32_combine_ OF((uLong adler1, uLong adler2, z_off64_t len2));
#define BASE 65521U /* largest prime smaller than 65536 */ #define BASE 65521U /* largest prime smaller than 65536 */
#define NMAX 5552 #define NMAX 5552
/* NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */ /* NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */
@ -60,11 +58,7 @@ local uLong adler32_combine_ OF((uLong adler1, uLong adler2, z_off64_t len2));
#endif #endif
/* ========================================================================= */ /* ========================================================================= */
uLong ZEXPORT adler32_z(adler, buf, len) uLong ZEXPORT adler32_z(uLong adler, const Bytef *buf, z_size_t len) {
uLong adler;
const Bytef *buf;
z_size_t len;
{
unsigned long sum2; unsigned long sum2;
unsigned n; unsigned n;
@ -131,20 +125,12 @@ uLong ZEXPORT adler32_z(adler, buf, len)
} }
/* ========================================================================= */ /* ========================================================================= */
uLong ZEXPORT adler32(adler, buf, len) uLong ZEXPORT adler32(uLong adler, const Bytef *buf, uInt len) {
uLong adler;
const Bytef *buf;
uInt len;
{
return adler32_z(adler, buf, len); return adler32_z(adler, buf, len);
} }
/* ========================================================================= */ /* ========================================================================= */
local uLong adler32_combine_(adler1, adler2, len2) local uLong adler32_combine_(uLong adler1, uLong adler2, z_off64_t len2) {
uLong adler1;
uLong adler2;
z_off64_t len2;
{
unsigned long sum1; unsigned long sum1;
unsigned long sum2; unsigned long sum2;
unsigned rem; unsigned rem;
@ -169,18 +155,10 @@ local uLong adler32_combine_(adler1, adler2, len2)
} }
/* ========================================================================= */ /* ========================================================================= */
uLong ZEXPORT adler32_combine(adler1, adler2, len2) uLong ZEXPORT adler32_combine(uLong adler1, uLong adler2, z_off_t len2) {
uLong adler1;
uLong adler2;
z_off_t len2;
{
return adler32_combine_(adler1, adler2, len2); return adler32_combine_(adler1, adler2, len2);
} }
uLong ZEXPORT adler32_combine64(adler1, adler2, len2) uLong ZEXPORT adler32_combine64(uLong adler1, uLong adler2, z_off64_t len2) {
uLong adler1;
uLong adler2;
z_off64_t len2;
{
return adler32_combine_(adler1, adler2, len2); return adler32_combine_(adler1, adler2, len2);
} }

View File

@ -19,13 +19,8 @@
memory, Z_BUF_ERROR if there was not enough room in the output buffer, memory, Z_BUF_ERROR if there was not enough room in the output buffer,
Z_STREAM_ERROR if the level parameter is invalid. Z_STREAM_ERROR if the level parameter is invalid.
*/ */
int ZEXPORT compress2 (dest, destLen, source, sourceLen, level) int ZEXPORT compress2(Bytef *dest, uLongf *destLen, const Bytef *source,
Bytef *dest; uLong sourceLen, int level) {
uLongf *destLen;
const Bytef *source;
uLong sourceLen;
int level;
{
z_stream stream; z_stream stream;
int err; int err;
const uInt max = (uInt)-1; const uInt max = (uInt)-1;
@ -65,12 +60,8 @@ int ZEXPORT compress2 (dest, destLen, source, sourceLen, level)
/* =========================================================================== /* ===========================================================================
*/ */
int ZEXPORT compress (dest, destLen, source, sourceLen) int ZEXPORT compress(Bytef *dest, uLongf *destLen, const Bytef *source,
Bytef *dest; uLong sourceLen) {
uLongf *destLen;
const Bytef *source;
uLong sourceLen;
{
return compress2(dest, destLen, source, sourceLen, Z_DEFAULT_COMPRESSION); return compress2(dest, destLen, source, sourceLen, Z_DEFAULT_COMPRESSION);
} }
@ -78,9 +69,7 @@ int ZEXPORT compress (dest, destLen, source, sourceLen)
If the default memLevel or windowBits for deflateInit() is changed, then If the default memLevel or windowBits for deflateInit() is changed, then
this function needs to be updated. this function needs to be updated.
*/ */
uLong ZEXPORT compressBound (sourceLen) uLong ZEXPORT compressBound(uLong sourceLen) {
uLong sourceLen;
{
return sourceLen + (sourceLen >> 12) + (sourceLen >> 14) + return sourceLen + (sourceLen >> 12) + (sourceLen >> 14) +
(sourceLen >> 25) + 13; (sourceLen >> 25) + 13;
} }

1283
3rdparty/zlib/crc32.c vendored

File diff suppressed because it is too large Load Diff

9877
3rdparty/zlib/crc32.h vendored

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,5 @@
/* deflate.h -- internal compression state /* deflate.h -- internal compression state
* Copyright (C) 1995-2016 Jean-loup Gailly * Copyright (C) 1995-2018 Jean-loup Gailly
* For conditions of distribution and use, see copyright notice in zlib.h * For conditions of distribution and use, see copyright notice in zlib.h
*/ */
@ -217,7 +217,7 @@ typedef struct internal_state {
/* Depth of each subtree used as tie breaker for trees of equal frequency /* Depth of each subtree used as tie breaker for trees of equal frequency
*/ */
uchf *l_buf; /* buffer for literals or lengths */ uchf *sym_buf; /* buffer for distances and literals/lengths */
uInt lit_bufsize; uInt lit_bufsize;
/* Size of match buffer for literals/lengths. There are 4 reasons for /* Size of match buffer for literals/lengths. There are 4 reasons for
@ -239,13 +239,8 @@ typedef struct internal_state {
* - I can't count above 4 * - I can't count above 4
*/ */
uInt last_lit; /* running index in l_buf */ uInt sym_next; /* running index in sym_buf */
uInt sym_end; /* symbol table full when sym_next reaches this */
ushf *d_buf;
/* Buffer for distances. To simplify the code, d_buf and l_buf have
* the same number of elements. To use different lengths, an extra flag
* array would be necessary.
*/
ulg opt_len; /* bit length of current block with optimal trees */ ulg opt_len; /* bit length of current block with optimal trees */
ulg static_len; /* bit length of current block with static trees */ ulg static_len; /* bit length of current block with static trees */
@ -296,14 +291,14 @@ typedef struct internal_state {
memory checker errors from longest match routines */ memory checker errors from longest match routines */
/* in trees.c */ /* in trees.c */
void ZLIB_INTERNAL _tr_init OF((deflate_state *s)); void ZLIB_INTERNAL _tr_init(deflate_state *s);
int ZLIB_INTERNAL _tr_tally OF((deflate_state *s, unsigned dist, unsigned lc)); int ZLIB_INTERNAL _tr_tally(deflate_state *s, unsigned dist, unsigned lc);
void ZLIB_INTERNAL _tr_flush_block OF((deflate_state *s, charf *buf, void ZLIB_INTERNAL _tr_flush_block(deflate_state *s, charf *buf,
ulg stored_len, int last)); ulg stored_len, int last);
void ZLIB_INTERNAL _tr_flush_bits OF((deflate_state *s)); void ZLIB_INTERNAL _tr_flush_bits(deflate_state *s);
void ZLIB_INTERNAL _tr_align OF((deflate_state *s)); void ZLIB_INTERNAL _tr_align(deflate_state *s);
void ZLIB_INTERNAL _tr_stored_block OF((deflate_state *s, charf *buf, void ZLIB_INTERNAL _tr_stored_block(deflate_state *s, charf *buf,
ulg stored_len, int last)); ulg stored_len, int last);
#define d_code(dist) \ #define d_code(dist) \
((dist) < 256 ? _dist_code[dist] : _dist_code[256+((dist)>>7)]) ((dist) < 256 ? _dist_code[dist] : _dist_code[256+((dist)>>7)])
@ -325,20 +320,22 @@ void ZLIB_INTERNAL _tr_stored_block OF((deflate_state *s, charf *buf,
# define _tr_tally_lit(s, c, flush) \ # define _tr_tally_lit(s, c, flush) \
{ uch cc = (c); \ { uch cc = (c); \
s->d_buf[s->last_lit] = 0; \ s->sym_buf[s->sym_next++] = 0; \
s->l_buf[s->last_lit++] = cc; \ s->sym_buf[s->sym_next++] = 0; \
s->sym_buf[s->sym_next++] = cc; \
s->dyn_ltree[cc].Freq++; \ s->dyn_ltree[cc].Freq++; \
flush = (s->last_lit == s->lit_bufsize-1); \ flush = (s->sym_next == s->sym_end); \
} }
# define _tr_tally_dist(s, distance, length, flush) \ # define _tr_tally_dist(s, distance, length, flush) \
{ uch len = (uch)(length); \ { uch len = (uch)(length); \
ush dist = (ush)(distance); \ ush dist = (ush)(distance); \
s->d_buf[s->last_lit] = dist; \ s->sym_buf[s->sym_next++] = (uch)dist; \
s->l_buf[s->last_lit++] = len; \ s->sym_buf[s->sym_next++] = (uch)(dist >> 8); \
s->sym_buf[s->sym_next++] = len; \
dist--; \ dist--; \
s->dyn_ltree[_length_code[len]+LITERALS+1].Freq++; \ s->dyn_ltree[_length_code[len]+LITERALS+1].Freq++; \
s->dyn_dtree[d_code(dist)].Freq++; \ s->dyn_dtree[d_code(dist)].Freq++; \
flush = (s->last_lit == s->lit_bufsize-1); \ flush = (s->sym_next == s->sym_end); \
} }
#else #else
# define _tr_tally_lit(s, c, flush) flush = _tr_tally(s, 0, c) # define _tr_tally_lit(s, c, flush) flush = _tr_tally(s, 0, c)

View File

@ -1,49 +0,0 @@
This directory contains examples of the use of zlib and other relevant
programs and documentation.
enough.c
calculation and justification of ENOUGH parameter in inftrees.h
- calculates the maximum table space used in inflate tree
construction over all possible Huffman codes
fitblk.c
compress just enough input to nearly fill a requested output size
- zlib isn't designed to do this, but fitblk does it anyway
gun.c
uncompress a gzip file
- illustrates the use of inflateBack() for high speed file-to-file
decompression using call-back functions
- is approximately twice as fast as gzip -d
- also provides Unix uncompress functionality, again twice as fast
gzappend.c
append to a gzip file
- illustrates the use of the Z_BLOCK flush parameter for inflate()
- illustrates the use of deflatePrime() to start at any bit
gzjoin.c
join gzip files without recalculating the crc or recompressing
- illustrates the use of the Z_BLOCK flush parameter for inflate()
- illustrates the use of crc32_combine()
gzlog.c
gzlog.h
efficiently and robustly maintain a message log file in gzip format
- illustrates use of raw deflate, Z_PARTIAL_FLUSH, deflatePrime(),
and deflateSetDictionary()
- illustrates use of a gzip header extra field
zlib_how.html
painfully comprehensive description of zpipe.c (see below)
- describes in excruciating detail the use of deflate() and inflate()
zpipe.c
reads and writes zlib streams from stdin to stdout
- illustrates the proper use of deflate() and inflate()
- deeply commented in zlib_how.html (see above)
zran.c
index a zlib or gzip stream and randomly access it
- illustrates the use of Z_BLOCK, inflatePrime(), and
inflateSetDictionary() to provide random access

View File

@ -1,572 +0,0 @@
/* enough.c -- determine the maximum size of inflate's Huffman code tables over
* all possible valid and complete Huffman codes, subject to a length limit.
* Copyright (C) 2007, 2008, 2012 Mark Adler
* Version 1.4 18 August 2012 Mark Adler
*/
/* Version history:
1.0 3 Jan 2007 First version (derived from codecount.c version 1.4)
1.1 4 Jan 2007 Use faster incremental table usage computation
Prune examine() search on previously visited states
1.2 5 Jan 2007 Comments clean up
As inflate does, decrease root for short codes
Refuse cases where inflate would increase root
1.3 17 Feb 2008 Add argument for initial root table size
Fix bug for initial root table size == max - 1
Use a macro to compute the history index
1.4 18 Aug 2012 Avoid shifts more than bits in type (caused endless loop!)
Clean up comparisons of different types
Clean up code indentation
*/
/*
Examine all possible Huffman codes for a given number of symbols and a
maximum code length in bits to determine the maximum table size for zilb's
inflate. Only complete Huffman codes are counted.
Two codes are considered distinct if the vectors of the number of codes per
length are not identical. So permutations of the symbol assignments result
in the same code for the counting, as do permutations of the assignments of
the bit values to the codes (i.e. only canonical codes are counted).
We build a code from shorter to longer lengths, determining how many symbols
are coded at each length. At each step, we have how many symbols remain to
be coded, what the last code length used was, and how many bit patterns of
that length remain unused. Then we add one to the code length and double the
number of unused patterns to graduate to the next code length. We then
assign all portions of the remaining symbols to that code length that
preserve the properties of a correct and eventually complete code. Those
properties are: we cannot use more bit patterns than are available; and when
all the symbols are used, there are exactly zero possible bit patterns
remaining.
The inflate Huffman decoding algorithm uses two-level lookup tables for
speed. There is a single first-level table to decode codes up to root bits
in length (root == 9 in the current inflate implementation). The table
has 1 << root entries and is indexed by the next root bits of input. Codes
shorter than root bits have replicated table entries, so that the correct
entry is pointed to regardless of the bits that follow the short code. If
the code is longer than root bits, then the table entry points to a second-
level table. The size of that table is determined by the longest code with
that root-bit prefix. If that longest code has length len, then the table
has size 1 << (len - root), to index the remaining bits in that set of
codes. Each subsequent root-bit prefix then has its own sub-table. The
total number of table entries required by the code is calculated
incrementally as the number of codes at each bit length is populated. When
all of the codes are shorter than root bits, then root is reduced to the
longest code length, resulting in a single, smaller, one-level table.
The inflate algorithm also provides for small values of root (relative to
the log2 of the number of symbols), where the shortest code has more bits
than root. In that case, root is increased to the length of the shortest
code. This program, by design, does not handle that case, so it is verified
that the number of symbols is less than 2^(root + 1).
In order to speed up the examination (by about ten orders of magnitude for
the default arguments), the intermediate states in the build-up of a code
are remembered and previously visited branches are pruned. The memory
required for this will increase rapidly with the total number of symbols and
the maximum code length in bits. However this is a very small price to pay
for the vast speedup.
First, all of the possible Huffman codes are counted, and reachable
intermediate states are noted by a non-zero count in a saved-results array.
Second, the intermediate states that lead to (root + 1) bit or longer codes
are used to look at all sub-codes from those junctures for their inflate
memory usage. (The amount of memory used is not affected by the number of
codes of root bits or less in length.) Third, the visited states in the
construction of those sub-codes and the associated calculation of the table
size is recalled in order to avoid recalculating from the same juncture.
Beginning the code examination at (root + 1) bit codes, which is enabled by
identifying the reachable nodes, accounts for about six of the orders of
magnitude of improvement for the default arguments. About another four
orders of magnitude come from not revisiting previous states. Out of
approximately 2x10^16 possible Huffman codes, only about 2x10^6 sub-codes
need to be examined to cover all of the possible table memory usage cases
for the default arguments of 286 symbols limited to 15-bit codes.
Note that an unsigned long long type is used for counting. It is quite easy
to exceed the capacity of an eight-byte integer with a large number of
symbols and a large maximum code length, so multiple-precision arithmetic
would need to replace the unsigned long long arithmetic in that case. This
program will abort if an overflow occurs. The big_t type identifies where
the counting takes place.
An unsigned long long type is also used for calculating the number of
possible codes remaining at the maximum length. This limits the maximum
code length to the number of bits in a long long minus the number of bits
needed to represent the symbols in a flat code. The code_t type identifies
where the bit pattern counting takes place.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#define local static
/* special data types */
typedef unsigned long long big_t; /* type for code counting */
typedef unsigned long long code_t; /* type for bit pattern counting */
struct tab { /* type for been here check */
size_t len; /* length of bit vector in char's */
char *vec; /* allocated bit vector */
};
/* The array for saving results, num[], is indexed with this triplet:
syms: number of symbols remaining to code
left: number of available bit patterns at length len
len: number of bits in the codes currently being assigned
Those indices are constrained thusly when saving results:
syms: 3..totsym (totsym == total symbols to code)
left: 2..syms - 1, but only the evens (so syms == 8 -> 2, 4, 6)
len: 1..max - 1 (max == maximum code length in bits)
syms == 2 is not saved since that immediately leads to a single code. left
must be even, since it represents the number of available bit patterns at
the current length, which is double the number at the previous length.
left ends at syms-1 since left == syms immediately results in a single code.
(left > sym is not allowed since that would result in an incomplete code.)
len is less than max, since the code completes immediately when len == max.
The offset into the array is calculated for the three indices with the
first one (syms) being outermost, and the last one (len) being innermost.
We build the array with length max-1 lists for the len index, with syms-3
of those for each symbol. There are totsym-2 of those, with each one
varying in length as a function of sym. See the calculation of index in
count() for the index, and the calculation of size in main() for the size
of the array.
For the deflate example of 286 symbols limited to 15-bit codes, the array
has 284,284 entries, taking up 2.17 MB for an 8-byte big_t. More than
half of the space allocated for saved results is actually used -- not all
possible triplets are reached in the generation of valid Huffman codes.
*/
/* The array for tracking visited states, done[], is itself indexed identically
to the num[] array as described above for the (syms, left, len) triplet.
Each element in the array is further indexed by the (mem, rem) doublet,
where mem is the amount of inflate table space used so far, and rem is the
remaining unused entries in the current inflate sub-table. Each indexed
element is simply one bit indicating whether the state has been visited or
not. Since the ranges for mem and rem are not known a priori, each bit
vector is of a variable size, and grows as needed to accommodate the visited
states. mem and rem are used to calculate a single index in a triangular
array. Since the range of mem is expected in the default case to be about
ten times larger than the range of rem, the array is skewed to reduce the
memory usage, with eight times the range for mem than for rem. See the
calculations for offset and bit in beenhere() for the details.
For the deflate example of 286 symbols limited to 15-bit codes, the bit
vectors grow to total approximately 21 MB, in addition to the 4.3 MB done[]
array itself.
*/
/* Globals to avoid propagating constants or constant pointers recursively */
local int max; /* maximum allowed bit length for the codes */
local int root; /* size of base code table in bits */
local int large; /* largest code table so far */
local size_t size; /* number of elements in num and done */
local int *code; /* number of symbols assigned to each bit length */
local big_t *num; /* saved results array for code counting */
local struct tab *done; /* states already evaluated array */
/* Index function for num[] and done[] */
#define INDEX(i,j,k) (((size_t)((i-1)>>1)*((i-2)>>1)+(j>>1)-1)*(max-1)+k-1)
/* Free allocated space. Uses globals code, num, and done. */
local void cleanup(void)
{
size_t n;
if (done != NULL) {
for (n = 0; n < size; n++)
if (done[n].len)
free(done[n].vec);
free(done);
}
if (num != NULL)
free(num);
if (code != NULL)
free(code);
}
/* Return the number of possible Huffman codes using bit patterns of lengths
len through max inclusive, coding syms symbols, with left bit patterns of
length len unused -- return -1 if there is an overflow in the counting.
Keep a record of previous results in num to prevent repeating the same
calculation. Uses the globals max and num. */
local big_t count(int syms, int len, int left)
{
big_t sum; /* number of possible codes from this juncture */
big_t got; /* value returned from count() */
int least; /* least number of syms to use at this juncture */
int most; /* most number of syms to use at this juncture */
int use; /* number of bit patterns to use in next call */
size_t index; /* index of this case in *num */
/* see if only one possible code */
if (syms == left)
return 1;
/* note and verify the expected state */
assert(syms > left && left > 0 && len < max);
/* see if we've done this one already */
index = INDEX(syms, left, len);
got = num[index];
if (got)
return got; /* we have -- return the saved result */
/* we need to use at least this many bit patterns so that the code won't be
incomplete at the next length (more bit patterns than symbols) */
least = (left << 1) - syms;
if (least < 0)
least = 0;
/* we can use at most this many bit patterns, lest there not be enough
available for the remaining symbols at the maximum length (if there were
no limit to the code length, this would become: most = left - 1) */
most = (((code_t)left << (max - len)) - syms) /
(((code_t)1 << (max - len)) - 1);
/* count all possible codes from this juncture and add them up */
sum = 0;
for (use = least; use <= most; use++) {
got = count(syms - use, len + 1, (left - use) << 1);
sum += got;
if (got == (big_t)0 - 1 || sum < got) /* overflow */
return (big_t)0 - 1;
}
/* verify that all recursive calls are productive */
assert(sum != 0);
/* save the result and return it */
num[index] = sum;
return sum;
}
/* Return true if we've been here before, set to true if not. Set a bit in a
bit vector to indicate visiting this state. Each (syms,len,left) state
has a variable size bit vector indexed by (mem,rem). The bit vector is
lengthened if needed to allow setting the (mem,rem) bit. */
local int beenhere(int syms, int len, int left, int mem, int rem)
{
size_t index; /* index for this state's bit vector */
size_t offset; /* offset in this state's bit vector */
int bit; /* mask for this state's bit */
size_t length; /* length of the bit vector in bytes */
char *vector; /* new or enlarged bit vector */
/* point to vector for (syms,left,len), bit in vector for (mem,rem) */
index = INDEX(syms, left, len);
mem -= 1 << root;
offset = (mem >> 3) + rem;
offset = ((offset * (offset + 1)) >> 1) + rem;
bit = 1 << (mem & 7);
/* see if we've been here */
length = done[index].len;
if (offset < length && (done[index].vec[offset] & bit) != 0)
return 1; /* done this! */
/* we haven't been here before -- set the bit to show we have now */
/* see if we need to lengthen the vector in order to set the bit */
if (length <= offset) {
/* if we have one already, enlarge it, zero out the appended space */
if (length) {
do {
length <<= 1;
} while (length <= offset);
vector = realloc(done[index].vec, length);
if (vector != NULL)
memset(vector + done[index].len, 0, length - done[index].len);
}
/* otherwise we need to make a new vector and zero it out */
else {
length = 1 << (len - root);
while (length <= offset)
length <<= 1;
vector = calloc(length, sizeof(char));
}
/* in either case, bail if we can't get the memory */
if (vector == NULL) {
fputs("abort: unable to allocate enough memory\n", stderr);
cleanup();
exit(1);
}
/* install the new vector */
done[index].len = length;
done[index].vec = vector;
}
/* set the bit */
done[index].vec[offset] |= bit;
return 0;
}
/* Examine all possible codes from the given node (syms, len, left). Compute
the amount of memory required to build inflate's decoding tables, where the
number of code structures used so far is mem, and the number remaining in
the current sub-table is rem. Uses the globals max, code, root, large, and
done. */
local void examine(int syms, int len, int left, int mem, int rem)
{
int least; /* least number of syms to use at this juncture */
int most; /* most number of syms to use at this juncture */
int use; /* number of bit patterns to use in next call */
/* see if we have a complete code */
if (syms == left) {
/* set the last code entry */
code[len] = left;
/* complete computation of memory used by this code */
while (rem < left) {
left -= rem;
rem = 1 << (len - root);
mem += rem;
}
assert(rem == left);
/* if this is a new maximum, show the entries used and the sub-code */
if (mem > large) {
large = mem;
printf("max %d: ", mem);
for (use = root + 1; use <= max; use++)
if (code[use])
printf("%d[%d] ", code[use], use);
putchar('\n');
fflush(stdout);
}
/* remove entries as we drop back down in the recursion */
code[len] = 0;
return;
}
/* prune the tree if we can */
if (beenhere(syms, len, left, mem, rem))
return;
/* we need to use at least this many bit patterns so that the code won't be
incomplete at the next length (more bit patterns than symbols) */
least = (left << 1) - syms;
if (least < 0)
least = 0;
/* we can use at most this many bit patterns, lest there not be enough
available for the remaining symbols at the maximum length (if there were
no limit to the code length, this would become: most = left - 1) */
most = (((code_t)left << (max - len)) - syms) /
(((code_t)1 << (max - len)) - 1);
/* occupy least table spaces, creating new sub-tables as needed */
use = least;
while (rem < use) {
use -= rem;
rem = 1 << (len - root);
mem += rem;
}
rem -= use;
/* examine codes from here, updating table space as we go */
for (use = least; use <= most; use++) {
code[len] = use;
examine(syms - use, len + 1, (left - use) << 1,
mem + (rem ? 1 << (len - root) : 0), rem << 1);
if (rem == 0) {
rem = 1 << (len - root);
mem += rem;
}
rem--;
}
/* remove entries as we drop back down in the recursion */
code[len] = 0;
}
/* Look at all sub-codes starting with root + 1 bits. Look at only the valid
intermediate code states (syms, left, len). For each completed code,
calculate the amount of memory required by inflate to build the decoding
tables. Find the maximum amount of memory required and show the code that
requires that maximum. Uses the globals max, root, and num. */
local void enough(int syms)
{
int n; /* number of remaing symbols for this node */
int left; /* number of unused bit patterns at this length */
size_t index; /* index of this case in *num */
/* clear code */
for (n = 0; n <= max; n++)
code[n] = 0;
/* look at all (root + 1) bit and longer codes */
large = 1 << root; /* base table */
if (root < max) /* otherwise, there's only a base table */
for (n = 3; n <= syms; n++)
for (left = 2; left < n; left += 2)
{
/* look at all reachable (root + 1) bit nodes, and the
resulting codes (complete at root + 2 or more) */
index = INDEX(n, left, root + 1);
if (root + 1 < max && num[index]) /* reachable node */
examine(n, root + 1, left, 1 << root, 0);
/* also look at root bit codes with completions at root + 1
bits (not saved in num, since complete), just in case */
if (num[index - 1] && n <= left << 1)
examine((n - left) << 1, root + 1, (n - left) << 1,
1 << root, 0);
}
/* done */
printf("done: maximum of %d table entries\n", large);
}
/*
Examine and show the total number of possible Huffman codes for a given
maximum number of symbols, initial root table size, and maximum code length
in bits -- those are the command arguments in that order. The default
values are 286, 9, and 15 respectively, for the deflate literal/length code.
The possible codes are counted for each number of coded symbols from two to
the maximum. The counts for each of those and the total number of codes are
shown. The maximum number of inflate table entires is then calculated
across all possible codes. Each new maximum number of table entries and the
associated sub-code (starting at root + 1 == 10 bits) is shown.
To count and examine Huffman codes that are not length-limited, provide a
maximum length equal to the number of symbols minus one.
For the deflate literal/length code, use "enough". For the deflate distance
code, use "enough 30 6".
This uses the %llu printf format to print big_t numbers, which assumes that
big_t is an unsigned long long. If the big_t type is changed (for example
to a multiple precision type), the method of printing will also need to be
updated.
*/
int main(int argc, char **argv)
{
int syms; /* total number of symbols to code */
int n; /* number of symbols to code for this run */
big_t got; /* return value of count() */
big_t sum; /* accumulated number of codes over n */
code_t word; /* for counting bits in code_t */
/* set up globals for cleanup() */
code = NULL;
num = NULL;
done = NULL;
/* get arguments -- default to the deflate literal/length code */
syms = 286;
root = 9;
max = 15;
if (argc > 1) {
syms = atoi(argv[1]);
if (argc > 2) {
root = atoi(argv[2]);
if (argc > 3)
max = atoi(argv[3]);
}
}
if (argc > 4 || syms < 2 || root < 1 || max < 1) {
fputs("invalid arguments, need: [sym >= 2 [root >= 1 [max >= 1]]]\n",
stderr);
return 1;
}
/* if not restricting the code length, the longest is syms - 1 */
if (max > syms - 1)
max = syms - 1;
/* determine the number of bits in a code_t */
for (n = 0, word = 1; word; n++, word <<= 1)
;
/* make sure that the calculation of most will not overflow */
if (max > n || (code_t)(syms - 2) >= (((code_t)0 - 1) >> (max - 1))) {
fputs("abort: code length too long for internal types\n", stderr);
return 1;
}
/* reject impossible code requests */
if ((code_t)(syms - 1) > ((code_t)1 << max) - 1) {
fprintf(stderr, "%d symbols cannot be coded in %d bits\n",
syms, max);
return 1;
}
/* allocate code vector */
code = calloc(max + 1, sizeof(int));
if (code == NULL) {
fputs("abort: unable to allocate enough memory\n", stderr);
return 1;
}
/* determine size of saved results array, checking for overflows,
allocate and clear the array (set all to zero with calloc()) */
if (syms == 2) /* iff max == 1 */
num = NULL; /* won't be saving any results */
else {
size = syms >> 1;
if (size > ((size_t)0 - 1) / (n = (syms - 1) >> 1) ||
(size *= n, size > ((size_t)0 - 1) / (n = max - 1)) ||
(size *= n, size > ((size_t)0 - 1) / sizeof(big_t)) ||
(num = calloc(size, sizeof(big_t))) == NULL) {
fputs("abort: unable to allocate enough memory\n", stderr);
cleanup();
return 1;
}
}
/* count possible codes for all numbers of symbols, add up counts */
sum = 0;
for (n = 2; n <= syms; n++) {
got = count(n, 1, 2);
sum += got;
if (got == (big_t)0 - 1 || sum < got) { /* overflow */
fputs("abort: can't count that high!\n", stderr);
cleanup();
return 1;
}
printf("%llu %d-codes\n", got, n);
}
printf("%llu total codes for 2 to %d symbols", sum, syms);
if (max < syms - 1)
printf(" (%d-bit length limit)\n", max);
else
puts(" (no length limit)");
/* allocate and clear done array for beenhere() */
if (syms == 2)
done = NULL;
else if (size > ((size_t)0 - 1) / sizeof(struct tab) ||
(done = calloc(size, sizeof(struct tab))) == NULL) {
fputs("abort: unable to allocate enough memory\n", stderr);
cleanup();
return 1;
}
/* find and show maximum inflate table usage */
if (root > max) /* reduce root to max length */
root = max;
if ((code_t)syms < ((code_t)1 << (root + 1)))
enough(syms);
else
puts("cannot handle minimum code lengths > root");
/* done */
cleanup();
return 0;
}

View File

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

View File

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

View File

@ -1,504 +0,0 @@
/* gzappend -- command to append to a gzip file
Copyright (C) 2003, 2012 Mark Adler, all rights reserved
version 1.2, 11 Oct 2012
This software is provided 'as-is', without any express or implied
warranty. In no event will the author be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
Mark Adler madler@alumni.caltech.edu
*/
/*
* Change history:
*
* 1.0 19 Oct 2003 - First version
* 1.1 4 Nov 2003 - Expand and clarify some comments and notes
* - Add version and copyright to help
* - Send help to stdout instead of stderr
* - Add some preemptive typecasts
* - Add L to constants in lseek() calls
* - Remove some debugging information in error messages
* - Use new data_type definition for zlib 1.2.1
* - Simplfy and unify file operations
* - Finish off gzip file in gztack()
* - Use deflatePrime() instead of adding empty blocks
* - Keep gzip file clean on appended file read errors
* - Use in-place rotate instead of auxiliary buffer
* (Why you ask? Because it was fun to write!)
* 1.2 11 Oct 2012 - Fix for proper z_const usage
* - Check for input buffer malloc failure
*/
/*
gzappend takes a gzip file and appends to it, compressing files from the
command line or data from stdin. The gzip file is written to directly, to
avoid copying that file, in case it's large. Note that this results in the
unfriendly behavior that if gzappend fails, the gzip file is corrupted.
This program was written to illustrate the use of the new Z_BLOCK option of
zlib 1.2.x's inflate() function. This option returns from inflate() at each
block boundary to facilitate locating and modifying the last block bit at
the start of the final deflate block. Also whether using Z_BLOCK or not,
another required feature of zlib 1.2.x is that inflate() now provides the
number of unusued bits in the last input byte used. gzappend will not work
with versions of zlib earlier than 1.2.1.
gzappend first decompresses the gzip file internally, discarding all but
the last 32K of uncompressed data, and noting the location of the last block
bit and the number of unused bits in the last byte of the compressed data.
The gzip trailer containing the CRC-32 and length of the uncompressed data
is verified. This trailer will be later overwritten.
Then the last block bit is cleared by seeking back in the file and rewriting
the byte that contains it. Seeking forward, the last byte of the compressed
data is saved along with the number of unused bits to initialize deflate.
A deflate process is initialized, using the last 32K of the uncompressed
data from the gzip file to initialize the dictionary. If the total
uncompressed data was less than 32K, then all of it is used to initialize
the dictionary. The deflate output bit buffer is also initialized with the
last bits from the original deflate stream. From here on, the data to
append is simply compressed using deflate, and written to the gzip file.
When that is complete, the new CRC-32 and uncompressed length are written
as the trailer of the gzip file.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#include "zlib.h"
#define local static
#define LGCHUNK 14
#define CHUNK (1U << LGCHUNK)
#define DSIZE 32768U
/* print an error message and terminate with extreme prejudice */
local void bye(char *msg1, char *msg2)
{
fprintf(stderr, "gzappend error: %s%s\n", msg1, msg2);
exit(1);
}
/* return the greatest common divisor of a and b using Euclid's algorithm,
modified to be fast when one argument much greater than the other, and
coded to avoid unnecessary swapping */
local unsigned gcd(unsigned a, unsigned b)
{
unsigned c;
while (a && b)
if (a > b) {
c = b;
while (a - c >= c)
c <<= 1;
a -= c;
}
else {
c = a;
while (b - c >= c)
c <<= 1;
b -= c;
}
return a + b;
}
/* rotate list[0..len-1] left by rot positions, in place */
local void rotate(unsigned char *list, unsigned len, unsigned rot)
{
unsigned char tmp;
unsigned cycles;
unsigned char *start, *last, *to, *from;
/* normalize rot and handle degenerate cases */
if (len < 2) return;
if (rot >= len) rot %= len;
if (rot == 0) return;
/* pointer to last entry in list */
last = list + (len - 1);
/* do simple left shift by one */
if (rot == 1) {
tmp = *list;
memcpy(list, list + 1, len - 1);
*last = tmp;
return;
}
/* do simple right shift by one */
if (rot == len - 1) {
tmp = *last;
memmove(list + 1, list, len - 1);
*list = tmp;
return;
}
/* otherwise do rotate as a set of cycles in place */
cycles = gcd(len, rot); /* number of cycles */
do {
start = from = list + cycles; /* start index is arbitrary */
tmp = *from; /* save entry to be overwritten */
for (;;) {
to = from; /* next step in cycle */
from += rot; /* go right rot positions */
if (from > last) from -= len; /* (pointer better not wrap) */
if (from == start) break; /* all but one shifted */
*to = *from; /* shift left */
}
*to = tmp; /* complete the circle */
} while (--cycles);
}
/* structure for gzip file read operations */
typedef struct {
int fd; /* file descriptor */
int size; /* 1 << size is bytes in buf */
unsigned left; /* bytes available at next */
unsigned char *buf; /* buffer */
z_const unsigned char *next; /* next byte in buffer */
char *name; /* file name for error messages */
} file;
/* reload buffer */
local int readin(file *in)
{
int len;
len = read(in->fd, in->buf, 1 << in->size);
if (len == -1) bye("error reading ", in->name);
in->left = (unsigned)len;
in->next = in->buf;
return len;
}
/* read from file in, exit if end-of-file */
local int readmore(file *in)
{
if (readin(in) == 0) bye("unexpected end of ", in->name);
return 0;
}
#define read1(in) (in->left == 0 ? readmore(in) : 0, \
in->left--, *(in->next)++)
/* skip over n bytes of in */
local void skip(file *in, unsigned n)
{
unsigned bypass;
if (n > in->left) {
n -= in->left;
bypass = n & ~((1U << in->size) - 1);
if (bypass) {
if (lseek(in->fd, (off_t)bypass, SEEK_CUR) == -1)
bye("seeking ", in->name);
n -= bypass;
}
readmore(in);
if (n > in->left)
bye("unexpected end of ", in->name);
}
in->left -= n;
in->next += n;
}
/* read a four-byte unsigned integer, little-endian, from in */
unsigned long read4(file *in)
{
unsigned long val;
val = read1(in);
val += (unsigned)read1(in) << 8;
val += (unsigned long)read1(in) << 16;
val += (unsigned long)read1(in) << 24;
return val;
}
/* skip over gzip header */
local void gzheader(file *in)
{
int flags;
unsigned n;
if (read1(in) != 31 || read1(in) != 139) bye(in->name, " not a gzip file");
if (read1(in) != 8) bye("unknown compression method in", in->name);
flags = read1(in);
if (flags & 0xe0) bye("unknown header flags set in", in->name);
skip(in, 6);
if (flags & 4) {
n = read1(in);
n += (unsigned)(read1(in)) << 8;
skip(in, n);
}
if (flags & 8) while (read1(in) != 0) ;
if (flags & 16) while (read1(in) != 0) ;
if (flags & 2) skip(in, 2);
}
/* decompress gzip file "name", return strm with a deflate stream ready to
continue compression of the data in the gzip file, and return a file
descriptor pointing to where to write the compressed data -- the deflate
stream is initialized to compress using level "level" */
local int gzscan(char *name, z_stream *strm, int level)
{
int ret, lastbit, left, full;
unsigned have;
unsigned long crc, tot;
unsigned char *window;
off_t lastoff, end;
file gz;
/* open gzip file */
gz.name = name;
gz.fd = open(name, O_RDWR, 0);
if (gz.fd == -1) bye("cannot open ", name);
gz.buf = malloc(CHUNK);
if (gz.buf == NULL) bye("out of memory", "");
gz.size = LGCHUNK;
gz.left = 0;
/* skip gzip header */
gzheader(&gz);
/* prepare to decompress */
window = malloc(DSIZE);
if (window == NULL) bye("out of memory", "");
strm->zalloc = Z_NULL;
strm->zfree = Z_NULL;
strm->opaque = Z_NULL;
ret = inflateInit2(strm, -15);
if (ret != Z_OK) bye("out of memory", " or library mismatch");
/* decompress the deflate stream, saving append information */
lastbit = 0;
lastoff = lseek(gz.fd, 0L, SEEK_CUR) - gz.left;
left = 0;
strm->avail_in = gz.left;
strm->next_in = gz.next;
crc = crc32(0L, Z_NULL, 0);
have = full = 0;
do {
/* if needed, get more input */
if (strm->avail_in == 0) {
readmore(&gz);
strm->avail_in = gz.left;
strm->next_in = gz.next;
}
/* set up output to next available section of sliding window */
strm->avail_out = DSIZE - have;
strm->next_out = window + have;
/* inflate and check for errors */
ret = inflate(strm, Z_BLOCK);
if (ret == Z_STREAM_ERROR) bye("internal stream error!", "");
if (ret == Z_MEM_ERROR) bye("out of memory", "");
if (ret == Z_DATA_ERROR)
bye("invalid compressed data--format violated in", name);
/* update crc and sliding window pointer */
crc = crc32(crc, window + have, DSIZE - have - strm->avail_out);
if (strm->avail_out)
have = DSIZE - strm->avail_out;
else {
have = 0;
full = 1;
}
/* process end of block */
if (strm->data_type & 128) {
if (strm->data_type & 64)
left = strm->data_type & 0x1f;
else {
lastbit = strm->data_type & 0x1f;
lastoff = lseek(gz.fd, 0L, SEEK_CUR) - strm->avail_in;
}
}
} while (ret != Z_STREAM_END);
inflateEnd(strm);
gz.left = strm->avail_in;
gz.next = strm->next_in;
/* save the location of the end of the compressed data */
end = lseek(gz.fd, 0L, SEEK_CUR) - gz.left;
/* check gzip trailer and save total for deflate */
if (crc != read4(&gz))
bye("invalid compressed data--crc mismatch in ", name);
tot = strm->total_out;
if ((tot & 0xffffffffUL) != read4(&gz))
bye("invalid compressed data--length mismatch in", name);
/* if not at end of file, warn */
if (gz.left || readin(&gz))
fprintf(stderr,
"gzappend warning: junk at end of gzip file overwritten\n");
/* clear last block bit */
lseek(gz.fd, lastoff - (lastbit != 0), SEEK_SET);
if (read(gz.fd, gz.buf, 1) != 1) bye("reading after seek on ", name);
*gz.buf = (unsigned char)(*gz.buf ^ (1 << ((8 - lastbit) & 7)));
lseek(gz.fd, -1L, SEEK_CUR);
if (write(gz.fd, gz.buf, 1) != 1) bye("writing after seek to ", name);
/* if window wrapped, build dictionary from window by rotating */
if (full) {
rotate(window, DSIZE, have);
have = DSIZE;
}
/* set up deflate stream with window, crc, total_in, and leftover bits */
ret = deflateInit2(strm, level, Z_DEFLATED, -15, 8, Z_DEFAULT_STRATEGY);
if (ret != Z_OK) bye("out of memory", "");
deflateSetDictionary(strm, window, have);
strm->adler = crc;
strm->total_in = tot;
if (left) {
lseek(gz.fd, --end, SEEK_SET);
if (read(gz.fd, gz.buf, 1) != 1) bye("reading after seek on ", name);
deflatePrime(strm, 8 - left, *gz.buf);
}
lseek(gz.fd, end, SEEK_SET);
/* clean up and return */
free(window);
free(gz.buf);
return gz.fd;
}
/* append file "name" to gzip file gd using deflate stream strm -- if last
is true, then finish off the deflate stream at the end */
local void gztack(char *name, int gd, z_stream *strm, int last)
{
int fd, len, ret;
unsigned left;
unsigned char *in, *out;
/* open file to compress and append */
fd = 0;
if (name != NULL) {
fd = open(name, O_RDONLY, 0);
if (fd == -1)
fprintf(stderr, "gzappend warning: %s not found, skipping ...\n",
name);
}
/* allocate buffers */
in = malloc(CHUNK);
out = malloc(CHUNK);
if (in == NULL || out == NULL) bye("out of memory", "");
/* compress input file and append to gzip file */
do {
/* get more input */
len = read(fd, in, CHUNK);
if (len == -1) {
fprintf(stderr,
"gzappend warning: error reading %s, skipping rest ...\n",
name);
len = 0;
}
strm->avail_in = (unsigned)len;
strm->next_in = in;
if (len) strm->adler = crc32(strm->adler, in, (unsigned)len);
/* compress and write all available output */
do {
strm->avail_out = CHUNK;
strm->next_out = out;
ret = deflate(strm, last && len == 0 ? Z_FINISH : Z_NO_FLUSH);
left = CHUNK - strm->avail_out;
while (left) {
len = write(gd, out + CHUNK - strm->avail_out - left, left);
if (len == -1) bye("writing gzip file", "");
left -= (unsigned)len;
}
} while (strm->avail_out == 0 && ret != Z_STREAM_END);
} while (len != 0);
/* write trailer after last entry */
if (last) {
deflateEnd(strm);
out[0] = (unsigned char)(strm->adler);
out[1] = (unsigned char)(strm->adler >> 8);
out[2] = (unsigned char)(strm->adler >> 16);
out[3] = (unsigned char)(strm->adler >> 24);
out[4] = (unsigned char)(strm->total_in);
out[5] = (unsigned char)(strm->total_in >> 8);
out[6] = (unsigned char)(strm->total_in >> 16);
out[7] = (unsigned char)(strm->total_in >> 24);
len = 8;
do {
ret = write(gd, out + 8 - len, len);
if (ret == -1) bye("writing gzip file", "");
len -= ret;
} while (len);
close(gd);
}
/* clean up and return */
free(out);
free(in);
if (fd > 0) close(fd);
}
/* process the compression level option if present, scan the gzip file, and
append the specified files, or append the data from stdin if no other file
names are provided on the command line -- the gzip file must be writable
and seekable */
int main(int argc, char **argv)
{
int gd, level;
z_stream strm;
/* ignore command name */
argc--; argv++;
/* provide usage if no arguments */
if (*argv == NULL) {
printf(
"gzappend 1.2 (11 Oct 2012) Copyright (C) 2003, 2012 Mark Adler\n"
);
printf(
"usage: gzappend [-level] file.gz [ addthis [ andthis ... ]]\n");
return 0;
}
/* set compression level */
level = Z_DEFAULT_COMPRESSION;
if (argv[0][0] == '-') {
if (argv[0][1] < '0' || argv[0][1] > '9' || argv[0][2] != 0)
bye("invalid compression level", "");
level = argv[0][1] - '0';
if (*++argv == NULL) bye("no gzip file name after options", "");
}
/* prepare to append to gzip file */
gd = gzscan(*argv++, &strm, level);
/* append files on command line, or from stdin if none */
if (*argv == NULL)
gztack(NULL, gd, &strm, 1);
else
do {
gztack(*argv, gd, &strm, argv[1] == NULL);
} while (*++argv != NULL);
return 0;
}

View File

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

File diff suppressed because it is too large Load Diff

View File

@ -1,91 +0,0 @@
/* gzlog.h
Copyright (C) 2004, 2008, 2012 Mark Adler, all rights reserved
version 2.2, 14 Aug 2012
This software is provided 'as-is', without any express or implied
warranty. In no event will the author be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
Mark Adler madler@alumni.caltech.edu
*/
/* Version History:
1.0 26 Nov 2004 First version
2.0 25 Apr 2008 Complete redesign for recovery of interrupted operations
Interface changed slightly in that now path is a prefix
Compression now occurs as needed during gzlog_write()
gzlog_write() now always leaves the log file as valid gzip
2.1 8 Jul 2012 Fix argument checks in gzlog_compress() and gzlog_write()
2.2 14 Aug 2012 Clean up signed comparisons
*/
/*
The gzlog object allows writing short messages to a gzipped log file,
opening the log file locked for small bursts, and then closing it. The log
object works by appending stored (uncompressed) data to the gzip file until
1 MB has been accumulated. At that time, the stored data is compressed, and
replaces the uncompressed data in the file. The log file is truncated to
its new size at that time. After each write operation, the log file is a
valid gzip file that can decompressed to recover what was written.
The gzlog operations can be interupted at any point due to an application or
system crash, and the log file will be recovered the next time the log is
opened with gzlog_open().
*/
#ifndef GZLOG_H
#define GZLOG_H
/* gzlog object type */
typedef void gzlog;
/* Open a gzlog object, creating the log file if it does not exist. Return
NULL on error. Note that gzlog_open() could take a while to complete if it
has to wait to verify that a lock is stale (possibly for five minutes), or
if there is significant contention with other instantiations of this object
when locking the resource. path is the prefix of the file names created by
this object. If path is "foo", then the log file will be "foo.gz", and
other auxiliary files will be created and destroyed during the process:
"foo.dict" for a compression dictionary, "foo.temp" for a temporary (next)
dictionary, "foo.add" for data being added or compressed, "foo.lock" for the
lock file, and "foo.repairs" to log recovery operations performed due to
interrupted gzlog operations. A gzlog_open() followed by a gzlog_close()
will recover a previously interrupted operation, if any. */
gzlog *gzlog_open(char *path);
/* Write to a gzlog object. Return zero on success, -1 if there is a file i/o
error on any of the gzlog files (this should not happen if gzlog_open()
succeeded, unless the device has run out of space or leftover auxiliary
files have permissions or ownership that prevent their use), -2 if there is
a memory allocation failure, or -3 if the log argument is invalid (e.g. if
it was not created by gzlog_open()). This function will write data to the
file uncompressed, until 1 MB has been accumulated, at which time that data
will be compressed. The log file will be a valid gzip file upon successful
return. */
int gzlog_write(gzlog *log, void *data, size_t len);
/* Force compression of any uncompressed data in the log. This should be used
sparingly, if at all. The main application would be when a log file will
not be appended to again. If this is used to compress frequently while
appending, it will both significantly increase the execution time and
reduce the compression ratio. The return codes are the same as for
gzlog_write(). */
int gzlog_compress(gzlog *log);
/* Close a gzlog object. Return zero on success, -3 if the log argument is
invalid. The log object is freed, and so cannot be referenced again. */
int gzlog_close(gzlog *log);
#endif

View File

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

View File

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

View File

@ -1,409 +0,0 @@
/* zran.c -- example of zlib/gzip stream indexing and random access
* Copyright (C) 2005, 2012 Mark Adler
* For conditions of distribution and use, see copyright notice in zlib.h
Version 1.1 29 Sep 2012 Mark Adler */
/* Version History:
1.0 29 May 2005 First version
1.1 29 Sep 2012 Fix memory reallocation error
*/
/* Illustrate the use of Z_BLOCK, inflatePrime(), and inflateSetDictionary()
for random access of a compressed file. A file containing a zlib or gzip
stream is provided on the command line. The compressed stream is decoded in
its entirety, and an index built with access points about every SPAN bytes
in the uncompressed output. The compressed file is left open, and can then
be read randomly, having to decompress on the average SPAN/2 uncompressed
bytes before getting to the desired block of data.
An access point can be created at the start of any deflate block, by saving
the starting file offset and bit of that block, and the 32K bytes of
uncompressed data that precede that block. Also the uncompressed offset of
that block is saved to provide a referece for locating a desired starting
point in the uncompressed stream. build_index() works by decompressing the
input zlib or gzip stream a block at a time, and at the end of each block
deciding if enough uncompressed data has gone by to justify the creation of
a new access point. If so, that point is saved in a data structure that
grows as needed to accommodate the points.
To use the index, an offset in the uncompressed data is provided, for which
the latest access point at or preceding that offset is located in the index.
The input file is positioned to the specified location in the index, and if
necessary the first few bits of the compressed data is read from the file.
inflate is initialized with those bits and the 32K of uncompressed data, and
the decompression then proceeds until the desired offset in the file is
reached. Then the decompression continues to read the desired uncompressed
data from the file.
Another approach would be to generate the index on demand. In that case,
requests for random access reads from the compressed data would try to use
the index, but if a read far enough past the end of the index is required,
then further index entries would be generated and added.
There is some fair bit of overhead to starting inflation for the random
access, mainly copying the 32K byte dictionary. So if small pieces of the
file are being accessed, it would make sense to implement a cache to hold
some lookahead and avoid many calls to extract() for small lengths.
Another way to build an index would be to use inflateCopy(). That would
not be constrained to have access points at block boundaries, but requires
more memory per access point, and also cannot be saved to file due to the
use of pointers in the state. The approach here allows for storage of the
index in a file.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "zlib.h"
#define local static
#define SPAN 1048576L /* desired distance between access points */
#define WINSIZE 32768U /* sliding window size */
#define CHUNK 16384 /* file input buffer size */
/* access point entry */
struct point {
off_t out; /* corresponding offset in uncompressed data */
off_t in; /* offset in input file of first full byte */
int bits; /* number of bits (1-7) from byte at in - 1, or 0 */
unsigned char window[WINSIZE]; /* preceding 32K of uncompressed data */
};
/* access point list */
struct access {
int have; /* number of list entries filled in */
int size; /* number of list entries allocated */
struct point *list; /* allocated list */
};
/* Deallocate an index built by build_index() */
local void free_index(struct access *index)
{
if (index != NULL) {
free(index->list);
free(index);
}
}
/* Add an entry to the access point list. If out of memory, deallocate the
existing list and return NULL. */
local struct access *addpoint(struct access *index, int bits,
off_t in, off_t out, unsigned left, unsigned char *window)
{
struct point *next;
/* if list is empty, create it (start with eight points) */
if (index == NULL) {
index = malloc(sizeof(struct access));
if (index == NULL) return NULL;
index->list = malloc(sizeof(struct point) << 3);
if (index->list == NULL) {
free(index);
return NULL;
}
index->size = 8;
index->have = 0;
}
/* if list is full, make it bigger */
else if (index->have == index->size) {
index->size <<= 1;
next = realloc(index->list, sizeof(struct point) * index->size);
if (next == NULL) {
free_index(index);
return NULL;
}
index->list = next;
}
/* fill in entry and increment how many we have */
next = index->list + index->have;
next->bits = bits;
next->in = in;
next->out = out;
if (left)
memcpy(next->window, window + WINSIZE - left, left);
if (left < WINSIZE)
memcpy(next->window + left, window, WINSIZE - left);
index->have++;
/* return list, possibly reallocated */
return index;
}
/* Make one entire pass through the compressed stream and build an index, with
access points about every span bytes of uncompressed output -- span is
chosen to balance the speed of random access against the memory requirements
of the list, about 32K bytes per access point. Note that data after the end
of the first zlib or gzip stream in the file is ignored. build_index()
returns the number of access points on success (>= 1), Z_MEM_ERROR for out
of memory, Z_DATA_ERROR for an error in the input file, or Z_ERRNO for a
file read error. On success, *built points to the resulting index. */
local int build_index(FILE *in, off_t span, struct access **built)
{
int ret;
off_t totin, totout; /* our own total counters to avoid 4GB limit */
off_t last; /* totout value of last access point */
struct access *index; /* access points being generated */
z_stream strm;
unsigned char input[CHUNK];
unsigned char window[WINSIZE];
/* initialize inflate */
strm.zalloc = Z_NULL;
strm.zfree = Z_NULL;
strm.opaque = Z_NULL;
strm.avail_in = 0;
strm.next_in = Z_NULL;
ret = inflateInit2(&strm, 47); /* automatic zlib or gzip decoding */
if (ret != Z_OK)
return ret;
/* inflate the input, maintain a sliding window, and build an index -- this
also validates the integrity of the compressed data using the check
information at the end of the gzip or zlib stream */
totin = totout = last = 0;
index = NULL; /* will be allocated by first addpoint() */
strm.avail_out = 0;
do {
/* get some compressed data from input file */
strm.avail_in = fread(input, 1, CHUNK, in);
if (ferror(in)) {
ret = Z_ERRNO;
goto build_index_error;
}
if (strm.avail_in == 0) {
ret = Z_DATA_ERROR;
goto build_index_error;
}
strm.next_in = input;
/* process all of that, or until end of stream */
do {
/* reset sliding window if necessary */
if (strm.avail_out == 0) {
strm.avail_out = WINSIZE;
strm.next_out = window;
}
/* inflate until out of input, output, or at end of block --
update the total input and output counters */
totin += strm.avail_in;
totout += strm.avail_out;
ret = inflate(&strm, Z_BLOCK); /* return at end of block */
totin -= strm.avail_in;
totout -= strm.avail_out;
if (ret == Z_NEED_DICT)
ret = Z_DATA_ERROR;
if (ret == Z_MEM_ERROR || ret == Z_DATA_ERROR)
goto build_index_error;
if (ret == Z_STREAM_END)
break;
/* if at end of block, consider adding an index entry (note that if
data_type indicates an end-of-block, then all of the
uncompressed data from that block has been delivered, and none
of the compressed data after that block has been consumed,
except for up to seven bits) -- the totout == 0 provides an
entry point after the zlib or gzip header, and assures that the
index always has at least one access point; we avoid creating an
access point after the last block by checking bit 6 of data_type
*/
if ((strm.data_type & 128) && !(strm.data_type & 64) &&
(totout == 0 || totout - last > span)) {
index = addpoint(index, strm.data_type & 7, totin,
totout, strm.avail_out, window);
if (index == NULL) {
ret = Z_MEM_ERROR;
goto build_index_error;
}
last = totout;
}
} while (strm.avail_in != 0);
} while (ret != Z_STREAM_END);
/* clean up and return index (release unused entries in list) */
(void)inflateEnd(&strm);
index->list = realloc(index->list, sizeof(struct point) * index->have);
index->size = index->have;
*built = index;
return index->size;
/* return error */
build_index_error:
(void)inflateEnd(&strm);
if (index != NULL)
free_index(index);
return ret;
}
/* Use the index to read len bytes from offset into buf, return bytes read or
negative for error (Z_DATA_ERROR or Z_MEM_ERROR). If data is requested past
the end of the uncompressed data, then extract() will return a value less
than len, indicating how much as actually read into buf. This function
should not return a data error unless the file was modified since the index
was generated. extract() may also return Z_ERRNO if there is an error on
reading or seeking the input file. */
local int extract(FILE *in, struct access *index, off_t offset,
unsigned char *buf, int len)
{
int ret, skip;
z_stream strm;
struct point *here;
unsigned char input[CHUNK];
unsigned char discard[WINSIZE];
/* proceed only if something reasonable to do */
if (len < 0)
return 0;
/* find where in stream to start */
here = index->list;
ret = index->have;
while (--ret && here[1].out <= offset)
here++;
/* initialize file and inflate state to start there */
strm.zalloc = Z_NULL;
strm.zfree = Z_NULL;
strm.opaque = Z_NULL;
strm.avail_in = 0;
strm.next_in = Z_NULL;
ret = inflateInit2(&strm, -15); /* raw inflate */
if (ret != Z_OK)
return ret;
ret = fseeko(in, here->in - (here->bits ? 1 : 0), SEEK_SET);
if (ret == -1)
goto extract_ret;
if (here->bits) {
ret = getc(in);
if (ret == -1) {
ret = ferror(in) ? Z_ERRNO : Z_DATA_ERROR;
goto extract_ret;
}
(void)inflatePrime(&strm, here->bits, ret >> (8 - here->bits));
}
(void)inflateSetDictionary(&strm, here->window, WINSIZE);
/* skip uncompressed bytes until offset reached, then satisfy request */
offset -= here->out;
strm.avail_in = 0;
skip = 1; /* while skipping to offset */
do {
/* define where to put uncompressed data, and how much */
if (offset == 0 && skip) { /* at offset now */
strm.avail_out = len;
strm.next_out = buf;
skip = 0; /* only do this once */
}
if (offset > WINSIZE) { /* skip WINSIZE bytes */
strm.avail_out = WINSIZE;
strm.next_out = discard;
offset -= WINSIZE;
}
else if (offset != 0) { /* last skip */
strm.avail_out = (unsigned)offset;
strm.next_out = discard;
offset = 0;
}
/* uncompress until avail_out filled, or end of stream */
do {
if (strm.avail_in == 0) {
strm.avail_in = fread(input, 1, CHUNK, in);
if (ferror(in)) {
ret = Z_ERRNO;
goto extract_ret;
}
if (strm.avail_in == 0) {
ret = Z_DATA_ERROR;
goto extract_ret;
}
strm.next_in = input;
}
ret = inflate(&strm, Z_NO_FLUSH); /* normal inflate */
if (ret == Z_NEED_DICT)
ret = Z_DATA_ERROR;
if (ret == Z_MEM_ERROR || ret == Z_DATA_ERROR)
goto extract_ret;
if (ret == Z_STREAM_END)
break;
} while (strm.avail_out != 0);
/* if reach end of stream, then don't keep trying to get more */
if (ret == Z_STREAM_END)
break;
/* do until offset reached and requested data read, or stream ends */
} while (skip);
/* compute number of uncompressed bytes read after offset */
ret = skip ? 0 : len - strm.avail_out;
/* clean up and return bytes read or error */
extract_ret:
(void)inflateEnd(&strm);
return ret;
}
/* Demonstrate the use of build_index() and extract() by processing the file
provided on the command line, and the extracting 16K from about 2/3rds of
the way through the uncompressed output, and writing that to stdout. */
int main(int argc, char **argv)
{
int len;
off_t offset;
FILE *in;
struct access *index = NULL;
unsigned char buf[CHUNK];
/* open input file */
if (argc != 2) {
fprintf(stderr, "usage: zran file.gz\n");
return 1;
}
in = fopen(argv[1], "rb");
if (in == NULL) {
fprintf(stderr, "zran: could not open %s for reading\n", argv[1]);
return 1;
}
/* build index */
len = build_index(in, SPAN, &index);
if (len < 0) {
fclose(in);
switch (len) {
case Z_MEM_ERROR:
fprintf(stderr, "zran: out of memory\n");
break;
case Z_DATA_ERROR:
fprintf(stderr, "zran: compressed data error in %s\n", argv[1]);
break;
case Z_ERRNO:
fprintf(stderr, "zran: read error on %s\n", argv[1]);
break;
default:
fprintf(stderr, "zran: error %d while building index\n", len);
}
return 1;
}
fprintf(stderr, "zran: built index with %d access points\n", len);
/* use index by reading some bytes from an arbitrary offset */
offset = (index->list[index->have - 1].out << 1) / 3;
len = extract(in, index, offset, buf, CHUNK);
if (len < 0)
fprintf(stderr, "zran: extraction failed: %s error\n",
len == Z_MEM_ERROR ? "out of memory" : "input corrupted");
else {
fwrite(buf, 1, len, stdout);
fprintf(stderr, "zran: extracted %d bytes at %llu\n", len, offset);
}
/* clean up and exit */
free_index(index);
fclose(in);
return 0;
}

View File

@ -8,9 +8,7 @@
/* gzclose() is in a separate file so that it is linked in only if it is used. /* gzclose() is in a separate file so that it is linked in only if it is used.
That way the other gzclose functions can be used instead to avoid linking in That way the other gzclose functions can be used instead to avoid linking in
unneeded compression or decompression routines. */ unneeded compression or decompression routines. */
int ZEXPORT gzclose(file) int ZEXPORT gzclose(gzFile file) {
gzFile file;
{
#ifndef NO_GZCOMPRESS #ifndef NO_GZCOMPRESS
gz_statep state; gz_statep state;

View File

@ -1,5 +1,5 @@
/* gzguts.h -- zlib internal header definitions for gz* operations /* gzguts.h -- zlib internal header definitions for gz* operations
* Copyright (C) 2004, 2005, 2010, 2011, 2012, 2013, 2016 Mark Adler * Copyright (C) 2004-2019 Mark Adler
* For conditions of distribution and use, see copyright notice in zlib.h * For conditions of distribution and use, see copyright notice in zlib.h
*/ */
@ -7,9 +7,8 @@
# ifndef _LARGEFILE_SOURCE # ifndef _LARGEFILE_SOURCE
# define _LARGEFILE_SOURCE 1 # define _LARGEFILE_SOURCE 1
# endif # endif
# ifdef _FILE_OFFSET_BITS # undef _FILE_OFFSET_BITS
# undef _FILE_OFFSET_BITS # undef _TIME_BITS
# endif
#endif #endif
#ifdef HAVE_HIDDEN #ifdef HAVE_HIDDEN
@ -39,7 +38,7 @@
# include <io.h> # include <io.h>
#endif #endif
#if defined(_WIN32) || defined(__CYGWIN__) #if defined(_WIN32)
# define WIDECHAR # define WIDECHAR
#endif #endif
@ -119,8 +118,8 @@
/* gz* functions always use library allocation functions */ /* gz* functions always use library allocation functions */
#ifndef STDC #ifndef STDC
extern voidp malloc OF((uInt size)); extern voidp malloc(uInt size);
extern void free OF((voidpf ptr)); extern void free(voidpf ptr);
#endif #endif
/* get errno and strerror definition */ /* get errno and strerror definition */
@ -138,10 +137,10 @@
/* provide prototypes for these when building zlib without LFS */ /* provide prototypes for these when building zlib without LFS */
#if !defined(_LARGEFILE64_SOURCE) || _LFS64_LARGEFILE-0 == 0 #if !defined(_LARGEFILE64_SOURCE) || _LFS64_LARGEFILE-0 == 0
ZEXTERN gzFile ZEXPORT gzopen64 OF((const char *, const char *)); ZEXTERN gzFile ZEXPORT gzopen64(const char *, const char *);
ZEXTERN z_off64_t ZEXPORT gzseek64 OF((gzFile, z_off64_t, int)); ZEXTERN z_off64_t ZEXPORT gzseek64(gzFile, z_off64_t, int);
ZEXTERN z_off64_t ZEXPORT gztell64 OF((gzFile)); ZEXTERN z_off64_t ZEXPORT gztell64(gzFile);
ZEXTERN z_off64_t ZEXPORT gzoffset64 OF((gzFile)); ZEXTERN z_off64_t ZEXPORT gzoffset64(gzFile);
#endif #endif
/* default memLevel */ /* default memLevel */
@ -190,6 +189,7 @@ typedef struct {
/* just for writing */ /* just for writing */
int level; /* compression level */ int level; /* compression level */
int strategy; /* compression strategy */ int strategy; /* compression strategy */
int reset; /* true if a reset is pending after a Z_FINISH */
/* seek request */ /* seek request */
z_off64_t skip; /* amount to skip (already rewound if backwards) */ z_off64_t skip; /* amount to skip (already rewound if backwards) */
int seek; /* true if seek request pending */ int seek; /* true if seek request pending */
@ -202,9 +202,9 @@ typedef struct {
typedef gz_state FAR *gz_statep; typedef gz_state FAR *gz_statep;
/* shared functions */ /* shared functions */
void ZLIB_INTERNAL gz_error OF((gz_statep, int, const char *)); void ZLIB_INTERNAL gz_error(gz_statep, int, const char *);
#if defined UNDER_CE #if defined UNDER_CE
char ZLIB_INTERNAL *gz_strwinerror OF((DWORD error)); char ZLIB_INTERNAL *gz_strwinerror(DWORD error);
#endif #endif
/* GT_OFF(x), where x is an unsigned value, is true if x > maximum z_off64_t /* GT_OFF(x), where x is an unsigned value, is true if x > maximum z_off64_t
@ -213,6 +213,6 @@ char ZLIB_INTERNAL *gz_strwinerror OF((DWORD error));
#ifdef INT_MAX #ifdef INT_MAX
# define GT_OFF(x) (sizeof(int) == sizeof(z_off64_t) && (x) > INT_MAX) # define GT_OFF(x) (sizeof(int) == sizeof(z_off64_t) && (x) > INT_MAX)
#else #else
unsigned ZLIB_INTERNAL gz_intmax OF((void)); unsigned ZLIB_INTERNAL gz_intmax(void);
# define GT_OFF(x) (sizeof(int) == sizeof(z_off64_t) && (x) > gz_intmax()) # define GT_OFF(x) (sizeof(int) == sizeof(z_off64_t) && (x) > gz_intmax())
#endif #endif

109
3rdparty/zlib/gzlib.c vendored
View File

@ -1,11 +1,11 @@
/* gzlib.c -- zlib functions common to reading and writing gzip files /* gzlib.c -- zlib functions common to reading and writing gzip files
* Copyright (C) 2004-2017 Mark Adler * Copyright (C) 2004-2019 Mark Adler
* For conditions of distribution and use, see copyright notice in zlib.h * For conditions of distribution and use, see copyright notice in zlib.h
*/ */
#include "gzguts.h" #include "gzguts.h"
#if defined(_WIN32) && !defined(__BORLANDC__) && !defined(__MINGW32__) #if defined(_WIN32) && !defined(__BORLANDC__)
# define LSEEK _lseeki64 # define LSEEK _lseeki64
#else #else
#if defined(_LARGEFILE64_SOURCE) && _LFS64_LARGEFILE-0 #if defined(_LARGEFILE64_SOURCE) && _LFS64_LARGEFILE-0
@ -15,10 +15,6 @@
#endif #endif
#endif #endif
/* Local functions */
local void gz_reset OF((gz_statep));
local gzFile gz_open OF((const void *, int, const char *));
#if defined UNDER_CE #if defined UNDER_CE
/* Map the Windows error number in ERROR to a locale-dependent error message /* Map the Windows error number in ERROR to a locale-dependent error message
@ -30,9 +26,7 @@ local gzFile gz_open OF((const void *, int, const char *));
The gz_strwinerror function does not change the current setting of The gz_strwinerror function does not change the current setting of
GetLastError. */ GetLastError. */
char ZLIB_INTERNAL *gz_strwinerror (error) char ZLIB_INTERNAL *gz_strwinerror(DWORD error) {
DWORD error;
{
static char buf[1024]; static char buf[1024];
wchar_t *msgbuf; wchar_t *msgbuf;
@ -72,15 +66,15 @@ char ZLIB_INTERNAL *gz_strwinerror (error)
#endif /* UNDER_CE */ #endif /* UNDER_CE */
/* Reset gzip file state */ /* Reset gzip file state */
local void gz_reset(state) local void gz_reset(gz_statep state) {
gz_statep state;
{
state->x.have = 0; /* no output data available */ state->x.have = 0; /* no output data available */
if (state->mode == GZ_READ) { /* for reading ... */ if (state->mode == GZ_READ) { /* for reading ... */
state->eof = 0; /* not at end of file */ state->eof = 0; /* not at end of file */
state->past = 0; /* have not read past end yet */ state->past = 0; /* have not read past end yet */
state->how = LOOK; /* look for gzip header */ state->how = LOOK; /* look for gzip header */
} }
else /* for writing ... */
state->reset = 0; /* no deflateReset pending */
state->seek = 0; /* no seek request pending */ state->seek = 0; /* no seek request pending */
gz_error(state, Z_OK, NULL); /* clear error */ gz_error(state, Z_OK, NULL); /* clear error */
state->x.pos = 0; /* no uncompressed data yet */ state->x.pos = 0; /* no uncompressed data yet */
@ -88,11 +82,7 @@ local void gz_reset(state)
} }
/* Open a gzip file either by name or file descriptor. */ /* Open a gzip file either by name or file descriptor. */
local gzFile gz_open(path, fd, mode) local gzFile gz_open(const void *path, int fd, const char *mode) {
const void *path;
int fd;
const char *mode;
{
gz_statep state; gz_statep state;
z_size_t len; z_size_t len;
int oflag; int oflag;
@ -267,26 +257,17 @@ local gzFile gz_open(path, fd, mode)
} }
/* -- see zlib.h -- */ /* -- see zlib.h -- */
gzFile ZEXPORT gzopen(path, mode) gzFile ZEXPORT gzopen(const char *path, const char *mode) {
const char *path;
const char *mode;
{
return gz_open(path, -1, mode); return gz_open(path, -1, mode);
} }
/* -- see zlib.h -- */ /* -- see zlib.h -- */
gzFile ZEXPORT gzopen64(path, mode) gzFile ZEXPORT gzopen64(const char *path, const char *mode) {
const char *path;
const char *mode;
{
return gz_open(path, -1, mode); return gz_open(path, -1, mode);
} }
/* -- see zlib.h -- */ /* -- see zlib.h -- */
gzFile ZEXPORT gzdopen(fd, mode) gzFile ZEXPORT gzdopen(int fd, const char *mode) {
int fd;
const char *mode;
{
char *path; /* identifier for error messages */ char *path; /* identifier for error messages */
gzFile gz; gzFile gz;
@ -304,19 +285,13 @@ gzFile ZEXPORT gzdopen(fd, mode)
/* -- see zlib.h -- */ /* -- see zlib.h -- */
#ifdef WIDECHAR #ifdef WIDECHAR
gzFile ZEXPORT gzopen_w(path, mode) gzFile ZEXPORT gzopen_w(const wchar_t *path, const char *mode) {
const wchar_t *path;
const char *mode;
{
return gz_open(path, -2, mode); return gz_open(path, -2, mode);
} }
#endif #endif
/* -- see zlib.h -- */ /* -- see zlib.h -- */
int ZEXPORT gzbuffer(file, size) int ZEXPORT gzbuffer(gzFile file, unsigned size) {
gzFile file;
unsigned size;
{
gz_statep state; gz_statep state;
/* get internal structure and check integrity */ /* get internal structure and check integrity */
@ -333,16 +308,14 @@ int ZEXPORT gzbuffer(file, size)
/* check and set requested size */ /* check and set requested size */
if ((size << 1) < size) if ((size << 1) < size)
return -1; /* need to be able to double it */ return -1; /* need to be able to double it */
if (size < 2) if (size < 8)
size = 2; /* need two bytes to check magic header */ size = 8; /* needed to behave well with flushing */
state->want = size; state->want = size;
return 0; return 0;
} }
/* -- see zlib.h -- */ /* -- see zlib.h -- */
int ZEXPORT gzrewind(file) int ZEXPORT gzrewind(gzFile file) {
gzFile file;
{
gz_statep state; gz_statep state;
/* get internal structure */ /* get internal structure */
@ -363,11 +336,7 @@ int ZEXPORT gzrewind(file)
} }
/* -- see zlib.h -- */ /* -- see zlib.h -- */
z_off64_t ZEXPORT gzseek64(file, offset, whence) z_off64_t ZEXPORT gzseek64(gzFile file, z_off64_t offset, int whence) {
gzFile file;
z_off64_t offset;
int whence;
{
unsigned n; unsigned n;
z_off64_t ret; z_off64_t ret;
gz_statep state; gz_statep state;
@ -397,7 +366,7 @@ z_off64_t ZEXPORT gzseek64(file, offset, whence)
/* if within raw area while reading, just go there */ /* if within raw area while reading, just go there */
if (state->mode == GZ_READ && state->how == COPY && if (state->mode == GZ_READ && state->how == COPY &&
state->x.pos + offset >= 0) { state->x.pos + offset >= 0) {
ret = LSEEK(state->fd, offset - state->x.have, SEEK_CUR); ret = LSEEK(state->fd, offset - (z_off64_t)state->x.have, SEEK_CUR);
if (ret == -1) if (ret == -1)
return -1; return -1;
state->x.have = 0; state->x.have = 0;
@ -440,11 +409,7 @@ z_off64_t ZEXPORT gzseek64(file, offset, whence)
} }
/* -- see zlib.h -- */ /* -- see zlib.h -- */
z_off_t ZEXPORT gzseek(file, offset, whence) z_off_t ZEXPORT gzseek(gzFile file, z_off_t offset, int whence) {
gzFile file;
z_off_t offset;
int whence;
{
z_off64_t ret; z_off64_t ret;
ret = gzseek64(file, (z_off64_t)offset, whence); ret = gzseek64(file, (z_off64_t)offset, whence);
@ -452,9 +417,7 @@ z_off_t ZEXPORT gzseek(file, offset, whence)
} }
/* -- see zlib.h -- */ /* -- see zlib.h -- */
z_off64_t ZEXPORT gztell64(file) z_off64_t ZEXPORT gztell64(gzFile file) {
gzFile file;
{
gz_statep state; gz_statep state;
/* get internal structure and check integrity */ /* get internal structure and check integrity */
@ -469,9 +432,7 @@ z_off64_t ZEXPORT gztell64(file)
} }
/* -- see zlib.h -- */ /* -- see zlib.h -- */
z_off_t ZEXPORT gztell(file) z_off_t ZEXPORT gztell(gzFile file) {
gzFile file;
{
z_off64_t ret; z_off64_t ret;
ret = gztell64(file); ret = gztell64(file);
@ -479,9 +440,7 @@ z_off_t ZEXPORT gztell(file)
} }
/* -- see zlib.h -- */ /* -- see zlib.h -- */
z_off64_t ZEXPORT gzoffset64(file) z_off64_t ZEXPORT gzoffset64(gzFile file) {
gzFile file;
{
z_off64_t offset; z_off64_t offset;
gz_statep state; gz_statep state;
@ -502,9 +461,7 @@ z_off64_t ZEXPORT gzoffset64(file)
} }
/* -- see zlib.h -- */ /* -- see zlib.h -- */
z_off_t ZEXPORT gzoffset(file) z_off_t ZEXPORT gzoffset(gzFile file) {
gzFile file;
{
z_off64_t ret; z_off64_t ret;
ret = gzoffset64(file); ret = gzoffset64(file);
@ -512,9 +469,7 @@ z_off_t ZEXPORT gzoffset(file)
} }
/* -- see zlib.h -- */ /* -- see zlib.h -- */
int ZEXPORT gzeof(file) int ZEXPORT gzeof(gzFile file) {
gzFile file;
{
gz_statep state; gz_statep state;
/* get internal structure and check integrity */ /* get internal structure and check integrity */
@ -529,10 +484,7 @@ int ZEXPORT gzeof(file)
} }
/* -- see zlib.h -- */ /* -- see zlib.h -- */
const char * ZEXPORT gzerror(file, errnum) const char * ZEXPORT gzerror(gzFile file, int *errnum) {
gzFile file;
int *errnum;
{
gz_statep state; gz_statep state;
/* get internal structure and check integrity */ /* get internal structure and check integrity */
@ -550,9 +502,7 @@ const char * ZEXPORT gzerror(file, errnum)
} }
/* -- see zlib.h -- */ /* -- see zlib.h -- */
void ZEXPORT gzclearerr(file) void ZEXPORT gzclearerr(gzFile file) {
gzFile file;
{
gz_statep state; gz_statep state;
/* get internal structure and check integrity */ /* get internal structure and check integrity */
@ -576,11 +526,7 @@ void ZEXPORT gzclearerr(file)
memory). Simply save the error message as a static string. If there is an memory). Simply save the error message as a static string. If there is an
allocation failure constructing the error message, then convert the error to allocation failure constructing the error message, then convert the error to
out of memory. */ out of memory. */
void ZLIB_INTERNAL gz_error(state, err, msg) void ZLIB_INTERNAL gz_error(gz_statep state, int err, const char *msg) {
gz_statep state;
int err;
const char *msg;
{
/* free previously allocated message and clear */ /* free previously allocated message and clear */
if (state->msg != NULL) { if (state->msg != NULL) {
if (state->err != Z_MEM_ERROR) if (state->err != Z_MEM_ERROR)
@ -622,8 +568,7 @@ void ZLIB_INTERNAL gz_error(state, err, msg)
available) -- we need to do this to cover cases where 2's complement not available) -- we need to do this to cover cases where 2's complement not
used, since C standard permits 1's complement and sign-bit representations, used, since C standard permits 1's complement and sign-bit representations,
otherwise we could just use ((unsigned)-1) >> 1 */ otherwise we could just use ((unsigned)-1) >> 1 */
unsigned ZLIB_INTERNAL gz_intmax() unsigned ZLIB_INTERNAL gz_intmax(void) {
{
unsigned p, q; unsigned p, q;
p = 1; p = 1;

108
3rdparty/zlib/gzread.c vendored
View File

@ -1,29 +1,16 @@
/* gzread.c -- zlib functions for reading gzip files /* gzread.c -- zlib functions for reading gzip files
* Copyright (C) 2004, 2005, 2010, 2011, 2012, 2013, 2016 Mark Adler * Copyright (C) 2004-2017 Mark Adler
* For conditions of distribution and use, see copyright notice in zlib.h * For conditions of distribution and use, see copyright notice in zlib.h
*/ */
#include "gzguts.h" #include "gzguts.h"
/* Local functions */
local int gz_load OF((gz_statep, unsigned char *, unsigned, unsigned *));
local int gz_avail OF((gz_statep));
local int gz_look OF((gz_statep));
local int gz_decomp OF((gz_statep));
local int gz_fetch OF((gz_statep));
local int gz_skip OF((gz_statep, z_off64_t));
local z_size_t gz_read OF((gz_statep, voidp, z_size_t));
/* Use read() to load a buffer -- return -1 on error, otherwise 0. Read from /* Use read() to load a buffer -- return -1 on error, otherwise 0. Read from
state->fd, and update state->eof, state->err, and state->msg as appropriate. state->fd, and update state->eof, state->err, and state->msg as appropriate.
This function needs to loop on read(), since read() is not guaranteed to This function needs to loop on read(), since read() is not guaranteed to
read the number of bytes requested, depending on the type of descriptor. */ read the number of bytes requested, depending on the type of descriptor. */
local int gz_load(state, buf, len, have) local int gz_load(gz_statep state, unsigned char *buf, unsigned len,
gz_statep state; unsigned *have) {
unsigned char *buf;
unsigned len;
unsigned *have;
{
int ret; int ret;
unsigned get, max = ((unsigned)-1 >> 2) + 1; unsigned get, max = ((unsigned)-1 >> 2) + 1;
@ -53,9 +40,7 @@ local int gz_load(state, buf, len, have)
If strm->avail_in != 0, then the current data is moved to the beginning of If strm->avail_in != 0, then the current data is moved to the beginning of
the input buffer, and then the remainder of the buffer is loaded with the the input buffer, and then the remainder of the buffer is loaded with the
available data from the input file. */ available data from the input file. */
local int gz_avail(state) local int gz_avail(gz_statep state) {
gz_statep state;
{
unsigned got; unsigned got;
z_streamp strm = &(state->strm); z_streamp strm = &(state->strm);
@ -88,9 +73,7 @@ local int gz_avail(state)
case, all further file reads will be directly to either the output buffer or case, all further file reads will be directly to either the output buffer or
a user buffer. If decompressing, the inflate state will be initialized. a user buffer. If decompressing, the inflate state will be initialized.
gz_look() will return 0 on success or -1 on failure. */ gz_look() will return 0 on success or -1 on failure. */
local int gz_look(state) local int gz_look(gz_statep state) {
gz_statep state;
{
z_streamp strm = &(state->strm); z_streamp strm = &(state->strm);
/* allocate read buffers and inflate memory */ /* allocate read buffers and inflate memory */
@ -157,11 +140,9 @@ local int gz_look(state)
the output buffer is larger than the input buffer, which also assures the output buffer is larger than the input buffer, which also assures
space for gzungetc() */ space for gzungetc() */
state->x.next = state->out; state->x.next = state->out;
if (strm->avail_in) { memcpy(state->x.next, strm->next_in, strm->avail_in);
memcpy(state->x.next, strm->next_in, strm->avail_in); state->x.have = strm->avail_in;
state->x.have = strm->avail_in; strm->avail_in = 0;
strm->avail_in = 0;
}
state->how = COPY; state->how = COPY;
state->direct = 1; state->direct = 1;
return 0; return 0;
@ -172,9 +153,7 @@ local int gz_look(state)
data. If the gzip stream completes, state->how is reset to LOOK to look for data. If the gzip stream completes, state->how is reset to LOOK to look for
the next gzip stream or raw data, once state->x.have is depleted. Returns 0 the next gzip stream or raw data, once state->x.have is depleted. Returns 0
on success, -1 on failure. */ on success, -1 on failure. */
local int gz_decomp(state) local int gz_decomp(gz_statep state) {
gz_statep state;
{
int ret = Z_OK; int ret = Z_OK;
unsigned had; unsigned had;
z_streamp strm = &(state->strm); z_streamp strm = &(state->strm);
@ -226,9 +205,7 @@ local int gz_decomp(state)
looked for to determine whether to copy or decompress. Returns -1 on error, looked for to determine whether to copy or decompress. Returns -1 on error,
otherwise 0. gz_fetch() will leave state->how as COPY or GZIP unless the otherwise 0. gz_fetch() will leave state->how as COPY or GZIP unless the
end of the input file has been reached and all data has been processed. */ end of the input file has been reached and all data has been processed. */
local int gz_fetch(state) local int gz_fetch(gz_statep state) {
gz_statep state;
{
z_streamp strm = &(state->strm); z_streamp strm = &(state->strm);
do { do {
@ -256,10 +233,7 @@ local int gz_fetch(state)
} }
/* Skip len uncompressed bytes of output. Return -1 on error, 0 on success. */ /* Skip len uncompressed bytes of output. Return -1 on error, 0 on success. */
local int gz_skip(state, len) local int gz_skip(gz_statep state, z_off64_t len) {
gz_statep state;
z_off64_t len;
{
unsigned n; unsigned n;
/* skip over len bytes or reach end-of-file, whichever comes first */ /* skip over len bytes or reach end-of-file, whichever comes first */
@ -291,11 +265,7 @@ local int gz_skip(state, len)
input. Return the number of bytes read. If zero is returned, either the input. Return the number of bytes read. If zero is returned, either the
end of file was reached, or there was an error. state->err must be end of file was reached, or there was an error. state->err must be
consulted in that case to determine which. */ consulted in that case to determine which. */
local z_size_t gz_read(state, buf, len) local z_size_t gz_read(gz_statep state, voidp buf, z_size_t len) {
gz_statep state;
voidp buf;
z_size_t len;
{
z_size_t got; z_size_t got;
unsigned n; unsigned n;
@ -314,9 +284,9 @@ local z_size_t gz_read(state, buf, len)
got = 0; got = 0;
do { do {
/* set n to the maximum amount of len that fits in an unsigned int */ /* set n to the maximum amount of len that fits in an unsigned int */
n = -1; n = (unsigned)-1;
if (n > len) if (n > len)
n = len; n = (unsigned)len;
/* first just try copying data from the output buffer */ /* first just try copying data from the output buffer */
if (state->x.have) { if (state->x.have) {
@ -372,11 +342,7 @@ local z_size_t gz_read(state, buf, len)
} }
/* -- see zlib.h -- */ /* -- see zlib.h -- */
int ZEXPORT gzread(file, buf, len) int ZEXPORT gzread(gzFile file, voidp buf, unsigned len) {
gzFile file;
voidp buf;
unsigned len;
{
gz_statep state; gz_statep state;
/* get internal structure */ /* get internal structure */
@ -397,7 +363,7 @@ int ZEXPORT gzread(file, buf, len)
} }
/* read len or fewer bytes to buf */ /* read len or fewer bytes to buf */
len = gz_read(state, buf, len); len = (unsigned)gz_read(state, buf, len);
/* check for an error */ /* check for an error */
if (len == 0 && state->err != Z_OK && state->err != Z_BUF_ERROR) if (len == 0 && state->err != Z_OK && state->err != Z_BUF_ERROR)
@ -408,12 +374,7 @@ int ZEXPORT gzread(file, buf, len)
} }
/* -- see zlib.h -- */ /* -- see zlib.h -- */
z_size_t ZEXPORT gzfread(buf, size, nitems, file) z_size_t ZEXPORT gzfread(voidp buf, z_size_t size, z_size_t nitems, gzFile file) {
voidp buf;
z_size_t size;
z_size_t nitems;
gzFile file;
{
z_size_t len; z_size_t len;
gz_statep state; gz_statep state;
@ -444,10 +405,7 @@ z_size_t ZEXPORT gzfread(buf, size, nitems, file)
#else #else
# undef gzgetc # undef gzgetc
#endif #endif
int ZEXPORT gzgetc(file) int ZEXPORT gzgetc(gzFile file) {
gzFile file;
{
int ret;
unsigned char buf[1]; unsigned char buf[1];
gz_statep state; gz_statep state;
@ -469,21 +427,15 @@ int ZEXPORT gzgetc(file)
} }
/* nothing there -- try gz_read() */ /* nothing there -- try gz_read() */
ret = gz_read(state, buf, 1); return gz_read(state, buf, 1) < 1 ? -1 : buf[0];
return ret < 1 ? -1 : buf[0];
} }
int ZEXPORT gzgetc_(file) int ZEXPORT gzgetc_(gzFile file) {
gzFile file;
{
return gzgetc(file); return gzgetc(file);
} }
/* -- see zlib.h -- */ /* -- see zlib.h -- */
int ZEXPORT gzungetc(c, file) int ZEXPORT gzungetc(int c, gzFile file) {
int c;
gzFile file;
{
gz_statep state; gz_statep state;
/* get internal structure */ /* get internal structure */
@ -491,6 +443,10 @@ int ZEXPORT gzungetc(c, file)
return -1; return -1;
state = (gz_statep)file; state = (gz_statep)file;
/* in case this was just opened, set up the input buffer */
if (state->mode == GZ_READ && state->how == LOOK && state->x.have == 0)
(void)gz_look(state);
/* check that we're reading and that there's no (serious) error */ /* check that we're reading and that there's no (serious) error */
if (state->mode != GZ_READ || if (state->mode != GZ_READ ||
(state->err != Z_OK && state->err != Z_BUF_ERROR)) (state->err != Z_OK && state->err != Z_BUF_ERROR))
@ -540,11 +496,7 @@ int ZEXPORT gzungetc(c, file)
} }
/* -- see zlib.h -- */ /* -- see zlib.h -- */
char * ZEXPORT gzgets(file, buf, len) char * ZEXPORT gzgets(gzFile file, char *buf, int len) {
gzFile file;
char *buf;
int len;
{
unsigned left, n; unsigned left, n;
char *str; char *str;
unsigned char *eol; unsigned char *eol;
@ -604,9 +556,7 @@ char * ZEXPORT gzgets(file, buf, len)
} }
/* -- see zlib.h -- */ /* -- see zlib.h -- */
int ZEXPORT gzdirect(file) int ZEXPORT gzdirect(gzFile file) {
gzFile file;
{
gz_statep state; gz_statep state;
/* get internal structure */ /* get internal structure */
@ -624,9 +574,7 @@ int ZEXPORT gzdirect(file)
} }
/* -- see zlib.h -- */ /* -- see zlib.h -- */
int ZEXPORT gzclose_r(file) int ZEXPORT gzclose_r(gzFile file) {
gzFile file;
{
int ret, err; int ret, err;
gz_statep state; gz_statep state;

View File

@ -1,22 +1,14 @@
/* gzwrite.c -- zlib functions for writing gzip files /* gzwrite.c -- zlib functions for writing gzip files
* Copyright (C) 2004-2017 Mark Adler * Copyright (C) 2004-2019 Mark Adler
* For conditions of distribution and use, see copyright notice in zlib.h * For conditions of distribution and use, see copyright notice in zlib.h
*/ */
#include "gzguts.h" #include "gzguts.h"
/* Local functions */
local int gz_init OF((gz_statep));
local int gz_comp OF((gz_statep, int));
local int gz_zero OF((gz_statep, z_off64_t));
local z_size_t gz_write OF((gz_statep, voidpc, z_size_t));
/* Initialize state for writing a gzip file. Mark initialization by setting /* Initialize state for writing a gzip file. Mark initialization by setting
state->size to non-zero. Return -1 on a memory allocation failure, or 0 on state->size to non-zero. Return -1 on a memory allocation failure, or 0 on
success. */ success. */
local int gz_init(state) local int gz_init(gz_statep state) {
gz_statep state;
{
int ret; int ret;
z_streamp strm = &(state->strm); z_streamp strm = &(state->strm);
@ -70,10 +62,7 @@ local int gz_init(state)
deflate() flush value. If flush is Z_FINISH, then the deflate() state is deflate() flush value. If flush is Z_FINISH, then the deflate() state is
reset to start a new gzip stream. If gz->direct is true, then simply write reset to start a new gzip stream. If gz->direct is true, then simply write
to the output file without compressing, and ignore flush. */ to the output file without compressing, and ignore flush. */
local int gz_comp(state, flush) local int gz_comp(gz_statep state, int flush) {
gz_statep state;
int flush;
{
int ret, writ; int ret, writ;
unsigned have, put, max = ((unsigned)-1 >> 2) + 1; unsigned have, put, max = ((unsigned)-1 >> 2) + 1;
z_streamp strm = &(state->strm); z_streamp strm = &(state->strm);
@ -97,6 +86,15 @@ local int gz_comp(state, flush)
return 0; return 0;
} }
/* check for a pending reset */
if (state->reset) {
/* don't start a new gzip member unless there is data to write */
if (strm->avail_in == 0)
return 0;
deflateReset(strm);
state->reset = 0;
}
/* run deflate() on provided input until it produces no more output */ /* run deflate() on provided input until it produces no more output */
ret = Z_OK; ret = Z_OK;
do { do {
@ -134,7 +132,7 @@ local int gz_comp(state, flush)
/* if that completed a deflate stream, allow another to start */ /* if that completed a deflate stream, allow another to start */
if (flush == Z_FINISH) if (flush == Z_FINISH)
deflateReset(strm); state->reset = 1;
/* all done, no errors */ /* all done, no errors */
return 0; return 0;
@ -142,10 +140,7 @@ local int gz_comp(state, flush)
/* Compress len zeros to output. Return -1 on a write error or memory /* Compress len zeros to output. Return -1 on a write error or memory
allocation failure by gz_comp(), or 0 on success. */ allocation failure by gz_comp(), or 0 on success. */
local int gz_zero(state, len) local int gz_zero(gz_statep state, z_off64_t len) {
gz_statep state;
z_off64_t len;
{
int first; int first;
unsigned n; unsigned n;
z_streamp strm = &(state->strm); z_streamp strm = &(state->strm);
@ -175,11 +170,7 @@ local int gz_zero(state, len)
/* Write len bytes from buf to file. Return the number of bytes written. If /* Write len bytes from buf to file. Return the number of bytes written. If
the returned value is less than len, then there was an error. */ the returned value is less than len, then there was an error. */
local z_size_t gz_write(state, buf, len) local z_size_t gz_write(gz_statep state, voidpc buf, z_size_t len) {
gz_statep state;
voidpc buf;
z_size_t len;
{
z_size_t put = len; z_size_t put = len;
/* if len is zero, avoid unnecessary operations */ /* if len is zero, avoid unnecessary operations */
@ -209,7 +200,7 @@ local z_size_t gz_write(state, buf, len)
state->in); state->in);
copy = state->size - have; copy = state->size - have;
if (copy > len) if (copy > len)
copy = len; copy = (unsigned)len;
memcpy(state->in + have, buf, copy); memcpy(state->in + have, buf, copy);
state->strm.avail_in += copy; state->strm.avail_in += copy;
state->x.pos += copy; state->x.pos += copy;
@ -229,7 +220,7 @@ local z_size_t gz_write(state, buf, len)
do { do {
unsigned n = (unsigned)-1; unsigned n = (unsigned)-1;
if (n > len) if (n > len)
n = len; n = (unsigned)len;
state->strm.avail_in = n; state->strm.avail_in = n;
state->x.pos += n; state->x.pos += n;
if (gz_comp(state, Z_NO_FLUSH) == -1) if (gz_comp(state, Z_NO_FLUSH) == -1)
@ -243,11 +234,7 @@ local z_size_t gz_write(state, buf, len)
} }
/* -- see zlib.h -- */ /* -- see zlib.h -- */
int ZEXPORT gzwrite(file, buf, len) int ZEXPORT gzwrite(gzFile file, voidpc buf, unsigned len) {
gzFile file;
voidpc buf;
unsigned len;
{
gz_statep state; gz_statep state;
/* get internal structure */ /* get internal structure */
@ -271,12 +258,8 @@ int ZEXPORT gzwrite(file, buf, len)
} }
/* -- see zlib.h -- */ /* -- see zlib.h -- */
z_size_t ZEXPORT gzfwrite(buf, size, nitems, file) z_size_t ZEXPORT gzfwrite(voidpc buf, z_size_t size, z_size_t nitems,
voidpc buf; gzFile file) {
z_size_t size;
z_size_t nitems;
gzFile file;
{
z_size_t len; z_size_t len;
gz_statep state; gz_statep state;
@ -301,10 +284,7 @@ z_size_t ZEXPORT gzfwrite(buf, size, nitems, file)
} }
/* -- see zlib.h -- */ /* -- see zlib.h -- */
int ZEXPORT gzputc(file, c) int ZEXPORT gzputc(gzFile file, int c) {
gzFile file;
int c;
{
unsigned have; unsigned have;
unsigned char buf[1]; unsigned char buf[1];
gz_statep state; gz_statep state;
@ -349,12 +329,8 @@ int ZEXPORT gzputc(file, c)
} }
/* -- see zlib.h -- */ /* -- see zlib.h -- */
int ZEXPORT gzputs(file, str) int ZEXPORT gzputs(gzFile file, const char *s) {
gzFile file; z_size_t len, put;
const char *str;
{
int ret;
z_size_t len;
gz_statep state; gz_statep state;
/* get internal structure */ /* get internal structure */
@ -367,17 +343,20 @@ int ZEXPORT gzputs(file, str)
return -1; return -1;
/* write string */ /* write string */
len = strlen(str); len = strlen(s);
ret = gz_write(state, str, len); if ((int)len < 0 || (unsigned)len != len) {
return ret == 0 && len != 0 ? -1 : ret; gz_error(state, Z_STREAM_ERROR, "string length does not fit in int");
return -1;
}
put = gz_write(state, s, len);
return put < len ? -1 : (int)len;
} }
#if defined(STDC) || defined(Z_HAVE_STDARG_H) #if defined(STDC) || defined(Z_HAVE_STDARG_H)
#include <stdarg.h> #include <stdarg.h>
/* -- see zlib.h -- */ /* -- see zlib.h -- */
int ZEXPORTVA gzvprintf(gzFile file, const char *format, va_list va) int ZEXPORTVA gzvprintf(gzFile file, const char *format, va_list va) {
{
int len; int len;
unsigned left; unsigned left;
char *next; char *next;
@ -441,15 +420,14 @@ int ZEXPORTVA gzvprintf(gzFile file, const char *format, va_list va)
strm->avail_in = state->size; strm->avail_in = state->size;
if (gz_comp(state, Z_NO_FLUSH) == -1) if (gz_comp(state, Z_NO_FLUSH) == -1)
return state->err; return state->err;
memcpy(state->in, state->in + state->size, left); memmove(state->in, state->in + state->size, left);
strm->next_in = state->in; strm->next_in = state->in;
strm->avail_in = left; strm->avail_in = left;
} }
return len; return len;
} }
int ZEXPORTVA gzprintf(gzFile file, const char *format, ...) int ZEXPORTVA gzprintf(gzFile file, const char *format, ...) {
{
va_list va; va_list va;
int ret; int ret;
@ -462,13 +440,10 @@ int ZEXPORTVA gzprintf(gzFile file, const char *format, ...)
#else /* !STDC && !Z_HAVE_STDARG_H */ #else /* !STDC && !Z_HAVE_STDARG_H */
/* -- see zlib.h -- */ /* -- see zlib.h -- */
int ZEXPORTVA gzprintf (file, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, int ZEXPORTVA gzprintf(gzFile file, const char *format, int a1, int a2, int a3,
a11, a12, a13, a14, a15, a16, a17, a18, a19, a20) int a4, int a5, int a6, int a7, int a8, int a9, int a10,
gzFile file; int a11, int a12, int a13, int a14, int a15, int a16,
const char *format; int a17, int a18, int a19, int a20) {
int a1, a2, a3, a4, a5, a6, a7, a8, a9, a10,
a11, a12, a13, a14, a15, a16, a17, a18, a19, a20;
{
unsigned len, left; unsigned len, left;
char *next; char *next;
gz_statep state; gz_statep state;
@ -540,7 +515,7 @@ int ZEXPORTVA gzprintf (file, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10,
strm->avail_in = state->size; strm->avail_in = state->size;
if (gz_comp(state, Z_NO_FLUSH) == -1) if (gz_comp(state, Z_NO_FLUSH) == -1)
return state->err; return state->err;
memcpy(state->in, state->in + state->size, left); memmove(state->in, state->in + state->size, left);
strm->next_in = state->in; strm->next_in = state->in;
strm->avail_in = left; strm->avail_in = left;
} }
@ -550,10 +525,7 @@ int ZEXPORTVA gzprintf (file, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10,
#endif #endif
/* -- see zlib.h -- */ /* -- see zlib.h -- */
int ZEXPORT gzflush(file, flush) int ZEXPORT gzflush(gzFile file, int flush) {
gzFile file;
int flush;
{
gz_statep state; gz_statep state;
/* get internal structure */ /* get internal structure */
@ -582,11 +554,7 @@ int ZEXPORT gzflush(file, flush)
} }
/* -- see zlib.h -- */ /* -- see zlib.h -- */
int ZEXPORT gzsetparams(file, level, strategy) int ZEXPORT gzsetparams(gzFile file, int level, int strategy) {
gzFile file;
int level;
int strategy;
{
gz_statep state; gz_statep state;
z_streamp strm; z_streamp strm;
@ -597,7 +565,7 @@ int ZEXPORT gzsetparams(file, level, strategy)
strm = &(state->strm); strm = &(state->strm);
/* check that we're writing and that there's no error */ /* check that we're writing and that there's no error */
if (state->mode != GZ_WRITE || state->err != Z_OK) if (state->mode != GZ_WRITE || state->err != Z_OK || state->direct)
return Z_STREAM_ERROR; return Z_STREAM_ERROR;
/* if no change is requested, then do nothing */ /* if no change is requested, then do nothing */
@ -624,9 +592,7 @@ int ZEXPORT gzsetparams(file, level, strategy)
} }
/* -- see zlib.h -- */ /* -- see zlib.h -- */
int ZEXPORT gzclose_w(file) int ZEXPORT gzclose_w(gzFile file) {
gzFile file;
{
int ret = Z_OK; int ret = Z_OK;
gz_statep state; gz_statep state;

View File

@ -1,5 +1,5 @@
/* infback.c -- inflate using a call-back interface /* infback.c -- inflate using a call-back interface
* Copyright (C) 1995-2016 Mark Adler * Copyright (C) 1995-2022 Mark Adler
* For conditions of distribution and use, see copyright notice in zlib.h * For conditions of distribution and use, see copyright notice in zlib.h
*/ */
@ -15,9 +15,6 @@
#include "inflate.h" #include "inflate.h"
#include "inffast.h" #include "inffast.h"
/* function prototypes */
local void fixedtables OF((struct inflate_state FAR *state));
/* /*
strm provides memory allocation functions in zalloc and zfree, or strm provides memory allocation functions in zalloc and zfree, or
Z_NULL to use the library memory allocation functions. Z_NULL to use the library memory allocation functions.
@ -25,13 +22,9 @@ local void fixedtables OF((struct inflate_state FAR *state));
windowBits is in the range 8..15, and window is a user-supplied windowBits is in the range 8..15, and window is a user-supplied
window and output buffer that is 2**windowBits bytes. window and output buffer that is 2**windowBits bytes.
*/ */
int ZEXPORT inflateBackInit_(strm, windowBits, window, version, stream_size) int ZEXPORT inflateBackInit_(z_streamp strm, int windowBits,
z_streamp strm; unsigned char FAR *window, const char *version,
int windowBits; int stream_size) {
unsigned char FAR *window;
const char *version;
int stream_size;
{
struct inflate_state FAR *state; struct inflate_state FAR *state;
if (version == Z_NULL || version[0] != ZLIB_VERSION[0] || if (version == Z_NULL || version[0] != ZLIB_VERSION[0] ||
@ -66,6 +59,7 @@ int stream_size;
state->window = window; state->window = window;
state->wnext = 0; state->wnext = 0;
state->whave = 0; state->whave = 0;
state->sane = 1;
return Z_OK; return Z_OK;
} }
@ -79,9 +73,7 @@ int stream_size;
used for threaded applications, since the rewriting of the tables and virgin used for threaded applications, since the rewriting of the tables and virgin
may not be thread-safe. may not be thread-safe.
*/ */
local void fixedtables(state) local void fixedtables(struct inflate_state FAR *state) {
struct inflate_state FAR *state;
{
#ifdef BUILDFIXED #ifdef BUILDFIXED
static int virgin = 1; static int virgin = 1;
static code *lenfix, *distfix; static code *lenfix, *distfix;
@ -247,13 +239,8 @@ struct inflate_state FAR *state;
inflateBack() can also return Z_STREAM_ERROR if the input parameters inflateBack() can also return Z_STREAM_ERROR if the input parameters
are not correct, i.e. strm is Z_NULL or the state was not initialized. are not correct, i.e. strm is Z_NULL or the state was not initialized.
*/ */
int ZEXPORT inflateBack(strm, in, in_desc, out, out_desc) int ZEXPORT inflateBack(z_streamp strm, in_func in, void FAR *in_desc,
z_streamp strm; out_func out, void FAR *out_desc) {
in_func in;
void FAR *in_desc;
out_func out;
void FAR *out_desc;
{
struct inflate_state FAR *state; struct inflate_state FAR *state;
z_const unsigned char FAR *next; /* next input */ z_const unsigned char FAR *next; /* next input */
unsigned char FAR *put; /* next output */ unsigned char FAR *put; /* next output */
@ -477,6 +464,7 @@ void FAR *out_desc;
} }
Tracev((stderr, "inflate: codes ok\n")); Tracev((stderr, "inflate: codes ok\n"));
state->mode = LEN; state->mode = LEN;
/* fallthrough */
case LEN: case LEN:
/* use inflate_fast() if we have enough input and output */ /* use inflate_fast() if we have enough input and output */
@ -604,33 +592,33 @@ void FAR *out_desc;
break; break;
case DONE: case DONE:
/* inflate stream terminated properly -- write leftover output */ /* inflate stream terminated properly */
ret = Z_STREAM_END; ret = Z_STREAM_END;
if (left < state->wsize) {
if (out(out_desc, state->window, state->wsize - left))
ret = Z_BUF_ERROR;
}
goto inf_leave; goto inf_leave;
case BAD: case BAD:
ret = Z_DATA_ERROR; ret = Z_DATA_ERROR;
goto inf_leave; goto inf_leave;
default: /* can't happen, but makes compilers happy */ default:
/* can't happen, but makes compilers happy */
ret = Z_STREAM_ERROR; ret = Z_STREAM_ERROR;
goto inf_leave; goto inf_leave;
} }
/* Return unused input */ /* Write leftover output and return unused input */
inf_leave: inf_leave:
if (left < state->wsize) {
if (out(out_desc, state->window, state->wsize - left) &&
ret == Z_STREAM_END)
ret = Z_BUF_ERROR;
}
strm->next_in = next; strm->next_in = next;
strm->avail_in = have; strm->avail_in = have;
return ret; return ret;
} }
int ZEXPORT inflateBackEnd(strm) int ZEXPORT inflateBackEnd(z_streamp strm) {
z_streamp strm;
{
if (strm == Z_NULL || strm->state == Z_NULL || strm->zfree == (free_func)0) if (strm == Z_NULL || strm->state == Z_NULL || strm->zfree == (free_func)0)
return Z_STREAM_ERROR; return Z_STREAM_ERROR;
ZFREE(strm, strm->state); ZFREE(strm, strm->state);

View File

@ -47,10 +47,7 @@
requires strm->avail_out >= 258 for each loop to avoid checking for requires strm->avail_out >= 258 for each loop to avoid checking for
output space. output space.
*/ */
void ZLIB_INTERNAL inflate_fast(strm, start) void ZLIB_INTERNAL inflate_fast(z_streamp strm, unsigned start) {
z_streamp strm;
unsigned start; /* inflate()'s starting value for strm->avail_out */
{
struct inflate_state FAR *state; struct inflate_state FAR *state;
z_const unsigned char FAR *in; /* local strm->next_in */ z_const unsigned char FAR *in; /* local strm->next_in */
z_const unsigned char FAR *last; /* have enough input while in < last */ z_const unsigned char FAR *last; /* have enough input while in < last */
@ -70,7 +67,7 @@ unsigned start; /* inflate()'s starting value for strm->avail_out */
code const FAR *dcode; /* local strm->distcode */ code const FAR *dcode; /* local strm->distcode */
unsigned lmask; /* mask for first level of length codes */ unsigned lmask; /* mask for first level of length codes */
unsigned dmask; /* mask for first level of distance codes */ unsigned dmask; /* mask for first level of distance codes */
code here; /* retrieved table entry */ code const *here; /* retrieved table entry */
unsigned op; /* code bits, operation, extra bits, or */ unsigned op; /* code bits, operation, extra bits, or */
/* window position, window bytes to copy */ /* window position, window bytes to copy */
unsigned len; /* match length, unused bytes */ unsigned len; /* match length, unused bytes */
@ -107,20 +104,20 @@ unsigned start; /* inflate()'s starting value for strm->avail_out */
hold += (unsigned long)(*in++) << bits; hold += (unsigned long)(*in++) << bits;
bits += 8; bits += 8;
} }
here = lcode[hold & lmask]; here = lcode + (hold & lmask);
dolen: dolen:
op = (unsigned)(here.bits); op = (unsigned)(here->bits);
hold >>= op; hold >>= op;
bits -= op; bits -= op;
op = (unsigned)(here.op); op = (unsigned)(here->op);
if (op == 0) { /* literal */ if (op == 0) { /* literal */
Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ? Tracevv((stderr, here->val >= 0x20 && here->val < 0x7f ?
"inflate: literal '%c'\n" : "inflate: literal '%c'\n" :
"inflate: literal 0x%02x\n", here.val)); "inflate: literal 0x%02x\n", here->val));
*out++ = (unsigned char)(here.val); *out++ = (unsigned char)(here->val);
} }
else if (op & 16) { /* length base */ else if (op & 16) { /* length base */
len = (unsigned)(here.val); len = (unsigned)(here->val);
op &= 15; /* number of extra bits */ op &= 15; /* number of extra bits */
if (op) { if (op) {
if (bits < op) { if (bits < op) {
@ -138,14 +135,14 @@ unsigned start; /* inflate()'s starting value for strm->avail_out */
hold += (unsigned long)(*in++) << bits; hold += (unsigned long)(*in++) << bits;
bits += 8; bits += 8;
} }
here = dcode[hold & dmask]; here = dcode + (hold & dmask);
dodist: dodist:
op = (unsigned)(here.bits); op = (unsigned)(here->bits);
hold >>= op; hold >>= op;
bits -= op; bits -= op;
op = (unsigned)(here.op); op = (unsigned)(here->op);
if (op & 16) { /* distance base */ if (op & 16) { /* distance base */
dist = (unsigned)(here.val); dist = (unsigned)(here->val);
op &= 15; /* number of extra bits */ op &= 15; /* number of extra bits */
if (bits < op) { if (bits < op) {
hold += (unsigned long)(*in++) << bits; hold += (unsigned long)(*in++) << bits;
@ -264,7 +261,7 @@ unsigned start; /* inflate()'s starting value for strm->avail_out */
} }
} }
else if ((op & 64) == 0) { /* 2nd level distance code */ else if ((op & 64) == 0) { /* 2nd level distance code */
here = dcode[here.val + (hold & ((1U << op) - 1))]; here = dcode + here->val + (hold & ((1U << op) - 1));
goto dodist; goto dodist;
} }
else { else {
@ -274,7 +271,7 @@ unsigned start; /* inflate()'s starting value for strm->avail_out */
} }
} }
else if ((op & 64) == 0) { /* 2nd level length code */ else if ((op & 64) == 0) { /* 2nd level length code */
here = lcode[here.val + (hold & ((1U << op) - 1))]; here = lcode + here->val + (hold & ((1U << op) - 1));
goto dolen; goto dolen;
} }
else if (op & 32) { /* end-of-block */ else if (op & 32) { /* end-of-block */

View File

@ -8,4 +8,4 @@
subject to change. Applications should only use zlib.h. subject to change. Applications should only use zlib.h.
*/ */
void ZLIB_INTERNAL inflate_fast OF((z_streamp strm, unsigned start)); void ZLIB_INTERNAL inflate_fast(z_streamp strm, unsigned start);

View File

@ -1,5 +1,5 @@
/* inflate.c -- zlib decompression /* inflate.c -- zlib decompression
* Copyright (C) 1995-2016 Mark Adler * Copyright (C) 1995-2022 Mark Adler
* For conditions of distribution and use, see copyright notice in zlib.h * For conditions of distribution and use, see copyright notice in zlib.h
*/ */
@ -91,20 +91,7 @@
# endif # endif
#endif #endif
/* function prototypes */ local int inflateStateCheck(z_streamp strm) {
local int inflateStateCheck OF((z_streamp strm));
local void fixedtables OF((struct inflate_state FAR *state));
local int updatewindow OF((z_streamp strm, const unsigned char FAR *end,
unsigned copy));
#ifdef BUILDFIXED
void makefixed OF((void));
#endif
local unsigned syncsearch OF((unsigned FAR *have, const unsigned char FAR *buf,
unsigned len));
local int inflateStateCheck(strm)
z_streamp strm;
{
struct inflate_state FAR *state; struct inflate_state FAR *state;
if (strm == Z_NULL || if (strm == Z_NULL ||
strm->zalloc == (alloc_func)0 || strm->zfree == (free_func)0) strm->zalloc == (alloc_func)0 || strm->zfree == (free_func)0)
@ -116,9 +103,7 @@ z_streamp strm;
return 0; return 0;
} }
int ZEXPORT inflateResetKeep(strm) int ZEXPORT inflateResetKeep(z_streamp strm) {
z_streamp strm;
{
struct inflate_state FAR *state; struct inflate_state FAR *state;
if (inflateStateCheck(strm)) return Z_STREAM_ERROR; if (inflateStateCheck(strm)) return Z_STREAM_ERROR;
@ -130,6 +115,7 @@ z_streamp strm;
state->mode = HEAD; state->mode = HEAD;
state->last = 0; state->last = 0;
state->havedict = 0; state->havedict = 0;
state->flags = -1;
state->dmax = 32768U; state->dmax = 32768U;
state->head = Z_NULL; state->head = Z_NULL;
state->hold = 0; state->hold = 0;
@ -141,9 +127,7 @@ z_streamp strm;
return Z_OK; return Z_OK;
} }
int ZEXPORT inflateReset(strm) int ZEXPORT inflateReset(z_streamp strm) {
z_streamp strm;
{
struct inflate_state FAR *state; struct inflate_state FAR *state;
if (inflateStateCheck(strm)) return Z_STREAM_ERROR; if (inflateStateCheck(strm)) return Z_STREAM_ERROR;
@ -154,10 +138,7 @@ z_streamp strm;
return inflateResetKeep(strm); return inflateResetKeep(strm);
} }
int ZEXPORT inflateReset2(strm, windowBits) int ZEXPORT inflateReset2(z_streamp strm, int windowBits) {
z_streamp strm;
int windowBits;
{
int wrap; int wrap;
struct inflate_state FAR *state; struct inflate_state FAR *state;
@ -167,6 +148,8 @@ int windowBits;
/* extract wrap request from windowBits parameter */ /* extract wrap request from windowBits parameter */
if (windowBits < 0) { if (windowBits < 0) {
if (windowBits < -15)
return Z_STREAM_ERROR;
wrap = 0; wrap = 0;
windowBits = -windowBits; windowBits = -windowBits;
} }
@ -192,12 +175,8 @@ int windowBits;
return inflateReset(strm); return inflateReset(strm);
} }
int ZEXPORT inflateInit2_(strm, windowBits, version, stream_size) int ZEXPORT inflateInit2_(z_streamp strm, int windowBits,
z_streamp strm; const char *version, int stream_size) {
int windowBits;
const char *version;
int stream_size;
{
int ret; int ret;
struct inflate_state FAR *state; struct inflate_state FAR *state;
@ -236,22 +215,17 @@ int stream_size;
return ret; return ret;
} }
int ZEXPORT inflateInit_(strm, version, stream_size) int ZEXPORT inflateInit_(z_streamp strm, const char *version,
z_streamp strm; int stream_size) {
const char *version;
int stream_size;
{
return inflateInit2_(strm, DEF_WBITS, version, stream_size); return inflateInit2_(strm, DEF_WBITS, version, stream_size);
} }
int ZEXPORT inflatePrime(strm, bits, value) int ZEXPORT inflatePrime(z_streamp strm, int bits, int value) {
z_streamp strm;
int bits;
int value;
{
struct inflate_state FAR *state; struct inflate_state FAR *state;
if (inflateStateCheck(strm)) return Z_STREAM_ERROR; if (inflateStateCheck(strm)) return Z_STREAM_ERROR;
if (bits == 0)
return Z_OK;
state = (struct inflate_state FAR *)strm->state; state = (struct inflate_state FAR *)strm->state;
if (bits < 0) { if (bits < 0) {
state->hold = 0; state->hold = 0;
@ -275,9 +249,7 @@ int value;
used for threaded applications, since the rewriting of the tables and virgin used for threaded applications, since the rewriting of the tables and virgin
may not be thread-safe. may not be thread-safe.
*/ */
local void fixedtables(state) local void fixedtables(struct inflate_state FAR *state) {
struct inflate_state FAR *state;
{
#ifdef BUILDFIXED #ifdef BUILDFIXED
static int virgin = 1; static int virgin = 1;
static code *lenfix, *distfix; static code *lenfix, *distfix;
@ -339,7 +311,7 @@ struct inflate_state FAR *state;
a.out > inffixed.h a.out > inffixed.h
*/ */
void makefixed() void makefixed(void)
{ {
unsigned low, size; unsigned low, size;
struct inflate_state state; struct inflate_state state;
@ -393,11 +365,7 @@ void makefixed()
output will fall in the output data, making match copies simpler and faster. output will fall in the output data, making match copies simpler and faster.
The advantage may be dependent on the size of the processor's data caches. The advantage may be dependent on the size of the processor's data caches.
*/ */
local int updatewindow(strm, end, copy) local int updatewindow(z_streamp strm, const Bytef *end, unsigned copy) {
z_streamp strm;
const Bytef *end;
unsigned copy;
{
struct inflate_state FAR *state; struct inflate_state FAR *state;
unsigned dist; unsigned dist;
@ -447,10 +415,10 @@ unsigned copy;
/* check function to use adler32() for zlib or crc32() for gzip */ /* check function to use adler32() for zlib or crc32() for gzip */
#ifdef GUNZIP #ifdef GUNZIP
# define UPDATE(check, buf, len) \ # define UPDATE_CHECK(check, buf, len) \
(state->flags ? crc32(check, buf, len) : adler32(check, buf, len)) (state->flags ? crc32(check, buf, len) : adler32(check, buf, len))
#else #else
# define UPDATE(check, buf, len) adler32(check, buf, len) # define UPDATE_CHECK(check, buf, len) adler32(check, buf, len)
#endif #endif
/* check macros for header crc */ /* check macros for header crc */
@ -619,10 +587,7 @@ unsigned copy;
will return Z_BUF_ERROR if it has not reached the end of the stream. will return Z_BUF_ERROR if it has not reached the end of the stream.
*/ */
int ZEXPORT inflate(strm, flush) int ZEXPORT inflate(z_streamp strm, int flush) {
z_streamp strm;
int flush;
{
struct inflate_state FAR *state; struct inflate_state FAR *state;
z_const unsigned char FAR *next; /* next input */ z_const unsigned char FAR *next; /* next input */
unsigned char FAR *put; /* next output */ unsigned char FAR *put; /* next output */
@ -670,7 +635,6 @@ int flush;
state->mode = FLAGS; state->mode = FLAGS;
break; break;
} }
state->flags = 0; /* expect zlib header */
if (state->head != Z_NULL) if (state->head != Z_NULL)
state->head->done = -1; state->head->done = -1;
if (!(state->wrap & 1) || /* check if zlib header allowed */ if (!(state->wrap & 1) || /* check if zlib header allowed */
@ -697,6 +661,7 @@ int flush;
break; break;
} }
state->dmax = 1U << len; state->dmax = 1U << len;
state->flags = 0; /* indicate zlib header */
Tracev((stderr, "inflate: zlib header ok\n")); Tracev((stderr, "inflate: zlib header ok\n"));
strm->adler = state->check = adler32(0L, Z_NULL, 0); strm->adler = state->check = adler32(0L, Z_NULL, 0);
state->mode = hold & 0x200 ? DICTID : TYPE; state->mode = hold & 0x200 ? DICTID : TYPE;
@ -722,6 +687,7 @@ int flush;
CRC2(state->check, hold); CRC2(state->check, hold);
INITBITS(); INITBITS();
state->mode = TIME; state->mode = TIME;
/* fallthrough */
case TIME: case TIME:
NEEDBITS(32); NEEDBITS(32);
if (state->head != Z_NULL) if (state->head != Z_NULL)
@ -730,6 +696,7 @@ int flush;
CRC4(state->check, hold); CRC4(state->check, hold);
INITBITS(); INITBITS();
state->mode = OS; state->mode = OS;
/* fallthrough */
case OS: case OS:
NEEDBITS(16); NEEDBITS(16);
if (state->head != Z_NULL) { if (state->head != Z_NULL) {
@ -740,6 +707,7 @@ int flush;
CRC2(state->check, hold); CRC2(state->check, hold);
INITBITS(); INITBITS();
state->mode = EXLEN; state->mode = EXLEN;
/* fallthrough */
case EXLEN: case EXLEN:
if (state->flags & 0x0400) { if (state->flags & 0x0400) {
NEEDBITS(16); NEEDBITS(16);
@ -753,14 +721,16 @@ int flush;
else if (state->head != Z_NULL) else if (state->head != Z_NULL)
state->head->extra = Z_NULL; state->head->extra = Z_NULL;
state->mode = EXTRA; state->mode = EXTRA;
/* fallthrough */
case EXTRA: case EXTRA:
if (state->flags & 0x0400) { if (state->flags & 0x0400) {
copy = state->length; copy = state->length;
if (copy > have) copy = have; if (copy > have) copy = have;
if (copy) { if (copy) {
if (state->head != Z_NULL && if (state->head != Z_NULL &&
state->head->extra != Z_NULL) { state->head->extra != Z_NULL &&
len = state->head->extra_len - state->length; (len = state->head->extra_len - state->length) <
state->head->extra_max) {
zmemcpy(state->head->extra + len, next, zmemcpy(state->head->extra + len, next,
len + copy > state->head->extra_max ? len + copy > state->head->extra_max ?
state->head->extra_max - len : copy); state->head->extra_max - len : copy);
@ -775,6 +745,7 @@ int flush;
} }
state->length = 0; state->length = 0;
state->mode = NAME; state->mode = NAME;
/* fallthrough */
case NAME: case NAME:
if (state->flags & 0x0800) { if (state->flags & 0x0800) {
if (have == 0) goto inf_leave; if (have == 0) goto inf_leave;
@ -796,6 +767,7 @@ int flush;
state->head->name = Z_NULL; state->head->name = Z_NULL;
state->length = 0; state->length = 0;
state->mode = COMMENT; state->mode = COMMENT;
/* fallthrough */
case COMMENT: case COMMENT:
if (state->flags & 0x1000) { if (state->flags & 0x1000) {
if (have == 0) goto inf_leave; if (have == 0) goto inf_leave;
@ -816,6 +788,7 @@ int flush;
else if (state->head != Z_NULL) else if (state->head != Z_NULL)
state->head->comment = Z_NULL; state->head->comment = Z_NULL;
state->mode = HCRC; state->mode = HCRC;
/* fallthrough */
case HCRC: case HCRC:
if (state->flags & 0x0200) { if (state->flags & 0x0200) {
NEEDBITS(16); NEEDBITS(16);
@ -839,6 +812,7 @@ int flush;
strm->adler = state->check = ZSWAP32(hold); strm->adler = state->check = ZSWAP32(hold);
INITBITS(); INITBITS();
state->mode = DICT; state->mode = DICT;
/* fallthrough */
case DICT: case DICT:
if (state->havedict == 0) { if (state->havedict == 0) {
RESTORE(); RESTORE();
@ -846,8 +820,10 @@ int flush;
} }
strm->adler = state->check = adler32(0L, Z_NULL, 0); strm->adler = state->check = adler32(0L, Z_NULL, 0);
state->mode = TYPE; state->mode = TYPE;
/* fallthrough */
case TYPE: case TYPE:
if (flush == Z_BLOCK || flush == Z_TREES) goto inf_leave; if (flush == Z_BLOCK || flush == Z_TREES) goto inf_leave;
/* fallthrough */
case TYPEDO: case TYPEDO:
if (state->last) { if (state->last) {
BYTEBITS(); BYTEBITS();
@ -898,8 +874,10 @@ int flush;
INITBITS(); INITBITS();
state->mode = COPY_; state->mode = COPY_;
if (flush == Z_TREES) goto inf_leave; if (flush == Z_TREES) goto inf_leave;
/* fallthrough */
case COPY_: case COPY_:
state->mode = COPY; state->mode = COPY;
/* fallthrough */
case COPY: case COPY:
copy = state->length; copy = state->length;
if (copy) { if (copy) {
@ -935,6 +913,7 @@ int flush;
Tracev((stderr, "inflate: table sizes ok\n")); Tracev((stderr, "inflate: table sizes ok\n"));
state->have = 0; state->have = 0;
state->mode = LENLENS; state->mode = LENLENS;
/* fallthrough */
case LENLENS: case LENLENS:
while (state->have < state->ncode) { while (state->have < state->ncode) {
NEEDBITS(3); NEEDBITS(3);
@ -956,6 +935,7 @@ int flush;
Tracev((stderr, "inflate: code lengths ok\n")); Tracev((stderr, "inflate: code lengths ok\n"));
state->have = 0; state->have = 0;
state->mode = CODELENS; state->mode = CODELENS;
/* fallthrough */
case CODELENS: case CODELENS:
while (state->have < state->nlen + state->ndist) { while (state->have < state->nlen + state->ndist) {
for (;;) { for (;;) {
@ -1039,8 +1019,10 @@ int flush;
Tracev((stderr, "inflate: codes ok\n")); Tracev((stderr, "inflate: codes ok\n"));
state->mode = LEN_; state->mode = LEN_;
if (flush == Z_TREES) goto inf_leave; if (flush == Z_TREES) goto inf_leave;
/* fallthrough */
case LEN_: case LEN_:
state->mode = LEN; state->mode = LEN;
/* fallthrough */
case LEN: case LEN:
if (have >= 6 && left >= 258) { if (have >= 6 && left >= 258) {
RESTORE(); RESTORE();
@ -1090,6 +1072,7 @@ int flush;
} }
state->extra = (unsigned)(here.op) & 15; state->extra = (unsigned)(here.op) & 15;
state->mode = LENEXT; state->mode = LENEXT;
/* fallthrough */
case LENEXT: case LENEXT:
if (state->extra) { if (state->extra) {
NEEDBITS(state->extra); NEEDBITS(state->extra);
@ -1100,6 +1083,7 @@ int flush;
Tracevv((stderr, "inflate: length %u\n", state->length)); Tracevv((stderr, "inflate: length %u\n", state->length));
state->was = state->length; state->was = state->length;
state->mode = DIST; state->mode = DIST;
/* fallthrough */
case DIST: case DIST:
for (;;) { for (;;) {
here = state->distcode[BITS(state->distbits)]; here = state->distcode[BITS(state->distbits)];
@ -1127,6 +1111,7 @@ int flush;
state->offset = (unsigned)here.val; state->offset = (unsigned)here.val;
state->extra = (unsigned)(here.op) & 15; state->extra = (unsigned)(here.op) & 15;
state->mode = DISTEXT; state->mode = DISTEXT;
/* fallthrough */
case DISTEXT: case DISTEXT:
if (state->extra) { if (state->extra) {
NEEDBITS(state->extra); NEEDBITS(state->extra);
@ -1143,6 +1128,7 @@ int flush;
#endif #endif
Tracevv((stderr, "inflate: distance %u\n", state->offset)); Tracevv((stderr, "inflate: distance %u\n", state->offset));
state->mode = MATCH; state->mode = MATCH;
/* fallthrough */
case MATCH: case MATCH:
if (left == 0) goto inf_leave; if (left == 0) goto inf_leave;
copy = out - left; copy = out - left;
@ -1202,7 +1188,7 @@ int flush;
state->total += out; state->total += out;
if ((state->wrap & 4) && out) if ((state->wrap & 4) && out)
strm->adler = state->check = strm->adler = state->check =
UPDATE(state->check, put - out, out); UPDATE_CHECK(state->check, put - out, out);
out = left; out = left;
if ((state->wrap & 4) && ( if ((state->wrap & 4) && (
#ifdef GUNZIP #ifdef GUNZIP
@ -1218,10 +1204,11 @@ int flush;
} }
#ifdef GUNZIP #ifdef GUNZIP
state->mode = LENGTH; state->mode = LENGTH;
/* fallthrough */
case LENGTH: case LENGTH:
if (state->wrap && state->flags) { if (state->wrap && state->flags) {
NEEDBITS(32); NEEDBITS(32);
if (hold != (state->total & 0xffffffffUL)) { if ((state->wrap & 4) && hold != (state->total & 0xffffffff)) {
strm->msg = (char *)"incorrect length check"; strm->msg = (char *)"incorrect length check";
state->mode = BAD; state->mode = BAD;
break; break;
@ -1231,6 +1218,7 @@ int flush;
} }
#endif #endif
state->mode = DONE; state->mode = DONE;
/* fallthrough */
case DONE: case DONE:
ret = Z_STREAM_END; ret = Z_STREAM_END;
goto inf_leave; goto inf_leave;
@ -1240,6 +1228,7 @@ int flush;
case MEM: case MEM:
return Z_MEM_ERROR; return Z_MEM_ERROR;
case SYNC: case SYNC:
/* fallthrough */
default: default:
return Z_STREAM_ERROR; return Z_STREAM_ERROR;
} }
@ -1265,7 +1254,7 @@ int flush;
state->total += out; state->total += out;
if ((state->wrap & 4) && out) if ((state->wrap & 4) && out)
strm->adler = state->check = strm->adler = state->check =
UPDATE(state->check, strm->next_out - out, out); UPDATE_CHECK(state->check, strm->next_out - out, out);
strm->data_type = (int)state->bits + (state->last ? 64 : 0) + strm->data_type = (int)state->bits + (state->last ? 64 : 0) +
(state->mode == TYPE ? 128 : 0) + (state->mode == TYPE ? 128 : 0) +
(state->mode == LEN_ || state->mode == COPY_ ? 256 : 0); (state->mode == LEN_ || state->mode == COPY_ ? 256 : 0);
@ -1274,9 +1263,7 @@ int flush;
return ret; return ret;
} }
int ZEXPORT inflateEnd(strm) int ZEXPORT inflateEnd(z_streamp strm) {
z_streamp strm;
{
struct inflate_state FAR *state; struct inflate_state FAR *state;
if (inflateStateCheck(strm)) if (inflateStateCheck(strm))
return Z_STREAM_ERROR; return Z_STREAM_ERROR;
@ -1288,11 +1275,8 @@ z_streamp strm;
return Z_OK; return Z_OK;
} }
int ZEXPORT inflateGetDictionary(strm, dictionary, dictLength) int ZEXPORT inflateGetDictionary(z_streamp strm, Bytef *dictionary,
z_streamp strm; uInt *dictLength) {
Bytef *dictionary;
uInt *dictLength;
{
struct inflate_state FAR *state; struct inflate_state FAR *state;
/* check state */ /* check state */
@ -1311,11 +1295,8 @@ uInt *dictLength;
return Z_OK; return Z_OK;
} }
int ZEXPORT inflateSetDictionary(strm, dictionary, dictLength) int ZEXPORT inflateSetDictionary(z_streamp strm, const Bytef *dictionary,
z_streamp strm; uInt dictLength) {
const Bytef *dictionary;
uInt dictLength;
{
struct inflate_state FAR *state; struct inflate_state FAR *state;
unsigned long dictid; unsigned long dictid;
int ret; int ret;
@ -1346,10 +1327,7 @@ uInt dictLength;
return Z_OK; return Z_OK;
} }
int ZEXPORT inflateGetHeader(strm, head) int ZEXPORT inflateGetHeader(z_streamp strm, gz_headerp head) {
z_streamp strm;
gz_headerp head;
{
struct inflate_state FAR *state; struct inflate_state FAR *state;
/* check state */ /* check state */
@ -1374,11 +1352,8 @@ gz_headerp head;
called again with more data and the *have state. *have is initialized to called again with more data and the *have state. *have is initialized to
zero for the first call. zero for the first call.
*/ */
local unsigned syncsearch(have, buf, len) local unsigned syncsearch(unsigned FAR *have, const unsigned char FAR *buf,
unsigned FAR *have; unsigned len) {
const unsigned char FAR *buf;
unsigned len;
{
unsigned got; unsigned got;
unsigned next; unsigned next;
@ -1397,10 +1372,9 @@ unsigned len;
return next; return next;
} }
int ZEXPORT inflateSync(strm) int ZEXPORT inflateSync(z_streamp strm) {
z_streamp strm;
{
unsigned len; /* number of bytes to look at or looked at */ unsigned len; /* number of bytes to look at or looked at */
int flags; /* temporary to save header status */
unsigned long in, out; /* temporary to save total_in and total_out */ unsigned long in, out; /* temporary to save total_in and total_out */
unsigned char buf[4]; /* to restore bit buffer to byte string */ unsigned char buf[4]; /* to restore bit buffer to byte string */
struct inflate_state FAR *state; struct inflate_state FAR *state;
@ -1433,9 +1407,15 @@ z_streamp strm;
/* return no joy or set up to restart inflate() on a new block */ /* return no joy or set up to restart inflate() on a new block */
if (state->have != 4) return Z_DATA_ERROR; if (state->have != 4) return Z_DATA_ERROR;
if (state->flags == -1)
state->wrap = 0; /* if no header yet, treat as raw */
else
state->wrap &= ~4; /* no point in computing a check value now */
flags = state->flags;
in = strm->total_in; out = strm->total_out; in = strm->total_in; out = strm->total_out;
inflateReset(strm); inflateReset(strm);
strm->total_in = in; strm->total_out = out; strm->total_in = in; strm->total_out = out;
state->flags = flags;
state->mode = TYPE; state->mode = TYPE;
return Z_OK; return Z_OK;
} }
@ -1448,9 +1428,7 @@ z_streamp strm;
block. When decompressing, PPP checks that at the end of input packet, block. When decompressing, PPP checks that at the end of input packet,
inflate is waiting for these length bytes. inflate is waiting for these length bytes.
*/ */
int ZEXPORT inflateSyncPoint(strm) int ZEXPORT inflateSyncPoint(z_streamp strm) {
z_streamp strm;
{
struct inflate_state FAR *state; struct inflate_state FAR *state;
if (inflateStateCheck(strm)) return Z_STREAM_ERROR; if (inflateStateCheck(strm)) return Z_STREAM_ERROR;
@ -1458,10 +1436,7 @@ z_streamp strm;
return state->mode == STORED && state->bits == 0; return state->mode == STORED && state->bits == 0;
} }
int ZEXPORT inflateCopy(dest, source) int ZEXPORT inflateCopy(z_streamp dest, z_streamp source) {
z_streamp dest;
z_streamp source;
{
struct inflate_state FAR *state; struct inflate_state FAR *state;
struct inflate_state FAR *copy; struct inflate_state FAR *copy;
unsigned char FAR *window; unsigned char FAR *window;
@ -1505,10 +1480,7 @@ z_streamp source;
return Z_OK; return Z_OK;
} }
int ZEXPORT inflateUndermine(strm, subvert) int ZEXPORT inflateUndermine(z_streamp strm, int subvert) {
z_streamp strm;
int subvert;
{
struct inflate_state FAR *state; struct inflate_state FAR *state;
if (inflateStateCheck(strm)) return Z_STREAM_ERROR; if (inflateStateCheck(strm)) return Z_STREAM_ERROR;
@ -1523,24 +1495,19 @@ int subvert;
#endif #endif
} }
int ZEXPORT inflateValidate(strm, check) int ZEXPORT inflateValidate(z_streamp strm, int check) {
z_streamp strm;
int check;
{
struct inflate_state FAR *state; struct inflate_state FAR *state;
if (inflateStateCheck(strm)) return Z_STREAM_ERROR; if (inflateStateCheck(strm)) return Z_STREAM_ERROR;
state = (struct inflate_state FAR *)strm->state; state = (struct inflate_state FAR *)strm->state;
if (check) if (check && state->wrap)
state->wrap |= 4; state->wrap |= 4;
else else
state->wrap &= ~4; state->wrap &= ~4;
return Z_OK; return Z_OK;
} }
long ZEXPORT inflateMark(strm) long ZEXPORT inflateMark(z_streamp strm) {
z_streamp strm;
{
struct inflate_state FAR *state; struct inflate_state FAR *state;
if (inflateStateCheck(strm)) if (inflateStateCheck(strm))
@ -1551,9 +1518,7 @@ z_streamp strm;
(state->mode == MATCH ? state->was - state->length : 0)); (state->mode == MATCH ? state->was - state->length : 0));
} }
unsigned long ZEXPORT inflateCodesUsed(strm) unsigned long ZEXPORT inflateCodesUsed(z_streamp strm) {
z_streamp strm;
{
struct inflate_state FAR *state; struct inflate_state FAR *state;
if (inflateStateCheck(strm)) return (unsigned long)-1; if (inflateStateCheck(strm)) return (unsigned long)-1;
state = (struct inflate_state FAR *)strm->state; state = (struct inflate_state FAR *)strm->state;

View File

@ -1,5 +1,5 @@
/* inflate.h -- internal inflate state definition /* inflate.h -- internal inflate state definition
* Copyright (C) 1995-2016 Mark Adler * Copyright (C) 1995-2019 Mark Adler
* For conditions of distribution and use, see copyright notice in zlib.h * For conditions of distribution and use, see copyright notice in zlib.h
*/ */
@ -86,7 +86,8 @@ struct inflate_state {
int wrap; /* bit 0 true for zlib, bit 1 true for gzip, int wrap; /* bit 0 true for zlib, bit 1 true for gzip,
bit 2 true to validate check value */ bit 2 true to validate check value */
int havedict; /* true if dictionary provided */ int havedict; /* true if dictionary provided */
int flags; /* gzip header method and flags (0 if zlib) */ int flags; /* gzip header method and flags, 0 if zlib, or
-1 if raw or no header yet */
unsigned dmax; /* zlib header max distance (INFLATE_STRICT) */ unsigned dmax; /* zlib header max distance (INFLATE_STRICT) */
unsigned long check; /* protected copy of check value */ unsigned long check; /* protected copy of check value */
unsigned long total; /* protected copy of output count */ unsigned long total; /* protected copy of output count */

View File

@ -1,5 +1,5 @@
/* inftrees.c -- generate Huffman trees for efficient decoding /* inftrees.c -- generate Huffman trees for efficient decoding
* Copyright (C) 1995-2017 Mark Adler * Copyright (C) 1995-2023 Mark Adler
* For conditions of distribution and use, see copyright notice in zlib.h * For conditions of distribution and use, see copyright notice in zlib.h
*/ */
@ -9,7 +9,7 @@
#define MAXBITS 15 #define MAXBITS 15
const char inflate_copyright[] = const char inflate_copyright[] =
" inflate 1.2.11 Copyright 1995-2017 Mark Adler "; " inflate 1.3 Copyright 1995-2023 Mark Adler ";
/* /*
If you use the zlib library in a product, an acknowledgment is welcome If you use the zlib library in a product, an acknowledgment is welcome
in the documentation of your product. If for some reason you cannot in the documentation of your product. If for some reason you cannot
@ -29,14 +29,9 @@ const char inflate_copyright[] =
table index bits. It will differ if the request is greater than the table index bits. It will differ if the request is greater than the
longest code or if it is less than the shortest code. longest code or if it is less than the shortest code.
*/ */
int ZLIB_INTERNAL inflate_table(type, lens, codes, table, bits, work) int ZLIB_INTERNAL inflate_table(codetype type, unsigned short FAR *lens,
codetype type; unsigned codes, code FAR * FAR *table,
unsigned short FAR *lens; unsigned FAR *bits, unsigned short FAR *work) {
unsigned codes;
code FAR * FAR *table;
unsigned FAR *bits;
unsigned short FAR *work;
{
unsigned len; /* a code's length in bits */ unsigned len; /* a code's length in bits */
unsigned sym; /* index of code symbols */ unsigned sym; /* index of code symbols */
unsigned min, max; /* minimum and maximum code lengths */ unsigned min, max; /* minimum and maximum code lengths */
@ -62,7 +57,7 @@ unsigned short FAR *work;
35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0}; 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0};
static const unsigned short lext[31] = { /* Length codes 257..285 extra */ static const unsigned short lext[31] = { /* Length codes 257..285 extra */
16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 18, 18, 18, 18, 16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 18, 18, 18, 18,
19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 16, 77, 202}; 19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 16, 198, 203};
static const unsigned short dbase[32] = { /* Distance codes 0..29 base */ static const unsigned short dbase[32] = { /* Distance codes 0..29 base */
1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193,
257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145,

View File

@ -38,7 +38,7 @@ typedef struct {
/* Maximum size of the dynamic table. The maximum number of code structures is /* Maximum size of the dynamic table. The maximum number of code structures is
1444, which is the sum of 852 for literal/length codes and 592 for distance 1444, which is the sum of 852 for literal/length codes and 592 for distance
codes. These values were found by exhaustive searches using the program codes. These values were found by exhaustive searches using the program
examples/enough.c found in the zlib distribtution. The arguments to that examples/enough.c found in the zlib distribution. The arguments to that
program are the number of symbols, the initial root table size, and the program are the number of symbols, the initial root table size, and the
maximum bit length of a code. "enough 286 9 15" for literal/length codes maximum bit length of a code. "enough 286 9 15" for literal/length codes
returns returns 852, and "enough 30 6 15" for distance codes returns 592. returns returns 852, and "enough 30 6 15" for distance codes returns 592.
@ -57,6 +57,6 @@ typedef enum {
DISTS DISTS
} codetype; } codetype;
int ZLIB_INTERNAL inflate_table OF((codetype type, unsigned short FAR *lens, int ZLIB_INTERNAL inflate_table(codetype type, unsigned short FAR *lens,
unsigned codes, code FAR * FAR *table, unsigned codes, code FAR * FAR *table,
unsigned FAR *bits, unsigned short FAR *work)); unsigned FAR *bits, unsigned short FAR *work);

660
3rdparty/zlib/trees.c vendored
View File

@ -1,5 +1,5 @@
/* trees.c -- output deflated data using Huffman coding /* trees.c -- output deflated data using Huffman coding
* Copyright (C) 1995-2017 Jean-loup Gailly * Copyright (C) 1995-2021 Jean-loup Gailly
* detect_data_type() function provided freely by Cosmin Truta, 2006 * detect_data_type() function provided freely by Cosmin Truta, 2006
* For conditions of distribution and use, see copyright notice in zlib.h * For conditions of distribution and use, see copyright notice in zlib.h
*/ */
@ -122,39 +122,116 @@ struct static_tree_desc_s {
int max_length; /* max bit length for the codes */ int max_length; /* max bit length for the codes */
}; };
local const static_tree_desc static_l_desc = #ifdef NO_INIT_GLOBAL_POINTERS
# define TCONST
#else
# define TCONST const
#endif
local TCONST static_tree_desc static_l_desc =
{static_ltree, extra_lbits, LITERALS+1, L_CODES, MAX_BITS}; {static_ltree, extra_lbits, LITERALS+1, L_CODES, MAX_BITS};
local const static_tree_desc static_d_desc = local TCONST static_tree_desc static_d_desc =
{static_dtree, extra_dbits, 0, D_CODES, MAX_BITS}; {static_dtree, extra_dbits, 0, D_CODES, MAX_BITS};
local const static_tree_desc static_bl_desc = local TCONST static_tree_desc static_bl_desc =
{(const ct_data *)0, extra_blbits, 0, BL_CODES, MAX_BL_BITS}; {(const ct_data *)0, extra_blbits, 0, BL_CODES, MAX_BL_BITS};
/* =========================================================================== /* ===========================================================================
* Local (static) routines in this file. * Output a short LSB first on the stream.
* IN assertion: there is enough room in pendingBuf.
*/ */
#define put_short(s, w) { \
put_byte(s, (uch)((w) & 0xff)); \
put_byte(s, (uch)((ush)(w) >> 8)); \
}
local void tr_static_init OF((void)); /* ===========================================================================
local void init_block OF((deflate_state *s)); * Reverse the first len bits of a code, using straightforward code (a faster
local void pqdownheap OF((deflate_state *s, ct_data *tree, int k)); * method would use a table)
local void gen_bitlen OF((deflate_state *s, tree_desc *desc)); * IN assertion: 1 <= len <= 15
local void gen_codes OF((ct_data *tree, int max_code, ushf *bl_count)); */
local void build_tree OF((deflate_state *s, tree_desc *desc)); local unsigned bi_reverse(unsigned code, int len) {
local void scan_tree OF((deflate_state *s, ct_data *tree, int max_code)); register unsigned res = 0;
local void send_tree OF((deflate_state *s, ct_data *tree, int max_code)); do {
local int build_bl_tree OF((deflate_state *s)); res |= code & 1;
local void send_all_trees OF((deflate_state *s, int lcodes, int dcodes, code >>= 1, res <<= 1;
int blcodes)); } while (--len > 0);
local void compress_block OF((deflate_state *s, const ct_data *ltree, return res >> 1;
const ct_data *dtree)); }
local int detect_data_type OF((deflate_state *s));
local unsigned bi_reverse OF((unsigned value, int length)); /* ===========================================================================
local void bi_windup OF((deflate_state *s)); * Flush the bit buffer, keeping at most 7 bits in it.
local void bi_flush OF((deflate_state *s)); */
local void bi_flush(deflate_state *s) {
if (s->bi_valid == 16) {
put_short(s, s->bi_buf);
s->bi_buf = 0;
s->bi_valid = 0;
} else if (s->bi_valid >= 8) {
put_byte(s, (Byte)s->bi_buf);
s->bi_buf >>= 8;
s->bi_valid -= 8;
}
}
/* ===========================================================================
* Flush the bit buffer and align the output on a byte boundary
*/
local void bi_windup(deflate_state *s) {
if (s->bi_valid > 8) {
put_short(s, s->bi_buf);
} else if (s->bi_valid > 0) {
put_byte(s, (Byte)s->bi_buf);
}
s->bi_buf = 0;
s->bi_valid = 0;
#ifdef ZLIB_DEBUG
s->bits_sent = (s->bits_sent + 7) & ~7;
#endif
}
/* ===========================================================================
* Generate the codes for a given tree and bit counts (which need not be
* optimal).
* IN assertion: the array bl_count contains the bit length statistics for
* the given tree and the field len is set for all tree elements.
* OUT assertion: the field code is set for all tree elements of non
* zero code length.
*/
local void gen_codes(ct_data *tree, int max_code, ushf *bl_count) {
ush next_code[MAX_BITS+1]; /* next code value for each bit length */
unsigned code = 0; /* running code value */
int bits; /* bit index */
int n; /* code index */
/* The distribution counts are first used to generate the code values
* without bit reversal.
*/
for (bits = 1; bits <= MAX_BITS; bits++) {
code = (code + bl_count[bits - 1]) << 1;
next_code[bits] = (ush)code;
}
/* Check that the bit counts in bl_count are consistent. The last code
* must be all ones.
*/
Assert (code + bl_count[MAX_BITS] - 1 == (1 << MAX_BITS) - 1,
"inconsistent bit counts");
Tracev((stderr,"\ngen_codes: max_code %d ", max_code));
for (n = 0; n <= max_code; n++) {
int len = tree[n].Len;
if (len == 0) continue;
/* Now reverse the bits */
tree[n].Code = (ush)bi_reverse(next_code[len]++, len);
Tracecv(tree != static_ltree, (stderr,"\nn %3d %c l %2d c %4x (%x) ",
n, (isgraph(n) ? n : ' '), len, tree[n].Code, next_code[len] - 1));
}
}
#ifdef GEN_TREES_H #ifdef GEN_TREES_H
local void gen_trees_header OF((void)); local void gen_trees_header(void);
#endif #endif
#ifndef ZLIB_DEBUG #ifndef ZLIB_DEBUG
@ -167,33 +244,18 @@ local void gen_trees_header OF((void));
send_bits(s, tree[c].Code, tree[c].Len); } send_bits(s, tree[c].Code, tree[c].Len); }
#endif #endif
/* ===========================================================================
* Output a short LSB first on the stream.
* IN assertion: there is enough room in pendingBuf.
*/
#define put_short(s, w) { \
put_byte(s, (uch)((w) & 0xff)); \
put_byte(s, (uch)((ush)(w) >> 8)); \
}
/* =========================================================================== /* ===========================================================================
* Send a value on a given number of bits. * Send a value on a given number of bits.
* IN assertion: length <= 16 and value fits in length bits. * IN assertion: length <= 16 and value fits in length bits.
*/ */
#ifdef ZLIB_DEBUG #ifdef ZLIB_DEBUG
local void send_bits OF((deflate_state *s, int value, int length)); local void send_bits(deflate_state *s, int value, int length) {
local void send_bits(s, value, length)
deflate_state *s;
int value; /* value to send */
int length; /* number of bits */
{
Tracevv((stderr," l %2d v %4x ", length, value)); Tracevv((stderr," l %2d v %4x ", length, value));
Assert(length > 0 && length <= 15, "invalid length"); Assert(length > 0 && length <= 15, "invalid length");
s->bits_sent += (ulg)length; s->bits_sent += (ulg)length;
/* If not enough room in bi_buf, use (valid) bits from bi_buf and /* If not enough room in bi_buf, use (valid) bits from bi_buf and
* (16 - bi_valid) bits from value, leaving (width - (16-bi_valid)) * (16 - bi_valid) bits from value, leaving (width - (16 - bi_valid))
* unused bits in value. * unused bits in value.
*/ */
if (s->bi_valid > (int)Buf_size - length) { if (s->bi_valid > (int)Buf_size - length) {
@ -229,8 +291,7 @@ local void send_bits(s, value, length)
/* =========================================================================== /* ===========================================================================
* Initialize the various 'constant' tables. * Initialize the various 'constant' tables.
*/ */
local void tr_static_init() local void tr_static_init(void) {
{
#if defined(GEN_TREES_H) || !defined(STDC) #if defined(GEN_TREES_H) || !defined(STDC)
static int static_init_done = 0; static int static_init_done = 0;
int n; /* iterates over tree elements */ int n; /* iterates over tree elements */
@ -256,7 +317,7 @@ local void tr_static_init()
length = 0; length = 0;
for (code = 0; code < LENGTH_CODES-1; code++) { for (code = 0; code < LENGTH_CODES-1; code++) {
base_length[code] = length; base_length[code] = length;
for (n = 0; n < (1<<extra_lbits[code]); n++) { for (n = 0; n < (1 << extra_lbits[code]); n++) {
_length_code[length++] = (uch)code; _length_code[length++] = (uch)code;
} }
} }
@ -265,13 +326,13 @@ local void tr_static_init()
* in two different ways: code 284 + 5 bits or code 285, so we * in two different ways: code 284 + 5 bits or code 285, so we
* overwrite length_code[255] to use the best encoding: * overwrite length_code[255] to use the best encoding:
*/ */
_length_code[length-1] = (uch)code; _length_code[length - 1] = (uch)code;
/* Initialize the mapping dist (0..32K) -> dist code (0..29) */ /* Initialize the mapping dist (0..32K) -> dist code (0..29) */
dist = 0; dist = 0;
for (code = 0 ; code < 16; code++) { for (code = 0 ; code < 16; code++) {
base_dist[code] = dist; base_dist[code] = dist;
for (n = 0; n < (1<<extra_dbits[code]); n++) { for (n = 0; n < (1 << extra_dbits[code]); n++) {
_dist_code[dist++] = (uch)code; _dist_code[dist++] = (uch)code;
} }
} }
@ -279,11 +340,11 @@ local void tr_static_init()
dist >>= 7; /* from now on, all distances are divided by 128 */ dist >>= 7; /* from now on, all distances are divided by 128 */
for ( ; code < D_CODES; code++) { for ( ; code < D_CODES; code++) {
base_dist[code] = dist << 7; base_dist[code] = dist << 7;
for (n = 0; n < (1<<(extra_dbits[code]-7)); n++) { for (n = 0; n < (1 << (extra_dbits[code] - 7)); n++) {
_dist_code[256 + dist++] = (uch)code; _dist_code[256 + dist++] = (uch)code;
} }
} }
Assert (dist == 256, "tr_static_init: 256+dist != 512"); Assert (dist == 256, "tr_static_init: 256 + dist != 512");
/* Construct the codes of the static literal tree */ /* Construct the codes of the static literal tree */
for (bits = 0; bits <= MAX_BITS; bits++) bl_count[bits] = 0; for (bits = 0; bits <= MAX_BITS; bits++) bl_count[bits] = 0;
@ -312,7 +373,7 @@ local void tr_static_init()
} }
/* =========================================================================== /* ===========================================================================
* Genererate the file trees.h describing the static trees. * Generate the file trees.h describing the static trees.
*/ */
#ifdef GEN_TREES_H #ifdef GEN_TREES_H
# ifndef ZLIB_DEBUG # ifndef ZLIB_DEBUG
@ -321,10 +382,9 @@ local void tr_static_init()
# define SEPARATOR(i, last, width) \ # define SEPARATOR(i, last, width) \
((i) == (last)? "\n};\n\n" : \ ((i) == (last)? "\n};\n\n" : \
((i) % (width) == (width)-1 ? ",\n" : ", ")) ((i) % (width) == (width) - 1 ? ",\n" : ", "))
void gen_trees_header() void gen_trees_header(void) {
{
FILE *header = fopen("trees.h", "w"); FILE *header = fopen("trees.h", "w");
int i; int i;
@ -373,12 +433,26 @@ void gen_trees_header()
} }
#endif /* GEN_TREES_H */ #endif /* GEN_TREES_H */
/* ===========================================================================
* Initialize a new block.
*/
local void init_block(deflate_state *s) {
int n; /* iterates over tree elements */
/* Initialize the trees. */
for (n = 0; n < L_CODES; n++) s->dyn_ltree[n].Freq = 0;
for (n = 0; n < D_CODES; n++) s->dyn_dtree[n].Freq = 0;
for (n = 0; n < BL_CODES; n++) s->bl_tree[n].Freq = 0;
s->dyn_ltree[END_BLOCK].Freq = 1;
s->opt_len = s->static_len = 0L;
s->sym_next = s->matches = 0;
}
/* =========================================================================== /* ===========================================================================
* Initialize the tree data structures for a new zlib stream. * Initialize the tree data structures for a new zlib stream.
*/ */
void ZLIB_INTERNAL _tr_init(s) void ZLIB_INTERNAL _tr_init(deflate_state *s) {
deflate_state *s;
{
tr_static_init(); tr_static_init();
s->l_desc.dyn_tree = s->dyn_ltree; s->l_desc.dyn_tree = s->dyn_ltree;
@ -401,24 +475,6 @@ void ZLIB_INTERNAL _tr_init(s)
init_block(s); init_block(s);
} }
/* ===========================================================================
* Initialize a new block.
*/
local void init_block(s)
deflate_state *s;
{
int n; /* iterates over tree elements */
/* Initialize the trees. */
for (n = 0; n < L_CODES; n++) s->dyn_ltree[n].Freq = 0;
for (n = 0; n < D_CODES; n++) s->dyn_dtree[n].Freq = 0;
for (n = 0; n < BL_CODES; n++) s->bl_tree[n].Freq = 0;
s->dyn_ltree[END_BLOCK].Freq = 1;
s->opt_len = s->static_len = 0L;
s->last_lit = s->matches = 0;
}
#define SMALLEST 1 #define SMALLEST 1
/* Index within the heap array of least frequent node in the Huffman tree */ /* Index within the heap array of least frequent node in the Huffman tree */
@ -448,17 +504,13 @@ local void init_block(s)
* when the heap property is re-established (each father smaller than its * when the heap property is re-established (each father smaller than its
* two sons). * two sons).
*/ */
local void pqdownheap(s, tree, k) local void pqdownheap(deflate_state *s, ct_data *tree, int k) {
deflate_state *s;
ct_data *tree; /* the tree to restore */
int k; /* node to move down */
{
int v = s->heap[k]; int v = s->heap[k];
int j = k << 1; /* left son of k */ int j = k << 1; /* left son of k */
while (j <= s->heap_len) { while (j <= s->heap_len) {
/* Set j to the smallest of the two sons: */ /* Set j to the smallest of the two sons: */
if (j < s->heap_len && if (j < s->heap_len &&
smaller(tree, s->heap[j+1], s->heap[j], s->depth)) { smaller(tree, s->heap[j + 1], s->heap[j], s->depth)) {
j++; j++;
} }
/* Exit if v is smaller than both sons */ /* Exit if v is smaller than both sons */
@ -483,10 +535,7 @@ local void pqdownheap(s, tree, k)
* The length opt_len is updated; static_len is also updated if stree is * The length opt_len is updated; static_len is also updated if stree is
* not null. * not null.
*/ */
local void gen_bitlen(s, desc) local void gen_bitlen(deflate_state *s, tree_desc *desc) {
deflate_state *s;
tree_desc *desc; /* the tree descriptor */
{
ct_data *tree = desc->dyn_tree; ct_data *tree = desc->dyn_tree;
int max_code = desc->max_code; int max_code = desc->max_code;
const ct_data *stree = desc->stat_desc->static_tree; const ct_data *stree = desc->stat_desc->static_tree;
@ -507,7 +556,7 @@ local void gen_bitlen(s, desc)
*/ */
tree[s->heap[s->heap_max]].Len = 0; /* root of the heap */ tree[s->heap[s->heap_max]].Len = 0; /* root of the heap */
for (h = s->heap_max+1; h < HEAP_SIZE; h++) { for (h = s->heap_max + 1; h < HEAP_SIZE; h++) {
n = s->heap[h]; n = s->heap[h];
bits = tree[tree[n].Dad].Len + 1; bits = tree[tree[n].Dad].Len + 1;
if (bits > max_length) bits = max_length, overflow++; if (bits > max_length) bits = max_length, overflow++;
@ -518,7 +567,7 @@ local void gen_bitlen(s, desc)
s->bl_count[bits]++; s->bl_count[bits]++;
xbits = 0; xbits = 0;
if (n >= base) xbits = extra[n-base]; if (n >= base) xbits = extra[n - base];
f = tree[n].Freq; f = tree[n].Freq;
s->opt_len += (ulg)f * (unsigned)(bits + xbits); s->opt_len += (ulg)f * (unsigned)(bits + xbits);
if (stree) s->static_len += (ulg)f * (unsigned)(stree[n].Len + xbits); if (stree) s->static_len += (ulg)f * (unsigned)(stree[n].Len + xbits);
@ -530,10 +579,10 @@ local void gen_bitlen(s, desc)
/* Find the first bit length which could increase: */ /* Find the first bit length which could increase: */
do { do {
bits = max_length-1; bits = max_length - 1;
while (s->bl_count[bits] == 0) bits--; while (s->bl_count[bits] == 0) bits--;
s->bl_count[bits]--; /* move one leaf down the tree */ s->bl_count[bits]--; /* move one leaf down the tree */
s->bl_count[bits+1] += 2; /* move one overflow item as its brother */ s->bl_count[bits + 1] += 2; /* move one overflow item as its brother */
s->bl_count[max_length]--; s->bl_count[max_length]--;
/* The brother of the overflow item also moves one step up, /* The brother of the overflow item also moves one step up,
* but this does not affect bl_count[max_length] * but this does not affect bl_count[max_length]
@ -561,48 +610,9 @@ local void gen_bitlen(s, desc)
} }
} }
/* =========================================================================== #ifdef DUMP_BL_TREE
* Generate the codes for a given tree and bit counts (which need not be # include <stdio.h>
* optimal). #endif
* IN assertion: the array bl_count contains the bit length statistics for
* the given tree and the field len is set for all tree elements.
* OUT assertion: the field code is set for all tree elements of non
* zero code length.
*/
local void gen_codes (tree, max_code, bl_count)
ct_data *tree; /* the tree to decorate */
int max_code; /* largest code with non zero frequency */
ushf *bl_count; /* number of codes at each bit length */
{
ush next_code[MAX_BITS+1]; /* next code value for each bit length */
unsigned code = 0; /* running code value */
int bits; /* bit index */
int n; /* code index */
/* The distribution counts are first used to generate the code values
* without bit reversal.
*/
for (bits = 1; bits <= MAX_BITS; bits++) {
code = (code + bl_count[bits-1]) << 1;
next_code[bits] = (ush)code;
}
/* Check that the bit counts in bl_count are consistent. The last code
* must be all ones.
*/
Assert (code + bl_count[MAX_BITS]-1 == (1<<MAX_BITS)-1,
"inconsistent bit counts");
Tracev((stderr,"\ngen_codes: max_code %d ", max_code));
for (n = 0; n <= max_code; n++) {
int len = tree[n].Len;
if (len == 0) continue;
/* Now reverse the bits */
tree[n].Code = (ush)bi_reverse(next_code[len]++, len);
Tracecv(tree != static_ltree, (stderr,"\nn %3d %c l %2d c %4x (%x) ",
n, (isgraph(n) ? n : ' '), len, tree[n].Code, next_code[len]-1));
}
}
/* =========================================================================== /* ===========================================================================
* Construct one Huffman tree and assigns the code bit strings and lengths. * Construct one Huffman tree and assigns the code bit strings and lengths.
@ -612,10 +622,7 @@ local void gen_codes (tree, max_code, bl_count)
* and corresponding code. The length opt_len is updated; static_len is * and corresponding code. The length opt_len is updated; static_len is
* also updated if stree is not null. The field max_code is set. * also updated if stree is not null. The field max_code is set.
*/ */
local void build_tree(s, desc) local void build_tree(deflate_state *s, tree_desc *desc) {
deflate_state *s;
tree_desc *desc; /* the tree descriptor */
{
ct_data *tree = desc->dyn_tree; ct_data *tree = desc->dyn_tree;
const ct_data *stree = desc->stat_desc->static_tree; const ct_data *stree = desc->stat_desc->static_tree;
int elems = desc->stat_desc->elems; int elems = desc->stat_desc->elems;
@ -624,7 +631,7 @@ local void build_tree(s, desc)
int node; /* new node being created */ int node; /* new node being created */
/* Construct the initial heap, with least frequent element in /* Construct the initial heap, with least frequent element in
* heap[SMALLEST]. The sons of heap[n] are heap[2*n] and heap[2*n+1]. * heap[SMALLEST]. The sons of heap[n] are heap[2*n] and heap[2*n + 1].
* heap[0] is not used. * heap[0] is not used.
*/ */
s->heap_len = 0, s->heap_max = HEAP_SIZE; s->heap_len = 0, s->heap_max = HEAP_SIZE;
@ -652,7 +659,7 @@ local void build_tree(s, desc)
} }
desc->max_code = max_code; desc->max_code = max_code;
/* The elements heap[heap_len/2+1 .. heap_len] are leaves of the tree, /* The elements heap[heap_len/2 + 1 .. heap_len] are leaves of the tree,
* establish sub-heaps of increasing lengths: * establish sub-heaps of increasing lengths:
*/ */
for (n = s->heap_len/2; n >= 1; n--) pqdownheap(s, tree, n); for (n = s->heap_len/2; n >= 1; n--) pqdownheap(s, tree, n);
@ -700,11 +707,7 @@ local void build_tree(s, desc)
* Scan a literal or distance tree to determine the frequencies of the codes * Scan a literal or distance tree to determine the frequencies of the codes
* in the bit length tree. * in the bit length tree.
*/ */
local void scan_tree (s, tree, max_code) local void scan_tree(deflate_state *s, ct_data *tree, int max_code) {
deflate_state *s;
ct_data *tree; /* the tree to be scanned */
int max_code; /* and its largest code of non zero frequency */
{
int n; /* iterates over all tree elements */ int n; /* iterates over all tree elements */
int prevlen = -1; /* last emitted length */ int prevlen = -1; /* last emitted length */
int curlen; /* length of current code */ int curlen; /* length of current code */
@ -714,10 +717,10 @@ local void scan_tree (s, tree, max_code)
int min_count = 4; /* min repeat count */ int min_count = 4; /* min repeat count */
if (nextlen == 0) max_count = 138, min_count = 3; if (nextlen == 0) max_count = 138, min_count = 3;
tree[max_code+1].Len = (ush)0xffff; /* guard */ tree[max_code + 1].Len = (ush)0xffff; /* guard */
for (n = 0; n <= max_code; n++) { for (n = 0; n <= max_code; n++) {
curlen = nextlen; nextlen = tree[n+1].Len; curlen = nextlen; nextlen = tree[n + 1].Len;
if (++count < max_count && curlen == nextlen) { if (++count < max_count && curlen == nextlen) {
continue; continue;
} else if (count < min_count) { } else if (count < min_count) {
@ -745,11 +748,7 @@ local void scan_tree (s, tree, max_code)
* Send a literal or distance tree in compressed form, using the codes in * Send a literal or distance tree in compressed form, using the codes in
* bl_tree. * bl_tree.
*/ */
local void send_tree (s, tree, max_code) local void send_tree(deflate_state *s, ct_data *tree, int max_code) {
deflate_state *s;
ct_data *tree; /* the tree to be scanned */
int max_code; /* and its largest code of non zero frequency */
{
int n; /* iterates over all tree elements */ int n; /* iterates over all tree elements */
int prevlen = -1; /* last emitted length */ int prevlen = -1; /* last emitted length */
int curlen; /* length of current code */ int curlen; /* length of current code */
@ -758,11 +757,11 @@ local void send_tree (s, tree, max_code)
int max_count = 7; /* max repeat count */ int max_count = 7; /* max repeat count */
int min_count = 4; /* min repeat count */ int min_count = 4; /* min repeat count */
/* tree[max_code+1].Len = -1; */ /* guard already set */ /* tree[max_code + 1].Len = -1; */ /* guard already set */
if (nextlen == 0) max_count = 138, min_count = 3; if (nextlen == 0) max_count = 138, min_count = 3;
for (n = 0; n <= max_code; n++) { for (n = 0; n <= max_code; n++) {
curlen = nextlen; nextlen = tree[n+1].Len; curlen = nextlen; nextlen = tree[n + 1].Len;
if (++count < max_count && curlen == nextlen) { if (++count < max_count && curlen == nextlen) {
continue; continue;
} else if (count < min_count) { } else if (count < min_count) {
@ -773,13 +772,13 @@ local void send_tree (s, tree, max_code)
send_code(s, curlen, s->bl_tree); count--; send_code(s, curlen, s->bl_tree); count--;
} }
Assert(count >= 3 && count <= 6, " 3_6?"); Assert(count >= 3 && count <= 6, " 3_6?");
send_code(s, REP_3_6, s->bl_tree); send_bits(s, count-3, 2); send_code(s, REP_3_6, s->bl_tree); send_bits(s, count - 3, 2);
} else if (count <= 10) { } else if (count <= 10) {
send_code(s, REPZ_3_10, s->bl_tree); send_bits(s, count-3, 3); send_code(s, REPZ_3_10, s->bl_tree); send_bits(s, count - 3, 3);
} else { } else {
send_code(s, REPZ_11_138, s->bl_tree); send_bits(s, count-11, 7); send_code(s, REPZ_11_138, s->bl_tree); send_bits(s, count - 11, 7);
} }
count = 0; prevlen = curlen; count = 0; prevlen = curlen;
if (nextlen == 0) { if (nextlen == 0) {
@ -796,9 +795,7 @@ local void send_tree (s, tree, max_code)
* Construct the Huffman tree for the bit lengths and return the index in * Construct the Huffman tree for the bit lengths and return the index in
* bl_order of the last bit length code to send. * bl_order of the last bit length code to send.
*/ */
local int build_bl_tree(s) local int build_bl_tree(deflate_state *s) {
deflate_state *s;
{
int max_blindex; /* index of last bit length code of non zero freq */ int max_blindex; /* index of last bit length code of non zero freq */
/* Determine the bit length frequencies for literal and distance trees */ /* Determine the bit length frequencies for literal and distance trees */
@ -807,8 +804,8 @@ local int build_bl_tree(s)
/* Build the bit length tree: */ /* Build the bit length tree: */
build_tree(s, (tree_desc *)(&(s->bl_desc))); build_tree(s, (tree_desc *)(&(s->bl_desc)));
/* opt_len now includes the length of the tree representations, except /* opt_len now includes the length of the tree representations, except the
* the lengths of the bit lengths codes and the 5+5+4 bits for the counts. * lengths of the bit lengths codes and the 5 + 5 + 4 bits for the counts.
*/ */
/* Determine the number of bit length codes to send. The pkzip format /* Determine the number of bit length codes to send. The pkzip format
@ -819,7 +816,7 @@ local int build_bl_tree(s)
if (s->bl_tree[bl_order[max_blindex]].Len != 0) break; if (s->bl_tree[bl_order[max_blindex]].Len != 0) break;
} }
/* Update opt_len to include the bit length tree and counts */ /* Update opt_len to include the bit length tree and counts */
s->opt_len += 3*((ulg)max_blindex+1) + 5+5+4; s->opt_len += 3*((ulg)max_blindex + 1) + 5 + 5 + 4;
Tracev((stderr, "\ndyn trees: dyn %ld, stat %ld", Tracev((stderr, "\ndyn trees: dyn %ld, stat %ld",
s->opt_len, s->static_len)); s->opt_len, s->static_len));
@ -831,61 +828,54 @@ local int build_bl_tree(s)
* lengths of the bit length codes, the literal tree and the distance tree. * lengths of the bit length codes, the literal tree and the distance tree.
* IN assertion: lcodes >= 257, dcodes >= 1, blcodes >= 4. * IN assertion: lcodes >= 257, dcodes >= 1, blcodes >= 4.
*/ */
local void send_all_trees(s, lcodes, dcodes, blcodes) local void send_all_trees(deflate_state *s, int lcodes, int dcodes,
deflate_state *s; int blcodes) {
int lcodes, dcodes, blcodes; /* number of codes for each tree */
{
int rank; /* index in bl_order */ int rank; /* index in bl_order */
Assert (lcodes >= 257 && dcodes >= 1 && blcodes >= 4, "not enough codes"); Assert (lcodes >= 257 && dcodes >= 1 && blcodes >= 4, "not enough codes");
Assert (lcodes <= L_CODES && dcodes <= D_CODES && blcodes <= BL_CODES, Assert (lcodes <= L_CODES && dcodes <= D_CODES && blcodes <= BL_CODES,
"too many codes"); "too many codes");
Tracev((stderr, "\nbl counts: ")); Tracev((stderr, "\nbl counts: "));
send_bits(s, lcodes-257, 5); /* not +255 as stated in appnote.txt */ send_bits(s, lcodes - 257, 5); /* not +255 as stated in appnote.txt */
send_bits(s, dcodes-1, 5); send_bits(s, dcodes - 1, 5);
send_bits(s, blcodes-4, 4); /* not -3 as stated in appnote.txt */ send_bits(s, blcodes - 4, 4); /* not -3 as stated in appnote.txt */
for (rank = 0; rank < blcodes; rank++) { for (rank = 0; rank < blcodes; rank++) {
Tracev((stderr, "\nbl code %2d ", bl_order[rank])); Tracev((stderr, "\nbl code %2d ", bl_order[rank]));
send_bits(s, s->bl_tree[bl_order[rank]].Len, 3); send_bits(s, s->bl_tree[bl_order[rank]].Len, 3);
} }
Tracev((stderr, "\nbl tree: sent %ld", s->bits_sent)); Tracev((stderr, "\nbl tree: sent %ld", s->bits_sent));
send_tree(s, (ct_data *)s->dyn_ltree, lcodes-1); /* literal tree */ send_tree(s, (ct_data *)s->dyn_ltree, lcodes - 1); /* literal tree */
Tracev((stderr, "\nlit tree: sent %ld", s->bits_sent)); Tracev((stderr, "\nlit tree: sent %ld", s->bits_sent));
send_tree(s, (ct_data *)s->dyn_dtree, dcodes-1); /* distance tree */ send_tree(s, (ct_data *)s->dyn_dtree, dcodes - 1); /* distance tree */
Tracev((stderr, "\ndist tree: sent %ld", s->bits_sent)); Tracev((stderr, "\ndist tree: sent %ld", s->bits_sent));
} }
/* =========================================================================== /* ===========================================================================
* Send a stored block * Send a stored block
*/ */
void ZLIB_INTERNAL _tr_stored_block(s, buf, stored_len, last) void ZLIB_INTERNAL _tr_stored_block(deflate_state *s, charf *buf,
deflate_state *s; ulg stored_len, int last) {
charf *buf; /* input block */ send_bits(s, (STORED_BLOCK<<1) + last, 3); /* send block type */
ulg stored_len; /* length of input block */
int last; /* one if this is the last block for a file */
{
send_bits(s, (STORED_BLOCK<<1)+last, 3); /* send block type */
bi_windup(s); /* align on byte boundary */ bi_windup(s); /* align on byte boundary */
put_short(s, (ush)stored_len); put_short(s, (ush)stored_len);
put_short(s, (ush)~stored_len); put_short(s, (ush)~stored_len);
zmemcpy(s->pending_buf + s->pending, (Bytef *)buf, stored_len); if (stored_len)
zmemcpy(s->pending_buf + s->pending, (Bytef *)buf, stored_len);
s->pending += stored_len; s->pending += stored_len;
#ifdef ZLIB_DEBUG #ifdef ZLIB_DEBUG
s->compressed_len = (s->compressed_len + 3 + 7) & (ulg)~7L; s->compressed_len = (s->compressed_len + 3 + 7) & (ulg)~7L;
s->compressed_len += (stored_len + 4) << 3; s->compressed_len += (stored_len + 4) << 3;
s->bits_sent += 2*16; s->bits_sent += 2*16;
s->bits_sent += stored_len<<3; s->bits_sent += stored_len << 3;
#endif #endif
} }
/* =========================================================================== /* ===========================================================================
* Flush the bits in the bit buffer to pending output (leaves at most 7 bits) * Flush the bits in the bit buffer to pending output (leaves at most 7 bits)
*/ */
void ZLIB_INTERNAL _tr_flush_bits(s) void ZLIB_INTERNAL _tr_flush_bits(deflate_state *s) {
deflate_state *s;
{
bi_flush(s); bi_flush(s);
} }
@ -893,9 +883,7 @@ void ZLIB_INTERNAL _tr_flush_bits(s)
* Send one empty static block to give enough lookahead for inflate. * Send one empty static block to give enough lookahead for inflate.
* This takes 10 bits, of which 7 may remain in the bit buffer. * This takes 10 bits, of which 7 may remain in the bit buffer.
*/ */
void ZLIB_INTERNAL _tr_align(s) void ZLIB_INTERNAL _tr_align(deflate_state *s) {
deflate_state *s;
{
send_bits(s, STATIC_TREES<<1, 3); send_bits(s, STATIC_TREES<<1, 3);
send_code(s, END_BLOCK, static_ltree); send_code(s, END_BLOCK, static_ltree);
#ifdef ZLIB_DEBUG #ifdef ZLIB_DEBUG
@ -904,16 +892,99 @@ void ZLIB_INTERNAL _tr_align(s)
bi_flush(s); bi_flush(s);
} }
/* ===========================================================================
* Send the block data compressed using the given Huffman trees
*/
local void compress_block(deflate_state *s, const ct_data *ltree,
const ct_data *dtree) {
unsigned dist; /* distance of matched string */
int lc; /* match length or unmatched char (if dist == 0) */
unsigned sx = 0; /* running index in sym_buf */
unsigned code; /* the code to send */
int extra; /* number of extra bits to send */
if (s->sym_next != 0) do {
dist = s->sym_buf[sx++] & 0xff;
dist += (unsigned)(s->sym_buf[sx++] & 0xff) << 8;
lc = s->sym_buf[sx++];
if (dist == 0) {
send_code(s, lc, ltree); /* send a literal byte */
Tracecv(isgraph(lc), (stderr," '%c' ", lc));
} else {
/* Here, lc is the match length - MIN_MATCH */
code = _length_code[lc];
send_code(s, code + LITERALS + 1, ltree); /* send length code */
extra = extra_lbits[code];
if (extra != 0) {
lc -= base_length[code];
send_bits(s, lc, extra); /* send the extra length bits */
}
dist--; /* dist is now the match distance - 1 */
code = d_code(dist);
Assert (code < D_CODES, "bad d_code");
send_code(s, code, dtree); /* send the distance code */
extra = extra_dbits[code];
if (extra != 0) {
dist -= (unsigned)base_dist[code];
send_bits(s, dist, extra); /* send the extra distance bits */
}
} /* literal or match pair ? */
/* Check that the overlay between pending_buf and sym_buf is ok: */
Assert(s->pending < s->lit_bufsize + sx, "pendingBuf overflow");
} while (sx < s->sym_next);
send_code(s, END_BLOCK, ltree);
}
/* ===========================================================================
* Check if the data type is TEXT or BINARY, using the following algorithm:
* - TEXT if the two conditions below are satisfied:
* a) There are no non-portable control characters belonging to the
* "block list" (0..6, 14..25, 28..31).
* b) There is at least one printable character belonging to the
* "allow list" (9 {TAB}, 10 {LF}, 13 {CR}, 32..255).
* - BINARY otherwise.
* - The following partially-portable control characters form a
* "gray list" that is ignored in this detection algorithm:
* (7 {BEL}, 8 {BS}, 11 {VT}, 12 {FF}, 26 {SUB}, 27 {ESC}).
* IN assertion: the fields Freq of dyn_ltree are set.
*/
local int detect_data_type(deflate_state *s) {
/* block_mask is the bit mask of block-listed bytes
* set bits 0..6, 14..25, and 28..31
* 0xf3ffc07f = binary 11110011111111111100000001111111
*/
unsigned long block_mask = 0xf3ffc07fUL;
int n;
/* Check for non-textual ("block-listed") bytes. */
for (n = 0; n <= 31; n++, block_mask >>= 1)
if ((block_mask & 1) && (s->dyn_ltree[n].Freq != 0))
return Z_BINARY;
/* Check for textual ("allow-listed") bytes. */
if (s->dyn_ltree[9].Freq != 0 || s->dyn_ltree[10].Freq != 0
|| s->dyn_ltree[13].Freq != 0)
return Z_TEXT;
for (n = 32; n < LITERALS; n++)
if (s->dyn_ltree[n].Freq != 0)
return Z_TEXT;
/* There are no "block-listed" or "allow-listed" bytes:
* this stream either is empty or has tolerated ("gray-listed") bytes only.
*/
return Z_BINARY;
}
/* =========================================================================== /* ===========================================================================
* Determine the best encoding for the current block: dynamic trees, static * Determine the best encoding for the current block: dynamic trees, static
* trees or store, and write out the encoded block. * trees or store, and write out the encoded block.
*/ */
void ZLIB_INTERNAL _tr_flush_block(s, buf, stored_len, last) void ZLIB_INTERNAL _tr_flush_block(deflate_state *s, charf *buf,
deflate_state *s; ulg stored_len, int last) {
charf *buf; /* input block, or NULL if too old */
ulg stored_len; /* length of input block */
int last; /* one if this is the last block for a file */
{
ulg opt_lenb, static_lenb; /* opt_len and static_len in bytes */ ulg opt_lenb, static_lenb; /* opt_len and static_len in bytes */
int max_blindex = 0; /* index of last bit length code of non zero freq */ int max_blindex = 0; /* index of last bit length code of non zero freq */
@ -942,14 +1013,17 @@ void ZLIB_INTERNAL _tr_flush_block(s, buf, stored_len, last)
max_blindex = build_bl_tree(s); max_blindex = build_bl_tree(s);
/* Determine the best encoding. Compute the block lengths in bytes. */ /* Determine the best encoding. Compute the block lengths in bytes. */
opt_lenb = (s->opt_len+3+7)>>3; opt_lenb = (s->opt_len + 3 + 7) >> 3;
static_lenb = (s->static_len+3+7)>>3; static_lenb = (s->static_len + 3 + 7) >> 3;
Tracev((stderr, "\nopt %lu(%lu) stat %lu(%lu) stored %lu lit %u ", Tracev((stderr, "\nopt %lu(%lu) stat %lu(%lu) stored %lu lit %u ",
opt_lenb, s->opt_len, static_lenb, s->static_len, stored_len, opt_lenb, s->opt_len, static_lenb, s->static_len, stored_len,
s->last_lit)); s->sym_next / 3));
if (static_lenb <= opt_lenb) opt_lenb = static_lenb; #ifndef FORCE_STATIC
if (static_lenb <= opt_lenb || s->strategy == Z_FIXED)
#endif
opt_lenb = static_lenb;
} else { } else {
Assert(buf != (char*)0, "lost buf"); Assert(buf != (char*)0, "lost buf");
@ -959,7 +1033,7 @@ void ZLIB_INTERNAL _tr_flush_block(s, buf, stored_len, last)
#ifdef FORCE_STORED #ifdef FORCE_STORED
if (buf != (char*)0) { /* force stored block */ if (buf != (char*)0) { /* force stored block */
#else #else
if (stored_len+4 <= opt_lenb && buf != (char*)0) { if (stored_len + 4 <= opt_lenb && buf != (char*)0) {
/* 4: two words for the lengths */ /* 4: two words for the lengths */
#endif #endif
/* The test buf != NULL is only necessary if LIT_BUFSIZE > WSIZE. /* The test buf != NULL is only necessary if LIT_BUFSIZE > WSIZE.
@ -970,21 +1044,17 @@ void ZLIB_INTERNAL _tr_flush_block(s, buf, stored_len, last)
*/ */
_tr_stored_block(s, buf, stored_len, last); _tr_stored_block(s, buf, stored_len, last);
#ifdef FORCE_STATIC } else if (static_lenb == opt_lenb) {
} else if (static_lenb >= 0) { /* force static trees */ send_bits(s, (STATIC_TREES<<1) + last, 3);
#else
} else if (s->strategy == Z_FIXED || static_lenb == opt_lenb) {
#endif
send_bits(s, (STATIC_TREES<<1)+last, 3);
compress_block(s, (const ct_data *)static_ltree, compress_block(s, (const ct_data *)static_ltree,
(const ct_data *)static_dtree); (const ct_data *)static_dtree);
#ifdef ZLIB_DEBUG #ifdef ZLIB_DEBUG
s->compressed_len += 3 + s->static_len; s->compressed_len += 3 + s->static_len;
#endif #endif
} else { } else {
send_bits(s, (DYN_TREES<<1)+last, 3); send_bits(s, (DYN_TREES<<1) + last, 3);
send_all_trees(s, s->l_desc.max_code+1, s->d_desc.max_code+1, send_all_trees(s, s->l_desc.max_code + 1, s->d_desc.max_code + 1,
max_blindex+1); max_blindex + 1);
compress_block(s, (const ct_data *)s->dyn_ltree, compress_block(s, (const ct_data *)s->dyn_ltree,
(const ct_data *)s->dyn_dtree); (const ct_data *)s->dyn_dtree);
#ifdef ZLIB_DEBUG #ifdef ZLIB_DEBUG
@ -1003,21 +1073,18 @@ void ZLIB_INTERNAL _tr_flush_block(s, buf, stored_len, last)
s->compressed_len += 7; /* align on byte boundary */ s->compressed_len += 7; /* align on byte boundary */
#endif #endif
} }
Tracev((stderr,"\ncomprlen %lu(%lu) ", s->compressed_len>>3, Tracev((stderr,"\ncomprlen %lu(%lu) ", s->compressed_len >> 3,
s->compressed_len-7*last)); s->compressed_len - 7*last));
} }
/* =========================================================================== /* ===========================================================================
* Save the match info and tally the frequency counts. Return true if * Save the match info and tally the frequency counts. Return true if
* the current block must be flushed. * the current block must be flushed.
*/ */
int ZLIB_INTERNAL _tr_tally (s, dist, lc) int ZLIB_INTERNAL _tr_tally(deflate_state *s, unsigned dist, unsigned lc) {
deflate_state *s; s->sym_buf[s->sym_next++] = (uch)dist;
unsigned dist; /* distance of matched string */ s->sym_buf[s->sym_next++] = (uch)(dist >> 8);
unsigned lc; /* match length-MIN_MATCH or unmatched char (if dist==0) */ s->sym_buf[s->sym_next++] = (uch)lc;
{
s->d_buf[s->last_lit] = (ush)dist;
s->l_buf[s->last_lit++] = (uch)lc;
if (dist == 0) { if (dist == 0) {
/* lc is the unmatched char */ /* lc is the unmatched char */
s->dyn_ltree[lc].Freq++; s->dyn_ltree[lc].Freq++;
@ -1029,175 +1096,8 @@ int ZLIB_INTERNAL _tr_tally (s, dist, lc)
(ush)lc <= (ush)(MAX_MATCH-MIN_MATCH) && (ush)lc <= (ush)(MAX_MATCH-MIN_MATCH) &&
(ush)d_code(dist) < (ush)D_CODES, "_tr_tally: bad match"); (ush)d_code(dist) < (ush)D_CODES, "_tr_tally: bad match");
s->dyn_ltree[_length_code[lc]+LITERALS+1].Freq++; s->dyn_ltree[_length_code[lc] + LITERALS + 1].Freq++;
s->dyn_dtree[d_code(dist)].Freq++; s->dyn_dtree[d_code(dist)].Freq++;
} }
return (s->sym_next == s->sym_end);
#ifdef TRUNCATE_BLOCK
/* Try to guess if it is profitable to stop the current block here */
if ((s->last_lit & 0x1fff) == 0 && s->level > 2) {
/* Compute an upper bound for the compressed length */
ulg out_length = (ulg)s->last_lit*8L;
ulg in_length = (ulg)((long)s->strstart - s->block_start);
int dcode;
for (dcode = 0; dcode < D_CODES; dcode++) {
out_length += (ulg)s->dyn_dtree[dcode].Freq *
(5L+extra_dbits[dcode]);
}
out_length >>= 3;
Tracev((stderr,"\nlast_lit %u, in %ld, out ~%ld(%ld%%) ",
s->last_lit, in_length, out_length,
100L - out_length*100L/in_length));
if (s->matches < s->last_lit/2 && out_length < in_length/2) return 1;
}
#endif
return (s->last_lit == s->lit_bufsize-1);
/* We avoid equality with lit_bufsize because of wraparound at 64K
* on 16 bit machines and because stored blocks are restricted to
* 64K-1 bytes.
*/
}
/* ===========================================================================
* Send the block data compressed using the given Huffman trees
*/
local void compress_block(s, ltree, dtree)
deflate_state *s;
const ct_data *ltree; /* literal tree */
const ct_data *dtree; /* distance tree */
{
unsigned dist; /* distance of matched string */
int lc; /* match length or unmatched char (if dist == 0) */
unsigned lx = 0; /* running index in l_buf */
unsigned code; /* the code to send */
int extra; /* number of extra bits to send */
if (s->last_lit != 0) do {
dist = s->d_buf[lx];
lc = s->l_buf[lx++];
if (dist == 0) {
send_code(s, lc, ltree); /* send a literal byte */
Tracecv(isgraph(lc), (stderr," '%c' ", lc));
} else {
/* Here, lc is the match length - MIN_MATCH */
code = _length_code[lc];
send_code(s, code+LITERALS+1, ltree); /* send the length code */
extra = extra_lbits[code];
if (extra != 0) {
lc -= base_length[code];
send_bits(s, lc, extra); /* send the extra length bits */
}
dist--; /* dist is now the match distance - 1 */
code = d_code(dist);
Assert (code < D_CODES, "bad d_code");
send_code(s, code, dtree); /* send the distance code */
extra = extra_dbits[code];
if (extra != 0) {
dist -= (unsigned)base_dist[code];
send_bits(s, dist, extra); /* send the extra distance bits */
}
} /* literal or match pair ? */
/* Check that the overlay between pending_buf and d_buf+l_buf is ok: */
Assert((uInt)(s->pending) < s->lit_bufsize + 2*lx,
"pendingBuf overflow");
} while (lx < s->last_lit);
send_code(s, END_BLOCK, ltree);
}
/* ===========================================================================
* Check if the data type is TEXT or BINARY, using the following algorithm:
* - TEXT if the two conditions below are satisfied:
* a) There are no non-portable control characters belonging to the
* "black list" (0..6, 14..25, 28..31).
* b) There is at least one printable character belonging to the
* "white list" (9 {TAB}, 10 {LF}, 13 {CR}, 32..255).
* - BINARY otherwise.
* - The following partially-portable control characters form a
* "gray list" that is ignored in this detection algorithm:
* (7 {BEL}, 8 {BS}, 11 {VT}, 12 {FF}, 26 {SUB}, 27 {ESC}).
* IN assertion: the fields Freq of dyn_ltree are set.
*/
local int detect_data_type(s)
deflate_state *s;
{
/* black_mask is the bit mask of black-listed bytes
* set bits 0..6, 14..25, and 28..31
* 0xf3ffc07f = binary 11110011111111111100000001111111
*/
unsigned long black_mask = 0xf3ffc07fUL;
int n;
/* Check for non-textual ("black-listed") bytes. */
for (n = 0; n <= 31; n++, black_mask >>= 1)
if ((black_mask & 1) && (s->dyn_ltree[n].Freq != 0))
return Z_BINARY;
/* Check for textual ("white-listed") bytes. */
if (s->dyn_ltree[9].Freq != 0 || s->dyn_ltree[10].Freq != 0
|| s->dyn_ltree[13].Freq != 0)
return Z_TEXT;
for (n = 32; n < LITERALS; n++)
if (s->dyn_ltree[n].Freq != 0)
return Z_TEXT;
/* There are no "black-listed" or "white-listed" bytes:
* this stream either is empty or has tolerated ("gray-listed") bytes only.
*/
return Z_BINARY;
}
/* ===========================================================================
* Reverse the first len bits of a code, using straightforward code (a faster
* method would use a table)
* IN assertion: 1 <= len <= 15
*/
local unsigned bi_reverse(code, len)
unsigned code; /* the value to invert */
int len; /* its bit length */
{
register unsigned res = 0;
do {
res |= code & 1;
code >>= 1, res <<= 1;
} while (--len > 0);
return res >> 1;
}
/* ===========================================================================
* Flush the bit buffer, keeping at most 7 bits in it.
*/
local void bi_flush(s)
deflate_state *s;
{
if (s->bi_valid == 16) {
put_short(s, s->bi_buf);
s->bi_buf = 0;
s->bi_valid = 0;
} else if (s->bi_valid >= 8) {
put_byte(s, (Byte)s->bi_buf);
s->bi_buf >>= 8;
s->bi_valid -= 8;
}
}
/* ===========================================================================
* Flush the bit buffer and align the output on a byte boundary
*/
local void bi_windup(s)
deflate_state *s;
{
if (s->bi_valid > 8) {
put_short(s, s->bi_buf);
} else if (s->bi_valid > 0) {
put_byte(s, (Byte)s->bi_buf);
}
s->bi_buf = 0;
s->bi_valid = 0;
#ifdef ZLIB_DEBUG
s->bits_sent = (s->bits_sent+7) & ~7;
#endif
} }

View File

@ -24,12 +24,8 @@
Z_DATA_ERROR if the input data was corrupted, including if the input data is Z_DATA_ERROR if the input data was corrupted, including if the input data is
an incomplete zlib stream. an incomplete zlib stream.
*/ */
int ZEXPORT uncompress2 (dest, destLen, source, sourceLen) int ZEXPORT uncompress2(Bytef *dest, uLongf *destLen, const Bytef *source,
Bytef *dest; uLong *sourceLen) {
uLongf *destLen;
const Bytef *source;
uLong *sourceLen;
{
z_stream stream; z_stream stream;
int err; int err;
const uInt max = (uInt)-1; const uInt max = (uInt)-1;
@ -83,11 +79,7 @@ int ZEXPORT uncompress2 (dest, destLen, source, sourceLen)
err; err;
} }
int ZEXPORT uncompress (dest, destLen, source, sourceLen) int ZEXPORT uncompress(Bytef *dest, uLongf *destLen, const Bytef *source,
Bytef *dest; uLong sourceLen) {
uLongf *destLen;
const Bytef *source;
uLong sourceLen;
{
return uncompress2(dest, destLen, source, &sourceLen); return uncompress2(dest, destLen, source, &sourceLen);
} }

27
3rdparty/zlib/zconf.h vendored
View File

@ -38,6 +38,9 @@
# define crc32 z_crc32 # define crc32 z_crc32
# define crc32_combine z_crc32_combine # define crc32_combine z_crc32_combine
# define crc32_combine64 z_crc32_combine64 # define crc32_combine64 z_crc32_combine64
# define crc32_combine_gen z_crc32_combine_gen
# define crc32_combine_gen64 z_crc32_combine_gen64
# define crc32_combine_op z_crc32_combine_op
# define crc32_z z_crc32_z # define crc32_z z_crc32_z
# define deflate z_deflate # define deflate z_deflate
# define deflateBound z_deflateBound # define deflateBound z_deflateBound
@ -238,7 +241,11 @@
#endif #endif
#ifdef Z_SOLO #ifdef Z_SOLO
typedef unsigned long z_size_t; # ifdef _WIN64
typedef unsigned long long z_size_t;
# else
typedef unsigned long z_size_t;
# endif
#else #else
# define z_longlong long long # define z_longlong long long
# if defined(NO_SIZE_T) # if defined(NO_SIZE_T)
@ -349,6 +356,9 @@
# ifdef FAR # ifdef FAR
# undef FAR # undef FAR
# endif # endif
# ifndef WIN32_LEAN_AND_MEAN
# define WIN32_LEAN_AND_MEAN
# endif
# include <windows.h> # include <windows.h>
/* No need for _export, use ZLIB.DEF instead. */ /* No need for _export, use ZLIB.DEF instead. */
/* For complete Windows compatibility, use WINAPI, not __stdcall. */ /* For complete Windows compatibility, use WINAPI, not __stdcall. */
@ -467,11 +477,18 @@ typedef uLong FAR uLongf;
# undef _LARGEFILE64_SOURCE # undef _LARGEFILE64_SOURCE
#endif #endif
#if defined(__WATCOMC__) && !defined(Z_HAVE_UNISTD_H) #ifndef Z_HAVE_UNISTD_H
# define Z_HAVE_UNISTD_H # ifdef __WATCOMC__
# define Z_HAVE_UNISTD_H
# endif
#endif
#ifndef Z_HAVE_UNISTD_H
# if defined(_LARGEFILE64_SOURCE) && !defined(_WIN32)
# define Z_HAVE_UNISTD_H
# endif
#endif #endif
#ifndef Z_SOLO #ifndef Z_SOLO
# if defined(Z_HAVE_UNISTD_H) || defined(_LARGEFILE64_SOURCE) # if defined(Z_HAVE_UNISTD_H)
# include <unistd.h> /* for SEEK_*, off_t, and _LFS64_LARGEFILE */ # include <unistd.h> /* for SEEK_*, off_t, and _LFS64_LARGEFILE */
# ifdef VMS # ifdef VMS
# include <unixio.h> /* for off_t */ # include <unixio.h> /* for off_t */
@ -507,7 +524,7 @@ typedef uLong FAR uLongf;
#if !defined(_WIN32) && defined(Z_LARGE64) #if !defined(_WIN32) && defined(Z_LARGE64)
# define z_off64_t off64_t # define z_off64_t off64_t
#else #else
# if defined(_WIN32) && !defined(__GNUC__) && !defined(Z_SOLO) # if defined(_WIN32) && !defined(__GNUC__)
# define z_off64_t __int64 # define z_off64_t __int64
# else # else
# define z_off64_t z_off_t # define z_off64_t z_off_t

584
3rdparty/zlib/zlib.h vendored

File diff suppressed because it is too large Load Diff

66
3rdparty/zlib/zutil.c vendored
View File

@ -24,13 +24,11 @@ z_const char * const z_errmsg[10] = {
}; };
const char * ZEXPORT zlibVersion() const char * ZEXPORT zlibVersion(void) {
{
return ZLIB_VERSION; return ZLIB_VERSION;
} }
uLong ZEXPORT zlibCompileFlags() uLong ZEXPORT zlibCompileFlags(void) {
{
uLong flags; uLong flags;
flags = 0; flags = 0;
@ -61,9 +59,11 @@ uLong ZEXPORT zlibCompileFlags()
#ifdef ZLIB_DEBUG #ifdef ZLIB_DEBUG
flags += 1 << 8; flags += 1 << 8;
#endif #endif
/*
#if defined(ASMV) || defined(ASMINF) #if defined(ASMV) || defined(ASMINF)
flags += 1 << 9; flags += 1 << 9;
#endif #endif
*/
#ifdef ZLIB_WINAPI #ifdef ZLIB_WINAPI
flags += 1 << 10; flags += 1 << 10;
#endif #endif
@ -119,9 +119,7 @@ uLong ZEXPORT zlibCompileFlags()
# endif # endif
int ZLIB_INTERNAL z_verbose = verbose; int ZLIB_INTERNAL z_verbose = verbose;
void ZLIB_INTERNAL z_error (m) void ZLIB_INTERNAL z_error(char *m) {
char *m;
{
fprintf(stderr, "%s\n", m); fprintf(stderr, "%s\n", m);
exit(1); exit(1);
} }
@ -130,14 +128,12 @@ void ZLIB_INTERNAL z_error (m)
/* exported to allow conversion of error code to string for compress() and /* exported to allow conversion of error code to string for compress() and
* uncompress() * uncompress()
*/ */
const char * ZEXPORT zError(err) const char * ZEXPORT zError(int err) {
int err;
{
return ERR_MSG(err); return ERR_MSG(err);
} }
#if defined(_WIN32_WCE) #if defined(_WIN32_WCE) && _WIN32_WCE < 0x800
/* The Microsoft C Run-Time Library for Windows CE doesn't have /* The older Microsoft C Run-Time Library for Windows CE doesn't have
* errno. We define it as a global variable to simplify porting. * errno. We define it as a global variable to simplify porting.
* Its value is always 0 and should not be used. * Its value is always 0 and should not be used.
*/ */
@ -146,22 +142,14 @@ const char * ZEXPORT zError(err)
#ifndef HAVE_MEMCPY #ifndef HAVE_MEMCPY
void ZLIB_INTERNAL zmemcpy(dest, source, len) void ZLIB_INTERNAL zmemcpy(Bytef* dest, const Bytef* source, uInt len) {
Bytef* dest;
const Bytef* source;
uInt len;
{
if (len == 0) return; if (len == 0) return;
do { do {
*dest++ = *source++; /* ??? to be unrolled */ *dest++ = *source++; /* ??? to be unrolled */
} while (--len != 0); } while (--len != 0);
} }
int ZLIB_INTERNAL zmemcmp(s1, s2, len) int ZLIB_INTERNAL zmemcmp(const Bytef* s1, const Bytef* s2, uInt len) {
const Bytef* s1;
const Bytef* s2;
uInt len;
{
uInt j; uInt j;
for (j = 0; j < len; j++) { for (j = 0; j < len; j++) {
@ -170,10 +158,7 @@ int ZLIB_INTERNAL zmemcmp(s1, s2, len)
return 0; return 0;
} }
void ZLIB_INTERNAL zmemzero(dest, len) void ZLIB_INTERNAL zmemzero(Bytef* dest, uInt len) {
Bytef* dest;
uInt len;
{
if (len == 0) return; if (len == 0) return;
do { do {
*dest++ = 0; /* ??? to be unrolled */ *dest++ = 0; /* ??? to be unrolled */
@ -214,8 +199,7 @@ local ptr_table table[MAX_PTR];
* a protected system like OS/2. Use Microsoft C instead. * a protected system like OS/2. Use Microsoft C instead.
*/ */
voidpf ZLIB_INTERNAL zcalloc (voidpf opaque, unsigned items, unsigned size) voidpf ZLIB_INTERNAL zcalloc(voidpf opaque, unsigned items, unsigned size) {
{
voidpf buf; voidpf buf;
ulg bsize = (ulg)items*size; ulg bsize = (ulg)items*size;
@ -240,8 +224,7 @@ voidpf ZLIB_INTERNAL zcalloc (voidpf opaque, unsigned items, unsigned size)
return buf; return buf;
} }
void ZLIB_INTERNAL zcfree (voidpf opaque, voidpf ptr) void ZLIB_INTERNAL zcfree(voidpf opaque, voidpf ptr) {
{
int n; int n;
(void)opaque; (void)opaque;
@ -277,14 +260,12 @@ void ZLIB_INTERNAL zcfree (voidpf opaque, voidpf ptr)
# define _hfree hfree # define _hfree hfree
#endif #endif
voidpf ZLIB_INTERNAL zcalloc (voidpf opaque, uInt items, uInt size) voidpf ZLIB_INTERNAL zcalloc(voidpf opaque, uInt items, uInt size) {
{
(void)opaque; (void)opaque;
return _halloc((long)items, size); return _halloc((long)items, size);
} }
void ZLIB_INTERNAL zcfree (voidpf opaque, voidpf ptr) void ZLIB_INTERNAL zcfree(voidpf opaque, voidpf ptr) {
{
(void)opaque; (void)opaque;
_hfree(ptr); _hfree(ptr);
} }
@ -297,25 +278,18 @@ void ZLIB_INTERNAL zcfree (voidpf opaque, voidpf ptr)
#ifndef MY_ZCALLOC /* Any system without a special alloc function */ #ifndef MY_ZCALLOC /* Any system without a special alloc function */
#ifndef STDC #ifndef STDC
extern voidp malloc OF((uInt size)); extern voidp malloc(uInt size);
extern voidp calloc OF((uInt items, uInt size)); extern voidp calloc(uInt items, uInt size);
extern void free OF((voidpf ptr)); extern void free(voidpf ptr);
#endif #endif
voidpf ZLIB_INTERNAL zcalloc (opaque, items, size) voidpf ZLIB_INTERNAL zcalloc(voidpf opaque, unsigned items, unsigned size) {
voidpf opaque;
unsigned items;
unsigned size;
{
(void)opaque; (void)opaque;
return sizeof(uInt) > 2 ? (voidpf)malloc(items * size) : return sizeof(uInt) > 2 ? (voidpf)malloc(items * size) :
(voidpf)calloc(items, size); (voidpf)calloc(items, size);
} }
void ZLIB_INTERNAL zcfree (opaque, ptr) void ZLIB_INTERNAL zcfree(voidpf opaque, voidpf ptr) {
voidpf opaque;
voidpf ptr;
{
(void)opaque; (void)opaque;
free(ptr); free(ptr);
} }

40
3rdparty/zlib/zutil.h vendored
View File

@ -1,5 +1,5 @@
/* zutil.h -- internal interface and configuration of the compression library /* zutil.h -- internal interface and configuration of the compression library
* Copyright (C) 1995-2016 Jean-loup Gailly, Mark Adler * Copyright (C) 1995-2022 Jean-loup Gailly, Mark Adler
* For conditions of distribution and use, see copyright notice in zlib.h * For conditions of distribution and use, see copyright notice in zlib.h
*/ */
@ -29,10 +29,6 @@
# include <stdlib.h> # include <stdlib.h>
#endif #endif
#ifdef Z_SOLO
typedef long ptrdiff_t; /* guess -- will be caught if guess is wrong */
#endif
#ifndef local #ifndef local
# define local static # define local static
#endif #endif
@ -46,6 +42,17 @@ typedef unsigned short ush;
typedef ush FAR ushf; typedef ush FAR ushf;
typedef unsigned long ulg; typedef unsigned long ulg;
#if !defined(Z_U8) && !defined(Z_SOLO) && defined(STDC)
# include <limits.h>
# if (ULONG_MAX == 0xffffffffffffffff)
# define Z_U8 unsigned long
# elif (ULLONG_MAX == 0xffffffffffffffff)
# define Z_U8 unsigned long long
# elif (UINT_MAX == 0xffffffffffffffff)
# define Z_U8 unsigned
# endif
#endif
extern z_const char * const z_errmsg[10]; /* indexed by 2-zlib_error */ extern z_const char * const z_errmsg[10]; /* indexed by 2-zlib_error */
/* (size given to avoid silly warnings with Visual C++) */ /* (size given to avoid silly warnings with Visual C++) */
@ -170,10 +177,6 @@ extern z_const char * const z_errmsg[10]; /* indexed by 2-zlib_error */
#if (defined(_MSC_VER) && (_MSC_VER > 600)) && !defined __INTERIX #if (defined(_MSC_VER) && (_MSC_VER > 600)) && !defined __INTERIX
# if defined(_WIN32_WCE) # if defined(_WIN32_WCE)
# define fdopen(fd,mode) NULL /* No fdopen() */ # define fdopen(fd,mode) NULL /* No fdopen() */
# ifndef _PTRDIFF_T_DEFINED
typedef int ptrdiff_t;
# define _PTRDIFF_T_DEFINED
# endif
# else # else
# define fdopen(fd,type) _fdopen(fd,type) # define fdopen(fd,type) _fdopen(fd,type)
# endif # endif
@ -188,8 +191,9 @@ extern z_const char * const z_errmsg[10]; /* indexed by 2-zlib_error */
/* provide prototypes for these when building zlib without LFS */ /* provide prototypes for these when building zlib without LFS */
#if !defined(_WIN32) && \ #if !defined(_WIN32) && \
(!defined(_LARGEFILE64_SOURCE) || _LFS64_LARGEFILE-0 == 0) (!defined(_LARGEFILE64_SOURCE) || _LFS64_LARGEFILE-0 == 0)
ZEXTERN uLong ZEXPORT adler32_combine64 OF((uLong, uLong, z_off_t)); ZEXTERN uLong ZEXPORT adler32_combine64(uLong, uLong, z_off_t);
ZEXTERN uLong ZEXPORT crc32_combine64 OF((uLong, uLong, z_off_t)); ZEXTERN uLong ZEXPORT crc32_combine64(uLong, uLong, z_off_t);
ZEXTERN uLong ZEXPORT crc32_combine_gen64(z_off_t);
#endif #endif
/* common defaults */ /* common defaults */
@ -228,16 +232,16 @@ extern z_const char * const z_errmsg[10]; /* indexed by 2-zlib_error */
# define zmemzero(dest, len) memset(dest, 0, len) # define zmemzero(dest, len) memset(dest, 0, len)
# endif # endif
#else #else
void ZLIB_INTERNAL zmemcpy OF((Bytef* dest, const Bytef* source, uInt len)); void ZLIB_INTERNAL zmemcpy(Bytef* dest, const Bytef* source, uInt len);
int ZLIB_INTERNAL zmemcmp OF((const Bytef* s1, const Bytef* s2, uInt len)); int ZLIB_INTERNAL zmemcmp(const Bytef* s1, const Bytef* s2, uInt len);
void ZLIB_INTERNAL zmemzero OF((Bytef* dest, uInt len)); void ZLIB_INTERNAL zmemzero(Bytef* dest, uInt len);
#endif #endif
/* Diagnostic functions */ /* Diagnostic functions */
#ifdef ZLIB_DEBUG #ifdef ZLIB_DEBUG
# include <stdio.h> # include <stdio.h>
extern int ZLIB_INTERNAL z_verbose; extern int ZLIB_INTERNAL z_verbose;
extern void ZLIB_INTERNAL z_error OF((char *m)); extern void ZLIB_INTERNAL z_error(char *m);
# define Assert(cond,msg) {if(!(cond)) z_error(msg);} # define Assert(cond,msg) {if(!(cond)) z_error(msg);}
# define Trace(x) {if (z_verbose>=0) fprintf x ;} # define Trace(x) {if (z_verbose>=0) fprintf x ;}
# define Tracev(x) {if (z_verbose>0) fprintf x ;} # define Tracev(x) {if (z_verbose>0) fprintf x ;}
@ -254,9 +258,9 @@ extern z_const char * const z_errmsg[10]; /* indexed by 2-zlib_error */
#endif #endif
#ifndef Z_SOLO #ifndef Z_SOLO
voidpf ZLIB_INTERNAL zcalloc OF((voidpf opaque, unsigned items, voidpf ZLIB_INTERNAL zcalloc(voidpf opaque, unsigned items,
unsigned size)); unsigned size);
void ZLIB_INTERNAL zcfree OF((voidpf opaque, voidpf ptr)); void ZLIB_INTERNAL zcfree(voidpf opaque, voidpf ptr);
#endif #endif
#define ZALLOC(strm, items, size) \ #define ZALLOC(strm, items, size) \