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