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