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