19e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project/* zpipe.c: example of proper use of zlib's inflate() and deflate() 29e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project Not copyrighted -- provided to the public domain 3381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes Version 1.4 11 December 2005 Mark Adler */ 49e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project 59e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project/* Version history: 69e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project 1.0 30 Oct 2004 First version 79e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project 1.1 8 Nov 2004 Add void casting for unused return values 89e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project Use switch statement for inflate() return values 99e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project 1.2 9 Nov 2004 Add assertions to document zlib guarantees 109e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project 1.3 6 Apr 2005 Remove incorrect assertion in inf() 11381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes 1.4 11 Dec 2005 Add hack to avoid MSDOS end-of-line conversions 12381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes Avoid some compiler warnings for input and output buffers 139e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project */ 149e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project 159e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project#include <stdio.h> 169e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project#include <string.h> 179e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project#include <assert.h> 189e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project#include "zlib.h" 199e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project 20381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes#if defined(MSDOS) || defined(OS2) || defined(WIN32) || defined(__CYGWIN__) 21381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes# include <fcntl.h> 22381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes# include <io.h> 23381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes# define SET_BINARY_MODE(file) setmode(fileno(file), O_BINARY) 24381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes#else 25381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes# define SET_BINARY_MODE(file) 26381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes#endif 27381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes 289e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project#define CHUNK 16384 299e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project 309e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project/* Compress from file source to file dest until EOF on source. 319e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project def() returns Z_OK on success, Z_MEM_ERROR if memory could not be 329e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project allocated for processing, Z_STREAM_ERROR if an invalid compression 339e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project level is supplied, Z_VERSION_ERROR if the version of zlib.h and the 349e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project version of the library linked do not match, or Z_ERRNO if there is 359e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project an error reading or writing the files. */ 369e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Projectint def(FILE *source, FILE *dest, int level) 379e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project{ 389e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project int ret, flush; 399e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project unsigned have; 409e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project z_stream strm; 41381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes unsigned char in[CHUNK]; 42381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes unsigned char out[CHUNK]; 439e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project 449e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project /* allocate deflate state */ 459e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project strm.zalloc = Z_NULL; 469e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project strm.zfree = Z_NULL; 479e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project strm.opaque = Z_NULL; 489e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project ret = deflateInit(&strm, level); 499e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project if (ret != Z_OK) 509e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project return ret; 519e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project 529e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project /* compress until end of file */ 539e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project do { 549e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project strm.avail_in = fread(in, 1, CHUNK, source); 559e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project if (ferror(source)) { 569e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project (void)deflateEnd(&strm); 579e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project return Z_ERRNO; 589e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project } 599e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project flush = feof(source) ? Z_FINISH : Z_NO_FLUSH; 609e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project strm.next_in = in; 619e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project 629e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project /* run deflate() on input until output buffer not full, finish 639e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project compression if all of source has been read in */ 649e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project do { 659e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project strm.avail_out = CHUNK; 669e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project strm.next_out = out; 679e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project ret = deflate(&strm, flush); /* no bad return value */ 689e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project assert(ret != Z_STREAM_ERROR); /* state not clobbered */ 699e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project have = CHUNK - strm.avail_out; 709e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project if (fwrite(out, 1, have, dest) != have || ferror(dest)) { 719e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project (void)deflateEnd(&strm); 729e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project return Z_ERRNO; 739e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project } 749e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project } while (strm.avail_out == 0); 759e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project assert(strm.avail_in == 0); /* all input will be used */ 769e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project 779e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project /* done when last data in file processed */ 789e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project } while (flush != Z_FINISH); 799e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project assert(ret == Z_STREAM_END); /* stream will be complete */ 809e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project 819e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project /* clean up and return */ 829e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project (void)deflateEnd(&strm); 839e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project return Z_OK; 849e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project} 859e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project 869e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project/* Decompress from file source to file dest until stream ends or EOF. 879e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project inf() returns Z_OK on success, Z_MEM_ERROR if memory could not be 889e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project allocated for processing, Z_DATA_ERROR if the deflate data is 899e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project invalid or incomplete, Z_VERSION_ERROR if the version of zlib.h and 909e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project the version of the library linked do not match, or Z_ERRNO if there 919e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project is an error reading or writing the files. */ 929e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Projectint inf(FILE *source, FILE *dest) 939e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project{ 949e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project int ret; 959e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project unsigned have; 969e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project z_stream strm; 97381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes unsigned char in[CHUNK]; 98381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes unsigned char out[CHUNK]; 999e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project 1009e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project /* allocate inflate state */ 1019e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project strm.zalloc = Z_NULL; 1029e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project strm.zfree = Z_NULL; 1039e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project strm.opaque = Z_NULL; 1049e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project strm.avail_in = 0; 1059e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project strm.next_in = Z_NULL; 1069e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project ret = inflateInit(&strm); 1079e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project if (ret != Z_OK) 1089e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project return ret; 1099e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project 1109e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project /* decompress until deflate stream ends or end of file */ 1119e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project do { 1129e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project strm.avail_in = fread(in, 1, CHUNK, source); 1139e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project if (ferror(source)) { 1149e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project (void)inflateEnd(&strm); 1159e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project return Z_ERRNO; 1169e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project } 1179e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project if (strm.avail_in == 0) 1189e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project break; 1199e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project strm.next_in = in; 1209e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project 1219e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project /* run inflate() on input until output buffer not full */ 1229e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project do { 1239e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project strm.avail_out = CHUNK; 1249e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project strm.next_out = out; 1259e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project ret = inflate(&strm, Z_NO_FLUSH); 1269e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project assert(ret != Z_STREAM_ERROR); /* state not clobbered */ 1279e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project switch (ret) { 1289e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project case Z_NEED_DICT: 1299e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project ret = Z_DATA_ERROR; /* and fall through */ 1309e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project case Z_DATA_ERROR: 1319e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project case Z_MEM_ERROR: 1329e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project (void)inflateEnd(&strm); 1339e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project return ret; 1349e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project } 1359e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project have = CHUNK - strm.avail_out; 1369e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project if (fwrite(out, 1, have, dest) != have || ferror(dest)) { 1379e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project (void)inflateEnd(&strm); 1389e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project return Z_ERRNO; 1399e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project } 1409e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project } while (strm.avail_out == 0); 1419e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project 1429e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project /* done when inflate() says it's done */ 1439e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project } while (ret != Z_STREAM_END); 1449e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project 1459e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project /* clean up and return */ 1469e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project (void)inflateEnd(&strm); 1479e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project return ret == Z_STREAM_END ? Z_OK : Z_DATA_ERROR; 1489e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project} 1499e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project 1509e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project/* report a zlib or i/o error */ 1519e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Projectvoid zerr(int ret) 1529e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project{ 1539e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project fputs("zpipe: ", stderr); 1549e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project switch (ret) { 1559e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project case Z_ERRNO: 1569e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project if (ferror(stdin)) 1579e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project fputs("error reading stdin\n", stderr); 1589e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project if (ferror(stdout)) 1599e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project fputs("error writing stdout\n", stderr); 1609e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project break; 1619e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project case Z_STREAM_ERROR: 1629e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project fputs("invalid compression level\n", stderr); 1639e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project break; 1649e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project case Z_DATA_ERROR: 1659e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project fputs("invalid or incomplete deflate data\n", stderr); 1669e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project break; 1679e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project case Z_MEM_ERROR: 1689e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project fputs("out of memory\n", stderr); 1699e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project break; 1709e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project case Z_VERSION_ERROR: 1719e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project fputs("zlib version mismatch!\n", stderr); 1729e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project } 1739e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project} 1749e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project 1759e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project/* compress or decompress from stdin to stdout */ 1769e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Projectint main(int argc, char **argv) 1779e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project{ 1789e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project int ret; 1799e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project 180381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes /* avoid end-of-line conversions */ 181381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes SET_BINARY_MODE(stdin); 182381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes SET_BINARY_MODE(stdout); 183381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes 1849e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project /* do compression if no arguments */ 1859e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project if (argc == 1) { 1869e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project ret = def(stdin, stdout, Z_DEFAULT_COMPRESSION); 1879e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project if (ret != Z_OK) 1889e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project zerr(ret); 1899e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project return ret; 1909e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project } 1919e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project 1929e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project /* do decompression if -d specified */ 1939e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project else if (argc == 2 && strcmp(argv[1], "-d") == 0) { 1949e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project ret = inf(stdin, stdout); 1959e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project if (ret != Z_OK) 1969e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project zerr(ret); 1979e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project return ret; 1989e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project } 1999e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project 2009e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project /* otherwise, report usage */ 2019e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project else { 2029e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project fputs("zpipe usage: zpipe [-d] < source > dest\n", stderr); 2039e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project return 1; 2049e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project } 2059e38dfa2f95fce609707a0941f10af9a785288deThe Android Open Source Project} 206