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