istereo2

annotate libs/zlib/gzio.c @ 20:2b85d05df3f2

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