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
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
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync */
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync#include <stdio.h>
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync#include <string.h>
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync#include <assert.h>
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync#include "zlib.h"
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync
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#else
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync# define SET_BINARY_MODE(file)
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync#endif
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync#define CHUNK 16384
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync
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)
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync{
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync int ret, flush;
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync unsigned have;
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync z_stream strm;
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync unsigned char in[CHUNK];
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync unsigned char out[CHUNK];
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync /* allocate deflate state */
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync strm.zalloc = Z_NULL;
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync strm.zfree = Z_NULL;
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync strm.opaque = Z_NULL;
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync ret = deflateInit(&strm, level);
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync if (ret != Z_OK)
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync return ret;
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync /* compress until end of file */
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync do {
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync strm.avail_in = fread(in, 1, CHUNK, source);
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync if (ferror(source)) {
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync (void)deflateEnd(&strm);
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync return Z_ERRNO;
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync }
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync flush = feof(source) ? Z_FINISH : Z_NO_FLUSH;
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync strm.next_in = in;
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync /* run deflate() on input until output buffer not full, finish
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync compression if all of source has been read in */
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync do {
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync strm.avail_out = CHUNK;
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync strm.next_out = out;
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync ret = deflate(&strm, flush); /* no bad return value */
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync assert(ret != Z_STREAM_ERROR); /* state not clobbered */
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync have = CHUNK - strm.avail_out;
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync if (fwrite(out, 1, have, dest) != have || ferror(dest)) {
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync (void)deflateEnd(&strm);
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync return Z_ERRNO;
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync }
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync } while (strm.avail_out == 0);
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync assert(strm.avail_in == 0); /* all input will be used */
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync /* done when last data in file processed */
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync } while (flush != Z_FINISH);
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync assert(ret == Z_STREAM_END); /* stream will be complete */
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync /* clean up and return */
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync (void)deflateEnd(&strm);
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync return Z_OK;
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync}
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync
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)
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync{
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync int ret;
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync unsigned have;
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync z_stream strm;
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync unsigned char in[CHUNK];
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync unsigned char out[CHUNK];
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync /* allocate inflate state */
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync strm.zalloc = Z_NULL;
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync strm.zfree = Z_NULL;
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync strm.opaque = Z_NULL;
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync strm.avail_in = 0;
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync strm.next_in = Z_NULL;
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync ret = inflateInit(&strm);
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync if (ret != Z_OK)
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync return ret;
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync /* decompress until deflate stream ends or end of file */
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync do {
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync strm.avail_in = fread(in, 1, CHUNK, source);
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync if (ferror(source)) {
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync (void)inflateEnd(&strm);
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync return Z_ERRNO;
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync }
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync if (strm.avail_in == 0)
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync break;
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync strm.next_in = in;
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync /* run inflate() on input until output buffer not full */
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync do {
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync strm.avail_out = CHUNK;
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync strm.next_out = out;
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;
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync }
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync have = CHUNK - strm.avail_out;
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync if (fwrite(out, 1, have, dest) != have || ferror(dest)) {
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync (void)inflateEnd(&strm);
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync return Z_ERRNO;
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync }
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync } while (strm.avail_out == 0);
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync /* done when inflate() says it's done */
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync } while (ret != Z_STREAM_END);
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync /* clean up and return */
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync (void)inflateEnd(&strm);
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync return ret == Z_STREAM_END ? Z_OK : Z_DATA_ERROR;
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync}
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync/* report a zlib or i/o error */
1b33c96954667ba382fa595baf7b31290bfdd517vboxsyncvoid zerr(int ret)
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync{
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 break;
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync case Z_STREAM_ERROR:
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync fputs("invalid compression level\n", stderr);
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync break;
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync case Z_DATA_ERROR:
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync fputs("invalid or incomplete deflate data\n", stderr);
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync break;
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync case Z_MEM_ERROR:
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync fputs("out of memory\n", stderr);
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync break;
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync case Z_VERSION_ERROR:
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync fputs("zlib version mismatch!\n", stderr);
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync }
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync}
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync/* compress or decompress from stdin to stdout */
1b33c96954667ba382fa595baf7b31290bfdd517vboxsyncint main(int argc, char **argv)
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync{
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync int ret;
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync /* avoid end-of-line conversions */
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync SET_BINARY_MODE(stdin);
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync SET_BINARY_MODE(stdout);
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync /* do compression if no arguments */
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync if (argc == 1) {
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync ret = def(stdin, stdout, Z_DEFAULT_COMPRESSION);
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync if (ret != Z_OK)
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync zerr(ret);
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync return ret;
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync }
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync
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 zerr(ret);
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync return ret;
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync }
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync /* otherwise, report usage */
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync else {
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync fputs("zpipe usage: zpipe [-d] < source > dest\n", stderr);
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync return 1;
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync }
1b33c96954667ba382fa595baf7b31290bfdd517vboxsync}