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