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, uLong uncomprLen) { 368 int err; 369 z_stream d_stream; /* decompression stream */ 370 371 strcpy((char*)uncompr, "garbage"); 372 373 d_stream.zalloc = zalloc; 374 d_stream.zfree = zfree; 375 d_stream.opaque = (voidpf)0; 376 377 d_stream.next_in = compr; 378 d_stream.avail_in = 2; /* just read the zlib header */ 379 380 err = inflateInit(&d_stream); 381 CHECK_ERR(err, "inflateInit"); 382 383 d_stream.next_out = uncompr; 384 d_stream.avail_out = (uInt)uncomprLen; 385 386 err = inflate(&d_stream, Z_NO_FLUSH); 387 CHECK_ERR(err, "inflate"); 388 389 d_stream.avail_in = (uInt)comprLen-2; /* read all compressed data */ 390 err = inflateSync(&d_stream); /* but skip the damaged part */ 391 CHECK_ERR(err, "inflateSync"); 392 393 err = inflate(&d_stream, Z_FINISH); 394 if (err != Z_STREAM_END) { 395 fprintf(stderr, "inflate should report Z_STREAM_END\n"); 396 exit(1); 397 } 398 err = inflateEnd(&d_stream); 399 CHECK_ERR(err, "inflateEnd"); 400 401 printf("after inflateSync(): hel%s\n", (char *)uncompr); 402 } 403 404 /* =========================================================================== 405 * Test deflate() with preset dictionary 406 */ 407 static void test_dict_deflate(Byte *compr, uLong comprLen) { 408 z_stream c_stream; /* compression stream */ 409 int err; 410 411 c_stream.zalloc = zalloc; 412 c_stream.zfree = zfree; 413 c_stream.opaque = (voidpf)0; 414 415 err = deflateInit(&c_stream, Z_BEST_COMPRESSION); 416 CHECK_ERR(err, "deflateInit"); 417 418 err = deflateSetDictionary(&c_stream, 419 (const Bytef*)dictionary, (int)sizeof(dictionary)); 420 CHECK_ERR(err, "deflateSetDictionary"); 421 422 dictId = c_stream.adler; 423 c_stream.next_out = compr; 424 c_stream.avail_out = (uInt)comprLen; 425 426 c_stream.next_in = (z_const unsigned char *)hello; 427 c_stream.avail_in = (uInt)strlen(hello)+1; 428 429 err = deflate(&c_stream, Z_FINISH); 430 if (err != Z_STREAM_END) { 431 fprintf(stderr, "deflate should report Z_STREAM_END\n"); 432 exit(1); 433 } 434 err = deflateEnd(&c_stream); 435 CHECK_ERR(err, "deflateEnd"); 436 } 437 438 /* =========================================================================== 439 * Test inflate() with a preset dictionary 440 */ 441 static void test_dict_inflate(Byte *compr, uLong comprLen, Byte *uncompr, 442 uLong uncomprLen) { 443 int err; 444 z_stream d_stream; /* decompression stream */ 445 446 strcpy((char*)uncompr, "garbage"); 447 448 d_stream.zalloc = zalloc; 449 d_stream.zfree = zfree; 450 d_stream.opaque = (voidpf)0; 451 452 d_stream.next_in = compr; 453 d_stream.avail_in = (uInt)comprLen; 454 455 err = inflateInit(&d_stream); 456 CHECK_ERR(err, "inflateInit"); 457 458 d_stream.next_out = uncompr; 459 d_stream.avail_out = (uInt)uncomprLen; 460 461 for (;;) { 462 err = inflate(&d_stream, Z_NO_FLUSH); 463 if (err == Z_STREAM_END) break; 464 if (err == Z_NEED_DICT) { 465 if (d_stream.adler != dictId) { 466 fprintf(stderr, "unexpected dictionary"); 467 exit(1); 468 } 469 err = inflateSetDictionary(&d_stream, (const Bytef*)dictionary, 470 (int)sizeof(dictionary)); 471 } 472 CHECK_ERR(err, "inflate with dict"); 473 } 474 475 err = inflateEnd(&d_stream); 476 CHECK_ERR(err, "inflateEnd"); 477 478 if (strcmp((char*)uncompr, hello)) { 479 fprintf(stderr, "bad inflate with dict\n"); 480 exit(1); 481 } else { 482 printf("inflate with dictionary: %s\n", (char *)uncompr); 483 } 484 } 485 486 /* =========================================================================== 487 * Usage: example [output.gz [input.gz]] 488 */ 489 490 int main(int argc, char *argv[]) { 491 Byte *compr, *uncompr; 492 uLong uncomprLen = 20000; 493 uLong comprLen = 3 * uncomprLen; 494 static const char* myVersion = ZLIB_VERSION; 495 496 if (zlibVersion()[0] != myVersion[0]) { 497 fprintf(stderr, "incompatible zlib version\n"); 498 exit(1); 499 500 } else if (strcmp(zlibVersion(), ZLIB_VERSION) != 0) { 501 fprintf(stderr, "warning: different zlib version linked: %s\n", 502 zlibVersion()); 503 } 504 505 printf("zlib version %s = 0x%04x, compile flags = 0x%lx\n", 506 ZLIB_VERSION, ZLIB_VERNUM, zlibCompileFlags()); 507 508 compr = (Byte*)calloc((uInt)comprLen, 1); 509 uncompr = (Byte*)calloc((uInt)uncomprLen, 1); 510 /* compr and uncompr are cleared to avoid reading uninitialized 511 * data and to ensure that uncompr compresses well. 512 */ 513 if (compr == Z_NULL || uncompr == Z_NULL) { 514 printf("out of memory\n"); 515 exit(1); 516 } 517 518 #ifdef Z_SOLO 519 (void)argc; 520 (void)argv; 521 #else 522 test_compress(compr, comprLen, uncompr, uncomprLen); 523 524 test_gzio((argc > 1 ? argv[1] : TESTFILE), 525 uncompr, uncomprLen); 526 #endif 527 528 test_deflate(compr, comprLen); 529 test_inflate(compr, comprLen, uncompr, uncomprLen); 530 531 test_large_deflate(compr, comprLen, uncompr, uncomprLen); 532 test_large_inflate(compr, comprLen, uncompr, uncomprLen); 533 534 test_flush(compr, &comprLen); 535 test_sync(compr, comprLen, uncompr, uncomprLen); 536 comprLen = 3 * uncomprLen; 537 538 test_dict_deflate(compr, comprLen); 539 test_dict_inflate(compr, comprLen, uncompr, uncomprLen); 540 541 free(compr); 542 free(uncompr); 543 544 return 0; 545 } 546