xref: /freebsd/sys/contrib/zlib/test/example.c (revision cd8822075a38d0734e74b1735e4b5dbef9789170)
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 /* @(#) $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 static 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 static const char dictionary[] = "hello";
35 static 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 
58 void *myalloc(q, n, m)
59     void *q;
60     unsigned n, m;
61 {
62     (void)q;
63     return calloc(n, m);
64 }
65 
66 void myfree(void *q, void *p)
67 {
68     (void)q;
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  */
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  */
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  */
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  */
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  */
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  */
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  */
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  */
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     err = 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_STREAM_END) {
444         fprintf(stderr, "inflate should report Z_STREAM_END\n");
445         exit(1);
446     }
447     err = inflateEnd(&d_stream);
448     CHECK_ERR(err, "inflateEnd");
449 
450     printf("after inflateSync(): hel%s\n", (char *)uncompr);
451 }
452 
453 /* ===========================================================================
454  * Test deflate() with preset dictionary
455  */
456 void test_dict_deflate(compr, comprLen)
457     Byte *compr;
458     uLong comprLen;
459 {
460     z_stream c_stream; /* compression stream */
461     int err;
462 
463     c_stream.zalloc = zalloc;
464     c_stream.zfree = zfree;
465     c_stream.opaque = (voidpf)0;
466 
467     err = deflateInit(&c_stream, Z_BEST_COMPRESSION);
468     CHECK_ERR(err, "deflateInit");
469 
470     err = deflateSetDictionary(&c_stream,
471                 (const Bytef*)dictionary, (int)sizeof(dictionary));
472     CHECK_ERR(err, "deflateSetDictionary");
473 
474     dictId = c_stream.adler;
475     c_stream.next_out = compr;
476     c_stream.avail_out = (uInt)comprLen;
477 
478     c_stream.next_in = (z_const unsigned char *)hello;
479     c_stream.avail_in = (uInt)strlen(hello)+1;
480 
481     err = deflate(&c_stream, Z_FINISH);
482     if (err != Z_STREAM_END) {
483         fprintf(stderr, "deflate should report Z_STREAM_END\n");
484         exit(1);
485     }
486     err = deflateEnd(&c_stream);
487     CHECK_ERR(err, "deflateEnd");
488 }
489 
490 /* ===========================================================================
491  * Test inflate() with a preset dictionary
492  */
493 void test_dict_inflate(compr, comprLen, uncompr, uncomprLen)
494     Byte *compr, *uncompr;
495     uLong comprLen, uncomprLen;
496 {
497     int err;
498     z_stream d_stream; /* decompression stream */
499 
500     strcpy((char*)uncompr, "garbage");
501 
502     d_stream.zalloc = zalloc;
503     d_stream.zfree = zfree;
504     d_stream.opaque = (voidpf)0;
505 
506     d_stream.next_in  = compr;
507     d_stream.avail_in = (uInt)comprLen;
508 
509     err = inflateInit(&d_stream);
510     CHECK_ERR(err, "inflateInit");
511 
512     d_stream.next_out = uncompr;
513     d_stream.avail_out = (uInt)uncomprLen;
514 
515     for (;;) {
516         err = inflate(&d_stream, Z_NO_FLUSH);
517         if (err == Z_STREAM_END) break;
518         if (err == Z_NEED_DICT) {
519             if (d_stream.adler != dictId) {
520                 fprintf(stderr, "unexpected dictionary");
521                 exit(1);
522             }
523             err = inflateSetDictionary(&d_stream, (const Bytef*)dictionary,
524                                        (int)sizeof(dictionary));
525         }
526         CHECK_ERR(err, "inflate with dict");
527     }
528 
529     err = inflateEnd(&d_stream);
530     CHECK_ERR(err, "inflateEnd");
531 
532     if (strcmp((char*)uncompr, hello)) {
533         fprintf(stderr, "bad inflate with dict\n");
534         exit(1);
535     } else {
536         printf("inflate with dictionary: %s\n", (char *)uncompr);
537     }
538 }
539 
540 /* ===========================================================================
541  * Usage:  example [output.gz  [input.gz]]
542  */
543 
544 int main(argc, argv)
545     int argc;
546     char *argv[];
547 {
548     Byte *compr, *uncompr;
549     uLong comprLen = 10000*sizeof(int); /* don't overflow on MSDOS */
550     uLong uncomprLen = comprLen;
551     static const char* myVersion = ZLIB_VERSION;
552 
553     if (zlibVersion()[0] != myVersion[0]) {
554         fprintf(stderr, "incompatible zlib version\n");
555         exit(1);
556 
557     } else if (strcmp(zlibVersion(), ZLIB_VERSION) != 0) {
558         fprintf(stderr, "warning: different zlib version\n");
559     }
560 
561     printf("zlib version %s = 0x%04x, compile flags = 0x%lx\n",
562             ZLIB_VERSION, ZLIB_VERNUM, zlibCompileFlags());
563 
564     compr    = (Byte*)calloc((uInt)comprLen, 1);
565     uncompr  = (Byte*)calloc((uInt)uncomprLen, 1);
566     /* compr and uncompr are cleared to avoid reading uninitialized
567      * data and to ensure that uncompr compresses well.
568      */
569     if (compr == Z_NULL || uncompr == Z_NULL) {
570         printf("out of memory\n");
571         exit(1);
572     }
573 
574 #ifdef Z_SOLO
575     (void)argc;
576     (void)argv;
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