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 
  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 
  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  */
  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     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  */
 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  */
 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 
 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 }