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