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