Created
April 16, 2017 23:00
-
-
Save pmqs/d685ea47ad1cf1e3f2dc6fbf6f767b5b to your computer and use it in GitHub Desktop.
infsync.c
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* 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 <stdlib.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 1024 | |
voidpf my_zalloc (voidpf opaque, unsigned items, unsigned size) | |
{ | |
#if 1 | |
return malloc(items * size); | |
#else | |
return calloc(size, items); | |
#endif | |
} | |
void my_zfree (voidpf opaque, voidpf ptr) | |
{ | |
free(ptr); | |
return; | |
} | |
int | |
defl(FILE* dest) | |
{ | |
int ret, flush; | |
unsigned have; | |
z_stream strm; | |
unsigned char in[CHUNK]; | |
unsigned char out[CHUNK]; | |
strm.zalloc = Z_NULL; | |
strm.zfree = Z_NULL; | |
strm.opaque = Z_NULL; | |
ret = deflateInit2(&strm, Z_BEST_COMPRESSION, Z_DEFLATED, MAX_WBITS, MAX_MEM_LEVEL, Z_DEFAULT_STRATEGY ); | |
//fprintf(stderr, "DEF INIT %d\n", ret); | |
assert(ret == Z_OK) ; | |
char * message = "Mary had a little lamb"; | |
int length = strlen(message); | |
int i; | |
int size = 4000; | |
for (i = 1; i <= size; ++i) | |
{ | |
if (i == size/2) | |
flush = Z_FULL_FLUSH; | |
else if (i == size) | |
flush = Z_FINISH ; | |
else | |
flush = Z_NO_FLUSH; | |
//fprintf(stderr, "DEFLATE with flush\n"); | |
/* run deflate() on input until output buffer not full, finish | |
compression if all of source has been read in */ | |
strm.avail_in = length; | |
strm.next_in = message; | |
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 */ | |
//fprintf(stderr, "RET %d\n" , ret); | |
have = CHUNK - strm.avail_out; | |
if (fwrite(out, 1, have, dest) != have || ferror(dest)) { | |
(void)deflateEnd(&strm); | |
return Z_ERRNO; | |
} | |
} while (strm.avail_out == 1); | |
assert(strm.avail_in == 0); /* all input will be used */ | |
} | |
/* 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]; | |
int found = 0; | |
int chunk = 1 ; | |
int one = 1 ; | |
/* allocate inflate state */ | |
#if 0 | |
strm.zalloc = my_zalloc; | |
strm.zfree = my_zfree; | |
#else | |
strm.zalloc = Z_NULL; | |
strm.zfree = Z_NULL; | |
#endif | |
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 first byte */ | |
if (one == 1) | |
{ | |
//fprintf(stderr, "ONE BYTE %d\n", strm.avail_in); | |
//chunk = CHUNK; | |
one = 0; | |
strm.avail_out = CHUNK; | |
strm.next_out = out; | |
ret = inflate(&strm, Z_NO_FLUSH); | |
assert(ret == Z_OK); | |
//goto OUTER; | |
continue; | |
} | |
/* run inflateSync() */ | |
if ( ! found) | |
{ | |
do { | |
strm.avail_out = CHUNK; | |
strm.next_out = out; | |
//fprintf(stderr, "SYNC %p %d\n", strm.next_in, strm.avail_in); | |
ret = inflateSync(&strm); | |
assert(ret != Z_STREAM_ERROR); /* state not clobbered */ | |
if (ret == Z_OK) | |
{ | |
//fprintf(stderr, "SYNC Found %p %d\n", strm.next_in, strm.avail_in); | |
found = 1 ; | |
break; | |
} | |
} while (ret != Z_OK && strm.avail_in != 0); | |
} | |
if (strm.avail_in == 0) | |
continue; | |
/* run inflate() on input until output buffer not full */ | |
do { | |
//fprintf(stderr, "INFLATE\n"); | |
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; | |
} 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 = defl(stdout); | |
//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; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment