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