/*zpipe.c: example of proper use of zlib's inflate() and deflate()
Not copyrighted -- provided to the public domain
Version 1.2 9 November 2004 Mark Adler*/
/*Version history:
1.0 30 Oct 2004 First version
1.1 8 Nov 2004 Add void casting for unused return values
Use switch statement for inflate() return values
1.2 9 Nov 2004 Add assertions to document zlib guarantees
1.3 6 Apr 2005 Remove incorrect assertion in inf()*/#include#include#include#include"zlib.h"
#define CHUNK 16384
/*Compress from file source to file dest until EOF on source.
def() returns Z_OK on success, Z_MEM_ERROR if memory could not be
allocated for processing, Z_STREAM_ERROR if an invalid compression
level is supplied, Z_VERSION_ERROR if the version of zlib.h and the
version of the library linked do not match, or Z_ERRNO if there is
an error reading or writing the files.*/
int def(FILE *source, FILE *dest, intlevel)
{intret, flush;
unsigned have;
z_stream strm;char in[CHUNK];char out[CHUNK];/*allocate deflate state*/strm.zalloc=Z_NULL;
strm.zfree=Z_NULL;
strm.opaque=Z_NULL;
ret= deflateInit(&strm, level);if (ret !=Z_OK)returnret;/*compress until end of file*/
do{
strm.avail_in= fread(in, 1, CHUNK, source);if(ferror(source)) {
(void)deflateEnd(&strm);returnZ_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);returnZ_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);returnZ_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)
{intret;
unsigned have;
z_stream strm;char in[CHUNK];char out[CHUNK];/*allocate inflate state*/strm.zalloc=Z_NULL;
strm.zfree=Z_NULL;
strm.opaque=Z_NULL;
strm.avail_in= 0;
strm.next_in=Z_NULL;
ret= inflateInit(&strm);if (ret !=Z_OK)returnret;/*decompress until deflate stream ends or end of file*/
do{
strm.avail_in= fread(in, 1, CHUNK, source);if(ferror(source)) {
(void)inflateEnd(&strm);returnZ_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) {caseZ_NEED_DICT:
ret= Z_DATA_ERROR; /*and fall through*/
caseZ_DATA_ERROR:caseZ_MEM_ERROR:
(void)inflateEnd(&strm);returnret;
}
have= CHUNK -strm.avail_out;if (fwrite(out, 1, have, dest) != have ||ferror(dest)) {
(void)inflateEnd(&strm);returnZ_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(intret)
{
fputs("zpipe:", stderr);switch(ret) {caseZ_ERRNO:if(ferror(stdin))
fputs("error reading stdin\n", stderr);if(ferror(stdout))
fputs("error writing stdout\n", stderr);break;caseZ_STREAM_ERROR:
fputs("invalid compression level\n", stderr);break;caseZ_DATA_ERROR:
fputs("invalid or incomplete deflate data\n", stderr);break;caseZ_MEM_ERROR:
fputs("out of memory\n", stderr);break;caseZ_VERSION_ERROR:
fputs("zlib version mismatch!\n", stderr);
}
}/*compress or decompress from stdin to stdout*/
int main(int argc, char **argv)
{intret;
FILE*filein, *fileout;if((filein = fopen(argv[1], "rb")) ==NULL)
{
printf("Can\'t open %s!\n", argv[1]);return -1;
}if((fileout = fopen(argv[2], "wb")) ==NULL)
{
printf("Can\'t open %s!\n", argv[1]);return -1;
}/*do compression if no arguments*/
if (argc == 3) {
ret=def(filein, fileout, Z_DEFAULT_COMPRESSION);if (ret !=Z_OK)
zerr(ret);returnret;
}/*do decompression if -d specified*/
else if (argc == 4 && strcmp(argv[3], "-d") == 0) {
ret=inf(filein, fileout);if (ret !=Z_OK)
zerr(ret);returnret;
}/*otherwise, report usage*/
else{
fputs("zpipe usage: zpipe (source) (dest) [-d] \n", stderr);return 1;
}
}