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