1/* example.c -- usage example of the zlib compression library
2 */
3/*
4 Copyright (c) 1995-2006, 2011 Jean-loup Gailly
5
6This software is provided 'as-is', without any express or implied
7warranty. In no event will the authors be held liable for any damages
8arising from the use of this software.
9
10Permission is granted to anyone to use this software for any purpose,
11including commercial applications, and to alter it and redistribute it
12freely, subject to the following restrictions:
13
141. 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.
182. Altered source versions must be plainly marked as such, and must not be
19   misrepresented as being the original software.
203. 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
46z_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
51const char dictionary[] = "hello";
52uLong dictId; /* Adler32 value of the dictionary */
53
54void test_deflate       OF((Byte *compr, uLong comprLen));
55void test_inflate       OF((Byte *compr, uLong comprLen,
56                            Byte *uncompr, uLong uncomprLen));
57void test_large_deflate OF((Byte *compr, uLong comprLen,
58                            Byte *uncompr, uLong uncomprLen));
59void test_large_inflate OF((Byte *compr, uLong comprLen,
60                            Byte *uncompr, uLong uncomprLen));
61void test_flush         OF((Byte *compr, uLong *comprLen));
62void test_sync          OF((Byte *compr, uLong comprLen,
63                            Byte *uncompr, uLong uncomprLen));
64void test_dict_deflate  OF((Byte *compr, uLong comprLen));
65void test_dict_inflate  OF((Byte *compr, uLong comprLen,
66                            Byte *uncompr, uLong uncomprLen));
67int  main               OF((int argc, char *argv[]));
68
69
70#ifdef Z_SOLO
71
72void *myalloc OF((void *, unsigned, unsigned));
73void myfree OF((void *, void *));
74
75void *myalloc(q, n, m)
76    void *q;
77    unsigned n, m;
78{
79    q = Z_NULL;
80    return calloc(n, m);
81}
82
83void myfree(void *q, void *p)
84{
85    q = Z_NULL;
86    free(p);
87}
88
89static alloc_func zalloc = myalloc;
90static free_func zfree = myfree;
91
92#else /* !Z_SOLO */
93
94static alloc_func zalloc = (alloc_func)0;
95static free_func zfree = (free_func)0;
96
97void test_compress      OF((Byte *compr, uLong comprLen,
98                            Byte *uncompr, uLong uncomprLen));
99void test_gzio          OF((const char *fname,
100                            Byte *uncompr, uLong uncomprLen));
101
102/* ===========================================================================
103 * Test compress() and uncompress()
104 */
105void 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 */
131void 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 */
217void 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 */
255void 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 */
296void 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 */
351void 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 */
392void 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 */
430void 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 */
474void 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 */
511void 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
562int 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