ยปCore Development>Code coverage>Modules/zlib/gzio.c

Python code coverage for Modules/zlib/gzio.c

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