1 /* gzio.c -- IO on .gz files 2 * Copyright (C) 1995-2005 Jean-loup Gailly. 3 * For conditions of distribution and use, see copyright notice in zlib.h 4 * 5 * Compile this file with -DNO_GZCOMPRESS to avoid the compression code. 6 */ 7 8 /* @(#) $Id: gzio.c,v 3.7 2005/08/04 19:14:14 tor%cs.brown.edu Exp $ */ 9 10 #include <stdio.h> 11 12 #include "zutil.h" 13 14 #ifdef NO_DEFLATE /* for compatibility with old definition */ 15 # define NO_GZCOMPRESS 16 #endif 17 18 #ifndef NO_DUMMY_DECL 19 struct internal_state {int dummy;}; /* for buggy compilers */ 20 #endif 21 22 #ifndef Z_BUFSIZE 23 # ifdef MAXSEG_64K 24 # define Z_BUFSIZE 4096 /* minimize memory usage for 16-bit DOS */ 25 # else 26 # define Z_BUFSIZE 16384 27 # endif 28 #endif 29 #ifndef Z_PRINTF_BUFSIZE 30 # define Z_PRINTF_BUFSIZE 4096 31 #endif 32 33 #ifdef __MVS__ 34 # pragma map (fdopen , "\174\174FDOPEN") 35 FILE *fdopen(int, const char *); 36 #endif 37 38 #ifndef STDC 39 extern voidp malloc OF((uInt size)); 40 extern void free OF((voidpf ptr)); 41 #endif 42 43 #define ALLOC(size) malloc(size) 44 #define TRYFREE(p) {if (p) free(p);} 45 46 static int const gz_magic[2] = {0x1f, 0x8b}; /* gzip magic header */ 47 48 /* gzip flag byte */ 49 #define ASCII_FLAG 0x01 /* bit 0 set: file probably ascii text */ 50 #define HEAD_CRC 0x02 /* bit 1 set: header CRC present */ 51 #define EXTRA_FIELD 0x04 /* bit 2 set: extra field present */ 52 #define ORIG_NAME 0x08 /* bit 3 set: original file name present */ 53 #define COMMENT 0x10 /* bit 4 set: file comment present */ 54 #define RESERVED 0xE0 /* bits 5..7: reserved */ 55 56 typedef struct gz_stream { 57 z_stream stream; 58 int z_err; /* error code for last stream operation */ 59 int z_eof; /* set if end of input file */ 60 FILE *file; /* .gz file */ 61 Byte *inbuf; /* input buffer */ 62 Byte *outbuf; /* output buffer */ 63 uLong crc; /* crc32 of uncompressed data */ 64 char *msg; /* error message */ 65 char *path; /* path name for debugging only */ 66 int transparent; /* 1 if input file is not a .gz file */ 67 char mode; /* 'w' or 'r' */ 68 z_off_t start; /* start of compressed data in file (header skipped) */ 69 z_off_t in; /* bytes into deflate or inflate */ 70 z_off_t out; /* bytes out of deflate or inflate */ 71 int back; /* one character push-back */ 72 int last; /* true if push-back is last character */ 73 } gz_stream; 74 75 76 local gzFile gz_open OF((const char *path, const char *mode, int fd)); 77 #ifndef NO_GZCOMPRESS // Google Gears addition, to avoid compile warning 78 local int do_flush OF((gzFile file, int flush)); 79 #endif 80 local int get_byte OF((gz_stream *s)); 81 local void check_header OF((gz_stream *s)); 82 local int destroy OF((gz_stream *s)); 83 #ifndef NO_GZCOMPRESS // Google Gears addition, to avoid compile warning 84 local void putLong OF((FILE *file, uLong x)); 85 #endif 86 local uLong getLong OF((gz_stream *s)); 87 88 /* =========================================================================== 89 Opens a gzip (.gz) file for reading or writing. The mode parameter 90 is as in fopen ("rb" or "wb"). The file is given either by file descriptor 91 or path name (if fd == -1). 92 gz_open returns NULL if the file could not be opened or if there was 93 insufficient memory to allocate the (de)compression state; errno 94 can be checked to distinguish the two cases (if errno is zero, the 95 zlib error is Z_MEM_ERROR). 96 */ 97 local gzFile gz_open (path, mode, fd) 98 const char *path; 99 const char *mode; 100 int fd; 101 { 102 int err; 103 int level = Z_DEFAULT_COMPRESSION; /* compression level */ 104 int strategy = Z_DEFAULT_STRATEGY; /* compression strategy */ 105 char *p = (char*)mode; 106 gz_stream *s; 107 char fmode[80]; /* copy of mode, without the compression level */ 108 char *m = fmode; 109 110 if (!path || !mode) return Z_NULL; 111 112 s = (gz_stream *)ALLOC(sizeof(gz_stream)); 113 if (!s) return Z_NULL; 114 115 s->stream.zalloc = (alloc_func)0; 116 s->stream.zfree = (free_func)0; 117 s->stream.opaque = (voidpf)0; 118 s->stream.next_in = s->inbuf = Z_NULL; 119 s->stream.next_out = s->outbuf = Z_NULL; 120 s->stream.avail_in = s->stream.avail_out = 0; 121 s->file = NULL; 122 s->z_err = Z_OK; 123 s->z_eof = 0; 124 s->in = 0; 125 s->out = 0; 126 s->back = EOF; 127 s->crc = crc32(0L, Z_NULL, 0); 128 s->msg = NULL; 129 s->transparent = 0; 130 131 s->path = (char*)ALLOC(strlen(path)+1); 132 if (s->path == NULL) { 133 return destroy(s), (gzFile)Z_NULL; 134 } 135 strcpy(s->path, path); /* do this early for debugging */ 136 137 s->mode = '\0'; 138 do { 139 if (*p == 'r') s->mode = 'r'; 140 if (*p == 'w' || *p == 'a') s->mode = 'w'; 141 if (*p >= '0' && *p <= '9') { 142 level = *p - '0'; 143 } else if (*p == 'f') { 144 strategy = Z_FILTERED; 145 } else if (*p == 'h') { 146 strategy = Z_HUFFMAN_ONLY; 147 } else if (*p == 'R') { 148 strategy = Z_RLE; 149 } else { 150 *m++ = *p; /* copy the mode */ 151 } 152 } while (*p++ && m != fmode + sizeof(fmode)); 153 if (s->mode == '\0') return destroy(s), (gzFile)Z_NULL; 154 155 if (s->mode == 'w') { 156 #ifdef NO_GZCOMPRESS 157 err = Z_STREAM_ERROR; 158 #else 159 err = deflateInit2(&(s->stream), level, 160 Z_DEFLATED, -MAX_WBITS, DEF_MEM_LEVEL, strategy); 161 /* windowBits is passed < 0 to suppress zlib header */ 162 163 s->stream.next_out = s->outbuf = (Byte*)ALLOC(Z_BUFSIZE); 164 #endif 165 if (err != Z_OK || s->outbuf == Z_NULL) { 166 return destroy(s), (gzFile)Z_NULL; 167 } 168 } else { 169 s->stream.next_in = s->inbuf = (Byte*)ALLOC(Z_BUFSIZE); 170 171 err = inflateInit2(&(s->stream), -MAX_WBITS); 172 /* windowBits is passed < 0 to tell that there is no zlib header. 173 * Note that in this case inflate *requires* an extra "dummy" byte 174 * after the compressed stream in order to complete decompression and 175 * return Z_STREAM_END. Here the gzip CRC32 ensures that 4 bytes are 176 * present after the compressed stream. 177 */ 178 if (err != Z_OK || s->inbuf == Z_NULL) { 179 return destroy(s), (gzFile)Z_NULL; 180 } 181 } 182 s->stream.avail_out = Z_BUFSIZE; 183 184 errno = 0; 185 s->file = fd < 0 ? F_OPEN(path, fmode) : (FILE*)fdopen(fd, fmode); 186 187 if (s->file == NULL) { 188 return destroy(s), (gzFile)Z_NULL; 189 } 190 if (s->mode == 'w') { 191 /* Write a very simple .gz header: 192 */ 193 fprintf(s->file, "%c%c%c%c%c%c%c%c%c%c", gz_magic[0], gz_magic[1], 194 Z_DEFLATED, 0 /*flags*/, 0,0,0,0 /*time*/, 0 /*xflags*/, OS_CODE); 195 s->start = 10L; 196 /* We use 10L instead of ftell(s->file) to because ftell causes an 197 * fflush on some systems. This version of the library doesn't use 198 * start anyway in write mode, so this initialization is not 199 * necessary. 200 */ 201 } else { 202 check_header(s); /* skip the .gz header */ 203 s->start = ftell(s->file) - s->stream.avail_in; 204 } 205 206 return (gzFile)s; 207 } 208 209 /* =========================================================================== 210 Opens a gzip (.gz) file for reading or writing. 211 */ 212 gzFile ZEXPORT gzopen (path, mode) 213 const char *path; 214 const char *mode; 215 { 216 return gz_open (path, mode, -1); 217 } 218 219 /* =========================================================================== 220 Associate a gzFile with the file descriptor fd. fd is not dup'ed here 221 to mimic the behavio(u)r of fdopen. 222 */ 223 gzFile ZEXPORT gzdopen (fd, mode) 224 int fd; 225 const char *mode; 226 { 227 char name[46]; /* allow for up to 128-bit integers */ 228 229 if (fd < 0) return (gzFile)Z_NULL; 230 sprintf(name, "<fd:%d>", fd); /* for debugging */ 231 232 return gz_open (name, mode, fd); 233 } 234 235 /* =========================================================================== 236 * Update the compression level and strategy 237 */ 238 int ZEXPORT gzsetparams (file, level, strategy) 239 gzFile file; 240 int level; 241 int strategy; 242 { 243 gz_stream *s = (gz_stream*)file; 244 245 if (s == NULL || s->mode != 'w') return Z_STREAM_ERROR; 246 247 /* Make room to allow flushing */ 248 if (s->stream.avail_out == 0) { 249 250 s->stream.next_out = s->outbuf; 251 if (fwrite(s->outbuf, 1, Z_BUFSIZE, s->file) != Z_BUFSIZE) { 252 s->z_err = Z_ERRNO; 253 } 254 s->stream.avail_out = Z_BUFSIZE; 255 } 256 257 return deflateParams (&(s->stream), level, strategy); 258 } 259 260 /* =========================================================================== 261 Read a byte from a gz_stream; update next_in and avail_in. Return EOF 262 for end of file. 263 IN assertion: the stream s has been sucessfully opened for reading. 264 */ 265 local int get_byte(s) 266 gz_stream *s; 267 { 268 if (s->z_eof) return EOF; 269 if (s->stream.avail_in == 0) { 270 errno = 0; 271 s->stream.avail_in = (uInt)fread(s->inbuf, 1, Z_BUFSIZE, s->file); 272 if (s->stream.avail_in == 0) { 273 s->z_eof = 1; 274 if (ferror(s->file)) s->z_err = Z_ERRNO; 275 return EOF; 276 } 277 s->stream.next_in = s->inbuf; 278 } 279 s->stream.avail_in--; 280 return *(s->stream.next_in)++; 281 } 282 283 /* =========================================================================== 284 Check the gzip header of a gz_stream opened for reading. Set the stream 285 mode to transparent if the gzip magic header is not present; set s->err 286 to Z_DATA_ERROR if the magic header is present but the rest of the header 287 is incorrect. 288 IN assertion: the stream s has already been created sucessfully; 289 s->stream.avail_in is zero for the first time, but may be non-zero 290 for concatenated .gz files. 291 */ 292 local void check_header(s) 293 gz_stream *s; 294 { 295 int method; /* method byte */ 296 int flags; /* flags byte */ 297 uInt len; 298 int c; 299 300 /* Assure two bytes in the buffer so we can peek ahead -- handle case 301 where first byte of header is at the end of the buffer after the last 302 gzip segment */ 303 len = s->stream.avail_in; 304 if (len < 2) { 305 if (len) s->inbuf[0] = s->stream.next_in[0]; 306 errno = 0; 307 len = (uInt)fread(s->inbuf + len, 1, Z_BUFSIZE >> len, s->file); 308 if (len == 0 && ferror(s->file)) s->z_err = Z_ERRNO; 309 s->stream.avail_in += len; 310 s->stream.next_in = s->inbuf; 311 if (s->stream.avail_in < 2) { 312 s->transparent = s->stream.avail_in; 313 return; 314 } 315 } 316 317 /* Peek ahead to check the gzip magic header */ 318 if (s->stream.next_in[0] != gz_magic[0] || 319 s->stream.next_in[1] != gz_magic[1]) { 320 s->transparent = 1; 321 return; 322 } 323 s->stream.avail_in -= 2; 324 s->stream.next_in += 2; 325 326 /* Check the rest of the gzip header */ 327 method = get_byte(s); 328 flags = get_byte(s); 329 if (method != Z_DEFLATED || (flags & RESERVED) != 0) { 330 s->z_err = Z_DATA_ERROR; 331 return; 332 } 333 334 /* Discard time, xflags and OS code: */ 335 for (len = 0; len < 6; len++) (void)get_byte(s); 336 337 if ((flags & EXTRA_FIELD) != 0) { /* skip the extra field */ 338 len = (uInt)get_byte(s); 339 len += ((uInt)get_byte(s))<<8; 340 /* len is garbage if EOF but the loop below will quit anyway */ 341 while (len-- != 0 && get_byte(s) != EOF) ; 342 } 343 if ((flags & ORIG_NAME) != 0) { /* skip the original file name */ 344 while ((c = get_byte(s)) != 0 && c != EOF) ; 345 } 346 if ((flags & COMMENT) != 0) { /* skip the .gz file comment */ 347 while ((c = get_byte(s)) != 0 && c != EOF) ; 348 } 349 if ((flags & HEAD_CRC) != 0) { /* skip the header crc */ 350 for (len = 0; len < 2; len++) (void)get_byte(s); 351 } 352 s->z_err = s->z_eof ? Z_DATA_ERROR : Z_OK; 353 } 354 355 /* =========================================================================== 356 * Cleanup then free the given gz_stream. Return a zlib error code. 357 Try freeing in the reverse order of allocations. 358 */ 359 local int destroy (s) 360 gz_stream *s; 361 { 362 int err = Z_OK; 363 364 if (!s) return Z_STREAM_ERROR; 365 366 TRYFREE(s->msg); 367 368 if (s->stream.state != NULL) { 369 if (s->mode == 'w') { 370 #ifdef NO_GZCOMPRESS 371 err = Z_STREAM_ERROR; 372 #else 373 err = deflateEnd(&(s->stream)); 374 #endif 375 } else if (s->mode == 'r') { 376 err = inflateEnd(&(s->stream)); 377 } 378 } 379 if (s->file != NULL && fclose(s->file)) { 380 #ifdef ESPIPE 381 if (errno != ESPIPE) /* fclose is broken for pipes in HP/UX */ 382 #endif 383 err = Z_ERRNO; 384 } 385 if (s->z_err < 0) err = s->z_err; 386 387 TRYFREE(s->inbuf); 388 TRYFREE(s->outbuf); 389 TRYFREE(s->path); 390 TRYFREE(s); 391 return err; 392 } 393 394 /* =========================================================================== 395 Reads the given number of uncompressed bytes from the compressed file. 396 gzread returns the number of bytes actually read (0 for end of file). 397 */ 398 int ZEXPORT gzread (file, buf, len) 399 gzFile file; 400 voidp buf; 401 unsigned len; 402 { 403 gz_stream *s = (gz_stream*)file; 404 Bytef *start = (Bytef*)buf; /* starting point for crc computation */ 405 Byte *next_out; /* == stream.next_out but not forced far (for MSDOS) */ 406 407 if (s == NULL || s->mode != 'r') return Z_STREAM_ERROR; 408 409 if (s->z_err == Z_DATA_ERROR || s->z_err == Z_ERRNO) return -1; 410 if (s->z_err == Z_STREAM_END) return 0; /* EOF */ 411 412 next_out = (Byte*)buf; 413 s->stream.next_out = (Bytef*)buf; 414 s->stream.avail_out = len; 415 416 if (s->stream.avail_out && s->back != EOF) { 417 *next_out++ = s->back; 418 s->stream.next_out++; 419 s->stream.avail_out--; 420 s->back = EOF; 421 s->out++; 422 start++; 423 if (s->last) { 424 s->z_err = Z_STREAM_END; 425 return 1; 426 } 427 } 428 429 while (s->stream.avail_out != 0) { 430 431 if (s->transparent) { 432 /* Copy first the lookahead bytes: */ 433 uInt n = s->stream.avail_in; 434 if (n > s->stream.avail_out) n = s->stream.avail_out; 435 if (n > 0) { 436 zmemcpy(s->stream.next_out, s->stream.next_in, n); 437 next_out += n; 438 s->stream.next_out = next_out; 439 s->stream.next_in += n; 440 s->stream.avail_out -= n; 441 s->stream.avail_in -= n; 442 } 443 if (s->stream.avail_out > 0) { 444 s->stream.avail_out -= 445 (uInt)fread(next_out, 1, s->stream.avail_out, s->file); 446 } 447 len -= s->stream.avail_out; 448 s->in += len; 449 s->out += len; 450 if (len == 0) s->z_eof = 1; 451 return (int)len; 452 } 453 if (s->stream.avail_in == 0 && !s->z_eof) { 454 455 errno = 0; 456 s->stream.avail_in = (uInt)fread(s->inbuf, 1, Z_BUFSIZE, s->file); 457 if (s->stream.avail_in == 0) { 458 s->z_eof = 1; 459 if (ferror(s->file)) { 460 s->z_err = Z_ERRNO; 461 break; 462 } 463 } 464 s->stream.next_in = s->inbuf; 465 } 466 s->in += s->stream.avail_in; 467 s->out += s->stream.avail_out; 468 s->z_err = inflate(&(s->stream), Z_NO_FLUSH); 469 s->in -= s->stream.avail_in; 470 s->out -= s->stream.avail_out; 471 472 if (s->z_err == Z_STREAM_END) { 473 /* Check CRC and original size */ 474 s->crc = crc32(s->crc, start, (uInt)(s->stream.next_out - start)); 475 start = s->stream.next_out; 476 477 if (getLong(s) != s->crc) { 478 s->z_err = Z_DATA_ERROR; 479 } else { 480 (void)getLong(s); 481 /* The uncompressed length returned by above getlong() may be 482 * different from s->out in case of concatenated .gz files. 483 * Check for such files: 484 */ 485 check_header(s); 486 if (s->z_err == Z_OK) { 487 inflateReset(&(s->stream)); 488 s->crc = crc32(0L, Z_NULL, 0); 489 } 490 } 491 } 492 if (s->z_err != Z_OK || s->z_eof) break; 493 } 494 s->crc = crc32(s->crc, start, (uInt)(s->stream.next_out - start)); 495 496 if (len == s->stream.avail_out && 497 (s->z_err == Z_DATA_ERROR || s->z_err == Z_ERRNO)) 498 return -1; 499 return (int)(len - s->stream.avail_out); 500 } 501 502 503 /* =========================================================================== 504 Reads one byte from the compressed file. gzgetc returns this byte 505 or -1 in case of end of file or error. 506 */ 507 int ZEXPORT gzgetc(file) 508 gzFile file; 509 { 510 unsigned char c; 511 512 return gzread(file, &c, 1) == 1 ? c : -1; 513 } 514 515 516 /* =========================================================================== 517 Push one byte back onto the stream. 518 */ 519 int ZEXPORT gzungetc(c, file) 520 int c; 521 gzFile file; 522 { 523 gz_stream *s = (gz_stream*)file; 524 525 if (s == NULL || s->mode != 'r' || c == EOF || s->back != EOF) return EOF; 526 s->back = c; 527 s->out--; 528 s->last = (s->z_err == Z_STREAM_END); 529 if (s->last) s->z_err = Z_OK; 530 s->z_eof = 0; 531 return c; 532 } 533 534 535 /* =========================================================================== 536 Reads bytes from the compressed file until len-1 characters are 537 read, or a newline character is read and transferred to buf, or an 538 end-of-file condition is encountered. The string is then terminated 539 with a null character. 540 gzgets returns buf, or Z_NULL in case of error. 541 542 The current implementation is not optimized at all. 543 */ 544 char * ZEXPORT gzgets(file, buf, len) 545 gzFile file; 546 char *buf; 547 int len; 548 { 549 char *b = buf; 550 if (buf == Z_NULL || len <= 0) return Z_NULL; 551 552 while (--len > 0 && gzread(file, buf, 1) == 1 && *buf++ != '\n') ; 553 *buf = '\0'; 554 return b == buf && len > 0 ? Z_NULL : b; 555 } 556 557 558 #ifndef NO_GZCOMPRESS 559 /* =========================================================================== 560 Writes the given number of uncompressed bytes into the compressed file. 561 gzwrite returns the number of bytes actually written (0 in case of error). 562 */ 563 int ZEXPORT gzwrite (file, buf, len) 564 gzFile file; 565 voidpc buf; 566 unsigned len; 567 { 568 gz_stream *s = (gz_stream*)file; 569 570 if (s == NULL || s->mode != 'w') return Z_STREAM_ERROR; 571 572 s->stream.next_in = (Bytef*)buf; 573 s->stream.avail_in = len; 574 575 while (s->stream.avail_in != 0) { 576 577 if (s->stream.avail_out == 0) { 578 579 s->stream.next_out = s->outbuf; 580 if (fwrite(s->outbuf, 1, Z_BUFSIZE, s->file) != Z_BUFSIZE) { 581 s->z_err = Z_ERRNO; 582 break; 583 } 584 s->stream.avail_out = Z_BUFSIZE; 585 } 586 s->in += s->stream.avail_in; 587 s->out += s->stream.avail_out; 588 s->z_err = deflate(&(s->stream), Z_NO_FLUSH); 589 s->in -= s->stream.avail_in; 590 s->out -= s->stream.avail_out; 591 if (s->z_err != Z_OK) break; 592 } 593 s->crc = crc32(s->crc, (const Bytef *)buf, len); 594 595 return (int)(len - s->stream.avail_in); 596 } 597 598 599 /* =========================================================================== 600 Converts, formats, and writes the args to the compressed file under 601 control of the format string, as in fprintf. gzprintf returns the number of 602 uncompressed bytes actually written (0 in case of error). 603 */ 604 #ifdef STDC 605 #include <stdarg.h> 606 607 int ZEXPORTVA gzprintf (gzFile file, const char *format, /* args */ ...) 608 { 609 char buf[Z_PRINTF_BUFSIZE]; 610 va_list va; 611 int len; 612 613 buf[sizeof(buf) - 1] = 0; 614 va_start(va, format); 615 #ifdef NO_vsnprintf 616 # ifdef HAS_vsprintf_void 617 (void)vsprintf(buf, format, va); 618 va_end(va); 619 for (len = 0; len < sizeof(buf); len++) 620 if (buf[len] == 0) break; 621 # else 622 len = vsprintf(buf, format, va); 623 va_end(va); 624 # endif 625 #else 626 # ifdef HAS_vsnprintf_void 627 (void)vsnprintf(buf, sizeof(buf), format, va); 628 va_end(va); 629 len = strlen(buf); 630 # else 631 len = vsnprintf(buf, sizeof(buf), format, va); 632 va_end(va); 633 # endif 634 #endif 635 if (len <= 0 || len >= (int)sizeof(buf) || buf[sizeof(buf) - 1] != 0) 636 return 0; 637 return gzwrite(file, buf, (unsigned)len); 638 } 639 #else /* not ANSI C */ 640 641 int ZEXPORTVA gzprintf (file, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, 642 a11, a12, a13, a14, a15, a16, a17, a18, a19, a20) 643 gzFile file; 644 const char *format; 645 int a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, 646 a11, a12, a13, a14, a15, a16, a17, a18, a19, a20; 647 { 648 char buf[Z_PRINTF_BUFSIZE]; 649 int len; 650 651 buf[sizeof(buf) - 1] = 0; 652 #ifdef NO_snprintf 653 # ifdef HAS_sprintf_void 654 sprintf(buf, format, a1, a2, a3, a4, a5, a6, a7, a8, 655 a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20); 656 for (len = 0; len < sizeof(buf); len++) 657 if (buf[len] == 0) break; 658 # else 659 len = sprintf(buf, format, a1, a2, a3, a4, a5, a6, a7, a8, 660 a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20); 661 # endif 662 #else 663 # ifdef HAS_snprintf_void 664 snprintf(buf, sizeof(buf), format, a1, a2, a3, a4, a5, a6, a7, a8, 665 a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20); 666 len = strlen(buf); 667 # else 668 len = snprintf(buf, sizeof(buf), format, a1, a2, a3, a4, a5, a6, a7, a8, 669 a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20); 670 # endif 671 #endif 672 if (len <= 0 || len >= sizeof(buf) || buf[sizeof(buf) - 1] != 0) 673 return 0; 674 return gzwrite(file, buf, len); 675 } 676 #endif 677 678 /* =========================================================================== 679 Writes c, converted to an unsigned char, into the compressed file. 680 gzputc returns the value that was written, or -1 in case of error. 681 */ 682 int ZEXPORT gzputc(file, c) 683 gzFile file; 684 int c; 685 { 686 unsigned char cc = (unsigned char) c; /* required for big endian systems */ 687 688 return gzwrite(file, &cc, 1) == 1 ? (int)cc : -1; 689 } 690 691 692 /* =========================================================================== 693 Writes the given null-terminated string to the compressed file, excluding 694 the terminating null character. 695 gzputs returns the number of characters written, or -1 in case of error. 696 */ 697 int ZEXPORT gzputs(file, s) 698 gzFile file; 699 const char *s; 700 { 701 return gzwrite(file, (char*)s, (unsigned)strlen(s)); 702 } 703 704 705 /* =========================================================================== 706 Flushes all pending output into the compressed file. The parameter 707 flush is as in the deflate() function. 708 */ 709 local int do_flush (file, flush) 710 gzFile file; 711 int flush; 712 { 713 uInt len; 714 int done = 0; 715 gz_stream *s = (gz_stream*)file; 716 717 if (s == NULL || s->mode != 'w') return Z_STREAM_ERROR; 718 719 s->stream.avail_in = 0; /* should be zero already anyway */ 720 721 for (;;) { 722 len = Z_BUFSIZE - s->stream.avail_out; 723 724 if (len != 0) { 725 if ((uInt)fwrite(s->outbuf, 1, len, s->file) != len) { 726 s->z_err = Z_ERRNO; 727 return Z_ERRNO; 728 } 729 s->stream.next_out = s->outbuf; 730 s->stream.avail_out = Z_BUFSIZE; 731 } 732 if (done) break; 733 s->out += s->stream.avail_out; 734 s->z_err = deflate(&(s->stream), flush); 735 s->out -= s->stream.avail_out; 736 737 /* Ignore the second of two consecutive flushes: */ 738 if (len == 0 && s->z_err == Z_BUF_ERROR) s->z_err = Z_OK; 739 740 /* deflate has finished flushing only when it hasn't used up 741 * all the available space in the output buffer: 742 */ 743 done = (s->stream.avail_out != 0 || s->z_err == Z_STREAM_END); 744 745 if (s->z_err != Z_OK && s->z_err != Z_STREAM_END) break; 746 } 747 return s->z_err == Z_STREAM_END ? Z_OK : s->z_err; 748 } 749 750 int ZEXPORT gzflush (file, flush) 751 gzFile file; 752 int flush; 753 { 754 gz_stream *s = (gz_stream*)file; 755 int err = do_flush (file, flush); 756 757 if (err) return err; 758 fflush(s->file); 759 return s->z_err == Z_STREAM_END ? Z_OK : s->z_err; 760 } 761 #endif /* NO_GZCOMPRESS */ 762 763 /* =========================================================================== 764 Sets the starting position for the next gzread or gzwrite on the given 765 compressed file. The offset represents a number of bytes in the 766 gzseek returns the resulting offset location as measured in bytes from 767 the beginning of the uncompressed stream, or -1 in case of error. 768 SEEK_END is not implemented, returns error. 769 In this version of the library, gzseek can be extremely slow. 770 */ 771 z_off_t ZEXPORT gzseek (file, offset, whence) 772 gzFile file; 773 z_off_t offset; 774 int whence; 775 { 776 gz_stream *s = (gz_stream*)file; 777 778 if (s == NULL || whence == SEEK_END || 779 s->z_err == Z_ERRNO || s->z_err == Z_DATA_ERROR) { 780 return -1L; 781 } 782 783 if (s->mode == 'w') { 784 #ifdef NO_GZCOMPRESS 785 return -1L; 786 #else 787 if (whence == SEEK_SET) { 788 offset -= s->in; 789 } 790 if (offset < 0) return -1L; 791 792 /* At this point, offset is the number of zero bytes to write. */ 793 if (s->inbuf == Z_NULL) { 794 s->inbuf = (Byte*)ALLOC(Z_BUFSIZE); /* for seeking */ 795 if (s->inbuf == Z_NULL) return -1L; 796 zmemzero(s->inbuf, Z_BUFSIZE); 797 } 798 while (offset > 0) { 799 uInt size = Z_BUFSIZE; 800 if (offset < Z_BUFSIZE) size = (uInt)offset; 801 802 size = gzwrite(file, s->inbuf, size); 803 if (size == 0) return -1L; 804 805 offset -= size; 806 } 807 return s->in; 808 #endif 809 } 810 /* Rest of function is for reading only */ 811 812 /* compute absolute position */ 813 if (whence == SEEK_CUR) { 814 offset += s->out; 815 } 816 if (offset < 0) return -1L; 817 818 if (s->transparent) { 819 /* map to fseek */ 820 s->back = EOF; 821 s->stream.avail_in = 0; 822 s->stream.next_in = s->inbuf; 823 if (fseek(s->file, offset, SEEK_SET) < 0) return -1L; 824 825 s->in = s->out = offset; 826 return offset; 827 } 828 829 /* For a negative seek, rewind and use positive seek */ 830 if (offset >= s->out) { 831 offset -= s->out; 832 } else if (gzrewind(file) < 0) { 833 return -1L; 834 } 835 /* offset is now the number of bytes to skip. */ 836 837 if (offset != 0 && s->outbuf == Z_NULL) { 838 s->outbuf = (Byte*)ALLOC(Z_BUFSIZE); 839 if (s->outbuf == Z_NULL) return -1L; 840 } 841 if (offset && s->back != EOF) { 842 s->back = EOF; 843 s->out++; 844 offset--; 845 if (s->last) s->z_err = Z_STREAM_END; 846 } 847 while (offset > 0) { 848 int size = Z_BUFSIZE; 849 if (offset < Z_BUFSIZE) size = (int)offset; 850 851 size = gzread(file, s->outbuf, (uInt)size); 852 if (size <= 0) return -1L; 853 offset -= size; 854 } 855 return s->out; 856 } 857 858 /* =========================================================================== 859 Rewinds input file. 860 */ 861 int ZEXPORT gzrewind (file) 862 gzFile file; 863 { 864 gz_stream *s = (gz_stream*)file; 865 866 if (s == NULL || s->mode != 'r') return -1; 867 868 s->z_err = Z_OK; 869 s->z_eof = 0; 870 s->back = EOF; 871 s->stream.avail_in = 0; 872 s->stream.next_in = s->inbuf; 873 s->crc = crc32(0L, Z_NULL, 0); 874 if (!s->transparent) (void)inflateReset(&s->stream); 875 s->in = 0; 876 s->out = 0; 877 return fseek(s->file, s->start, SEEK_SET); 878 } 879 880 /* =========================================================================== 881 Returns the starting position for the next gzread or gzwrite on the 882 given compressed file. This position represents a number of bytes in the 883 uncompressed data stream. 884 */ 885 z_off_t ZEXPORT gztell (file) 886 gzFile file; 887 { 888 return gzseek(file, 0L, SEEK_CUR); 889 } 890 891 /* =========================================================================== 892 Returns 1 when EOF has previously been detected reading the given 893 input stream, otherwise zero. 894 */ 895 int ZEXPORT gzeof (file) 896 gzFile file; 897 { 898 gz_stream *s = (gz_stream*)file; 899 900 /* With concatenated compressed files that can have embedded 901 * crc trailers, z_eof is no longer the only/best indicator of EOF 902 * on a gz_stream. Handle end-of-stream error explicitly here. 903 */ 904 if (s == NULL || s->mode != 'r') return 0; 905 if (s->z_eof) return 1; 906 return s->z_err == Z_STREAM_END; 907 } 908 909 /* =========================================================================== 910 Returns 1 if reading and doing so transparently, otherwise zero. 911 */ 912 int ZEXPORT gzdirect (file) 913 gzFile file; 914 { 915 gz_stream *s = (gz_stream*)file; 916 917 if (s == NULL || s->mode != 'r') return 0; 918 return s->transparent; 919 } 920 921 #ifndef NO_GZCOMPRESS // Google Gears addition, to avoid compile warning 922 /* =========================================================================== 923 Outputs a long in LSB order to the given file 924 */ 925 local void putLong (file, x) 926 FILE *file; 927 uLong x; 928 { 929 int n; 930 for (n = 0; n < 4; n++) { 931 fputc((int)(x & 0xff), file); 932 x >>= 8; 933 } 934 } 935 #endif 936 937 /* =========================================================================== 938 Reads a long in LSB order from the given gz_stream. Sets z_err in case 939 of error. 940 */ 941 local uLong getLong (s) 942 gz_stream *s; 943 { 944 uLong x = (uLong)get_byte(s); 945 int c; 946 947 x += ((uLong)get_byte(s))<<8; 948 x += ((uLong)get_byte(s))<<16; 949 c = get_byte(s); 950 if (c == EOF) s->z_err = Z_DATA_ERROR; 951 x += ((uLong)c)<<24; 952 return x; 953 } 954 955 /* =========================================================================== 956 Flushes all pending output if necessary, closes the compressed file 957 and deallocates all the (de)compression state. 958 */ 959 int ZEXPORT gzclose (file) 960 gzFile file; 961 { 962 gz_stream *s = (gz_stream*)file; 963 964 if (s == NULL) return Z_STREAM_ERROR; 965 966 if (s->mode == 'w') { 967 #ifdef NO_GZCOMPRESS 968 return Z_STREAM_ERROR; 969 #else 970 if (do_flush (file, Z_FINISH) != Z_OK) 971 return destroy((gz_stream*)file); 972 973 putLong (s->file, s->crc); 974 putLong (s->file, (uLong)(s->in & 0xffffffff)); 975 #endif 976 } 977 return destroy((gz_stream*)file); 978 } 979 980 // Google Gears modification: strerror is not present on WinCE. 981 #if defined(STDC) && !defined(_WIN32_WCE) 982 # define zstrerror(errnum) strerror(errnum) 983 #else 984 # define zstrerror(errnum) "" 985 #endif 986 987 /* =========================================================================== 988 Returns the error message for the last error which occurred on the 989 given compressed file. errnum is set to zlib error number. If an 990 error occurred in the file system and not in the compression library, 991 errnum is set to Z_ERRNO and the application may consult errno 992 to get the exact error code. 993 */ 994 const char * ZEXPORT gzerror (file, errnum) 995 gzFile file; 996 int *errnum; 997 { 998 char *m; 999 gz_stream *s = (gz_stream*)file; 1000 1001 if (s == NULL) { 1002 *errnum = Z_STREAM_ERROR; 1003 return (const char*)ERR_MSG(Z_STREAM_ERROR); 1004 } 1005 *errnum = s->z_err; 1006 if (*errnum == Z_OK) return (const char*)""; 1007 1008 m = (char*)(*errnum == Z_ERRNO ? zstrerror(errno) : s->stream.msg); 1009 1010 if (m == NULL || *m == '\0') m = (char*)ERR_MSG(s->z_err); 1011 1012 TRYFREE(s->msg); 1013 s->msg = (char*)ALLOC(strlen(s->path) + strlen(m) + 3); 1014 if (s->msg == Z_NULL) return (const char*)ERR_MSG(Z_MEM_ERROR); 1015 strcpy(s->msg, s->path); 1016 strcat(s->msg, ": "); 1017 strcat(s->msg, m); 1018 return (const char*)s->msg; 1019 } 1020 1021 /* =========================================================================== 1022 Clear the error and end-of-file flags, and do the same for the real file. 1023 */ 1024 void ZEXPORT gzclearerr (file) 1025 gzFile file; 1026 { 1027 gz_stream *s = (gz_stream*)file; 1028 1029 if (s == NULL) return; 1030 if (s->z_err != Z_STREAM_END) s->z_err = Z_OK; 1031 s->z_eof = 0; 1032 clearerr(s->file); 1033 } 1034