|
fltk 1.3.0rc3
About: FLTK (Fast Light Tool Kit) is a cross-platform C++ GUI toolkit for UNIX/Linux (X11), Microsoft Windows, and MacOS X. Release candidate.
SfR Fresh Dox: fltk-1.3.0rc3-source.tar.gz ("inofficial" and yet experimental doxygen-generated source code documentation) ![]() |
00001 /* gzio.c -- IO on .gz files 00002 * Copyright (C) 1995-2005 Jean-loup Gailly. 00003 * For conditions of distribution and use, see copyright notice in zlib.h 00004 * 00005 * Compile this file with -DNO_GZCOMPRESS to avoid the compression code. 00006 */ 00007 00008 /* @(#) $Id: gzio.c 5666 2007-02-06 22:02:28Z mike $ */ 00009 00010 #include <stdio.h> 00011 00012 #include "zutil.h" 00013 00014 #ifdef NO_DEFLATE /* for compatibility with old definition */ 00015 # define NO_GZCOMPRESS 00016 #endif 00017 00018 #ifndef NO_DUMMY_DECL 00019 struct internal_state {int dummy;}; /* for buggy compilers */ 00020 #endif 00021 00022 #ifndef Z_BUFSIZE 00023 # ifdef MAXSEG_64K 00024 # define Z_BUFSIZE 4096 /* minimize memory usage for 16-bit DOS */ 00025 # else 00026 # define Z_BUFSIZE 16384 00027 # endif 00028 #endif 00029 #ifndef Z_PRINTF_BUFSIZE 00030 # define Z_PRINTF_BUFSIZE 4096 00031 #endif 00032 00033 #ifdef __MVS__ 00034 # pragma map (fdopen , "\174\174FDOPEN") 00035 FILE *fdopen(int, const char *); 00036 #endif 00037 00038 #ifndef STDC 00039 extern voidp malloc OF((uInt size)); 00040 extern void free OF((voidpf ptr)); 00041 #endif 00042 00043 #define ALLOC(size) malloc(size) 00044 #define TRYFREE(p) {if (p) free(p);} 00045 00046 static int const gz_magic[2] = {0x1f, 0x8b}; /* gzip magic header */ 00047 00048 /* gzip flag byte */ 00049 #define ASCII_FLAG 0x01 /* bit 0 set: file probably ascii text */ 00050 #define HEAD_CRC 0x02 /* bit 1 set: header CRC present */ 00051 #define EXTRA_FIELD 0x04 /* bit 2 set: extra field present */ 00052 #define ORIG_NAME 0x08 /* bit 3 set: original file name present */ 00053 #define COMMENT 0x10 /* bit 4 set: file comment present */ 00054 #define RESERVED 0xE0 /* bits 5..7: reserved */ 00055 00056 typedef struct gz_stream { 00057 z_stream stream; 00058 int z_err; /* error code for last stream operation */ 00059 int z_eof; /* set if end of input file */ 00060 FILE *file; /* .gz file */ 00061 Byte *inbuf; /* input buffer */ 00062 Byte *outbuf; /* output buffer */ 00063 uLong crc; /* crc32 of uncompressed data */ 00064 char *msg; /* error message */ 00065 char *path; /* path name for debugging only */ 00066 int transparent; /* 1 if input file is not a .gz file */ 00067 char mode; /* 'w' or 'r' */ 00068 z_off_t start; /* start of compressed data in file (header skipped) */ 00069 z_off_t in; /* bytes into deflate or inflate */ 00070 z_off_t out; /* bytes out of deflate or inflate */ 00071 int back; /* one character push-back */ 00072 int last; /* true if push-back is last character */ 00073 } gz_stream; 00074 00075 00076 local gzFile gz_open OF((const char *path, const char *mode, int fd)); 00077 local int do_flush OF((gzFile file, int flush)); 00078 local int get_byte OF((gz_stream *s)); 00079 local void check_header OF((gz_stream *s)); 00080 local int destroy OF((gz_stream *s)); 00081 local void putLong OF((FILE *file, uLong x)); 00082 local uLong getLong OF((gz_stream *s)); 00083 00084 /* =========================================================================== 00085 Opens a gzip (.gz) file for reading or writing. The mode parameter 00086 is as in fopen ("rb" or "wb"). The file is given either by file descriptor 00087 or path name (if fd == -1). 00088 gz_open returns NULL if the file could not be opened or if there was 00089 insufficient memory to allocate the (de)compression state; errno 00090 can be checked to distinguish the two cases (if errno is zero, the 00091 zlib error is Z_MEM_ERROR). 00092 */ 00093 local gzFile gz_open (path, mode, fd) 00094 const char *path; 00095 const char *mode; 00096 int fd; 00097 { 00098 int err; 00099 int level = Z_DEFAULT_COMPRESSION; /* compression level */ 00100 int strategy = Z_DEFAULT_STRATEGY; /* compression strategy */ 00101 char *p = (char*)mode; 00102 gz_stream *s; 00103 char fmode[80]; /* copy of mode, without the compression level */ 00104 char *m = fmode; 00105 00106 if (!path || !mode) return Z_NULL; 00107 00108 s = (gz_stream *)ALLOC(sizeof(gz_stream)); 00109 if (!s) return Z_NULL; 00110 00111 s->stream.zalloc = (alloc_func)0; 00112 s->stream.zfree = (free_func)0; 00113 s->stream.opaque = (voidpf)0; 00114 s->stream.next_in = s->inbuf = Z_NULL; 00115 s->stream.next_out = s->outbuf = Z_NULL; 00116 s->stream.avail_in = s->stream.avail_out = 0; 00117 s->file = NULL; 00118 s->z_err = Z_OK; 00119 s->z_eof = 0; 00120 s->in = 0; 00121 s->out = 0; 00122 s->back = EOF; 00123 s->crc = crc32(0L, Z_NULL, 0); 00124 s->msg = NULL; 00125 s->transparent = 0; 00126 00127 s->path = (char*)ALLOC(strlen(path)+1); 00128 if (s->path == NULL) { 00129 return destroy(s), (gzFile)Z_NULL; 00130 } 00131 strcpy(s->path, path); /* do this early for debugging */ 00132 00133 s->mode = '\0'; 00134 do { 00135 if (*p == 'r') s->mode = 'r'; 00136 if (*p == 'w' || *p == 'a') s->mode = 'w'; 00137 if (*p >= '0' && *p <= '9') { 00138 level = *p - '0'; 00139 } else if (*p == 'f') { 00140 strategy = Z_FILTERED; 00141 } else if (*p == 'h') { 00142 strategy = Z_HUFFMAN_ONLY; 00143 } else if (*p == 'R') { 00144 strategy = Z_RLE; 00145 } else { 00146 *m++ = *p; /* copy the mode */ 00147 } 00148 } while (*p++ && m != fmode + sizeof(fmode)); 00149 if (s->mode == '\0') return destroy(s), (gzFile)Z_NULL; 00150 00151 if (s->mode == 'w') { 00152 #ifdef NO_GZCOMPRESS 00153 err = Z_STREAM_ERROR; 00154 #else 00155 err = deflateInit2(&(s->stream), level, 00156 Z_DEFLATED, -MAX_WBITS, DEF_MEM_LEVEL, strategy); 00157 /* windowBits is passed < 0 to suppress zlib header */ 00158 00159 s->stream.next_out = s->outbuf = (Byte*)ALLOC(Z_BUFSIZE); 00160 #endif 00161 if (err != Z_OK || s->outbuf == Z_NULL) { 00162 return destroy(s), (gzFile)Z_NULL; 00163 } 00164 } else { 00165 s->stream.next_in = s->inbuf = (Byte*)ALLOC(Z_BUFSIZE); 00166 00167 err = inflateInit2(&(s->stream), -MAX_WBITS); 00168 /* windowBits is passed < 0 to tell that there is no zlib header. 00169 * Note that in this case inflate *requires* an extra "dummy" byte 00170 * after the compressed stream in order to complete decompression and 00171 * return Z_STREAM_END. Here the gzip CRC32 ensures that 4 bytes are 00172 * present after the compressed stream. 00173 */ 00174 if (err != Z_OK || s->inbuf == Z_NULL) { 00175 return destroy(s), (gzFile)Z_NULL; 00176 } 00177 } 00178 s->stream.avail_out = Z_BUFSIZE; 00179 00180 errno = 0; 00181 s->file = fd < 0 ? F_OPEN(path, fmode) : (FILE*)fdopen(fd, fmode); 00182 00183 if (s->file == NULL) { 00184 return destroy(s), (gzFile)Z_NULL; 00185 } 00186 if (s->mode == 'w') { 00187 /* Write a very simple .gz header: 00188 */ 00189 fprintf(s->file, "%c%c%c%c%c%c%c%c%c%c", gz_magic[0], gz_magic[1], 00190 Z_DEFLATED, 0 /*flags*/, 0,0,0,0 /*time*/, 0 /*xflags*/, OS_CODE); 00191 s->start = 10L; 00192 /* We use 10L instead of ftell(s->file) to because ftell causes an 00193 * fflush on some systems. This version of the library doesn't use 00194 * start anyway in write mode, so this initialization is not 00195 * necessary. 00196 */ 00197 } else { 00198 check_header(s); /* skip the .gz header */ 00199 s->start = ftell(s->file) - s->stream.avail_in; 00200 } 00201 00202 return (gzFile)s; 00203 } 00204 00205 /* =========================================================================== 00206 Opens a gzip (.gz) file for reading or writing. 00207 */ 00208 gzFile ZEXPORT gzopen (path, mode) 00209 const char *path; 00210 const char *mode; 00211 { 00212 return gz_open (path, mode, -1); 00213 } 00214 00215 /* =========================================================================== 00216 Associate a gzFile with the file descriptor fd. fd is not dup'ed here 00217 to mimic the behavio(u)r of fdopen. 00218 */ 00219 gzFile ZEXPORT gzdopen (fd, mode) 00220 int fd; 00221 const char *mode; 00222 { 00223 char name[46]; /* allow for up to 128-bit integers */ 00224 00225 if (fd < 0) return (gzFile)Z_NULL; 00226 sprintf(name, "<fd:%d>", fd); /* for debugging */ 00227 00228 return gz_open (name, mode, fd); 00229 } 00230 00231 /* =========================================================================== 00232 * Update the compression level and strategy 00233 */ 00234 int ZEXPORT gzsetparams (file, level, strategy) 00235 gzFile file; 00236 int level; 00237 int strategy; 00238 { 00239 gz_stream *s = (gz_stream*)file; 00240 00241 if (s == NULL || s->mode != 'w') return Z_STREAM_ERROR; 00242 00243 /* Make room to allow flushing */ 00244 if (s->stream.avail_out == 0) { 00245 00246 s->stream.next_out = s->outbuf; 00247 if (fwrite(s->outbuf, 1, Z_BUFSIZE, s->file) != Z_BUFSIZE) { 00248 s->z_err = Z_ERRNO; 00249 } 00250 s->stream.avail_out = Z_BUFSIZE; 00251 } 00252 00253 return deflateParams (&(s->stream), level, strategy); 00254 } 00255 00256 /* =========================================================================== 00257 Read a byte from a gz_stream; update next_in and avail_in. Return EOF 00258 for end of file. 00259 IN assertion: the stream s has been sucessfully opened for reading. 00260 */ 00261 local int get_byte(s) 00262 gz_stream *s; 00263 { 00264 if (s->z_eof) return EOF; 00265 if (s->stream.avail_in == 0) { 00266 errno = 0; 00267 s->stream.avail_in = (uInt)fread(s->inbuf, 1, Z_BUFSIZE, s->file); 00268 if (s->stream.avail_in == 0) { 00269 s->z_eof = 1; 00270 if (ferror(s->file)) s->z_err = Z_ERRNO; 00271 return EOF; 00272 } 00273 s->stream.next_in = s->inbuf; 00274 } 00275 s->stream.avail_in--; 00276 return *(s->stream.next_in)++; 00277 } 00278 00279 /* =========================================================================== 00280 Check the gzip header of a gz_stream opened for reading. Set the stream 00281 mode to transparent if the gzip magic header is not present; set s->err 00282 to Z_DATA_ERROR if the magic header is present but the rest of the header 00283 is incorrect. 00284 IN assertion: the stream s has already been created sucessfully; 00285 s->stream.avail_in is zero for the first time, but may be non-zero 00286 for concatenated .gz files. 00287 */ 00288 local void check_header(s) 00289 gz_stream *s; 00290 { 00291 int method; /* method byte */ 00292 int flags; /* flags byte */ 00293 uInt len; 00294 int c; 00295 00296 /* Assure two bytes in the buffer so we can peek ahead -- handle case 00297 where first byte of header is at the end of the buffer after the last 00298 gzip segment */ 00299 len = s->stream.avail_in; 00300 if (len < 2) { 00301 if (len) s->inbuf[0] = s->stream.next_in[0]; 00302 errno = 0; 00303 len = (uInt)fread(s->inbuf + len, 1, Z_BUFSIZE >> len, s->file); 00304 if (len == 0 && ferror(s->file)) s->z_err = Z_ERRNO; 00305 s->stream.avail_in += len; 00306 s->stream.next_in = s->inbuf; 00307 if (s->stream.avail_in < 2) { 00308 s->transparent = s->stream.avail_in; 00309 return; 00310 } 00311 } 00312 00313 /* Peek ahead to check the gzip magic header */ 00314 if (s->stream.next_in[0] != gz_magic[0] || 00315 s->stream.next_in[1] != gz_magic[1]) { 00316 s->transparent = 1; 00317 return; 00318 } 00319 s->stream.avail_in -= 2; 00320 s->stream.next_in += 2; 00321 00322 /* Check the rest of the gzip header */ 00323 method = get_byte(s); 00324 flags = get_byte(s); 00325 if (method != Z_DEFLATED || (flags & RESERVED) != 0) { 00326 s->z_err = Z_DATA_ERROR; 00327 return; 00328 } 00329 00330 /* Discard time, xflags and OS code: */ 00331 for (len = 0; len < 6; len++) (void)get_byte(s); 00332 00333 if ((flags & EXTRA_FIELD) != 0) { /* skip the extra field */ 00334 len = (uInt)get_byte(s); 00335 len += ((uInt)get_byte(s))<<8; 00336 /* len is garbage if EOF but the loop below will quit anyway */ 00337 while (len-- != 0 && get_byte(s) != EOF) ; 00338 } 00339 if ((flags & ORIG_NAME) != 0) { /* skip the original file name */ 00340 while ((c = get_byte(s)) != 0 && c != EOF) ; 00341 } 00342 if ((flags & COMMENT) != 0) { /* skip the .gz file comment */ 00343 while ((c = get_byte(s)) != 0 && c != EOF) ; 00344 } 00345 if ((flags & HEAD_CRC) != 0) { /* skip the header crc */ 00346 for (len = 0; len < 2; len++) (void)get_byte(s); 00347 } 00348 s->z_err = s->z_eof ? Z_DATA_ERROR : Z_OK; 00349 } 00350 00351 /* =========================================================================== 00352 * Cleanup then free the given gz_stream. Return a zlib error code. 00353 Try freeing in the reverse order of allocations. 00354 */ 00355 local int destroy (s) 00356 gz_stream *s; 00357 { 00358 int err = Z_OK; 00359 00360 if (!s) return Z_STREAM_ERROR; 00361 00362 TRYFREE(s->msg); 00363 00364 if (s->stream.state != NULL) { 00365 if (s->mode == 'w') { 00366 #ifdef NO_GZCOMPRESS 00367 err = Z_STREAM_ERROR; 00368 #else 00369 err = deflateEnd(&(s->stream)); 00370 #endif 00371 } else if (s->mode == 'r') { 00372 err = inflateEnd(&(s->stream)); 00373 } 00374 } 00375 if (s->file != NULL && fclose(s->file)) { 00376 #ifdef ESPIPE 00377 if (errno != ESPIPE) /* fclose is broken for pipes in HP/UX */ 00378 #endif 00379 err = Z_ERRNO; 00380 } 00381 if (s->z_err < 0) err = s->z_err; 00382 00383 TRYFREE(s->inbuf); 00384 TRYFREE(s->outbuf); 00385 TRYFREE(s->path); 00386 TRYFREE(s); 00387 return err; 00388 } 00389 00390 /* =========================================================================== 00391 Reads the given number of uncompressed bytes from the compressed file. 00392 gzread returns the number of bytes actually read (0 for end of file). 00393 */ 00394 int ZEXPORT gzread (file, buf, len) 00395 gzFile file; 00396 voidp buf; 00397 unsigned len; 00398 { 00399 gz_stream *s = (gz_stream*)file; 00400 Bytef *start = (Bytef*)buf; /* starting point for crc computation */ 00401 Byte *next_out; /* == stream.next_out but not forced far (for MSDOS) */ 00402 00403 if (s == NULL || s->mode != 'r') return Z_STREAM_ERROR; 00404 00405 if (s->z_err == Z_DATA_ERROR || s->z_err == Z_ERRNO) return -1; 00406 if (s->z_err == Z_STREAM_END) return 0; /* EOF */ 00407 00408 next_out = (Byte*)buf; 00409 s->stream.next_out = (Bytef*)buf; 00410 s->stream.avail_out = len; 00411 00412 if (s->stream.avail_out && s->back != EOF) { 00413 *next_out++ = s->back; 00414 s->stream.next_out++; 00415 s->stream.avail_out--; 00416 s->back = EOF; 00417 s->out++; 00418 start++; 00419 if (s->last) { 00420 s->z_err = Z_STREAM_END; 00421 return 1; 00422 } 00423 } 00424 00425 while (s->stream.avail_out != 0) { 00426 00427 if (s->transparent) { 00428 /* Copy first the lookahead bytes: */ 00429 uInt n = s->stream.avail_in; 00430 if (n > s->stream.avail_out) n = s->stream.avail_out; 00431 if (n > 0) { 00432 zmemcpy(s->stream.next_out, s->stream.next_in, n); 00433 next_out += n; 00434 s->stream.next_out = next_out; 00435 s->stream.next_in += n; 00436 s->stream.avail_out -= n; 00437 s->stream.avail_in -= n; 00438 } 00439 if (s->stream.avail_out > 0) { 00440 s->stream.avail_out -= 00441 (uInt)fread(next_out, 1, s->stream.avail_out, s->file); 00442 } 00443 len -= s->stream.avail_out; 00444 s->in += len; 00445 s->out += len; 00446 if (len == 0) s->z_eof = 1; 00447 return (int)len; 00448 } 00449 if (s->stream.avail_in == 0 && !s->z_eof) { 00450 00451 errno = 0; 00452 s->stream.avail_in = (uInt)fread(s->inbuf, 1, Z_BUFSIZE, s->file); 00453 if (s->stream.avail_in == 0) { 00454 s->z_eof = 1; 00455 if (ferror(s->file)) { 00456 s->z_err = Z_ERRNO; 00457 break; 00458 } 00459 } 00460 s->stream.next_in = s->inbuf; 00461 } 00462 s->in += s->stream.avail_in; 00463 s->out += s->stream.avail_out; 00464 s->z_err = inflate(&(s->stream), Z_NO_FLUSH); 00465 s->in -= s->stream.avail_in; 00466 s->out -= s->stream.avail_out; 00467 00468 if (s->z_err == Z_STREAM_END) { 00469 /* Check CRC and original size */ 00470 s->crc = crc32(s->crc, start, (uInt)(s->stream.next_out - start)); 00471 start = s->stream.next_out; 00472 00473 if (getLong(s) != s->crc) { 00474 s->z_err = Z_DATA_ERROR; 00475 } else { 00476 (void)getLong(s); 00477 /* The uncompressed length returned by above getlong() may be 00478 * different from s->out in case of concatenated .gz files. 00479 * Check for such files: 00480 */ 00481 check_header(s); 00482 if (s->z_err == Z_OK) { 00483 inflateReset(&(s->stream)); 00484 s->crc = crc32(0L, Z_NULL, 0); 00485 } 00486 } 00487 } 00488 if (s->z_err != Z_OK || s->z_eof) break; 00489 } 00490 s->crc = crc32(s->crc, start, (uInt)(s->stream.next_out - start)); 00491 00492 if (len == s->stream.avail_out && 00493 (s->z_err == Z_DATA_ERROR || s->z_err == Z_ERRNO)) 00494 return -1; 00495 return (int)(len - s->stream.avail_out); 00496 } 00497 00498 00499 /* =========================================================================== 00500 Reads one byte from the compressed file. gzgetc returns this byte 00501 or -1 in case of end of file or error. 00502 */ 00503 int ZEXPORT gzgetc(file) 00504 gzFile file; 00505 { 00506 unsigned char c; 00507 00508 return gzread(file, &c, 1) == 1 ? c : -1; 00509 } 00510 00511 00512 /* =========================================================================== 00513 Push one byte back onto the stream. 00514 */ 00515 int ZEXPORT gzungetc(c, file) 00516 int c; 00517 gzFile file; 00518 { 00519 gz_stream *s = (gz_stream*)file; 00520 00521 if (s == NULL || s->mode != 'r' || c == EOF || s->back != EOF) return EOF; 00522 s->back = c; 00523 s->out--; 00524 s->last = (s->z_err == Z_STREAM_END); 00525 if (s->last) s->z_err = Z_OK; 00526 s->z_eof = 0; 00527 return c; 00528 } 00529 00530 00531 /* =========================================================================== 00532 Reads bytes from the compressed file until len-1 characters are 00533 read, or a newline character is read and transferred to buf, or an 00534 end-of-file condition is encountered. The string is then terminated 00535 with a null character. 00536 gzgets returns buf, or Z_NULL in case of error. 00537 00538 The current implementation is not optimized at all. 00539 */ 00540 char * ZEXPORT gzgets(file, buf, len) 00541 gzFile file; 00542 char *buf; 00543 int len; 00544 { 00545 char *b = buf; 00546 if (buf == Z_NULL || len <= 0) return Z_NULL; 00547 00548 while (--len > 0 && gzread(file, buf, 1) == 1 && *buf++ != '\n') ; 00549 *buf = '\0'; 00550 return b == buf && len > 0 ? Z_NULL : b; 00551 } 00552 00553 00554 #ifndef NO_GZCOMPRESS 00555 /* =========================================================================== 00556 Writes the given number of uncompressed bytes into the compressed file. 00557 gzwrite returns the number of bytes actually written (0 in case of error). 00558 */ 00559 int ZEXPORT gzwrite (file, buf, len) 00560 gzFile file; 00561 voidpc buf; 00562 unsigned len; 00563 { 00564 gz_stream *s = (gz_stream*)file; 00565 00566 if (s == NULL || s->mode != 'w') return Z_STREAM_ERROR; 00567 00568 s->stream.next_in = (Bytef*)buf; 00569 s->stream.avail_in = len; 00570 00571 while (s->stream.avail_in != 0) { 00572 00573 if (s->stream.avail_out == 0) { 00574 00575 s->stream.next_out = s->outbuf; 00576 if (fwrite(s->outbuf, 1, Z_BUFSIZE, s->file) != Z_BUFSIZE) { 00577 s->z_err = Z_ERRNO; 00578 break; 00579 } 00580 s->stream.avail_out = Z_BUFSIZE; 00581 } 00582 s->in += s->stream.avail_in; 00583 s->out += s->stream.avail_out; 00584 s->z_err = deflate(&(s->stream), Z_NO_FLUSH); 00585 s->in -= s->stream.avail_in; 00586 s->out -= s->stream.avail_out; 00587 if (s->z_err != Z_OK) break; 00588 } 00589 s->crc = crc32(s->crc, (const Bytef *)buf, len); 00590 00591 return (int)(len - s->stream.avail_in); 00592 } 00593 00594 00595 /* =========================================================================== 00596 Converts, formats, and writes the args to the compressed file under 00597 control of the format string, as in fprintf. gzprintf returns the number of 00598 uncompressed bytes actually written (0 in case of error). 00599 */ 00600 #ifdef STDC 00601 #include <stdarg.h> 00602 00603 int ZEXPORTVA gzprintf (gzFile file, const char *format, /* args */ ...) 00604 { 00605 char buf[Z_PRINTF_BUFSIZE]; 00606 va_list va; 00607 int len; 00608 00609 buf[sizeof(buf) - 1] = 0; 00610 va_start(va, format); 00611 #ifdef NO_vsnprintf 00612 # ifdef HAS_vsprintf_void 00613 (void)vsprintf(buf, format, va); 00614 va_end(va); 00615 for (len = 0; len < sizeof(buf); len++) 00616 if (buf[len] == 0) break; 00617 # else 00618 len = vsprintf(buf, format, va); 00619 va_end(va); 00620 # endif 00621 #else 00622 # ifdef HAS_vsnprintf_void 00623 (void)vsnprintf(buf, sizeof(buf), format, va); 00624 va_end(va); 00625 len = strlen(buf); 00626 # else 00627 len = vsnprintf(buf, sizeof(buf), format, va); 00628 va_end(va); 00629 # endif 00630 #endif 00631 if (len <= 0 || len >= (int)sizeof(buf) || buf[sizeof(buf) - 1] != 0) 00632 return 0; 00633 return gzwrite(file, buf, (unsigned)len); 00634 } 00635 #else /* not ANSI C */ 00636 00637 int ZEXPORTVA gzprintf (file, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, 00638 a11, a12, a13, a14, a15, a16, a17, a18, a19, a20) 00639 gzFile file; 00640 const char *format; 00641 int a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, 00642 a11, a12, a13, a14, a15, a16, a17, a18, a19, a20; 00643 { 00644 char buf[Z_PRINTF_BUFSIZE]; 00645 int len; 00646 00647 buf[sizeof(buf) - 1] = 0; 00648 #ifdef NO_snprintf 00649 # ifdef HAS_sprintf_void 00650 sprintf(buf, format, a1, a2, a3, a4, a5, a6, a7, a8, 00651 a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20); 00652 for (len = 0; len < sizeof(buf); len++) 00653 if (buf[len] == 0) break; 00654 # else 00655 len = sprintf(buf, format, a1, a2, a3, a4, a5, a6, a7, a8, 00656 a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20); 00657 # endif 00658 #else 00659 # ifdef HAS_snprintf_void 00660 snprintf(buf, sizeof(buf), format, a1, a2, a3, a4, a5, a6, a7, a8, 00661 a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20); 00662 len = strlen(buf); 00663 # else 00664 len = snprintf(buf, sizeof(buf), format, a1, a2, a3, a4, a5, a6, a7, a8, 00665 a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20); 00666 # endif 00667 #endif 00668 if (len <= 0 || len >= sizeof(buf) || buf[sizeof(buf) - 1] != 0) 00669 return 0; 00670 return gzwrite(file, buf, len); 00671 } 00672 #endif 00673 00674 /* =========================================================================== 00675 Writes c, converted to an unsigned char, into the compressed file. 00676 gzputc returns the value that was written, or -1 in case of error. 00677 */ 00678 int ZEXPORT gzputc(file, c) 00679 gzFile file; 00680 int c; 00681 { 00682 unsigned char cc = (unsigned char) c; /* required for big endian systems */ 00683 00684 return gzwrite(file, &cc, 1) == 1 ? (int)cc : -1; 00685 } 00686 00687 00688 /* =========================================================================== 00689 Writes the given null-terminated string to the compressed file, excluding 00690 the terminating null character. 00691 gzputs returns the number of characters written, or -1 in case of error. 00692 */ 00693 int ZEXPORT gzputs(file, s) 00694 gzFile file; 00695 const char *s; 00696 { 00697 return gzwrite(file, (char*)s, (unsigned)strlen(s)); 00698 } 00699 00700 00701 /* =========================================================================== 00702 Flushes all pending output into the compressed file. The parameter 00703 flush is as in the deflate() function. 00704 */ 00705 local int do_flush (file, flush) 00706 gzFile file; 00707 int flush; 00708 { 00709 uInt len; 00710 int done = 0; 00711 gz_stream *s = (gz_stream*)file; 00712 00713 if (s == NULL || s->mode != 'w') return Z_STREAM_ERROR; 00714 00715 s->stream.avail_in = 0; /* should be zero already anyway */ 00716 00717 for (;;) { 00718 len = Z_BUFSIZE - s->stream.avail_out; 00719 00720 if (len != 0) { 00721 if ((uInt)fwrite(s->outbuf, 1, len, s->file) != len) { 00722 s->z_err = Z_ERRNO; 00723 return Z_ERRNO; 00724 } 00725 s->stream.next_out = s->outbuf; 00726 s->stream.avail_out = Z_BUFSIZE; 00727 } 00728 if (done) break; 00729 s->out += s->stream.avail_out; 00730 s->z_err = deflate(&(s->stream), flush); 00731 s->out -= s->stream.avail_out; 00732 00733 /* Ignore the second of two consecutive flushes: */ 00734 if (len == 0 && s->z_err == Z_BUF_ERROR) s->z_err = Z_OK; 00735 00736 /* deflate has finished flushing only when it hasn't used up 00737 * all the available space in the output buffer: 00738 */ 00739 done = (s->stream.avail_out != 0 || s->z_err == Z_STREAM_END); 00740 00741 if (s->z_err != Z_OK && s->z_err != Z_STREAM_END) break; 00742 } 00743 return s->z_err == Z_STREAM_END ? Z_OK : s->z_err; 00744 } 00745 00746 int ZEXPORT gzflush (file, flush) 00747 gzFile file; 00748 int flush; 00749 { 00750 gz_stream *s = (gz_stream*)file; 00751 int err = do_flush (file, flush); 00752 00753 if (err) return err; 00754 fflush(s->file); 00755 return s->z_err == Z_STREAM_END ? Z_OK : s->z_err; 00756 } 00757 #endif /* NO_GZCOMPRESS */ 00758 00759 /* =========================================================================== 00760 Sets the starting position for the next gzread or gzwrite on the given 00761 compressed file. The offset represents a number of bytes in the 00762 gzseek returns the resulting offset location as measured in bytes from 00763 the beginning of the uncompressed stream, or -1 in case of error. 00764 SEEK_END is not implemented, returns error. 00765 In this version of the library, gzseek can be extremely slow. 00766 */ 00767 z_off_t ZEXPORT gzseek (file, offset, whence) 00768 gzFile file; 00769 z_off_t offset; 00770 int whence; 00771 { 00772 gz_stream *s = (gz_stream*)file; 00773 00774 if (s == NULL || whence == SEEK_END || 00775 s->z_err == Z_ERRNO || s->z_err == Z_DATA_ERROR) { 00776 return -1L; 00777 } 00778 00779 if (s->mode == 'w') { 00780 #ifdef NO_GZCOMPRESS 00781 return -1L; 00782 #else 00783 if (whence == SEEK_SET) { 00784 offset -= s->in; 00785 } 00786 if (offset < 0) return -1L; 00787 00788 /* At this point, offset is the number of zero bytes to write. */ 00789 if (s->inbuf == Z_NULL) { 00790 s->inbuf = (Byte*)ALLOC(Z_BUFSIZE); /* for seeking */ 00791 if (s->inbuf == Z_NULL) return -1L; 00792 zmemzero(s->inbuf, Z_BUFSIZE); 00793 } 00794 while (offset > 0) { 00795 uInt size = Z_BUFSIZE; 00796 if (offset < Z_BUFSIZE) size = (uInt)offset; 00797 00798 size = gzwrite(file, s->inbuf, size); 00799 if (size == 0) return -1L; 00800 00801 offset -= size; 00802 } 00803 return s->in; 00804 #endif 00805 } 00806 /* Rest of function is for reading only */ 00807 00808 /* compute absolute position */ 00809 if (whence == SEEK_CUR) { 00810 offset += s->out; 00811 } 00812 if (offset < 0) return -1L; 00813 00814 if (s->transparent) { 00815 /* map to fseek */ 00816 s->back = EOF; 00817 s->stream.avail_in = 0; 00818 s->stream.next_in = s->inbuf; 00819 if (fseek(s->file, offset, SEEK_SET) < 0) return -1L; 00820 00821 s->in = s->out = offset; 00822 return offset; 00823 } 00824 00825 /* For a negative seek, rewind and use positive seek */ 00826 if (offset >= s->out) { 00827 offset -= s->out; 00828 } else if (gzrewind(file) < 0) { 00829 return -1L; 00830 } 00831 /* offset is now the number of bytes to skip. */ 00832 00833 if (offset != 0 && s->outbuf == Z_NULL) { 00834 s->outbuf = (Byte*)ALLOC(Z_BUFSIZE); 00835 if (s->outbuf == Z_NULL) return -1L; 00836 } 00837 if (offset && s->back != EOF) { 00838 s->back = EOF; 00839 s->out++; 00840 offset--; 00841 if (s->last) s->z_err = Z_STREAM_END; 00842 } 00843 while (offset > 0) { 00844 int size = Z_BUFSIZE; 00845 if (offset < Z_BUFSIZE) size = (int)offset; 00846 00847 size = gzread(file, s->outbuf, (uInt)size); 00848 if (size <= 0) return -1L; 00849 offset -= size; 00850 } 00851 return s->out; 00852 } 00853 00854 /* =========================================================================== 00855 Rewinds input file. 00856 */ 00857 int ZEXPORT gzrewind (file) 00858 gzFile file; 00859 { 00860 gz_stream *s = (gz_stream*)file; 00861 00862 if (s == NULL || s->mode != 'r') return -1; 00863 00864 s->z_err = Z_OK; 00865 s->z_eof = 0; 00866 s->back = EOF; 00867 s->stream.avail_in = 0; 00868 s->stream.next_in = s->inbuf; 00869 s->crc = crc32(0L, Z_NULL, 0); 00870 if (!s->transparent) (void)inflateReset(&s->stream); 00871 s->in = 0; 00872 s->out = 0; 00873 return fseek(s->file, s->start, SEEK_SET); 00874 } 00875 00876 /* =========================================================================== 00877 Returns the starting position for the next gzread or gzwrite on the 00878 given compressed file. This position represents a number of bytes in the 00879 uncompressed data stream. 00880 */ 00881 z_off_t ZEXPORT gztell (file) 00882 gzFile file; 00883 { 00884 return gzseek(file, 0L, SEEK_CUR); 00885 } 00886 00887 /* =========================================================================== 00888 Returns 1 when EOF has previously been detected reading the given 00889 input stream, otherwise zero. 00890 */ 00891 int ZEXPORT gzeof (file) 00892 gzFile file; 00893 { 00894 gz_stream *s = (gz_stream*)file; 00895 00896 /* With concatenated compressed files that can have embedded 00897 * crc trailers, z_eof is no longer the only/best indicator of EOF 00898 * on a gz_stream. Handle end-of-stream error explicitly here. 00899 */ 00900 if (s == NULL || s->mode != 'r') return 0; 00901 if (s->z_eof) return 1; 00902 return s->z_err == Z_STREAM_END; 00903 } 00904 00905 /* =========================================================================== 00906 Returns 1 if reading and doing so transparently, otherwise zero. 00907 */ 00908 int ZEXPORT gzdirect (file) 00909 gzFile file; 00910 { 00911 gz_stream *s = (gz_stream*)file; 00912 00913 if (s == NULL || s->mode != 'r') return 0; 00914 return s->transparent; 00915 } 00916 00917 /* =========================================================================== 00918 Outputs a long in LSB order to the given file 00919 */ 00920 local void putLong (file, x) 00921 FILE *file; 00922 uLong x; 00923 { 00924 int n; 00925 for (n = 0; n < 4; n++) { 00926 fputc((int)(x & 0xff), file); 00927 x >>= 8; 00928 } 00929 } 00930 00931 /* =========================================================================== 00932 Reads a long in LSB order from the given gz_stream. Sets z_err in case 00933 of error. 00934 */ 00935 local uLong getLong (s) 00936 gz_stream *s; 00937 { 00938 uLong x = (uLong)get_byte(s); 00939 int c; 00940 00941 x += ((uLong)get_byte(s))<<8; 00942 x += ((uLong)get_byte(s))<<16; 00943 c = get_byte(s); 00944 if (c == EOF) s->z_err = Z_DATA_ERROR; 00945 x += ((uLong)c)<<24; 00946 return x; 00947 } 00948 00949 /* =========================================================================== 00950 Flushes all pending output if necessary, closes the compressed file 00951 and deallocates all the (de)compression state. 00952 */ 00953 int ZEXPORT gzclose (file) 00954 gzFile file; 00955 { 00956 gz_stream *s = (gz_stream*)file; 00957 00958 if (s == NULL) return Z_STREAM_ERROR; 00959 00960 if (s->mode == 'w') { 00961 #ifdef NO_GZCOMPRESS 00962 return Z_STREAM_ERROR; 00963 #else 00964 if (do_flush (file, Z_FINISH) != Z_OK) 00965 return destroy((gz_stream*)file); 00966 00967 putLong (s->file, s->crc); 00968 putLong (s->file, (uLong)(s->in & 0xffffffff)); 00969 #endif 00970 } 00971 return destroy((gz_stream*)file); 00972 } 00973 00974 #ifdef STDC 00975 # define zstrerror(errnum) strerror(errnum) 00976 #else 00977 # define zstrerror(errnum) "" 00978 #endif 00979 00980 /* =========================================================================== 00981 Returns the error message for the last error which occurred on the 00982 given compressed file. errnum is set to zlib error number. If an 00983 error occurred in the file system and not in the compression library, 00984 errnum is set to Z_ERRNO and the application may consult errno 00985 to get the exact error code. 00986 */ 00987 const char * ZEXPORT gzerror (file, errnum) 00988 gzFile file; 00989 int *errnum; 00990 { 00991 char *m; 00992 gz_stream *s = (gz_stream*)file; 00993 00994 if (s == NULL) { 00995 *errnum = Z_STREAM_ERROR; 00996 return (const char*)ERR_MSG(Z_STREAM_ERROR); 00997 } 00998 *errnum = s->z_err; 00999 if (*errnum == Z_OK) return (const char*)""; 01000 01001 m = (char*)(*errnum == Z_ERRNO ? zstrerror(errno) : s->stream.msg); 01002 01003 if (m == NULL || *m == '\0') m = (char*)ERR_MSG(s->z_err); 01004 01005 TRYFREE(s->msg); 01006 s->msg = (char*)ALLOC(strlen(s->path) + strlen(m) + 3); 01007 if (s->msg == Z_NULL) return (const char*)ERR_MSG(Z_MEM_ERROR); 01008 strcpy(s->msg, s->path); 01009 strcat(s->msg, ": "); 01010 strcat(s->msg, m); 01011 return (const char*)s->msg; 01012 } 01013 01014 /* =========================================================================== 01015 Clear the error and end-of-file flags, and do the same for the real file. 01016 */ 01017 void ZEXPORT gzclearerr (file) 01018 gzFile file; 01019 { 01020 gz_stream *s = (gz_stream*)file; 01021 01022 if (s == NULL) return; 01023 if (s->z_err != Z_STREAM_END) s->z_err = Z_OK; 01024 s->z_eof = 0; 01025 clearerr(s->file); 01026 }