dbf-halloween2015

annotate libs/zlib/gzio.c @ 3:c37fe5d8a4ed

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