vrshoot

annotate libs/zlib/gzio.c @ 0:b2f14e535253

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