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