example.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602
  1. /* example.c -- usage example of the zlib compression library
  2. * Copyright (C) 1995-2006, 2011, 2016 Jean-loup Gailly
  3. * For conditions of distribution and use, see copyright notice in zlib.h
  4. */
  5. /* @(#) $Id$ */
  6. #include "zlib.h"
  7. #include <stdio.h>
  8. #ifdef STDC
  9. # include <string.h>
  10. # include <stdlib.h>
  11. #endif
  12. #if defined(VMS) || defined(RISCOS)
  13. # define TESTFILE "foo-gz"
  14. #else
  15. # define TESTFILE "foo.gz"
  16. #endif
  17. #define CHECK_ERR(err, msg) { \
  18. if (err != Z_OK) { \
  19. fprintf(stderr, "%s error: %d\n", msg, err); \
  20. exit(1); \
  21. } \
  22. }
  23. static z_const char hello[] = "hello, hello!";
  24. /* "hello world" would be more standard, but the repeated "hello"
  25. * stresses the compression code better, sorry...
  26. */
  27. static const char dictionary[] = "hello";
  28. static uLong dictId; /* Adler32 value of the dictionary */
  29. void test_deflate OF((Byte *compr, uLong comprLen));
  30. void test_inflate OF((Byte *compr, uLong comprLen,
  31. Byte *uncompr, uLong uncomprLen));
  32. void test_large_deflate OF((Byte *compr, uLong comprLen,
  33. Byte *uncompr, uLong uncomprLen));
  34. void test_large_inflate OF((Byte *compr, uLong comprLen,
  35. Byte *uncompr, uLong uncomprLen));
  36. void test_flush OF((Byte *compr, uLong *comprLen));
  37. void test_sync OF((Byte *compr, uLong comprLen,
  38. Byte *uncompr, uLong uncomprLen));
  39. void test_dict_deflate OF((Byte *compr, uLong comprLen));
  40. void test_dict_inflate OF((Byte *compr, uLong comprLen,
  41. Byte *uncompr, uLong uncomprLen));
  42. int main OF((int argc, char *argv[]));
  43. #ifdef Z_SOLO
  44. void *myalloc OF((void *, unsigned, unsigned));
  45. void myfree OF((void *, void *));
  46. void *myalloc(q, n, m)
  47. void *q;
  48. unsigned n, m;
  49. {
  50. (void)q;
  51. return calloc(n, m);
  52. }
  53. void myfree(void *q, void *p)
  54. {
  55. (void)q;
  56. free(p);
  57. }
  58. static alloc_func zalloc = myalloc;
  59. static free_func zfree = myfree;
  60. #else /* !Z_SOLO */
  61. static alloc_func zalloc = (alloc_func)0;
  62. static free_func zfree = (free_func)0;
  63. void test_compress OF((Byte *compr, uLong comprLen,
  64. Byte *uncompr, uLong uncomprLen));
  65. void test_gzio OF((const char *fname,
  66. Byte *uncompr, uLong uncomprLen));
  67. /* ===========================================================================
  68. * Test compress() and uncompress()
  69. */
  70. void test_compress(compr, comprLen, uncompr, uncomprLen)
  71. Byte *compr, *uncompr;
  72. uLong comprLen, uncomprLen;
  73. {
  74. int err;
  75. uLong len = (uLong)strlen(hello)+1;
  76. err = compress(compr, &comprLen, (const Bytef*)hello, len);
  77. CHECK_ERR(err, "compress");
  78. strcpy((char*)uncompr, "garbage");
  79. err = uncompress(uncompr, &uncomprLen, compr, comprLen);
  80. CHECK_ERR(err, "uncompress");
  81. if (strcmp((char*)uncompr, hello)) {
  82. fprintf(stderr, "bad uncompress\n");
  83. exit(1);
  84. } else {
  85. printf("uncompress(): %s\n", (char *)uncompr);
  86. }
  87. }
  88. /* ===========================================================================
  89. * Test read/write of .gz files
  90. */
  91. void test_gzio(fname, uncompr, uncomprLen)
  92. const char *fname; /* compressed file name */
  93. Byte *uncompr;
  94. uLong uncomprLen;
  95. {
  96. #ifdef NO_GZCOMPRESS
  97. fprintf(stderr, "NO_GZCOMPRESS -- gz* functions cannot compress\n");
  98. #else
  99. int err;
  100. int len = (int)strlen(hello)+1;
  101. gzFile file;
  102. z_off_t pos;
  103. file = gzopen(fname, "wb");
  104. if (file == NULL) {
  105. fprintf(stderr, "gzopen error\n");
  106. exit(1);
  107. }
  108. gzputc(file, 'h');
  109. if (gzputs(file, "ello") != 4) {
  110. fprintf(stderr, "gzputs err: %s\n", gzerror(file, &err));
  111. exit(1);
  112. }
  113. if (gzprintf(file, ", %s!", "hello") != 8) {
  114. fprintf(stderr, "gzprintf err: %s\n", gzerror(file, &err));
  115. exit(1);
  116. }
  117. gzseek(file, 1L, SEEK_CUR); /* add one zero byte */
  118. gzclose(file);
  119. file = gzopen(fname, "rb");
  120. if (file == NULL) {
  121. fprintf(stderr, "gzopen error\n");
  122. exit(1);
  123. }
  124. strcpy((char*)uncompr, "garbage");
  125. if (gzread(file, uncompr, (unsigned)uncomprLen) != len) {
  126. fprintf(stderr, "gzread err: %s\n", gzerror(file, &err));
  127. exit(1);
  128. }
  129. if (strcmp((char*)uncompr, hello)) {
  130. fprintf(stderr, "bad gzread: %s\n", (char*)uncompr);
  131. exit(1);
  132. } else {
  133. printf("gzread(): %s\n", (char*)uncompr);
  134. }
  135. pos = gzseek(file, -8L, SEEK_CUR);
  136. if (pos != 6 || gztell(file) != pos) {
  137. fprintf(stderr, "gzseek error, pos=%ld, gztell=%ld\n",
  138. (long)pos, (long)gztell(file));
  139. exit(1);
  140. }
  141. if (gzgetc(file) != ' ') {
  142. fprintf(stderr, "gzgetc error\n");
  143. exit(1);
  144. }
  145. if (gzungetc(' ', file) != ' ') {
  146. fprintf(stderr, "gzungetc error\n");
  147. exit(1);
  148. }
  149. gzgets(file, (char*)uncompr, (int)uncomprLen);
  150. if (strlen((char*)uncompr) != 7) { /* " hello!" */
  151. fprintf(stderr, "gzgets err after gzseek: %s\n", gzerror(file, &err));
  152. exit(1);
  153. }
  154. if (strcmp((char*)uncompr, hello + 6)) {
  155. fprintf(stderr, "bad gzgets after gzseek\n");
  156. exit(1);
  157. } else {
  158. printf("gzgets() after gzseek: %s\n", (char*)uncompr);
  159. }
  160. gzclose(file);
  161. #endif
  162. }
  163. #endif /* Z_SOLO */
  164. /* ===========================================================================
  165. * Test deflate() with small buffers
  166. */
  167. void test_deflate(compr, comprLen)
  168. Byte *compr;
  169. uLong comprLen;
  170. {
  171. z_stream c_stream; /* compression stream */
  172. int err;
  173. uLong len = (uLong)strlen(hello)+1;
  174. c_stream.zalloc = zalloc;
  175. c_stream.zfree = zfree;
  176. c_stream.opaque = (voidpf)0;
  177. err = deflateInit(&c_stream, Z_DEFAULT_COMPRESSION);
  178. CHECK_ERR(err, "deflateInit");
  179. c_stream.next_in = (z_const unsigned char *)hello;
  180. c_stream.next_out = compr;
  181. while (c_stream.total_in != len && c_stream.total_out < comprLen) {
  182. c_stream.avail_in = c_stream.avail_out = 1; /* force small buffers */
  183. err = deflate(&c_stream, Z_NO_FLUSH);
  184. CHECK_ERR(err, "deflate");
  185. }
  186. /* Finish the stream, still forcing small buffers: */
  187. for (;;) {
  188. c_stream.avail_out = 1;
  189. err = deflate(&c_stream, Z_FINISH);
  190. if (err == Z_STREAM_END) break;
  191. CHECK_ERR(err, "deflate");
  192. }
  193. err = deflateEnd(&c_stream);
  194. CHECK_ERR(err, "deflateEnd");
  195. }
  196. /* ===========================================================================
  197. * Test inflate() with small buffers
  198. */
  199. void test_inflate(compr, comprLen, uncompr, uncomprLen)
  200. Byte *compr, *uncompr;
  201. uLong comprLen, uncomprLen;
  202. {
  203. int err;
  204. z_stream d_stream; /* decompression stream */
  205. strcpy((char*)uncompr, "garbage");
  206. d_stream.zalloc = zalloc;
  207. d_stream.zfree = zfree;
  208. d_stream.opaque = (voidpf)0;
  209. d_stream.next_in = compr;
  210. d_stream.avail_in = 0;
  211. d_stream.next_out = uncompr;
  212. err = inflateInit(&d_stream);
  213. CHECK_ERR(err, "inflateInit");
  214. while (d_stream.total_out < uncomprLen && d_stream.total_in < comprLen) {
  215. d_stream.avail_in = d_stream.avail_out = 1; /* force small buffers */
  216. err = inflate(&d_stream, Z_NO_FLUSH);
  217. if (err == Z_STREAM_END) break;
  218. CHECK_ERR(err, "inflate");
  219. }
  220. err = inflateEnd(&d_stream);
  221. CHECK_ERR(err, "inflateEnd");
  222. if (strcmp((char*)uncompr, hello)) {
  223. fprintf(stderr, "bad inflate\n");
  224. exit(1);
  225. } else {
  226. printf("inflate(): %s\n", (char *)uncompr);
  227. }
  228. }
  229. /* ===========================================================================
  230. * Test deflate() with large buffers and dynamic change of compression level
  231. */
  232. void test_large_deflate(compr, comprLen, uncompr, uncomprLen)
  233. Byte *compr, *uncompr;
  234. uLong comprLen, uncomprLen;
  235. {
  236. z_stream c_stream; /* compression stream */
  237. int err;
  238. c_stream.zalloc = zalloc;
  239. c_stream.zfree = zfree;
  240. c_stream.opaque = (voidpf)0;
  241. err = deflateInit(&c_stream, Z_BEST_SPEED);
  242. CHECK_ERR(err, "deflateInit");
  243. c_stream.next_out = compr;
  244. c_stream.avail_out = (uInt)comprLen;
  245. /* At this point, uncompr is still mostly zeroes, so it should compress
  246. * very well:
  247. */
  248. c_stream.next_in = uncompr;
  249. c_stream.avail_in = (uInt)uncomprLen;
  250. err = deflate(&c_stream, Z_NO_FLUSH);
  251. CHECK_ERR(err, "deflate");
  252. if (c_stream.avail_in != 0) {
  253. fprintf(stderr, "deflate not greedy\n");
  254. exit(1);
  255. }
  256. /* Feed in already compressed data and switch to no compression: */
  257. deflateParams(&c_stream, Z_NO_COMPRESSION, Z_DEFAULT_STRATEGY);
  258. c_stream.next_in = compr;
  259. c_stream.avail_in = (uInt)comprLen/2;
  260. err = deflate(&c_stream, Z_NO_FLUSH);
  261. CHECK_ERR(err, "deflate");
  262. /* Switch back to compressing mode: */
  263. deflateParams(&c_stream, Z_BEST_COMPRESSION, Z_FILTERED);
  264. c_stream.next_in = uncompr;
  265. c_stream.avail_in = (uInt)uncomprLen;
  266. err = deflate(&c_stream, Z_NO_FLUSH);
  267. CHECK_ERR(err, "deflate");
  268. err = deflate(&c_stream, Z_FINISH);
  269. if (err != Z_STREAM_END) {
  270. fprintf(stderr, "deflate should report Z_STREAM_END\n");
  271. exit(1);
  272. }
  273. err = deflateEnd(&c_stream);
  274. CHECK_ERR(err, "deflateEnd");
  275. }
  276. /* ===========================================================================
  277. * Test inflate() with large buffers
  278. */
  279. void test_large_inflate(compr, comprLen, uncompr, uncomprLen)
  280. Byte *compr, *uncompr;
  281. uLong comprLen, uncomprLen;
  282. {
  283. int err;
  284. z_stream d_stream; /* decompression stream */
  285. strcpy((char*)uncompr, "garbage");
  286. d_stream.zalloc = zalloc;
  287. d_stream.zfree = zfree;
  288. d_stream.opaque = (voidpf)0;
  289. d_stream.next_in = compr;
  290. d_stream.avail_in = (uInt)comprLen;
  291. err = inflateInit(&d_stream);
  292. CHECK_ERR(err, "inflateInit");
  293. for (;;) {
  294. d_stream.next_out = uncompr; /* discard the output */
  295. d_stream.avail_out = (uInt)uncomprLen;
  296. err = inflate(&d_stream, Z_NO_FLUSH);
  297. if (err == Z_STREAM_END) break;
  298. CHECK_ERR(err, "large inflate");
  299. }
  300. err = inflateEnd(&d_stream);
  301. CHECK_ERR(err, "inflateEnd");
  302. if (d_stream.total_out != 2*uncomprLen + comprLen/2) {
  303. fprintf(stderr, "bad large inflate: %ld\n", d_stream.total_out);
  304. exit(1);
  305. } else {
  306. printf("large_inflate(): OK\n");
  307. }
  308. }
  309. /* ===========================================================================
  310. * Test deflate() with full flush
  311. */
  312. void test_flush(compr, comprLen)
  313. Byte *compr;
  314. uLong *comprLen;
  315. {
  316. z_stream c_stream; /* compression stream */
  317. int err;
  318. uInt len = (uInt)strlen(hello)+1;
  319. c_stream.zalloc = zalloc;
  320. c_stream.zfree = zfree;
  321. c_stream.opaque = (voidpf)0;
  322. err = deflateInit(&c_stream, Z_DEFAULT_COMPRESSION);
  323. CHECK_ERR(err, "deflateInit");
  324. c_stream.next_in = (z_const unsigned char *)hello;
  325. c_stream.next_out = compr;
  326. c_stream.avail_in = 3;
  327. c_stream.avail_out = (uInt)*comprLen;
  328. err = deflate(&c_stream, Z_FULL_FLUSH);
  329. CHECK_ERR(err, "deflate");
  330. compr[3]++; /* force an error in first compressed block */
  331. c_stream.avail_in = len - 3;
  332. err = deflate(&c_stream, Z_FINISH);
  333. if (err != Z_STREAM_END) {
  334. CHECK_ERR(err, "deflate");
  335. }
  336. err = deflateEnd(&c_stream);
  337. CHECK_ERR(err, "deflateEnd");
  338. *comprLen = c_stream.total_out;
  339. }
  340. /* ===========================================================================
  341. * Test inflateSync()
  342. */
  343. void test_sync(compr, comprLen, uncompr, uncomprLen)
  344. Byte *compr, *uncompr;
  345. uLong comprLen, uncomprLen;
  346. {
  347. int err;
  348. z_stream d_stream; /* decompression stream */
  349. strcpy((char*)uncompr, "garbage");
  350. d_stream.zalloc = zalloc;
  351. d_stream.zfree = zfree;
  352. d_stream.opaque = (voidpf)0;
  353. d_stream.next_in = compr;
  354. d_stream.avail_in = 2; /* just read the zlib header */
  355. err = inflateInit(&d_stream);
  356. CHECK_ERR(err, "inflateInit");
  357. d_stream.next_out = uncompr;
  358. d_stream.avail_out = (uInt)uncomprLen;
  359. err = inflate(&d_stream, Z_NO_FLUSH);
  360. CHECK_ERR(err, "inflate");
  361. d_stream.avail_in = (uInt)comprLen-2; /* read all compressed data */
  362. err = inflateSync(&d_stream); /* but skip the damaged part */
  363. CHECK_ERR(err, "inflateSync");
  364. err = inflate(&d_stream, Z_FINISH);
  365. if (err != Z_DATA_ERROR) {
  366. fprintf(stderr, "inflate should report DATA_ERROR\n");
  367. /* Because of incorrect adler32 */
  368. exit(1);
  369. }
  370. err = inflateEnd(&d_stream);
  371. CHECK_ERR(err, "inflateEnd");
  372. printf("after inflateSync(): hel%s\n", (char *)uncompr);
  373. }
  374. /* ===========================================================================
  375. * Test deflate() with preset dictionary
  376. */
  377. void test_dict_deflate(compr, comprLen)
  378. Byte *compr;
  379. uLong comprLen;
  380. {
  381. z_stream c_stream; /* compression stream */
  382. int err;
  383. c_stream.zalloc = zalloc;
  384. c_stream.zfree = zfree;
  385. c_stream.opaque = (voidpf)0;
  386. err = deflateInit(&c_stream, Z_BEST_COMPRESSION);
  387. CHECK_ERR(err, "deflateInit");
  388. err = deflateSetDictionary(&c_stream,
  389. (const Bytef*)dictionary, (int)sizeof(dictionary));
  390. CHECK_ERR(err, "deflateSetDictionary");
  391. dictId = c_stream.adler;
  392. c_stream.next_out = compr;
  393. c_stream.avail_out = (uInt)comprLen;
  394. c_stream.next_in = (z_const unsigned char *)hello;
  395. c_stream.avail_in = (uInt)strlen(hello)+1;
  396. err = deflate(&c_stream, Z_FINISH);
  397. if (err != Z_STREAM_END) {
  398. fprintf(stderr, "deflate should report Z_STREAM_END\n");
  399. exit(1);
  400. }
  401. err = deflateEnd(&c_stream);
  402. CHECK_ERR(err, "deflateEnd");
  403. }
  404. /* ===========================================================================
  405. * Test inflate() with a preset dictionary
  406. */
  407. void test_dict_inflate(compr, comprLen, uncompr, uncomprLen)
  408. Byte *compr, *uncompr;
  409. uLong comprLen, uncomprLen;
  410. {
  411. int err;
  412. z_stream d_stream; /* decompression stream */
  413. strcpy((char*)uncompr, "garbage");
  414. d_stream.zalloc = zalloc;
  415. d_stream.zfree = zfree;
  416. d_stream.opaque = (voidpf)0;
  417. d_stream.next_in = compr;
  418. d_stream.avail_in = (uInt)comprLen;
  419. err = inflateInit(&d_stream);
  420. CHECK_ERR(err, "inflateInit");
  421. d_stream.next_out = uncompr;
  422. d_stream.avail_out = (uInt)uncomprLen;
  423. for (;;) {
  424. err = inflate(&d_stream, Z_NO_FLUSH);
  425. if (err == Z_STREAM_END) break;
  426. if (err == Z_NEED_DICT) {
  427. if (d_stream.adler != dictId) {
  428. fprintf(stderr, "unexpected dictionary");
  429. exit(1);
  430. }
  431. err = inflateSetDictionary(&d_stream, (const Bytef*)dictionary,
  432. (int)sizeof(dictionary));
  433. }
  434. CHECK_ERR(err, "inflate with dict");
  435. }
  436. err = inflateEnd(&d_stream);
  437. CHECK_ERR(err, "inflateEnd");
  438. if (strcmp((char*)uncompr, hello)) {
  439. fprintf(stderr, "bad inflate with dict\n");
  440. exit(1);
  441. } else {
  442. printf("inflate with dictionary: %s\n", (char *)uncompr);
  443. }
  444. }
  445. /* ===========================================================================
  446. * Usage: example [output.gz [input.gz]]
  447. */
  448. int main(argc, argv)
  449. int argc;
  450. char *argv[];
  451. {
  452. Byte *compr, *uncompr;
  453. uLong comprLen = 10000*sizeof(int); /* don't overflow on MSDOS */
  454. uLong uncomprLen = comprLen;
  455. static const char* myVersion = ZLIB_VERSION;
  456. if (zlibVersion()[0] != myVersion[0]) {
  457. fprintf(stderr, "incompatible zlib version\n");
  458. exit(1);
  459. } else if (strcmp(zlibVersion(), ZLIB_VERSION) != 0) {
  460. fprintf(stderr, "warning: different zlib version\n");
  461. }
  462. printf("zlib version %s = 0x%04x, compile flags = 0x%lx\n",
  463. ZLIB_VERSION, ZLIB_VERNUM, zlibCompileFlags());
  464. compr = (Byte*)calloc((uInt)comprLen, 1);
  465. uncompr = (Byte*)calloc((uInt)uncomprLen, 1);
  466. /* compr and uncompr are cleared to avoid reading uninitialized
  467. * data and to ensure that uncompr compresses well.
  468. */
  469. if (compr == Z_NULL || uncompr == Z_NULL) {
  470. printf("out of memory\n");
  471. exit(1);
  472. }
  473. #ifdef Z_SOLO
  474. (void)argc;
  475. (void)argv;
  476. #else
  477. test_compress(compr, comprLen, uncompr, uncomprLen);
  478. test_gzio((argc > 1 ? argv[1] : TESTFILE),
  479. uncompr, uncomprLen);
  480. #endif
  481. test_deflate(compr, comprLen);
  482. test_inflate(compr, comprLen, uncompr, uncomprLen);
  483. test_large_deflate(compr, comprLen, uncompr, uncomprLen);
  484. test_large_inflate(compr, comprLen, uncompr, uncomprLen);
  485. test_flush(compr, &comprLen);
  486. test_sync(compr, comprLen, uncompr, uncomprLen);
  487. comprLen = uncomprLen;
  488. test_dict_deflate(compr, comprLen);
  489. test_dict_inflate(compr, comprLen, uncompr, uncomprLen);
  490. free(compr);
  491. free(uncompr);
  492. return 0;
  493. }