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