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