istereo

annotate libs/zlib/gzio.c @ 33:33e9eedad390

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