vrshoot
diff 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 |
line diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/libs/zlib/gzio.c Sat Feb 01 19:58:19 2014 +0200 1.3 @@ -0,0 +1,1026 @@ 1.4 +/* gzio.c -- IO on .gz files 1.5 + * Copyright (C) 1995-2005 Jean-loup Gailly. 1.6 + * For conditions of distribution and use, see copyright notice in zlib.h 1.7 + * 1.8 + * Compile this file with -DNO_GZCOMPRESS to avoid the compression code. 1.9 + */ 1.10 + 1.11 +/* @(#) $Id$ */ 1.12 + 1.13 +#include <stdio.h> 1.14 + 1.15 +#include "zutil.h" 1.16 + 1.17 +#ifdef NO_DEFLATE /* for compatibility with old definition */ 1.18 +# define NO_GZCOMPRESS 1.19 +#endif 1.20 + 1.21 +#ifndef NO_DUMMY_DECL 1.22 +struct internal_state {int dummy;}; /* for buggy compilers */ 1.23 +#endif 1.24 + 1.25 +#ifndef Z_BUFSIZE 1.26 +# ifdef MAXSEG_64K 1.27 +# define Z_BUFSIZE 4096 /* minimize memory usage for 16-bit DOS */ 1.28 +# else 1.29 +# define Z_BUFSIZE 16384 1.30 +# endif 1.31 +#endif 1.32 +#ifndef Z_PRINTF_BUFSIZE 1.33 +# define Z_PRINTF_BUFSIZE 4096 1.34 +#endif 1.35 + 1.36 +#ifdef __MVS__ 1.37 +# pragma map (fdopen , "\174\174FDOPEN") 1.38 + FILE *fdopen(int, const char *); 1.39 +#endif 1.40 + 1.41 +#ifndef STDC 1.42 +extern voidp malloc OF((uInt size)); 1.43 +extern void free OF((voidpf ptr)); 1.44 +#endif 1.45 + 1.46 +#define ALLOC(size) malloc(size) 1.47 +#define TRYFREE(p) {if (p) free(p);} 1.48 + 1.49 +static int const gz_magic[2] = {0x1f, 0x8b}; /* gzip magic header */ 1.50 + 1.51 +/* gzip flag byte */ 1.52 +#define ASCII_FLAG 0x01 /* bit 0 set: file probably ascii text */ 1.53 +#define HEAD_CRC 0x02 /* bit 1 set: header CRC present */ 1.54 +#define EXTRA_FIELD 0x04 /* bit 2 set: extra field present */ 1.55 +#define ORIG_NAME 0x08 /* bit 3 set: original file name present */ 1.56 +#define COMMENT 0x10 /* bit 4 set: file comment present */ 1.57 +#define RESERVED 0xE0 /* bits 5..7: reserved */ 1.58 + 1.59 +typedef struct gz_stream { 1.60 + z_stream stream; 1.61 + int z_err; /* error code for last stream operation */ 1.62 + int z_eof; /* set if end of input file */ 1.63 + FILE *file; /* .gz file */ 1.64 + Byte *inbuf; /* input buffer */ 1.65 + Byte *outbuf; /* output buffer */ 1.66 + uLong crc; /* crc32 of uncompressed data */ 1.67 + char *msg; /* error message */ 1.68 + char *path; /* path name for debugging only */ 1.69 + int transparent; /* 1 if input file is not a .gz file */ 1.70 + char mode; /* 'w' or 'r' */ 1.71 + z_off_t start; /* start of compressed data in file (header skipped) */ 1.72 + z_off_t in; /* bytes into deflate or inflate */ 1.73 + z_off_t out; /* bytes out of deflate or inflate */ 1.74 + int back; /* one character push-back */ 1.75 + int last; /* true if push-back is last character */ 1.76 +} gz_stream; 1.77 + 1.78 + 1.79 +local gzFile gz_open OF((const char *path, const char *mode, int fd)); 1.80 +local int do_flush OF((gzFile file, int flush)); 1.81 +local int get_byte OF((gz_stream *s)); 1.82 +local void check_header OF((gz_stream *s)); 1.83 +local int destroy OF((gz_stream *s)); 1.84 +local void putLong OF((FILE *file, uLong x)); 1.85 +local uLong getLong OF((gz_stream *s)); 1.86 + 1.87 +/* =========================================================================== 1.88 + Opens a gzip (.gz) file for reading or writing. The mode parameter 1.89 + is as in fopen ("rb" or "wb"). The file is given either by file descriptor 1.90 + or path name (if fd == -1). 1.91 + gz_open returns NULL if the file could not be opened or if there was 1.92 + insufficient memory to allocate the (de)compression state; errno 1.93 + can be checked to distinguish the two cases (if errno is zero, the 1.94 + zlib error is Z_MEM_ERROR). 1.95 +*/ 1.96 +local gzFile gz_open (path, mode, fd) 1.97 + const char *path; 1.98 + const char *mode; 1.99 + int fd; 1.100 +{ 1.101 + int err; 1.102 + int level = Z_DEFAULT_COMPRESSION; /* compression level */ 1.103 + int strategy = Z_DEFAULT_STRATEGY; /* compression strategy */ 1.104 + char *p = (char*)mode; 1.105 + gz_stream *s; 1.106 + char fmode[80]; /* copy of mode, without the compression level */ 1.107 + char *m = fmode; 1.108 + 1.109 + if (!path || !mode) return Z_NULL; 1.110 + 1.111 + s = (gz_stream *)ALLOC(sizeof(gz_stream)); 1.112 + if (!s) return Z_NULL; 1.113 + 1.114 + s->stream.zalloc = (alloc_func)0; 1.115 + s->stream.zfree = (free_func)0; 1.116 + s->stream.opaque = (voidpf)0; 1.117 + s->stream.next_in = s->inbuf = Z_NULL; 1.118 + s->stream.next_out = s->outbuf = Z_NULL; 1.119 + s->stream.avail_in = s->stream.avail_out = 0; 1.120 + s->file = NULL; 1.121 + s->z_err = Z_OK; 1.122 + s->z_eof = 0; 1.123 + s->in = 0; 1.124 + s->out = 0; 1.125 + s->back = EOF; 1.126 + s->crc = crc32(0L, Z_NULL, 0); 1.127 + s->msg = NULL; 1.128 + s->transparent = 0; 1.129 + 1.130 + s->path = (char*)ALLOC(strlen(path)+1); 1.131 + if (s->path == NULL) { 1.132 + return destroy(s), (gzFile)Z_NULL; 1.133 + } 1.134 + strcpy(s->path, path); /* do this early for debugging */ 1.135 + 1.136 + s->mode = '\0'; 1.137 + do { 1.138 + if (*p == 'r') s->mode = 'r'; 1.139 + if (*p == 'w' || *p == 'a') s->mode = 'w'; 1.140 + if (*p >= '0' && *p <= '9') { 1.141 + level = *p - '0'; 1.142 + } else if (*p == 'f') { 1.143 + strategy = Z_FILTERED; 1.144 + } else if (*p == 'h') { 1.145 + strategy = Z_HUFFMAN_ONLY; 1.146 + } else if (*p == 'R') { 1.147 + strategy = Z_RLE; 1.148 + } else { 1.149 + *m++ = *p; /* copy the mode */ 1.150 + } 1.151 + } while (*p++ && m != fmode + sizeof(fmode)); 1.152 + if (s->mode == '\0') return destroy(s), (gzFile)Z_NULL; 1.153 + 1.154 + if (s->mode == 'w') { 1.155 +#ifdef NO_GZCOMPRESS 1.156 + err = Z_STREAM_ERROR; 1.157 +#else 1.158 + err = deflateInit2(&(s->stream), level, 1.159 + Z_DEFLATED, -MAX_WBITS, DEF_MEM_LEVEL, strategy); 1.160 + /* windowBits is passed < 0 to suppress zlib header */ 1.161 + 1.162 + s->stream.next_out = s->outbuf = (Byte*)ALLOC(Z_BUFSIZE); 1.163 +#endif 1.164 + if (err != Z_OK || s->outbuf == Z_NULL) { 1.165 + return destroy(s), (gzFile)Z_NULL; 1.166 + } 1.167 + } else { 1.168 + s->stream.next_in = s->inbuf = (Byte*)ALLOC(Z_BUFSIZE); 1.169 + 1.170 + err = inflateInit2(&(s->stream), -MAX_WBITS); 1.171 + /* windowBits is passed < 0 to tell that there is no zlib header. 1.172 + * Note that in this case inflate *requires* an extra "dummy" byte 1.173 + * after the compressed stream in order to complete decompression and 1.174 + * return Z_STREAM_END. Here the gzip CRC32 ensures that 4 bytes are 1.175 + * present after the compressed stream. 1.176 + */ 1.177 + if (err != Z_OK || s->inbuf == Z_NULL) { 1.178 + return destroy(s), (gzFile)Z_NULL; 1.179 + } 1.180 + } 1.181 + s->stream.avail_out = Z_BUFSIZE; 1.182 + 1.183 + errno = 0; 1.184 + s->file = fd < 0 ? F_OPEN(path, fmode) : (FILE*)fdopen(fd, fmode); 1.185 + 1.186 + if (s->file == NULL) { 1.187 + return destroy(s), (gzFile)Z_NULL; 1.188 + } 1.189 + if (s->mode == 'w') { 1.190 + /* Write a very simple .gz header: 1.191 + */ 1.192 + fprintf(s->file, "%c%c%c%c%c%c%c%c%c%c", gz_magic[0], gz_magic[1], 1.193 + Z_DEFLATED, 0 /*flags*/, 0,0,0,0 /*time*/, 0 /*xflags*/, OS_CODE); 1.194 + s->start = 10L; 1.195 + /* We use 10L instead of ftell(s->file) to because ftell causes an 1.196 + * fflush on some systems. This version of the library doesn't use 1.197 + * start anyway in write mode, so this initialization is not 1.198 + * necessary. 1.199 + */ 1.200 + } else { 1.201 + check_header(s); /* skip the .gz header */ 1.202 + s->start = ftell(s->file) - s->stream.avail_in; 1.203 + } 1.204 + 1.205 + return (gzFile)s; 1.206 +} 1.207 + 1.208 +/* =========================================================================== 1.209 + Opens a gzip (.gz) file for reading or writing. 1.210 +*/ 1.211 +gzFile ZEXPORT gzopen (path, mode) 1.212 + const char *path; 1.213 + const char *mode; 1.214 +{ 1.215 + return gz_open (path, mode, -1); 1.216 +} 1.217 + 1.218 +/* =========================================================================== 1.219 + Associate a gzFile with the file descriptor fd. fd is not dup'ed here 1.220 + to mimic the behavio(u)r of fdopen. 1.221 +*/ 1.222 +gzFile ZEXPORT gzdopen (fd, mode) 1.223 + int fd; 1.224 + const char *mode; 1.225 +{ 1.226 + char name[46]; /* allow for up to 128-bit integers */ 1.227 + 1.228 + if (fd < 0) return (gzFile)Z_NULL; 1.229 + sprintf(name, "<fd:%d>", fd); /* for debugging */ 1.230 + 1.231 + return gz_open (name, mode, fd); 1.232 +} 1.233 + 1.234 +/* =========================================================================== 1.235 + * Update the compression level and strategy 1.236 + */ 1.237 +int ZEXPORT gzsetparams (file, level, strategy) 1.238 + gzFile file; 1.239 + int level; 1.240 + int strategy; 1.241 +{ 1.242 + gz_stream *s = (gz_stream*)file; 1.243 + 1.244 + if (s == NULL || s->mode != 'w') return Z_STREAM_ERROR; 1.245 + 1.246 + /* Make room to allow flushing */ 1.247 + if (s->stream.avail_out == 0) { 1.248 + 1.249 + s->stream.next_out = s->outbuf; 1.250 + if (fwrite(s->outbuf, 1, Z_BUFSIZE, s->file) != Z_BUFSIZE) { 1.251 + s->z_err = Z_ERRNO; 1.252 + } 1.253 + s->stream.avail_out = Z_BUFSIZE; 1.254 + } 1.255 + 1.256 + return deflateParams (&(s->stream), level, strategy); 1.257 +} 1.258 + 1.259 +/* =========================================================================== 1.260 + Read a byte from a gz_stream; update next_in and avail_in. Return EOF 1.261 + for end of file. 1.262 + IN assertion: the stream s has been sucessfully opened for reading. 1.263 +*/ 1.264 +local int get_byte(s) 1.265 + gz_stream *s; 1.266 +{ 1.267 + if (s->z_eof) return EOF; 1.268 + if (s->stream.avail_in == 0) { 1.269 + errno = 0; 1.270 + s->stream.avail_in = (uInt)fread(s->inbuf, 1, Z_BUFSIZE, s->file); 1.271 + if (s->stream.avail_in == 0) { 1.272 + s->z_eof = 1; 1.273 + if (ferror(s->file)) s->z_err = Z_ERRNO; 1.274 + return EOF; 1.275 + } 1.276 + s->stream.next_in = s->inbuf; 1.277 + } 1.278 + s->stream.avail_in--; 1.279 + return *(s->stream.next_in)++; 1.280 +} 1.281 + 1.282 +/* =========================================================================== 1.283 + Check the gzip header of a gz_stream opened for reading. Set the stream 1.284 + mode to transparent if the gzip magic header is not present; set s->err 1.285 + to Z_DATA_ERROR if the magic header is present but the rest of the header 1.286 + is incorrect. 1.287 + IN assertion: the stream s has already been created sucessfully; 1.288 + s->stream.avail_in is zero for the first time, but may be non-zero 1.289 + for concatenated .gz files. 1.290 +*/ 1.291 +local void check_header(s) 1.292 + gz_stream *s; 1.293 +{ 1.294 + int method; /* method byte */ 1.295 + int flags; /* flags byte */ 1.296 + uInt len; 1.297 + int c; 1.298 + 1.299 + /* Assure two bytes in the buffer so we can peek ahead -- handle case 1.300 + where first byte of header is at the end of the buffer after the last 1.301 + gzip segment */ 1.302 + len = s->stream.avail_in; 1.303 + if (len < 2) { 1.304 + if (len) s->inbuf[0] = s->stream.next_in[0]; 1.305 + errno = 0; 1.306 + len = (uInt)fread(s->inbuf + len, 1, Z_BUFSIZE >> len, s->file); 1.307 + if (len == 0 && ferror(s->file)) s->z_err = Z_ERRNO; 1.308 + s->stream.avail_in += len; 1.309 + s->stream.next_in = s->inbuf; 1.310 + if (s->stream.avail_in < 2) { 1.311 + s->transparent = s->stream.avail_in; 1.312 + return; 1.313 + } 1.314 + } 1.315 + 1.316 + /* Peek ahead to check the gzip magic header */ 1.317 + if (s->stream.next_in[0] != gz_magic[0] || 1.318 + s->stream.next_in[1] != gz_magic[1]) { 1.319 + s->transparent = 1; 1.320 + return; 1.321 + } 1.322 + s->stream.avail_in -= 2; 1.323 + s->stream.next_in += 2; 1.324 + 1.325 + /* Check the rest of the gzip header */ 1.326 + method = get_byte(s); 1.327 + flags = get_byte(s); 1.328 + if (method != Z_DEFLATED || (flags & RESERVED) != 0) { 1.329 + s->z_err = Z_DATA_ERROR; 1.330 + return; 1.331 + } 1.332 + 1.333 + /* Discard time, xflags and OS code: */ 1.334 + for (len = 0; len < 6; len++) (void)get_byte(s); 1.335 + 1.336 + if ((flags & EXTRA_FIELD) != 0) { /* skip the extra field */ 1.337 + len = (uInt)get_byte(s); 1.338 + len += ((uInt)get_byte(s))<<8; 1.339 + /* len is garbage if EOF but the loop below will quit anyway */ 1.340 + while (len-- != 0 && get_byte(s) != EOF) ; 1.341 + } 1.342 + if ((flags & ORIG_NAME) != 0) { /* skip the original file name */ 1.343 + while ((c = get_byte(s)) != 0 && c != EOF) ; 1.344 + } 1.345 + if ((flags & COMMENT) != 0) { /* skip the .gz file comment */ 1.346 + while ((c = get_byte(s)) != 0 && c != EOF) ; 1.347 + } 1.348 + if ((flags & HEAD_CRC) != 0) { /* skip the header crc */ 1.349 + for (len = 0; len < 2; len++) (void)get_byte(s); 1.350 + } 1.351 + s->z_err = s->z_eof ? Z_DATA_ERROR : Z_OK; 1.352 +} 1.353 + 1.354 + /* =========================================================================== 1.355 + * Cleanup then free the given gz_stream. Return a zlib error code. 1.356 + Try freeing in the reverse order of allocations. 1.357 + */ 1.358 +local int destroy (s) 1.359 + gz_stream *s; 1.360 +{ 1.361 + int err = Z_OK; 1.362 + 1.363 + if (!s) return Z_STREAM_ERROR; 1.364 + 1.365 + TRYFREE(s->msg); 1.366 + 1.367 + if (s->stream.state != NULL) { 1.368 + if (s->mode == 'w') { 1.369 +#ifdef NO_GZCOMPRESS 1.370 + err = Z_STREAM_ERROR; 1.371 +#else 1.372 + err = deflateEnd(&(s->stream)); 1.373 +#endif 1.374 + } else if (s->mode == 'r') { 1.375 + err = inflateEnd(&(s->stream)); 1.376 + } 1.377 + } 1.378 + if (s->file != NULL && fclose(s->file)) { 1.379 +#ifdef ESPIPE 1.380 + if (errno != ESPIPE) /* fclose is broken for pipes in HP/UX */ 1.381 +#endif 1.382 + err = Z_ERRNO; 1.383 + } 1.384 + if (s->z_err < 0) err = s->z_err; 1.385 + 1.386 + TRYFREE(s->inbuf); 1.387 + TRYFREE(s->outbuf); 1.388 + TRYFREE(s->path); 1.389 + TRYFREE(s); 1.390 + return err; 1.391 +} 1.392 + 1.393 +/* =========================================================================== 1.394 + Reads the given number of uncompressed bytes from the compressed file. 1.395 + gzread returns the number of bytes actually read (0 for end of file). 1.396 +*/ 1.397 +int ZEXPORT gzread (file, buf, len) 1.398 + gzFile file; 1.399 + voidp buf; 1.400 + unsigned len; 1.401 +{ 1.402 + gz_stream *s = (gz_stream*)file; 1.403 + Bytef *start = (Bytef*)buf; /* starting point for crc computation */ 1.404 + Byte *next_out; /* == stream.next_out but not forced far (for MSDOS) */ 1.405 + 1.406 + if (s == NULL || s->mode != 'r') return Z_STREAM_ERROR; 1.407 + 1.408 + if (s->z_err == Z_DATA_ERROR || s->z_err == Z_ERRNO) return -1; 1.409 + if (s->z_err == Z_STREAM_END) return 0; /* EOF */ 1.410 + 1.411 + next_out = (Byte*)buf; 1.412 + s->stream.next_out = (Bytef*)buf; 1.413 + s->stream.avail_out = len; 1.414 + 1.415 + if (s->stream.avail_out && s->back != EOF) { 1.416 + *next_out++ = s->back; 1.417 + s->stream.next_out++; 1.418 + s->stream.avail_out--; 1.419 + s->back = EOF; 1.420 + s->out++; 1.421 + start++; 1.422 + if (s->last) { 1.423 + s->z_err = Z_STREAM_END; 1.424 + return 1; 1.425 + } 1.426 + } 1.427 + 1.428 + while (s->stream.avail_out != 0) { 1.429 + 1.430 + if (s->transparent) { 1.431 + /* Copy first the lookahead bytes: */ 1.432 + uInt n = s->stream.avail_in; 1.433 + if (n > s->stream.avail_out) n = s->stream.avail_out; 1.434 + if (n > 0) { 1.435 + zmemcpy(s->stream.next_out, s->stream.next_in, n); 1.436 + next_out += n; 1.437 + s->stream.next_out = next_out; 1.438 + s->stream.next_in += n; 1.439 + s->stream.avail_out -= n; 1.440 + s->stream.avail_in -= n; 1.441 + } 1.442 + if (s->stream.avail_out > 0) { 1.443 + s->stream.avail_out -= 1.444 + (uInt)fread(next_out, 1, s->stream.avail_out, s->file); 1.445 + } 1.446 + len -= s->stream.avail_out; 1.447 + s->in += len; 1.448 + s->out += len; 1.449 + if (len == 0) s->z_eof = 1; 1.450 + return (int)len; 1.451 + } 1.452 + if (s->stream.avail_in == 0 && !s->z_eof) { 1.453 + 1.454 + errno = 0; 1.455 + s->stream.avail_in = (uInt)fread(s->inbuf, 1, Z_BUFSIZE, s->file); 1.456 + if (s->stream.avail_in == 0) { 1.457 + s->z_eof = 1; 1.458 + if (ferror(s->file)) { 1.459 + s->z_err = Z_ERRNO; 1.460 + break; 1.461 + } 1.462 + } 1.463 + s->stream.next_in = s->inbuf; 1.464 + } 1.465 + s->in += s->stream.avail_in; 1.466 + s->out += s->stream.avail_out; 1.467 + s->z_err = inflate(&(s->stream), Z_NO_FLUSH); 1.468 + s->in -= s->stream.avail_in; 1.469 + s->out -= s->stream.avail_out; 1.470 + 1.471 + if (s->z_err == Z_STREAM_END) { 1.472 + /* Check CRC and original size */ 1.473 + s->crc = crc32(s->crc, start, (uInt)(s->stream.next_out - start)); 1.474 + start = s->stream.next_out; 1.475 + 1.476 + if (getLong(s) != s->crc) { 1.477 + s->z_err = Z_DATA_ERROR; 1.478 + } else { 1.479 + (void)getLong(s); 1.480 + /* The uncompressed length returned by above getlong() may be 1.481 + * different from s->out in case of concatenated .gz files. 1.482 + * Check for such files: 1.483 + */ 1.484 + check_header(s); 1.485 + if (s->z_err == Z_OK) { 1.486 + inflateReset(&(s->stream)); 1.487 + s->crc = crc32(0L, Z_NULL, 0); 1.488 + } 1.489 + } 1.490 + } 1.491 + if (s->z_err != Z_OK || s->z_eof) break; 1.492 + } 1.493 + s->crc = crc32(s->crc, start, (uInt)(s->stream.next_out - start)); 1.494 + 1.495 + if (len == s->stream.avail_out && 1.496 + (s->z_err == Z_DATA_ERROR || s->z_err == Z_ERRNO)) 1.497 + return -1; 1.498 + return (int)(len - s->stream.avail_out); 1.499 +} 1.500 + 1.501 + 1.502 +/* =========================================================================== 1.503 + Reads one byte from the compressed file. gzgetc returns this byte 1.504 + or -1 in case of end of file or error. 1.505 +*/ 1.506 +int ZEXPORT gzgetc(file) 1.507 + gzFile file; 1.508 +{ 1.509 + unsigned char c; 1.510 + 1.511 + return gzread(file, &c, 1) == 1 ? c : -1; 1.512 +} 1.513 + 1.514 + 1.515 +/* =========================================================================== 1.516 + Push one byte back onto the stream. 1.517 +*/ 1.518 +int ZEXPORT gzungetc(c, file) 1.519 + int c; 1.520 + gzFile file; 1.521 +{ 1.522 + gz_stream *s = (gz_stream*)file; 1.523 + 1.524 + if (s == NULL || s->mode != 'r' || c == EOF || s->back != EOF) return EOF; 1.525 + s->back = c; 1.526 + s->out--; 1.527 + s->last = (s->z_err == Z_STREAM_END); 1.528 + if (s->last) s->z_err = Z_OK; 1.529 + s->z_eof = 0; 1.530 + return c; 1.531 +} 1.532 + 1.533 + 1.534 +/* =========================================================================== 1.535 + Reads bytes from the compressed file until len-1 characters are 1.536 + read, or a newline character is read and transferred to buf, or an 1.537 + end-of-file condition is encountered. The string is then terminated 1.538 + with a null character. 1.539 + gzgets returns buf, or Z_NULL in case of error. 1.540 + 1.541 + The current implementation is not optimized at all. 1.542 +*/ 1.543 +char * ZEXPORT gzgets(file, buf, len) 1.544 + gzFile file; 1.545 + char *buf; 1.546 + int len; 1.547 +{ 1.548 + char *b = buf; 1.549 + if (buf == Z_NULL || len <= 0) return Z_NULL; 1.550 + 1.551 + while (--len > 0 && gzread(file, buf, 1) == 1 && *buf++ != '\n') ; 1.552 + *buf = '\0'; 1.553 + return b == buf && len > 0 ? Z_NULL : b; 1.554 +} 1.555 + 1.556 + 1.557 +#ifndef NO_GZCOMPRESS 1.558 +/* =========================================================================== 1.559 + Writes the given number of uncompressed bytes into the compressed file. 1.560 + gzwrite returns the number of bytes actually written (0 in case of error). 1.561 +*/ 1.562 +int ZEXPORT gzwrite (file, buf, len) 1.563 + gzFile file; 1.564 + voidpc buf; 1.565 + unsigned len; 1.566 +{ 1.567 + gz_stream *s = (gz_stream*)file; 1.568 + 1.569 + if (s == NULL || s->mode != 'w') return Z_STREAM_ERROR; 1.570 + 1.571 + s->stream.next_in = (Bytef*)buf; 1.572 + s->stream.avail_in = len; 1.573 + 1.574 + while (s->stream.avail_in != 0) { 1.575 + 1.576 + if (s->stream.avail_out == 0) { 1.577 + 1.578 + s->stream.next_out = s->outbuf; 1.579 + if (fwrite(s->outbuf, 1, Z_BUFSIZE, s->file) != Z_BUFSIZE) { 1.580 + s->z_err = Z_ERRNO; 1.581 + break; 1.582 + } 1.583 + s->stream.avail_out = Z_BUFSIZE; 1.584 + } 1.585 + s->in += s->stream.avail_in; 1.586 + s->out += s->stream.avail_out; 1.587 + s->z_err = deflate(&(s->stream), Z_NO_FLUSH); 1.588 + s->in -= s->stream.avail_in; 1.589 + s->out -= s->stream.avail_out; 1.590 + if (s->z_err != Z_OK) break; 1.591 + } 1.592 + s->crc = crc32(s->crc, (const Bytef *)buf, len); 1.593 + 1.594 + return (int)(len - s->stream.avail_in); 1.595 +} 1.596 + 1.597 + 1.598 +/* =========================================================================== 1.599 + Converts, formats, and writes the args to the compressed file under 1.600 + control of the format string, as in fprintf. gzprintf returns the number of 1.601 + uncompressed bytes actually written (0 in case of error). 1.602 +*/ 1.603 +#ifdef STDC 1.604 +#include <stdarg.h> 1.605 + 1.606 +int ZEXPORTVA gzprintf (gzFile file, const char *format, /* args */ ...) 1.607 +{ 1.608 + char buf[Z_PRINTF_BUFSIZE]; 1.609 + va_list va; 1.610 + int len; 1.611 + 1.612 + buf[sizeof(buf) - 1] = 0; 1.613 + va_start(va, format); 1.614 +#ifdef NO_vsnprintf 1.615 +# ifdef HAS_vsprintf_void 1.616 + (void)vsprintf(buf, format, va); 1.617 + va_end(va); 1.618 + for (len = 0; len < sizeof(buf); len++) 1.619 + if (buf[len] == 0) break; 1.620 +# else 1.621 + len = vsprintf(buf, format, va); 1.622 + va_end(va); 1.623 +# endif 1.624 +#else 1.625 +# ifdef HAS_vsnprintf_void 1.626 + (void)vsnprintf(buf, sizeof(buf), format, va); 1.627 + va_end(va); 1.628 + len = strlen(buf); 1.629 +# else 1.630 + len = vsnprintf(buf, sizeof(buf), format, va); 1.631 + va_end(va); 1.632 +# endif 1.633 +#endif 1.634 + if (len <= 0 || len >= (int)sizeof(buf) || buf[sizeof(buf) - 1] != 0) 1.635 + return 0; 1.636 + return gzwrite(file, buf, (unsigned)len); 1.637 +} 1.638 +#else /* not ANSI C */ 1.639 + 1.640 +int ZEXPORTVA gzprintf (file, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, 1.641 + a11, a12, a13, a14, a15, a16, a17, a18, a19, a20) 1.642 + gzFile file; 1.643 + const char *format; 1.644 + int a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, 1.645 + a11, a12, a13, a14, a15, a16, a17, a18, a19, a20; 1.646 +{ 1.647 + char buf[Z_PRINTF_BUFSIZE]; 1.648 + int len; 1.649 + 1.650 + buf[sizeof(buf) - 1] = 0; 1.651 +#ifdef NO_snprintf 1.652 +# ifdef HAS_sprintf_void 1.653 + sprintf(buf, format, a1, a2, a3, a4, a5, a6, a7, a8, 1.654 + a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20); 1.655 + for (len = 0; len < sizeof(buf); len++) 1.656 + if (buf[len] == 0) break; 1.657 +# else 1.658 + len = sprintf(buf, format, a1, a2, a3, a4, a5, a6, a7, a8, 1.659 + a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20); 1.660 +# endif 1.661 +#else 1.662 +# ifdef HAS_snprintf_void 1.663 + snprintf(buf, sizeof(buf), format, a1, a2, a3, a4, a5, a6, a7, a8, 1.664 + a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20); 1.665 + len = strlen(buf); 1.666 +# else 1.667 + len = snprintf(buf, sizeof(buf), format, a1, a2, a3, a4, a5, a6, a7, a8, 1.668 + a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20); 1.669 +# endif 1.670 +#endif 1.671 + if (len <= 0 || len >= sizeof(buf) || buf[sizeof(buf) - 1] != 0) 1.672 + return 0; 1.673 + return gzwrite(file, buf, len); 1.674 +} 1.675 +#endif 1.676 + 1.677 +/* =========================================================================== 1.678 + Writes c, converted to an unsigned char, into the compressed file. 1.679 + gzputc returns the value that was written, or -1 in case of error. 1.680 +*/ 1.681 +int ZEXPORT gzputc(file, c) 1.682 + gzFile file; 1.683 + int c; 1.684 +{ 1.685 + unsigned char cc = (unsigned char) c; /* required for big endian systems */ 1.686 + 1.687 + return gzwrite(file, &cc, 1) == 1 ? (int)cc : -1; 1.688 +} 1.689 + 1.690 + 1.691 +/* =========================================================================== 1.692 + Writes the given null-terminated string to the compressed file, excluding 1.693 + the terminating null character. 1.694 + gzputs returns the number of characters written, or -1 in case of error. 1.695 +*/ 1.696 +int ZEXPORT gzputs(file, s) 1.697 + gzFile file; 1.698 + const char *s; 1.699 +{ 1.700 + return gzwrite(file, (char*)s, (unsigned)strlen(s)); 1.701 +} 1.702 + 1.703 + 1.704 +/* =========================================================================== 1.705 + Flushes all pending output into the compressed file. The parameter 1.706 + flush is as in the deflate() function. 1.707 +*/ 1.708 +local int do_flush (file, flush) 1.709 + gzFile file; 1.710 + int flush; 1.711 +{ 1.712 + uInt len; 1.713 + int done = 0; 1.714 + gz_stream *s = (gz_stream*)file; 1.715 + 1.716 + if (s == NULL || s->mode != 'w') return Z_STREAM_ERROR; 1.717 + 1.718 + s->stream.avail_in = 0; /* should be zero already anyway */ 1.719 + 1.720 + for (;;) { 1.721 + len = Z_BUFSIZE - s->stream.avail_out; 1.722 + 1.723 + if (len != 0) { 1.724 + if ((uInt)fwrite(s->outbuf, 1, len, s->file) != len) { 1.725 + s->z_err = Z_ERRNO; 1.726 + return Z_ERRNO; 1.727 + } 1.728 + s->stream.next_out = s->outbuf; 1.729 + s->stream.avail_out = Z_BUFSIZE; 1.730 + } 1.731 + if (done) break; 1.732 + s->out += s->stream.avail_out; 1.733 + s->z_err = deflate(&(s->stream), flush); 1.734 + s->out -= s->stream.avail_out; 1.735 + 1.736 + /* Ignore the second of two consecutive flushes: */ 1.737 + if (len == 0 && s->z_err == Z_BUF_ERROR) s->z_err = Z_OK; 1.738 + 1.739 + /* deflate has finished flushing only when it hasn't used up 1.740 + * all the available space in the output buffer: 1.741 + */ 1.742 + done = (s->stream.avail_out != 0 || s->z_err == Z_STREAM_END); 1.743 + 1.744 + if (s->z_err != Z_OK && s->z_err != Z_STREAM_END) break; 1.745 + } 1.746 + return s->z_err == Z_STREAM_END ? Z_OK : s->z_err; 1.747 +} 1.748 + 1.749 +int ZEXPORT gzflush (file, flush) 1.750 + gzFile file; 1.751 + int flush; 1.752 +{ 1.753 + gz_stream *s = (gz_stream*)file; 1.754 + int err = do_flush (file, flush); 1.755 + 1.756 + if (err) return err; 1.757 + fflush(s->file); 1.758 + return s->z_err == Z_STREAM_END ? Z_OK : s->z_err; 1.759 +} 1.760 +#endif /* NO_GZCOMPRESS */ 1.761 + 1.762 +/* =========================================================================== 1.763 + Sets the starting position for the next gzread or gzwrite on the given 1.764 + compressed file. The offset represents a number of bytes in the 1.765 + gzseek returns the resulting offset location as measured in bytes from 1.766 + the beginning of the uncompressed stream, or -1 in case of error. 1.767 + SEEK_END is not implemented, returns error. 1.768 + In this version of the library, gzseek can be extremely slow. 1.769 +*/ 1.770 +z_off_t ZEXPORT gzseek (file, offset, whence) 1.771 + gzFile file; 1.772 + z_off_t offset; 1.773 + int whence; 1.774 +{ 1.775 + gz_stream *s = (gz_stream*)file; 1.776 + 1.777 + if (s == NULL || whence == SEEK_END || 1.778 + s->z_err == Z_ERRNO || s->z_err == Z_DATA_ERROR) { 1.779 + return -1L; 1.780 + } 1.781 + 1.782 + if (s->mode == 'w') { 1.783 +#ifdef NO_GZCOMPRESS 1.784 + return -1L; 1.785 +#else 1.786 + if (whence == SEEK_SET) { 1.787 + offset -= s->in; 1.788 + } 1.789 + if (offset < 0) return -1L; 1.790 + 1.791 + /* At this point, offset is the number of zero bytes to write. */ 1.792 + if (s->inbuf == Z_NULL) { 1.793 + s->inbuf = (Byte*)ALLOC(Z_BUFSIZE); /* for seeking */ 1.794 + if (s->inbuf == Z_NULL) return -1L; 1.795 + zmemzero(s->inbuf, Z_BUFSIZE); 1.796 + } 1.797 + while (offset > 0) { 1.798 + uInt size = Z_BUFSIZE; 1.799 + if (offset < Z_BUFSIZE) size = (uInt)offset; 1.800 + 1.801 + size = gzwrite(file, s->inbuf, size); 1.802 + if (size == 0) return -1L; 1.803 + 1.804 + offset -= size; 1.805 + } 1.806 + return s->in; 1.807 +#endif 1.808 + } 1.809 + /* Rest of function is for reading only */ 1.810 + 1.811 + /* compute absolute position */ 1.812 + if (whence == SEEK_CUR) { 1.813 + offset += s->out; 1.814 + } 1.815 + if (offset < 0) return -1L; 1.816 + 1.817 + if (s->transparent) { 1.818 + /* map to fseek */ 1.819 + s->back = EOF; 1.820 + s->stream.avail_in = 0; 1.821 + s->stream.next_in = s->inbuf; 1.822 + if (fseek(s->file, offset, SEEK_SET) < 0) return -1L; 1.823 + 1.824 + s->in = s->out = offset; 1.825 + return offset; 1.826 + } 1.827 + 1.828 + /* For a negative seek, rewind and use positive seek */ 1.829 + if (offset >= s->out) { 1.830 + offset -= s->out; 1.831 + } else if (gzrewind(file) < 0) { 1.832 + return -1L; 1.833 + } 1.834 + /* offset is now the number of bytes to skip. */ 1.835 + 1.836 + if (offset != 0 && s->outbuf == Z_NULL) { 1.837 + s->outbuf = (Byte*)ALLOC(Z_BUFSIZE); 1.838 + if (s->outbuf == Z_NULL) return -1L; 1.839 + } 1.840 + if (offset && s->back != EOF) { 1.841 + s->back = EOF; 1.842 + s->out++; 1.843 + offset--; 1.844 + if (s->last) s->z_err = Z_STREAM_END; 1.845 + } 1.846 + while (offset > 0) { 1.847 + int size = Z_BUFSIZE; 1.848 + if (offset < Z_BUFSIZE) size = (int)offset; 1.849 + 1.850 + size = gzread(file, s->outbuf, (uInt)size); 1.851 + if (size <= 0) return -1L; 1.852 + offset -= size; 1.853 + } 1.854 + return s->out; 1.855 +} 1.856 + 1.857 +/* =========================================================================== 1.858 + Rewinds input file. 1.859 +*/ 1.860 +int ZEXPORT gzrewind (file) 1.861 + gzFile file; 1.862 +{ 1.863 + gz_stream *s = (gz_stream*)file; 1.864 + 1.865 + if (s == NULL || s->mode != 'r') return -1; 1.866 + 1.867 + s->z_err = Z_OK; 1.868 + s->z_eof = 0; 1.869 + s->back = EOF; 1.870 + s->stream.avail_in = 0; 1.871 + s->stream.next_in = s->inbuf; 1.872 + s->crc = crc32(0L, Z_NULL, 0); 1.873 + if (!s->transparent) (void)inflateReset(&s->stream); 1.874 + s->in = 0; 1.875 + s->out = 0; 1.876 + return fseek(s->file, s->start, SEEK_SET); 1.877 +} 1.878 + 1.879 +/* =========================================================================== 1.880 + Returns the starting position for the next gzread or gzwrite on the 1.881 + given compressed file. This position represents a number of bytes in the 1.882 + uncompressed data stream. 1.883 +*/ 1.884 +z_off_t ZEXPORT gztell (file) 1.885 + gzFile file; 1.886 +{ 1.887 + return gzseek(file, 0L, SEEK_CUR); 1.888 +} 1.889 + 1.890 +/* =========================================================================== 1.891 + Returns 1 when EOF has previously been detected reading the given 1.892 + input stream, otherwise zero. 1.893 +*/ 1.894 +int ZEXPORT gzeof (file) 1.895 + gzFile file; 1.896 +{ 1.897 + gz_stream *s = (gz_stream*)file; 1.898 + 1.899 + /* With concatenated compressed files that can have embedded 1.900 + * crc trailers, z_eof is no longer the only/best indicator of EOF 1.901 + * on a gz_stream. Handle end-of-stream error explicitly here. 1.902 + */ 1.903 + if (s == NULL || s->mode != 'r') return 0; 1.904 + if (s->z_eof) return 1; 1.905 + return s->z_err == Z_STREAM_END; 1.906 +} 1.907 + 1.908 +/* =========================================================================== 1.909 + Returns 1 if reading and doing so transparently, otherwise zero. 1.910 +*/ 1.911 +int ZEXPORT gzdirect (file) 1.912 + gzFile file; 1.913 +{ 1.914 + gz_stream *s = (gz_stream*)file; 1.915 + 1.916 + if (s == NULL || s->mode != 'r') return 0; 1.917 + return s->transparent; 1.918 +} 1.919 + 1.920 +/* =========================================================================== 1.921 + Outputs a long in LSB order to the given file 1.922 +*/ 1.923 +local void putLong (file, x) 1.924 + FILE *file; 1.925 + uLong x; 1.926 +{ 1.927 + int n; 1.928 + for (n = 0; n < 4; n++) { 1.929 + fputc((int)(x & 0xff), file); 1.930 + x >>= 8; 1.931 + } 1.932 +} 1.933 + 1.934 +/* =========================================================================== 1.935 + Reads a long in LSB order from the given gz_stream. Sets z_err in case 1.936 + of error. 1.937 +*/ 1.938 +local uLong getLong (s) 1.939 + gz_stream *s; 1.940 +{ 1.941 + uLong x = (uLong)get_byte(s); 1.942 + int c; 1.943 + 1.944 + x += ((uLong)get_byte(s))<<8; 1.945 + x += ((uLong)get_byte(s))<<16; 1.946 + c = get_byte(s); 1.947 + if (c == EOF) s->z_err = Z_DATA_ERROR; 1.948 + x += ((uLong)c)<<24; 1.949 + return x; 1.950 +} 1.951 + 1.952 +/* =========================================================================== 1.953 + Flushes all pending output if necessary, closes the compressed file 1.954 + and deallocates all the (de)compression state. 1.955 +*/ 1.956 +int ZEXPORT gzclose (file) 1.957 + gzFile file; 1.958 +{ 1.959 + gz_stream *s = (gz_stream*)file; 1.960 + 1.961 + if (s == NULL) return Z_STREAM_ERROR; 1.962 + 1.963 + if (s->mode == 'w') { 1.964 +#ifdef NO_GZCOMPRESS 1.965 + return Z_STREAM_ERROR; 1.966 +#else 1.967 + if (do_flush (file, Z_FINISH) != Z_OK) 1.968 + return destroy((gz_stream*)file); 1.969 + 1.970 + putLong (s->file, s->crc); 1.971 + putLong (s->file, (uLong)(s->in & 0xffffffff)); 1.972 +#endif 1.973 + } 1.974 + return destroy((gz_stream*)file); 1.975 +} 1.976 + 1.977 +#ifdef STDC 1.978 +# define zstrerror(errnum) strerror(errnum) 1.979 +#else 1.980 +# define zstrerror(errnum) "" 1.981 +#endif 1.982 + 1.983 +/* =========================================================================== 1.984 + Returns the error message for the last error which occurred on the 1.985 + given compressed file. errnum is set to zlib error number. If an 1.986 + error occurred in the file system and not in the compression library, 1.987 + errnum is set to Z_ERRNO and the application may consult errno 1.988 + to get the exact error code. 1.989 +*/ 1.990 +const char * ZEXPORT gzerror (file, errnum) 1.991 + gzFile file; 1.992 + int *errnum; 1.993 +{ 1.994 + char *m; 1.995 + gz_stream *s = (gz_stream*)file; 1.996 + 1.997 + if (s == NULL) { 1.998 + *errnum = Z_STREAM_ERROR; 1.999 + return (const char*)ERR_MSG(Z_STREAM_ERROR); 1.1000 + } 1.1001 + *errnum = s->z_err; 1.1002 + if (*errnum == Z_OK) return (const char*)""; 1.1003 + 1.1004 + m = (char*)(*errnum == Z_ERRNO ? zstrerror(errno) : s->stream.msg); 1.1005 + 1.1006 + if (m == NULL || *m == '\0') m = (char*)ERR_MSG(s->z_err); 1.1007 + 1.1008 + TRYFREE(s->msg); 1.1009 + s->msg = (char*)ALLOC(strlen(s->path) + strlen(m) + 3); 1.1010 + if (s->msg == Z_NULL) return (const char*)ERR_MSG(Z_MEM_ERROR); 1.1011 + strcpy(s->msg, s->path); 1.1012 + strcat(s->msg, ": "); 1.1013 + strcat(s->msg, m); 1.1014 + return (const char*)s->msg; 1.1015 +} 1.1016 + 1.1017 +/* =========================================================================== 1.1018 + Clear the error and end-of-file flags, and do the same for the real file. 1.1019 +*/ 1.1020 +void ZEXPORT gzclearerr (file) 1.1021 + gzFile file; 1.1022 +{ 1.1023 + gz_stream *s = (gz_stream*)file; 1.1024 + 1.1025 + if (s == NULL) return; 1.1026 + if (s->z_err != Z_STREAM_END) s->z_err = Z_OK; 1.1027 + s->z_eof = 0; 1.1028 + clearerr(s->file); 1.1029 +}