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
6 #include "zbuild.h"
7 #ifdef ZLIB_COMPAT
8 # include "zlib.h"
9 #else
10 # include "zlib-ng.h"
11 #endif
12 #include "deflate.h"
13
14 #include <stdio.h>
15
16 #include <string.h>
17 #include <stdlib.h>
18 #include <inttypes.h>
19 #include <stdint.h>
20
21 #define TESTFILE "foo.gz"
22
23 #define CHECK_ERR(err, msg) { \
24 if (err != Z_OK) { \
25 fprintf(stderr, "%s error: %d\n", msg, err); \
26 exit(1); \
27 } \
28 }
29
30 static const char hello[] = "hello, hello!";
31 /* "hello world" would be more standard, but the repeated "hello"
32 * stresses the compression code better, sorry...
33 */
34
35 static const char dictionary[] = "hello";
36 static unsigned long dictId = 0; /* Adler32 value of the dictionary */
37
38
39 void test_compress (unsigned char *compr, z_size_t comprLen,unsigned char *uncompr, z_size_t uncomprLen);
40 void test_gzio (const char *fname, unsigned char *uncompr, z_size_t uncomprLen);
41 void test_deflate (unsigned char *compr, size_t comprLen);
42 void test_inflate (unsigned char *compr, size_t comprLen, unsigned char *uncompr, size_t uncomprLen);
43 void test_large_deflate (unsigned char *compr, size_t comprLen, unsigned char *uncompr, size_t uncomprLen, int zng_params);
44 void test_large_inflate (unsigned char *compr, size_t comprLen, unsigned char *uncompr, size_t uncomprLen);
45 void test_flush (unsigned char *compr, z_size_t *comprLen);
46 void test_sync (unsigned char *compr, size_t comprLen, unsigned char *uncompr, size_t uncomprLen);
47 void test_dict_deflate (unsigned char *compr, size_t comprLen);
48 void test_dict_inflate (unsigned char *compr, size_t comprLen, unsigned char *uncompr, size_t uncomprLen);
49 int main (int argc, char *argv[]);
50
51
52 static alloc_func zalloc = NULL;
53 static free_func zfree = NULL;
54
55 /* ===========================================================================
56 * Test compress() and uncompress()
57 */
test_compress(unsigned char * compr,z_size_t comprLen,unsigned char * uncompr,z_size_t uncomprLen)58 void test_compress(unsigned char *compr, z_size_t comprLen, unsigned char *uncompr, z_size_t uncomprLen) {
59 int err;
60 size_t len = strlen(hello)+1;
61
62 err = PREFIX(compress)(compr, &comprLen, (const unsigned char*)hello, (z_size_t)len);
63 CHECK_ERR(err, "compress");
64
65 strcpy((char*)uncompr, "garbage");
66
67 err = PREFIX(uncompress)(uncompr, &uncomprLen, compr, comprLen);
68 CHECK_ERR(err, "uncompress");
69
70 if (strcmp((char*)uncompr, hello)) {
71 fprintf(stderr, "bad uncompress\n");
72 exit(1);
73 } else {
74 printf("uncompress(): %s\n", (char *)uncompr);
75 }
76 }
77
78 /* ===========================================================================
79 * Test read/write of .gz files
80 */
test_gzio(const char * fname,unsigned char * uncompr,z_size_t uncomprLen)81 void test_gzio(const char *fname, unsigned char *uncompr, z_size_t uncomprLen) {
82 #ifdef NO_GZCOMPRESS
83 fprintf(stderr, "NO_GZCOMPRESS -- gz* functions cannot compress\n");
84 #else
85 int err;
86 size_t read;
87 size_t len = strlen(hello)+1;
88 gzFile file;
89 z_off64_t pos;
90 z_off64_t comprLen;
91
92 /* Write gz file with test data */
93 file = PREFIX(gzopen)(fname, "wb");
94 if (file == NULL) {
95 fprintf(stderr, "gzopen error\n");
96 exit(1);
97 }
98 /* Write hello, hello! using gzputs and gzprintf */
99 PREFIX(gzputc)(file, 'h');
100 if (PREFIX(gzputs)(file, "ello") != 4) {
101 fprintf(stderr, "gzputs err: %s\n", PREFIX(gzerror)(file, &err));
102 exit(1);
103 }
104 if (PREFIX(gzprintf)(file, ", %s!", "hello") != 8) {
105 fprintf(stderr, "gzprintf err: %s\n", PREFIX(gzerror)(file, &err));
106 exit(1);
107 }
108 /* Write string null-teriminator using gzseek */
109 if (PREFIX(gzseek)(file, 1L, SEEK_CUR) < 0)
110 {
111 fprintf(stderr, "gzseek error, gztell=%ld\n", (long)PREFIX(gztell)(file));
112 exit(1);
113 }
114 /* Write hello, hello! using gzfwrite using best compression level */
115 if (PREFIX(gzsetparams)(file, Z_BEST_COMPRESSION, Z_DEFAULT_STRATEGY) != Z_OK) {
116 fprintf(stderr, "gzsetparams err: %s\n", PREFIX(gzerror)(file, &err));
117 exit(1);
118 }
119 if (PREFIX(gzfwrite)(hello, len, 1, file) == 0) {
120 fprintf(stderr, "gzfwrite err: %s\n", PREFIX(gzerror)(file, &err));
121 exit(1);
122 }
123 /* Flush compressed bytes to file */
124 if (PREFIX(gzflush)(file, Z_SYNC_FLUSH) != Z_OK) {
125 fprintf(stderr, "gzflush err: %s\n", PREFIX(gzerror)(file, &err));
126 exit(1);
127 }
128 comprLen = PREFIX(gzoffset)(file);
129 if (comprLen <= 0) {
130 fprintf(stderr, "gzoffset err: %s\n", PREFIX(gzerror)(file, &err));
131 exit(1);
132 }
133 PREFIX(gzclose)(file);
134
135 /* Open gz file we previously wrote */
136 file = PREFIX(gzopen)(fname, "rb");
137 if (file == NULL) {
138 fprintf(stderr, "gzopen error\n");
139 exit(1);
140 }
141 /* Read uncompressed data - hello, hello! string twice */
142 strcpy((char*)uncompr, "garbages");
143 if (PREFIX(gzread)(file, uncompr, (unsigned)uncomprLen) != (int)(len + len)) {
144 fprintf(stderr, "gzread err: %s\n", PREFIX(gzerror)(file, &err));
145 exit(1);
146 }
147 if (strcmp((char*)uncompr, hello)) {
148 fprintf(stderr, "bad gzread: %s\n", (char*)uncompr);
149 exit(1);
150 } else {
151 printf("gzread(): %s\n", (char*)uncompr);
152 }
153 /* Check position at the end of the gz file */
154 if (PREFIX(gzeof)(file) != 1) {
155 fprintf(stderr, "gzeof err: not reporting end of stream\n");
156 exit(1);
157 }
158 /* Seek backwards mid-string and check char reading with gzgetc and gzungetc */
159 pos = PREFIX(gzseek)(file, -22L, SEEK_CUR);
160 if (pos != 6 || PREFIX(gztell)(file) != pos) {
161 fprintf(stderr, "gzseek error, pos=%ld, gztell=%ld\n",
162 (long)pos, (long)PREFIX(gztell)(file));
163 exit(1);
164 }
165 if (PREFIX(gzgetc)(file) != ' ') {
166 fprintf(stderr, "gzgetc error\n");
167 exit(1);
168 }
169 if (PREFIX(gzungetc)(' ', file) != ' ') {
170 fprintf(stderr, "gzungetc error\n");
171 exit(1);
172 }
173 /* Read first hello, hello! string with gzgets */
174 strcpy((char*)uncompr, "garbages");
175 PREFIX(gzgets)(file, (char*)uncompr, (int)uncomprLen);
176 if (strlen((char*)uncompr) != 7) { /* " hello!" */
177 fprintf(stderr, "gzgets err after gzseek: %s\n", PREFIX(gzerror)(file, &err));
178 exit(1);
179 }
180 if (strcmp((char*)uncompr, hello + 6)) {
181 fprintf(stderr, "bad gzgets after gzseek\n");
182 exit(1);
183 } else {
184 printf("gzgets() after gzseek: %s\n", (char*)uncompr);
185 }
186 /* Seek to second hello, hello! string */
187 pos = PREFIX(gzseek)(file, 14L, SEEK_SET);
188 if (pos != 14 || PREFIX(gztell)(file) != pos) {
189 fprintf(stderr, "gzseek error, pos=%ld, gztell=%ld\n",
190 (long)pos, (long)PREFIX(gztell)(file));
191 exit(1);
192 }
193 /* Check position not at end of file */
194 if (PREFIX(gzeof)(file) != 0) {
195 fprintf(stderr, "gzeof err: reporting end of stream\n");
196 exit(1);
197 }
198 /* Read first hello, hello! string with gzfread */
199 strcpy((char*)uncompr, "garbages");
200 read = PREFIX(gzfread)(uncompr, uncomprLen, 1, file);
201 if (strcmp((const char *)uncompr, hello) != 0) {
202 fprintf(stderr, "bad gzgets\n");
203 exit(1);
204 } else {
205 printf("gzgets(): %s\n", (char*)uncompr);
206 }
207 pos = PREFIX(gzoffset)(file);
208 if (pos < 0 || pos != (comprLen + 10)) {
209 fprintf(stderr, "gzoffset err: wrong offset at end\n");
210 exit(1);
211 }
212 /* Trigger an error and clear it with gzclearerr */
213 PREFIX(gzfread)(uncompr, (size_t)-1, (size_t)-1, file);
214 PREFIX(gzerror)(file, &err);
215 if (err == 0) {
216 fprintf(stderr, "gzerror err: no error returned\n");
217 exit(1);
218 }
219 PREFIX(gzclearerr)(file);
220 PREFIX(gzerror)(file, &err);
221 if (err != 0) {
222 fprintf(stderr, "gzclearerr err: not zero %d\n", err);
223 exit(1);
224 }
225
226 PREFIX(gzclose)(file);
227
228 if (PREFIX(gzclose)(NULL) != Z_STREAM_ERROR) {
229 fprintf(stderr, "gzclose unexpected return when handle null\n");
230 exit(1);
231 }
232 (void)read;
233 #endif
234 }
235
236 /* ===========================================================================
237 * Test deflate() with small buffers
238 */
test_deflate(unsigned char * compr,size_t comprLen)239 void test_deflate(unsigned char *compr, size_t comprLen) {
240 PREFIX3(stream) c_stream; /* compression stream */
241 int err;
242 size_t len = strlen(hello)+1;
243
244 c_stream.zalloc = zalloc;
245 c_stream.zfree = zfree;
246 c_stream.opaque = (void *)0;
247 c_stream.total_in = 0;
248 c_stream.total_out = 0;
249
250 err = PREFIX(deflateInit)(&c_stream, Z_DEFAULT_COMPRESSION);
251 CHECK_ERR(err, "deflateInit");
252
253 c_stream.next_in = (z_const unsigned char *)hello;
254 c_stream.next_out = compr;
255
256 while (c_stream.total_in != len && c_stream.total_out < comprLen) {
257 c_stream.avail_in = c_stream.avail_out = 1; /* force small buffers */
258 err = PREFIX(deflate)(&c_stream, Z_NO_FLUSH);
259 CHECK_ERR(err, "deflate");
260 }
261 /* Finish the stream, still forcing small buffers: */
262 for (;;) {
263 c_stream.avail_out = 1;
264 err = PREFIX(deflate)(&c_stream, Z_FINISH);
265 if (err == Z_STREAM_END) break;
266 CHECK_ERR(err, "deflate");
267 }
268
269 err = PREFIX(deflateEnd)(&c_stream);
270 CHECK_ERR(err, "deflateEnd");
271 }
272
273 /* ===========================================================================
274 * Test inflate() with small buffers
275 */
test_inflate(unsigned char * compr,size_t comprLen,unsigned char * uncompr,size_t uncomprLen)276 void test_inflate(unsigned char *compr, size_t comprLen, unsigned char *uncompr, size_t uncomprLen) {
277 int err;
278 PREFIX3(stream) d_stream; /* decompression stream */
279
280 strcpy((char*)uncompr, "garbage");
281
282 d_stream.zalloc = zalloc;
283 d_stream.zfree = zfree;
284 d_stream.opaque = (void *)0;
285
286 d_stream.next_in = compr;
287 d_stream.avail_in = 0;
288 d_stream.next_out = uncompr;
289 d_stream.total_in = 0;
290 d_stream.total_out = 0;
291
292 err = PREFIX(inflateInit)(&d_stream);
293 CHECK_ERR(err, "inflateInit");
294
295 while (d_stream.total_out < uncomprLen && d_stream.total_in < comprLen) {
296 d_stream.avail_in = d_stream.avail_out = 1; /* force small buffers */
297 err = PREFIX(inflate)(&d_stream, Z_NO_FLUSH);
298 if (err == Z_STREAM_END) break;
299 CHECK_ERR(err, "inflate");
300 }
301
302 err = PREFIX(inflateEnd)(&d_stream);
303 CHECK_ERR(err, "inflateEnd");
304
305 if (strcmp((char*)uncompr, hello)) {
306 fprintf(stderr, "bad inflate\n");
307 exit(1);
308 } else {
309 printf("inflate(): %s\n", (char *)uncompr);
310 }
311 }
312
313 static unsigned int diff;
314
315 /* ===========================================================================
316 * Test deflate() with large buffers and dynamic change of compression level
317 */
test_large_deflate(unsigned char * compr,size_t comprLen,unsigned char * uncompr,size_t uncomprLen,int zng_params)318 void test_large_deflate(unsigned char *compr, size_t comprLen, unsigned char *uncompr, size_t uncomprLen, int zng_params) {
319 PREFIX3(stream) c_stream; /* compression stream */
320 int err;
321 #ifndef ZLIB_COMPAT
322 int level = -1;
323 int strategy = -1;
324 zng_deflate_param_value params[2];
325
326 params[0].param = Z_DEFLATE_LEVEL;
327 params[0].buf = &level;
328 params[0].size = sizeof(level);
329
330 params[1].param = Z_DEFLATE_STRATEGY;
331 params[1].buf = &strategy;
332 params[1].size = sizeof(strategy);
333 #endif
334
335 c_stream.zalloc = zalloc;
336 c_stream.zfree = zfree;
337 c_stream.opaque = (void *)0;
338
339 err = PREFIX(deflateInit)(&c_stream, Z_BEST_SPEED);
340 CHECK_ERR(err, "deflateInit");
341
342 c_stream.next_out = compr;
343 c_stream.avail_out = (unsigned int)comprLen;
344
345 /* At this point, uncompr is still mostly zeroes, so it should compress
346 * very well:
347 */
348 c_stream.next_in = uncompr;
349 c_stream.avail_in = (unsigned int)uncomprLen;
350 err = PREFIX(deflate)(&c_stream, Z_NO_FLUSH);
351 CHECK_ERR(err, "deflate");
352 if (c_stream.avail_in != 0) {
353 fprintf(stderr, "deflate not greedy\n");
354 exit(1);
355 }
356
357 /* Feed in already compressed data and switch to no compression: */
358 if (zng_params) {
359 #ifndef ZLIB_COMPAT
360 zng_deflateGetParams(&c_stream, params, sizeof(params) / sizeof(params[0]));
361 if (level != Z_BEST_SPEED) {
362 fprintf(stderr, "Expected compression level Z_BEST_SPEED, got %d\n", level);
363 exit(1);
364 }
365 if (strategy != Z_DEFAULT_STRATEGY) {
366 fprintf(stderr, "Expected compression strategy Z_DEFAULT_STRATEGY, got %d\n", strategy);
367 exit(1);
368 }
369 level = Z_NO_COMPRESSION;
370 strategy = Z_DEFAULT_STRATEGY;
371 zng_deflateSetParams(&c_stream, params, sizeof(params) / sizeof(params[0]));
372 #else
373 fprintf(stderr, "test_large_deflate() called with zng_params=1 in compat mode\n");
374 exit(1);
375 #endif
376 } else {
377 PREFIX(deflateParams)(&c_stream, Z_NO_COMPRESSION, Z_DEFAULT_STRATEGY);
378 }
379 c_stream.next_in = compr;
380 diff = (unsigned int)(c_stream.next_out - compr);
381 c_stream.avail_in = diff;
382 err = PREFIX(deflate)(&c_stream, Z_NO_FLUSH);
383 CHECK_ERR(err, "deflate");
384
385 /* Switch back to compressing mode: */
386 if (zng_params) {
387 #ifndef ZLIB_COMPAT
388 level = -1;
389 strategy = -1;
390 zng_deflateGetParams(&c_stream, params, sizeof(params) / sizeof(params[0]));
391 if (level != Z_NO_COMPRESSION) {
392 fprintf(stderr, "Expected compression level Z_NO_COMPRESSION, got %d\n", level);
393 exit(1);
394 }
395 if (strategy != Z_DEFAULT_STRATEGY) {
396 fprintf(stderr, "Expected compression strategy Z_DEFAULT_STRATEGY, got %d\n", strategy);
397 exit(1);
398 }
399 level = Z_BEST_COMPRESSION;
400 strategy = Z_FILTERED;
401 zng_deflateSetParams(&c_stream, params, sizeof(params) / sizeof(params[0]));
402 #else
403 fprintf(stderr, "test_large_deflate() called with zng_params=1 in compat mode\n");
404 exit(1);
405 #endif
406 } else {
407 PREFIX(deflateParams)(&c_stream, Z_BEST_COMPRESSION, Z_FILTERED);
408 }
409 c_stream.next_in = uncompr;
410 c_stream.avail_in = (unsigned int)uncomprLen;
411 err = PREFIX(deflate)(&c_stream, Z_NO_FLUSH);
412 CHECK_ERR(err, "deflate");
413
414 err = PREFIX(deflate)(&c_stream, Z_FINISH);
415 if (err != Z_STREAM_END) {
416 fprintf(stderr, "deflate should report Z_STREAM_END\n");
417 exit(1);
418 }
419 err = PREFIX(deflateEnd)(&c_stream);
420 CHECK_ERR(err, "deflateEnd");
421 }
422
423 /* ===========================================================================
424 * Test inflate() with large buffers
425 */
test_large_inflate(unsigned char * compr,size_t comprLen,unsigned char * uncompr,size_t uncomprLen)426 void test_large_inflate(unsigned char *compr, size_t comprLen, unsigned char *uncompr, size_t uncomprLen) {
427 int err;
428 PREFIX3(stream) d_stream; /* decompression stream */
429
430 strcpy((char*)uncompr, "garbage");
431
432 d_stream.zalloc = zalloc;
433 d_stream.zfree = zfree;
434 d_stream.opaque = (void *)0;
435
436 d_stream.next_in = compr;
437 d_stream.avail_in = (unsigned int)comprLen;
438 d_stream.total_in = 0;
439 d_stream.total_out = 0;
440
441 err = PREFIX(inflateInit)(&d_stream);
442 CHECK_ERR(err, "inflateInit");
443
444 for (;;) {
445 d_stream.next_out = uncompr; /* discard the output */
446 d_stream.avail_out = (unsigned int)uncomprLen;
447 err = PREFIX(inflate)(&d_stream, Z_NO_FLUSH);
448 if (err == Z_STREAM_END) break;
449 CHECK_ERR(err, "large inflate");
450 }
451
452 err = PREFIX(inflateEnd)(&d_stream);
453 CHECK_ERR(err, "inflateEnd");
454
455 if (d_stream.total_out != 2*uncomprLen + diff) {
456 fprintf(stderr, "bad large inflate: %" PRIu64 "\n", (uint64_t)d_stream.total_out);
457 exit(1);
458 } else {
459 printf("large_inflate(): OK\n");
460 }
461 }
462
463 /* ===========================================================================
464 * Test deflate() with full flush
465 */
test_flush(unsigned char * compr,z_size_t * comprLen)466 void test_flush(unsigned char *compr, z_size_t *comprLen) {
467 PREFIX3(stream) c_stream; /* compression stream */
468 int err;
469 unsigned int len = (unsigned int)strlen(hello)+1;
470
471 c_stream.zalloc = zalloc;
472 c_stream.zfree = zfree;
473 c_stream.opaque = (void *)0;
474
475 err = PREFIX(deflateInit)(&c_stream, Z_DEFAULT_COMPRESSION);
476 CHECK_ERR(err, "deflateInit");
477
478 c_stream.next_in = (z_const unsigned char *)hello;
479 c_stream.next_out = compr;
480 c_stream.avail_in = 3;
481 c_stream.avail_out = (unsigned int)*comprLen;
482 err = PREFIX(deflate)(&c_stream, Z_FULL_FLUSH);
483 CHECK_ERR(err, "deflate");
484
485 compr[3]++; /* force an error in first compressed block */
486 c_stream.avail_in = len - 3;
487
488 err = PREFIX(deflate)(&c_stream, Z_FINISH);
489 if (err != Z_STREAM_END) {
490 CHECK_ERR(err, "deflate");
491 }
492 err = PREFIX(deflateEnd)(&c_stream);
493 CHECK_ERR(err, "deflateEnd");
494
495 *comprLen = (z_size_t)c_stream.total_out;
496 }
497
498 /* ===========================================================================
499 * Test inflateSync()
500 */
test_sync(unsigned char * compr,size_t comprLen,unsigned char * uncompr,size_t uncomprLen)501 void test_sync(unsigned char *compr, size_t comprLen, unsigned char *uncompr, size_t uncomprLen) {
502 int err;
503 PREFIX3(stream) d_stream; /* decompression stream */
504
505 strcpy((char*)uncompr, "garbage");
506
507 d_stream.zalloc = zalloc;
508 d_stream.zfree = zfree;
509 d_stream.opaque = (void *)0;
510
511 d_stream.next_in = compr;
512 d_stream.avail_in = 2; /* just read the zlib header */
513
514 err = PREFIX(inflateInit)(&d_stream);
515 CHECK_ERR(err, "inflateInit");
516
517 d_stream.next_out = uncompr;
518 d_stream.avail_out = (unsigned int)uncomprLen;
519
520 err = PREFIX(inflate)(&d_stream, Z_NO_FLUSH);
521 CHECK_ERR(err, "inflate");
522
523 d_stream.avail_in = (unsigned int)comprLen-2; /* read all compressed data */
524 err = PREFIX(inflateSync)(&d_stream); /* but skip the damaged part */
525 CHECK_ERR(err, "inflateSync");
526
527 err = PREFIX(inflate)(&d_stream, Z_FINISH);
528 if (err != Z_STREAM_END) {
529 fprintf(stderr, "inflate should report Z_STREAM_END\n");
530 exit(1);
531 }
532 err = PREFIX(inflateEnd)(&d_stream);
533 CHECK_ERR(err, "inflateEnd");
534
535 printf("after inflateSync(): hel%s\n", (char *)uncompr);
536 }
537
538 /* ===========================================================================
539 * Test deflate() with preset dictionary
540 */
test_dict_deflate(unsigned char * compr,size_t comprLen)541 void test_dict_deflate(unsigned char *compr, size_t comprLen) {
542 PREFIX3(stream) c_stream; /* compression stream */
543 int err;
544
545 c_stream.zalloc = zalloc;
546 c_stream.zfree = zfree;
547 c_stream.opaque = (void *)0;
548 c_stream.adler = 0;
549
550 err = PREFIX(deflateInit)(&c_stream, Z_BEST_COMPRESSION);
551 CHECK_ERR(err, "deflateInit");
552
553 err = PREFIX(deflateSetDictionary)(&c_stream,
554 (const unsigned char*)dictionary, (int)sizeof(dictionary));
555 CHECK_ERR(err, "deflateSetDictionary");
556
557 dictId = c_stream.adler;
558 c_stream.next_out = compr;
559 c_stream.avail_out = (unsigned int)comprLen;
560
561 c_stream.next_in = (z_const unsigned char *)hello;
562 c_stream.avail_in = (unsigned int)strlen(hello)+1;
563
564 err = PREFIX(deflate)(&c_stream, Z_FINISH);
565 if (err != Z_STREAM_END) {
566 fprintf(stderr, "deflate should report Z_STREAM_END\n");
567 exit(1);
568 }
569 err = PREFIX(deflateEnd)(&c_stream);
570 CHECK_ERR(err, "deflateEnd");
571 }
572
573 /* ===========================================================================
574 * Test inflate() with a preset dictionary
575 */
test_dict_inflate(unsigned char * compr,size_t comprLen,unsigned char * uncompr,size_t uncomprLen)576 void test_dict_inflate(unsigned char *compr, size_t comprLen, unsigned char *uncompr, size_t uncomprLen) {
577 int err;
578 PREFIX3(stream) d_stream; /* decompression stream */
579
580 strcpy((char*)uncompr, "garbage garbage garbage");
581
582 d_stream.zalloc = zalloc;
583 d_stream.zfree = zfree;
584 d_stream.opaque = (void *)0;
585 d_stream.adler = 0;
586 d_stream.next_in = compr;
587 d_stream.avail_in = (unsigned int)comprLen;
588
589 err = PREFIX(inflateInit)(&d_stream);
590 CHECK_ERR(err, "inflateInit");
591
592 d_stream.next_out = uncompr;
593 d_stream.avail_out = (unsigned int)uncomprLen;
594
595 for (;;) {
596 err = PREFIX(inflate)(&d_stream, Z_NO_FLUSH);
597 if (err == Z_STREAM_END) break;
598 if (err == Z_NEED_DICT) {
599 if (d_stream.adler != dictId) {
600 fprintf(stderr, "unexpected dictionary");
601 exit(1);
602 }
603 err = PREFIX(inflateSetDictionary)(&d_stream, (const unsigned char*)dictionary,
604 (int)sizeof(dictionary));
605 }
606 CHECK_ERR(err, "inflate with dict");
607 }
608
609 err = PREFIX(inflateEnd)(&d_stream);
610 CHECK_ERR(err, "inflateEnd");
611
612 if (strncmp((char*)uncompr, hello, sizeof(hello))) {
613 fprintf(stderr, "bad inflate with dict\n");
614 exit(1);
615 } else {
616 printf("inflate with dictionary: %s\n", (char *)uncompr);
617 }
618 }
619
620 /* ===========================================================================
621 * Test deflateBound() with small buffers
622 */
test_deflate_bound(void)623 void test_deflate_bound(void) {
624 PREFIX3(stream) c_stream; /* compression stream */
625 int err;
626 unsigned int len = (unsigned int)strlen(hello)+1;
627 int estimateLen = 0;
628 unsigned char *outBuf = NULL;
629
630 c_stream.zalloc = zalloc;
631 c_stream.zfree = zfree;
632 c_stream.opaque = (voidpf)0;
633 c_stream.avail_in = len;
634 c_stream.next_in = (z_const unsigned char *)hello;
635 c_stream.avail_out = 0;
636 c_stream.next_out = outBuf;
637
638 err = PREFIX(deflateInit)(&c_stream, Z_DEFAULT_COMPRESSION);
639 CHECK_ERR(err, "deflateInit");
640
641 /* calculate actual output length and update structure */
642 estimateLen = PREFIX(deflateBound)(&c_stream, len);
643 outBuf = malloc(estimateLen);
644
645 if (outBuf != NULL) {
646 /* update zlib configuration */
647 c_stream.avail_out = estimateLen;
648 c_stream.next_out = outBuf;
649
650 /* do the compression */
651 err = PREFIX(deflate)(&c_stream, Z_FINISH);
652 if (err == Z_STREAM_END) {
653 printf("deflateBound(): OK\n");
654 } else {
655 CHECK_ERR(err, "deflate");
656 }
657 }
658
659 err = PREFIX(deflateEnd)(&c_stream);
660 CHECK_ERR(err, "deflateEnd");
661
662 free(outBuf);
663 }
664
665 /* ===========================================================================
666 * Test deflateCopy() with small buffers
667 */
test_deflate_copy(unsigned char * compr,size_t comprLen)668 void test_deflate_copy(unsigned char *compr, size_t comprLen) {
669 PREFIX3(stream) c_stream, c_stream_copy; /* compression stream */
670 int err;
671 size_t len = strlen(hello)+1;
672
673 memset(&c_stream, 0, sizeof(c_stream));
674
675 c_stream.zalloc = zalloc;
676 c_stream.zfree = zfree;
677 c_stream.opaque = (voidpf)0;
678
679 err = PREFIX(deflateInit)(&c_stream, Z_DEFAULT_COMPRESSION);
680 CHECK_ERR(err, "deflateInit");
681
682 c_stream.next_in = (z_const unsigned char *)hello;
683 c_stream.next_out = compr;
684
685 while (c_stream.total_in != len && c_stream.total_out < comprLen) {
686 c_stream.avail_in = c_stream.avail_out = 1; /* force small buffers */
687 err = PREFIX(deflate)(&c_stream, Z_NO_FLUSH);
688 CHECK_ERR(err, "deflate");
689 }
690
691 /* Finish the stream, still forcing small buffers: */
692 for (;;) {
693 c_stream.avail_out = 1;
694 err = PREFIX(deflate)(&c_stream, Z_FINISH);
695 if (err == Z_STREAM_END) break;
696 CHECK_ERR(err, "deflate");
697 }
698
699 err = PREFIX(deflateCopy)(&c_stream_copy, &c_stream);
700 CHECK_ERR(err, "deflate_copy");
701
702 if (c_stream.state->status == c_stream_copy.state->status) {
703 printf("deflate_copy(): OK\n");
704 }
705
706 err = PREFIX(deflateEnd)(&c_stream);
707 CHECK_ERR(err, "deflateEnd original");
708
709 err = PREFIX(deflateEnd)(&c_stream_copy);
710 CHECK_ERR(err, "deflateEnd copy");
711 }
712
713 /* ===========================================================================
714 * Test deflateGetDictionary() with small buffers
715 */
test_deflate_get_dict(unsigned char * compr,size_t comprLen)716 void test_deflate_get_dict(unsigned char *compr, size_t comprLen) {
717 PREFIX3(stream) c_stream; /* compression stream */
718 int err;
719 unsigned char *dictNew = NULL;
720 unsigned int *dictLen;
721
722 c_stream.zalloc = zalloc;
723 c_stream.zfree = zfree;
724 c_stream.opaque = (voidpf)0;
725
726 err = PREFIX(deflateInit)(&c_stream, Z_BEST_COMPRESSION);
727 CHECK_ERR(err, "deflateInit");
728
729 c_stream.next_out = compr;
730 c_stream.avail_out = (uInt)comprLen;
731
732 c_stream.next_in = (z_const unsigned char *)hello;
733 c_stream.avail_in = (unsigned int)strlen(hello)+1;
734
735 err = PREFIX(deflate)(&c_stream, Z_FINISH);
736
737 if (err != Z_STREAM_END) {
738 fprintf(stderr, "deflate should report Z_STREAM_END\n");
739 exit(1);
740 }
741
742 dictNew = calloc(256, 1);
743 dictLen = (unsigned int *)calloc(4, 1);
744 err = PREFIX(deflateGetDictionary)(&c_stream, dictNew, dictLen);
745
746 CHECK_ERR(err, "deflateGetDictionary");
747 if (err == Z_OK) {
748 printf("deflateGetDictionary(): %s\n", dictNew);
749 }
750
751 err = PREFIX(deflateEnd)(&c_stream);
752 CHECK_ERR(err, "deflateEnd");
753
754 free(dictNew);
755 free(dictLen);
756 }
757
758 /* ===========================================================================
759 * Test deflatePending() with small buffers
760 */
test_deflate_pending(unsigned char * compr,size_t comprLen)761 void test_deflate_pending(unsigned char *compr, size_t comprLen) {
762 PREFIX3(stream) c_stream; /* compression stream */
763 int err;
764 int *bits = calloc(256, 1);
765 unsigned *ped = calloc(256, 1);
766 size_t len = strlen(hello)+1;
767
768
769 c_stream.zalloc = zalloc;
770 c_stream.zfree = zfree;
771 c_stream.opaque = (voidpf)0;
772
773 err = PREFIX(deflateInit)(&c_stream, Z_DEFAULT_COMPRESSION);
774 CHECK_ERR(err, "deflateInit");
775
776 c_stream.next_in = (z_const unsigned char *)hello;
777 c_stream.next_out = compr;
778
779 while (c_stream.total_in != len && c_stream.total_out < comprLen) {
780 c_stream.avail_in = c_stream.avail_out = 1; /* force small buffers */
781 err = PREFIX(deflate)(&c_stream, Z_NO_FLUSH);
782 CHECK_ERR(err, "deflate");
783 }
784
785 err = PREFIX(deflatePending)(&c_stream, ped, bits);
786 CHECK_ERR(err, "deflatePending");
787
788 if (*bits >= 0 && *bits <= 7) {
789 printf("deflatePending(): OK\n");
790 } else {
791 printf("deflatePending(): error\n");
792 }
793
794 /* Finish the stream, still forcing small buffers: */
795 for (;;) {
796 c_stream.avail_out = 1;
797 err = PREFIX(deflate)(&c_stream, Z_FINISH);
798 if (err == Z_STREAM_END) break;
799 CHECK_ERR(err, "deflate");
800 }
801
802 err = PREFIX(deflateEnd)(&c_stream);
803 CHECK_ERR(err, "deflateEnd");
804
805 free(bits);
806 free(ped);
807 }
808
809 /* ===========================================================================
810 * Test deflatePrime() wrapping gzip around deflate stream
811 */
test_deflate_prime(unsigned char * compr,size_t comprLen,unsigned char * uncompr,size_t uncomprLen)812 void test_deflate_prime(unsigned char *compr, size_t comprLen, unsigned char *uncompr, size_t uncomprLen) {
813 PREFIX3(stream) c_stream; /* compression stream */
814 PREFIX3(stream) d_stream; /* decompression stream */
815 int err;
816 size_t len = strlen(hello)+1;
817 uint32_t crc = 0;
818
819
820 c_stream.zalloc = zalloc;
821 c_stream.zfree = zfree;
822 c_stream.opaque = (voidpf)0;
823
824 /* Raw deflate windowBits is -15 */
825 err = PREFIX(deflateInit2)(&c_stream, Z_DEFAULT_COMPRESSION, Z_DEFLATED, -MAX_WBITS, 8, Z_DEFAULT_STRATEGY);
826 CHECK_ERR(err, "deflateInit2");
827
828 /* Gzip magic number */
829 err = PREFIX(deflatePrime)(&c_stream, 16, 0x8b1f);
830 CHECK_ERR(err, "deflatePrime");
831 /* Gzip compression method (deflate) */
832 err = PREFIX(deflatePrime)(&c_stream, 8, 0x08);
833 CHECK_ERR(err, "deflatePrime");
834 /* Gzip flags (one byte, using two odd bit calls) */
835 err = PREFIX(deflatePrime)(&c_stream, 3, 0x0);
836 CHECK_ERR(err, "deflatePrime");
837 err = PREFIX(deflatePrime)(&c_stream, 5, 0x0);
838 CHECK_ERR(err, "deflatePrime");
839 /* Gzip modified time */
840 err = PREFIX(deflatePrime)(&c_stream, 32, 0x0);
841 CHECK_ERR(err, "deflatePrime");
842 /* Gzip extra flags */
843 err = PREFIX(deflatePrime)(&c_stream, 8, 0x0);
844 CHECK_ERR(err, "deflatePrime");
845 /* Gzip operating system */
846 err = PREFIX(deflatePrime)(&c_stream, 8, 255);
847 CHECK_ERR(err, "deflatePrime");
848
849 c_stream.next_in = (z_const unsigned char *)hello;
850 c_stream.avail_in = (uint32_t)len;
851 c_stream.next_out = compr;
852 c_stream.avail_out = (uint32_t)comprLen;
853
854 err = PREFIX(deflate)(&c_stream, Z_FINISH);
855 if (err != Z_STREAM_END)
856 CHECK_ERR(err, "deflate");
857
858 /* Gzip uncompressed data crc32 */
859 crc = PREFIX(crc32)(0, (const uint8_t *)hello, (uint32_t)len);
860 err = PREFIX(deflatePrime)(&c_stream, 32, crc);
861 CHECK_ERR(err, "deflatePrime");
862 /* Gzip uncompressed data length */
863 err = PREFIX(deflatePrime)(&c_stream, 32, (uint32_t)len);
864 CHECK_ERR(err, "deflatePrime");
865
866 err = PREFIX(deflateEnd)(&c_stream);
867 CHECK_ERR(err, "deflateEnd");
868
869 d_stream.zalloc = zalloc;
870 d_stream.zfree = zfree;
871 d_stream.opaque = (void *)0;
872
873 d_stream.next_in = compr;
874 d_stream.avail_in = (uint32_t)c_stream.total_out;
875 d_stream.next_out = uncompr;
876 d_stream.avail_out = (uint32_t)uncomprLen;
877 d_stream.total_in = 0;
878 d_stream.total_out = 0;
879
880 /* Inflate with gzip header */
881 err = PREFIX(inflateInit2)(&d_stream, MAX_WBITS + 32);
882 CHECK_ERR(err, "inflateInit");
883
884 err = PREFIX(inflate)(&d_stream, Z_FINISH);
885 if (err != Z_BUF_ERROR) {
886 CHECK_ERR(err, "inflate");
887 }
888
889 err = PREFIX(inflateEnd)(&d_stream);
890 CHECK_ERR(err, "inflateEnd");
891
892 if (strcmp((const char *)uncompr, hello) != 0) {
893 fprintf(stderr, "bad deflatePrime\n");
894 exit(1);
895 }
896
897 if (err == Z_OK) {
898 printf("deflatePrime(): OK\n");
899 }
900 }
901
902 /* ===========================================================================
903 * Test deflateSetHeader() with small buffers
904 */
test_deflate_set_header(unsigned char * compr,size_t comprLen)905 void test_deflate_set_header(unsigned char *compr, size_t comprLen) {
906 PREFIX(gz_header) *head = calloc(1, sizeof(PREFIX(gz_header)));
907 PREFIX3(stream) c_stream; /* compression stream */
908 int err;
909 size_t len = strlen(hello)+1;
910
911
912 c_stream.zalloc = zalloc;
913 c_stream.zfree = zfree;
914 c_stream.opaque = (voidpf)0;
915
916 /* gzip */
917 err = PREFIX(deflateInit2)(&c_stream, Z_DEFAULT_COMPRESSION, Z_DEFLATED, MAX_WBITS + 16, 8, Z_DEFAULT_STRATEGY);
918 CHECK_ERR(err, "deflateInit2");
919
920 head->text = 1;
921 err = PREFIX(deflateSetHeader)(&c_stream, head);
922 CHECK_ERR(err, "deflateSetHeader");
923 if (err == Z_OK) {
924 printf("deflateSetHeader(): OK\n");
925 }
926
927 c_stream.next_in = (unsigned char *)hello;
928 c_stream.next_out = compr;
929
930 while (c_stream.total_in != len && c_stream.total_out < comprLen) {
931 c_stream.avail_in = c_stream.avail_out = 1; /* force small buffers */
932 err = PREFIX(deflate)(&c_stream, Z_NO_FLUSH);
933 CHECK_ERR(err, "deflate");
934 }
935
936 /* Finish the stream, still forcing small buffers: */
937 for (;;) {
938 c_stream.avail_out = 1;
939 err = PREFIX(deflate)(&c_stream, Z_FINISH);
940 if (err == Z_STREAM_END) break;
941 CHECK_ERR(err, "deflate");
942 }
943
944 err = PREFIX(deflateEnd)(&c_stream);
945 CHECK_ERR(err, "deflateEnd");
946
947 free(head);
948 }
949
950 /* ===========================================================================
951 * Test deflateTune() with small buffers
952 */
test_deflate_tune(unsigned char * compr,size_t comprLen)953 void test_deflate_tune(unsigned char *compr, size_t comprLen) {
954 PREFIX3(stream) c_stream; /* compression stream */
955 int err;
956 int good_length = 3;
957 int max_lazy = 5;
958 int nice_length = 18;
959 int max_chain = 6;
960 size_t len = strlen(hello)+1;
961
962
963 c_stream.zalloc = zalloc;
964 c_stream.zfree = zfree;
965 c_stream.opaque = (voidpf)0;
966
967 err = PREFIX(deflateInit)(&c_stream, Z_BEST_COMPRESSION);
968 CHECK_ERR(err, "deflateInit");
969
970 err = PREFIX(deflateTune)(&c_stream,(uInt)good_length,(uInt)max_lazy,nice_length,(uInt)max_chain);
971 CHECK_ERR(err, "deflateTune");
972 if (err == Z_OK) {
973 printf("deflateTune(): OK\n");
974 }
975
976 c_stream.next_in = (z_const unsigned char *)hello;
977 c_stream.next_out = compr;
978
979 while (c_stream.total_in != len && c_stream.total_out < comprLen) {
980 c_stream.avail_in = c_stream.avail_out = 1; /* force small buffers */
981 err = PREFIX(deflate)(&c_stream, Z_NO_FLUSH);
982 CHECK_ERR(err, "deflate");
983 }
984
985 /* Finish the stream, still forcing small buffers: */
986 for (;;) {
987 c_stream.avail_out = 1;
988 err = PREFIX(deflate)(&c_stream, Z_FINISH);
989 if (err == Z_STREAM_END) break;
990 CHECK_ERR(err, "deflate");
991 }
992
993 err = PREFIX(deflateEnd)(&c_stream);
994 CHECK_ERR(err, "deflateEnd");
995 }
996
997 /* ===========================================================================
998 * Usage: example [output.gz [input.gz]]
999 */
main(int argc,char * argv[])1000 int main(int argc, char *argv[]) {
1001 unsigned char *compr, *uncompr;
1002 z_size_t comprLen = 10000*sizeof(int); /* don't overflow on MSDOS */
1003 z_size_t uncomprLen = comprLen;
1004 static const char* myVersion = PREFIX2(VERSION);
1005
1006 if (zVersion()[0] != myVersion[0]) {
1007 fprintf(stderr, "incompatible zlib version\n");
1008 exit(1);
1009
1010 } else if (strcmp(zVersion(), PREFIX2(VERSION)) != 0) {
1011 fprintf(stderr, "warning: different zlib version\n");
1012 }
1013
1014 printf("zlib version %s = 0x%04x, compile flags = 0x%lx\n",
1015 PREFIX2(VERSION), PREFIX2(VERNUM), PREFIX(zlibCompileFlags)());
1016
1017 compr = (unsigned char*)calloc((unsigned int)comprLen, 1);
1018 uncompr = (unsigned char*)calloc((unsigned int)uncomprLen, 1);
1019 /* compr and uncompr are cleared to avoid reading uninitialized
1020 * data and to ensure that uncompr compresses well.
1021 */
1022 if (compr == NULL || uncompr == NULL) {
1023 printf("out of memory\n");
1024 exit(1);
1025 }
1026
1027 test_compress(compr, comprLen, uncompr, uncomprLen);
1028
1029 test_gzio((argc > 1 ? argv[1] : TESTFILE),
1030 uncompr, uncomprLen);
1031
1032 test_deflate(compr, comprLen);
1033 test_inflate(compr, comprLen, uncompr, uncomprLen);
1034
1035 test_large_deflate(compr, comprLen, uncompr, uncomprLen, 0);
1036 test_large_inflate(compr, comprLen, uncompr, uncomprLen);
1037
1038 #ifndef ZLIB_COMPAT
1039 test_large_deflate(compr, comprLen, uncompr, uncomprLen, 1);
1040 test_large_inflate(compr, comprLen, uncompr, uncomprLen);
1041 #endif
1042
1043 test_flush(compr, &comprLen);
1044 test_sync(compr, comprLen, uncompr, uncomprLen);
1045 comprLen = uncomprLen;
1046
1047 test_dict_deflate(compr, comprLen);
1048 test_dict_inflate(compr, comprLen, uncompr, uncomprLen);
1049
1050 test_deflate_bound();
1051 test_deflate_copy(compr, comprLen);
1052 test_deflate_get_dict(compr, comprLen);
1053 test_deflate_set_header(compr, comprLen);
1054 test_deflate_tune(compr, comprLen);
1055 test_deflate_pending(compr, comprLen);
1056 test_deflate_prime(compr, comprLen, uncompr, uncomprLen);
1057
1058 free(compr);
1059 free(uncompr);
1060
1061 return 0;
1062 }
1063