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