1381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes/* gzwrite.c -- zlib functions for writing gzip files
204351a92ecc8429c999acbfc5dfe5aa8bee1d19dElliott Hughes * Copyright (C) 2004, 2005, 2010, 2011, 2012, 2013 Mark Adler
3381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes * For conditions of distribution and use, see copyright notice in zlib.h
4381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes */
5381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
6381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes#include "gzguts.h"
7381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
8381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes/* Local functions */
9381716e9396b55b1adb8235b020c37344f60ab07Elliott Hugheslocal int gz_init OF((gz_statep));
10381716e9396b55b1adb8235b020c37344f60ab07Elliott Hugheslocal int gz_comp OF((gz_statep, int));
11381716e9396b55b1adb8235b020c37344f60ab07Elliott Hugheslocal int gz_zero OF((gz_statep, z_off64_t));
12381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
13381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes/* Initialize state for writing a gzip file.  Mark initialization by setting
14381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes   state->size to non-zero.  Return -1 on failure or 0 on success. */
15381716e9396b55b1adb8235b020c37344f60ab07Elliott Hugheslocal int gz_init(state)
16381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    gz_statep state;
17381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes{
18381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    int ret;
19381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    z_streamp strm = &(state->strm);
20381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
21ee9e11d0d4e3361533860bf04896abb86a291bfbElliott Hughes    /* allocate input buffer */
2204351a92ecc8429c999acbfc5dfe5aa8bee1d19dElliott Hughes    state->in = (unsigned char *)malloc(state->want);
23ee9e11d0d4e3361533860bf04896abb86a291bfbElliott Hughes    if (state->in == NULL) {
24381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        gz_error(state, Z_MEM_ERROR, "out of memory");
25381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        return -1;
26381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    }
27381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
28ee9e11d0d4e3361533860bf04896abb86a291bfbElliott Hughes    /* only need output buffer and deflate state if compressing */
29ee9e11d0d4e3361533860bf04896abb86a291bfbElliott Hughes    if (!state->direct) {
30ee9e11d0d4e3361533860bf04896abb86a291bfbElliott Hughes        /* allocate output buffer */
3104351a92ecc8429c999acbfc5dfe5aa8bee1d19dElliott Hughes        state->out = (unsigned char *)malloc(state->want);
32ee9e11d0d4e3361533860bf04896abb86a291bfbElliott Hughes        if (state->out == NULL) {
33ee9e11d0d4e3361533860bf04896abb86a291bfbElliott Hughes            free(state->in);
34ee9e11d0d4e3361533860bf04896abb86a291bfbElliott Hughes            gz_error(state, Z_MEM_ERROR, "out of memory");
35ee9e11d0d4e3361533860bf04896abb86a291bfbElliott Hughes            return -1;
36ee9e11d0d4e3361533860bf04896abb86a291bfbElliott Hughes        }
37ee9e11d0d4e3361533860bf04896abb86a291bfbElliott Hughes
38ee9e11d0d4e3361533860bf04896abb86a291bfbElliott Hughes        /* allocate deflate memory, set up for gzip compression */
39ee9e11d0d4e3361533860bf04896abb86a291bfbElliott Hughes        strm->zalloc = Z_NULL;
40ee9e11d0d4e3361533860bf04896abb86a291bfbElliott Hughes        strm->zfree = Z_NULL;
41ee9e11d0d4e3361533860bf04896abb86a291bfbElliott Hughes        strm->opaque = Z_NULL;
42ee9e11d0d4e3361533860bf04896abb86a291bfbElliott Hughes        ret = deflateInit2(strm, state->level, Z_DEFLATED,
43ee9e11d0d4e3361533860bf04896abb86a291bfbElliott Hughes                           MAX_WBITS + 16, DEF_MEM_LEVEL, state->strategy);
44ee9e11d0d4e3361533860bf04896abb86a291bfbElliott Hughes        if (ret != Z_OK) {
45ee9e11d0d4e3361533860bf04896abb86a291bfbElliott Hughes            free(state->out);
46ee9e11d0d4e3361533860bf04896abb86a291bfbElliott Hughes            free(state->in);
47ee9e11d0d4e3361533860bf04896abb86a291bfbElliott Hughes            gz_error(state, Z_MEM_ERROR, "out of memory");
48ee9e11d0d4e3361533860bf04896abb86a291bfbElliott Hughes            return -1;
49ee9e11d0d4e3361533860bf04896abb86a291bfbElliott Hughes        }
50381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    }
51381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
52381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    /* mark state as initialized */
53381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    state->size = state->want;
54381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
55ee9e11d0d4e3361533860bf04896abb86a291bfbElliott Hughes    /* initialize write buffer if compressing */
56ee9e11d0d4e3361533860bf04896abb86a291bfbElliott Hughes    if (!state->direct) {
57ee9e11d0d4e3361533860bf04896abb86a291bfbElliott Hughes        strm->avail_out = state->size;
58ee9e11d0d4e3361533860bf04896abb86a291bfbElliott Hughes        strm->next_out = state->out;
59ee9e11d0d4e3361533860bf04896abb86a291bfbElliott Hughes        state->x.next = strm->next_out;
60ee9e11d0d4e3361533860bf04896abb86a291bfbElliott Hughes    }
61381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    return 0;
62381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes}
63381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
64381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes/* Compress whatever is at avail_in and next_in and write to the output file.
65381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes   Return -1 if there is an error writing to the output file, otherwise 0.
66381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes   flush is assumed to be a valid deflate() flush value.  If flush is Z_FINISH,
67ee9e11d0d4e3361533860bf04896abb86a291bfbElliott Hughes   then the deflate() state is reset to start a new gzip stream.  If gz->direct
68ee9e11d0d4e3361533860bf04896abb86a291bfbElliott Hughes   is true, then simply write to the output file without compressing, and
69ee9e11d0d4e3361533860bf04896abb86a291bfbElliott Hughes   ignore flush. */
70381716e9396b55b1adb8235b020c37344f60ab07Elliott Hugheslocal int gz_comp(state, flush)
71381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    gz_statep state;
72381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    int flush;
73381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes{
74381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    int ret, got;
75381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    unsigned have;
76381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    z_streamp strm = &(state->strm);
77381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
78381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    /* allocate memory if this is the first time through */
79381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    if (state->size == 0 && gz_init(state) == -1)
80381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        return -1;
81381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
82ee9e11d0d4e3361533860bf04896abb86a291bfbElliott Hughes    /* write directly if requested */
83ee9e11d0d4e3361533860bf04896abb86a291bfbElliott Hughes    if (state->direct) {
84ee9e11d0d4e3361533860bf04896abb86a291bfbElliott Hughes        got = write(state->fd, strm->next_in, strm->avail_in);
85ee9e11d0d4e3361533860bf04896abb86a291bfbElliott Hughes        if (got < 0 || (unsigned)got != strm->avail_in) {
86ee9e11d0d4e3361533860bf04896abb86a291bfbElliott Hughes            gz_error(state, Z_ERRNO, zstrerror());
87ee9e11d0d4e3361533860bf04896abb86a291bfbElliott Hughes            return -1;
88ee9e11d0d4e3361533860bf04896abb86a291bfbElliott Hughes        }
89ee9e11d0d4e3361533860bf04896abb86a291bfbElliott Hughes        strm->avail_in = 0;
90ee9e11d0d4e3361533860bf04896abb86a291bfbElliott Hughes        return 0;
91ee9e11d0d4e3361533860bf04896abb86a291bfbElliott Hughes    }
92ee9e11d0d4e3361533860bf04896abb86a291bfbElliott Hughes
93381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    /* run deflate() on provided input until it produces no more output */
94381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    ret = Z_OK;
95381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    do {
96381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        /* write out current buffer contents if full, or if flushing, but if
97381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes           doing Z_FINISH then don't write until we get to Z_STREAM_END */
98381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        if (strm->avail_out == 0 || (flush != Z_NO_FLUSH &&
99381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes            (flush != Z_FINISH || ret == Z_STREAM_END))) {
100ee9e11d0d4e3361533860bf04896abb86a291bfbElliott Hughes            have = (unsigned)(strm->next_out - state->x.next);
101ee9e11d0d4e3361533860bf04896abb86a291bfbElliott Hughes            if (have && ((got = write(state->fd, state->x.next, have)) < 0 ||
102381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes                         (unsigned)got != have)) {
103381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes                gz_error(state, Z_ERRNO, zstrerror());
104381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes                return -1;
105381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes            }
106381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes            if (strm->avail_out == 0) {
107381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes                strm->avail_out = state->size;
108381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes                strm->next_out = state->out;
109381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes            }
110ee9e11d0d4e3361533860bf04896abb86a291bfbElliott Hughes            state->x.next = strm->next_out;
111381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        }
112381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
113381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        /* compress */
114381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        have = strm->avail_out;
115381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        ret = deflate(strm, flush);
116381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        if (ret == Z_STREAM_ERROR) {
117381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes            gz_error(state, Z_STREAM_ERROR,
118381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes                      "internal error: deflate stream corrupt");
119381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes            return -1;
120381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        }
121381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        have -= strm->avail_out;
122381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    } while (have);
123381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
124381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    /* if that completed a deflate stream, allow another to start */
125381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    if (flush == Z_FINISH)
126381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        deflateReset(strm);
127381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
128381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    /* all done, no errors */
129381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    return 0;
130381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes}
131381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
132381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes/* Compress len zeros to output.  Return -1 on error, 0 on success. */
133381716e9396b55b1adb8235b020c37344f60ab07Elliott Hugheslocal int gz_zero(state, len)
134381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    gz_statep state;
135381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    z_off64_t len;
136381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes{
137381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    int first;
138381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    unsigned n;
139381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    z_streamp strm = &(state->strm);
140381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
141381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    /* consume whatever's left in the input buffer */
142381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1)
143381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        return -1;
144381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
145381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    /* compress len zeros (len guaranteed > 0) */
146381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    first = 1;
147381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    while (len) {
148381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        n = GT_OFF(state->size) || (z_off64_t)state->size > len ?
149381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes            (unsigned)len : state->size;
150381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        if (first) {
151381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes            memset(state->in, 0, n);
152381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes            first = 0;
153381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        }
154381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        strm->avail_in = n;
155381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        strm->next_in = state->in;
156ee9e11d0d4e3361533860bf04896abb86a291bfbElliott Hughes        state->x.pos += n;
157381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        if (gz_comp(state, Z_NO_FLUSH) == -1)
158381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes            return -1;
159381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        len -= n;
160381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    }
161381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    return 0;
162381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes}
163381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
164381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes/* -- see zlib.h -- */
165381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughesint ZEXPORT gzwrite(file, buf, len)
166381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    gzFile file;
167381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    voidpc buf;
168381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    unsigned len;
169381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes{
170381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    unsigned put = len;
171381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    gz_statep state;
172381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    z_streamp strm;
173381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
174381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    /* get internal structure */
175381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    if (file == NULL)
176381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        return 0;
177381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    state = (gz_statep)file;
178381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    strm = &(state->strm);
179381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
180381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    /* check that we're writing and that there's no error */
181381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    if (state->mode != GZ_WRITE || state->err != Z_OK)
182381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        return 0;
183381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
184381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    /* since an int is returned, make sure len fits in one, otherwise return
185381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes       with an error (this avoids the flaw in the interface) */
186381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    if ((int)len < 0) {
187ee9e11d0d4e3361533860bf04896abb86a291bfbElliott Hughes        gz_error(state, Z_DATA_ERROR, "requested length does not fit in int");
188381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        return 0;
189381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    }
190381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
191381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    /* if len is zero, avoid unnecessary operations */
192381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    if (len == 0)
193381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        return 0;
194381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
195381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    /* allocate memory if this is the first time through */
196381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    if (state->size == 0 && gz_init(state) == -1)
197381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        return 0;
198381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
199381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    /* check for seek request */
200381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    if (state->seek) {
201381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        state->seek = 0;
202381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        if (gz_zero(state, state->skip) == -1)
203381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes            return 0;
204381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    }
205381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
206381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    /* for small len, copy to input buffer, otherwise compress directly */
207381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    if (len < state->size) {
208381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        /* copy to input buffer, compress when full */
209381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        do {
21004351a92ecc8429c999acbfc5dfe5aa8bee1d19dElliott Hughes            unsigned have, copy;
21104351a92ecc8429c999acbfc5dfe5aa8bee1d19dElliott Hughes
212381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes            if (strm->avail_in == 0)
213381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes                strm->next_in = state->in;
21404351a92ecc8429c999acbfc5dfe5aa8bee1d19dElliott Hughes            have = (unsigned)((strm->next_in + strm->avail_in) - state->in);
21504351a92ecc8429c999acbfc5dfe5aa8bee1d19dElliott Hughes            copy = state->size - have;
21604351a92ecc8429c999acbfc5dfe5aa8bee1d19dElliott Hughes            if (copy > len)
21704351a92ecc8429c999acbfc5dfe5aa8bee1d19dElliott Hughes                copy = len;
21804351a92ecc8429c999acbfc5dfe5aa8bee1d19dElliott Hughes            memcpy(state->in + have, buf, copy);
21904351a92ecc8429c999acbfc5dfe5aa8bee1d19dElliott Hughes            strm->avail_in += copy;
22004351a92ecc8429c999acbfc5dfe5aa8bee1d19dElliott Hughes            state->x.pos += copy;
22104351a92ecc8429c999acbfc5dfe5aa8bee1d19dElliott Hughes            buf = (const char *)buf + copy;
22204351a92ecc8429c999acbfc5dfe5aa8bee1d19dElliott Hughes            len -= copy;
223381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes            if (len && gz_comp(state, Z_NO_FLUSH) == -1)
224381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes                return 0;
225381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        } while (len);
226381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    }
227381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    else {
228381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        /* consume whatever's left in the input buffer */
229381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1)
230381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes            return 0;
231381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
232381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        /* directly compress user buffer to file */
233381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        strm->avail_in = len;
23404351a92ecc8429c999acbfc5dfe5aa8bee1d19dElliott Hughes        strm->next_in = (z_const Bytef *)buf;
235ee9e11d0d4e3361533860bf04896abb86a291bfbElliott Hughes        state->x.pos += len;
236381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        if (gz_comp(state, Z_NO_FLUSH) == -1)
237381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes            return 0;
238381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    }
239381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
240381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    /* input was all buffered or compressed (put will fit in int) */
241381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    return (int)put;
242381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes}
243381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
244381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes/* -- see zlib.h -- */
245381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughesint ZEXPORT gzputc(file, c)
246381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    gzFile file;
247381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    int c;
248381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes{
24904351a92ecc8429c999acbfc5dfe5aa8bee1d19dElliott Hughes    unsigned have;
250381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    unsigned char buf[1];
251381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    gz_statep state;
252381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    z_streamp strm;
253381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
254381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    /* get internal structure */
255381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    if (file == NULL)
256381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        return -1;
257381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    state = (gz_statep)file;
258381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    strm = &(state->strm);
259381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
260381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    /* check that we're writing and that there's no error */
261381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    if (state->mode != GZ_WRITE || state->err != Z_OK)
262381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        return -1;
263381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
264381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    /* check for seek request */
265381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    if (state->seek) {
266381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        state->seek = 0;
267381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        if (gz_zero(state, state->skip) == -1)
268381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes            return -1;
269381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    }
270381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
271381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    /* try writing to input buffer for speed (state->size == 0 if buffer not
272381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes       initialized) */
27304351a92ecc8429c999acbfc5dfe5aa8bee1d19dElliott Hughes    if (state->size) {
274381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        if (strm->avail_in == 0)
275381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes            strm->next_in = state->in;
27604351a92ecc8429c999acbfc5dfe5aa8bee1d19dElliott Hughes        have = (unsigned)((strm->next_in + strm->avail_in) - state->in);
27704351a92ecc8429c999acbfc5dfe5aa8bee1d19dElliott Hughes        if (have < state->size) {
27804351a92ecc8429c999acbfc5dfe5aa8bee1d19dElliott Hughes            state->in[have] = c;
27904351a92ecc8429c999acbfc5dfe5aa8bee1d19dElliott Hughes            strm->avail_in++;
28004351a92ecc8429c999acbfc5dfe5aa8bee1d19dElliott Hughes            state->x.pos++;
28104351a92ecc8429c999acbfc5dfe5aa8bee1d19dElliott Hughes            return c & 0xff;
28204351a92ecc8429c999acbfc5dfe5aa8bee1d19dElliott Hughes        }
283381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    }
284381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
285381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    /* no room in buffer or not initialized, use gz_write() */
286381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    buf[0] = c;
287381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    if (gzwrite(file, buf, 1) != 1)
288381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        return -1;
289ee9e11d0d4e3361533860bf04896abb86a291bfbElliott Hughes    return c & 0xff;
290381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes}
291381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
292381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes/* -- see zlib.h -- */
293381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughesint ZEXPORT gzputs(file, str)
294381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    gzFile file;
295381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    const char *str;
296381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes{
297381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    int ret;
298381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    unsigned len;
299381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
300381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    /* write string */
301381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    len = (unsigned)strlen(str);
302381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    ret = gzwrite(file, str, len);
303381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    return ret == 0 && len != 0 ? -1 : ret;
304381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes}
305381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
306ee9e11d0d4e3361533860bf04896abb86a291bfbElliott Hughes#if defined(STDC) || defined(Z_HAVE_STDARG_H)
307381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes#include <stdarg.h>
308381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
309381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes/* -- see zlib.h -- */
31004351a92ecc8429c999acbfc5dfe5aa8bee1d19dElliott Hughesint ZEXPORTVA gzvprintf(gzFile file, const char *format, va_list va)
311381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes{
312381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    int size, len;
313381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    gz_statep state;
314381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    z_streamp strm;
315381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
316381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    /* get internal structure */
317381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    if (file == NULL)
318381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        return -1;
319381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    state = (gz_statep)file;
320381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    strm = &(state->strm);
321381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
322381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    /* check that we're writing and that there's no error */
323381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    if (state->mode != GZ_WRITE || state->err != Z_OK)
324381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        return 0;
325381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
326381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    /* make sure we have some buffer space */
327381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    if (state->size == 0 && gz_init(state) == -1)
328381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        return 0;
329381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
330381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    /* check for seek request */
331381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    if (state->seek) {
332381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        state->seek = 0;
333381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        if (gz_zero(state, state->skip) == -1)
334381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes            return 0;
335381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    }
336381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
337381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    /* consume whatever's left in the input buffer */
338381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1)
339381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        return 0;
340381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
341381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    /* do the printf() into the input buffer, put length in len */
342381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    size = (int)(state->size);
343381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    state->in[size - 1] = 0;
344381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes#ifdef NO_vsnprintf
345381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes#  ifdef HAS_vsprintf_void
34609eb358bbbb9aad3fe48dd3368c8a7a481cbda1cElliott Hughes    (void)vsprintf((char *)(state->in), format, va);
347381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    for (len = 0; len < size; len++)
348381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        if (state->in[len] == 0) break;
349381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes#  else
35009eb358bbbb9aad3fe48dd3368c8a7a481cbda1cElliott Hughes    len = vsprintf((char *)(state->in), format, va);
351381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes#  endif
352381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes#else
353381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes#  ifdef HAS_vsnprintf_void
35409eb358bbbb9aad3fe48dd3368c8a7a481cbda1cElliott Hughes    (void)vsnprintf((char *)(state->in), size, format, va);
35509eb358bbbb9aad3fe48dd3368c8a7a481cbda1cElliott Hughes    len = strlen((char *)(state->in));
356381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes#  else
357381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    len = vsnprintf((char *)(state->in), size, format, va);
358381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes#  endif
359381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes#endif
360381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
361381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    /* check that printf() results fit in buffer */
362381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    if (len <= 0 || len >= (int)size || state->in[size - 1] != 0)
363381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        return 0;
364381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
365381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    /* update buffer and position, defer compression until needed */
366381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    strm->avail_in = (unsigned)len;
367381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    strm->next_in = state->in;
368ee9e11d0d4e3361533860bf04896abb86a291bfbElliott Hughes    state->x.pos += len;
369381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    return len;
370381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes}
371381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
37204351a92ecc8429c999acbfc5dfe5aa8bee1d19dElliott Hughesint ZEXPORTVA gzprintf(gzFile file, const char *format, ...)
37304351a92ecc8429c999acbfc5dfe5aa8bee1d19dElliott Hughes{
37404351a92ecc8429c999acbfc5dfe5aa8bee1d19dElliott Hughes    va_list va;
37504351a92ecc8429c999acbfc5dfe5aa8bee1d19dElliott Hughes    int ret;
37604351a92ecc8429c999acbfc5dfe5aa8bee1d19dElliott Hughes
37704351a92ecc8429c999acbfc5dfe5aa8bee1d19dElliott Hughes    va_start(va, format);
37804351a92ecc8429c999acbfc5dfe5aa8bee1d19dElliott Hughes    ret = gzvprintf(file, format, va);
37904351a92ecc8429c999acbfc5dfe5aa8bee1d19dElliott Hughes    va_end(va);
38004351a92ecc8429c999acbfc5dfe5aa8bee1d19dElliott Hughes    return ret;
38104351a92ecc8429c999acbfc5dfe5aa8bee1d19dElliott Hughes}
38204351a92ecc8429c999acbfc5dfe5aa8bee1d19dElliott Hughes
383ee9e11d0d4e3361533860bf04896abb86a291bfbElliott Hughes#else /* !STDC && !Z_HAVE_STDARG_H */
384381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
385381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes/* -- see zlib.h -- */
386381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughesint ZEXPORTVA gzprintf (file, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10,
387381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes                       a11, a12, a13, a14, a15, a16, a17, a18, a19, a20)
388381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    gzFile file;
389381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    const char *format;
390381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    int a1, a2, a3, a4, a5, a6, a7, a8, a9, a10,
391381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        a11, a12, a13, a14, a15, a16, a17, a18, a19, a20;
392381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes{
393381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    int size, len;
394381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    gz_statep state;
395381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    z_streamp strm;
396381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
397381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    /* get internal structure */
398381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    if (file == NULL)
399381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        return -1;
400381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    state = (gz_statep)file;
401381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    strm = &(state->strm);
402381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
403ee9e11d0d4e3361533860bf04896abb86a291bfbElliott Hughes    /* check that can really pass pointer in ints */
404ee9e11d0d4e3361533860bf04896abb86a291bfbElliott Hughes    if (sizeof(int) != sizeof(void *))
405ee9e11d0d4e3361533860bf04896abb86a291bfbElliott Hughes        return 0;
406ee9e11d0d4e3361533860bf04896abb86a291bfbElliott Hughes
407381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    /* check that we're writing and that there's no error */
408381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    if (state->mode != GZ_WRITE || state->err != Z_OK)
409381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        return 0;
410381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
411381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    /* make sure we have some buffer space */
412381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    if (state->size == 0 && gz_init(state) == -1)
413381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        return 0;
414381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
415381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    /* check for seek request */
416381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    if (state->seek) {
417381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        state->seek = 0;
418381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        if (gz_zero(state, state->skip) == -1)
419381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes            return 0;
420381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    }
421381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
422381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    /* consume whatever's left in the input buffer */
423381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1)
424381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        return 0;
425381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
426381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    /* do the printf() into the input buffer, put length in len */
427381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    size = (int)(state->size);
428381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    state->in[size - 1] = 0;
429381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes#ifdef NO_snprintf
430381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes#  ifdef HAS_sprintf_void
43109eb358bbbb9aad3fe48dd3368c8a7a481cbda1cElliott Hughes    sprintf((char *)(state->in), format, a1, a2, a3, a4, a5, a6, a7, a8,
432381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes            a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20);
433381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    for (len = 0; len < size; len++)
434381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        if (state->in[len] == 0) break;
435381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes#  else
43609eb358bbbb9aad3fe48dd3368c8a7a481cbda1cElliott Hughes    len = sprintf((char *)(state->in), format, a1, a2, a3, a4, a5, a6, a7, a8,
43709eb358bbbb9aad3fe48dd3368c8a7a481cbda1cElliott Hughes                  a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20);
438381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes#  endif
439381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes#else
440381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes#  ifdef HAS_snprintf_void
44109eb358bbbb9aad3fe48dd3368c8a7a481cbda1cElliott Hughes    snprintf((char *)(state->in), size, format, a1, a2, a3, a4, a5, a6, a7, a8,
442381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes             a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20);
44309eb358bbbb9aad3fe48dd3368c8a7a481cbda1cElliott Hughes    len = strlen((char *)(state->in));
444381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes#  else
44509eb358bbbb9aad3fe48dd3368c8a7a481cbda1cElliott Hughes    len = snprintf((char *)(state->in), size, format, a1, a2, a3, a4, a5, a6,
44609eb358bbbb9aad3fe48dd3368c8a7a481cbda1cElliott Hughes                   a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18,
44709eb358bbbb9aad3fe48dd3368c8a7a481cbda1cElliott Hughes                   a19, a20);
448381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes#  endif
449381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes#endif
450381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
451381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    /* check that printf() results fit in buffer */
452381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    if (len <= 0 || len >= (int)size || state->in[size - 1] != 0)
453381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        return 0;
454381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
455381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    /* update buffer and position, defer compression until needed */
456381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    strm->avail_in = (unsigned)len;
457381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    strm->next_in = state->in;
458ee9e11d0d4e3361533860bf04896abb86a291bfbElliott Hughes    state->x.pos += len;
459381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    return len;
460381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes}
461381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
462381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes#endif
463381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
464381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes/* -- see zlib.h -- */
465381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughesint ZEXPORT gzflush(file, flush)
466381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    gzFile file;
467381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    int flush;
468381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes{
469381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    gz_statep state;
470381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
471381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    /* get internal structure */
472381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    if (file == NULL)
473381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        return -1;
474381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    state = (gz_statep)file;
475381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
476381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    /* check that we're writing and that there's no error */
477381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    if (state->mode != GZ_WRITE || state->err != Z_OK)
478381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        return Z_STREAM_ERROR;
479381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
480381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    /* check flush parameter */
481381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    if (flush < 0 || flush > Z_FINISH)
482381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        return Z_STREAM_ERROR;
483381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
484381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    /* check for seek request */
485381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    if (state->seek) {
486381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        state->seek = 0;
487381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        if (gz_zero(state, state->skip) == -1)
488381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes            return -1;
489381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    }
490381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
491381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    /* compress remaining data with requested flush */
492381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    gz_comp(state, flush);
493381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    return state->err;
494381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes}
495381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
496381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes/* -- see zlib.h -- */
497381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughesint ZEXPORT gzsetparams(file, level, strategy)
498381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    gzFile file;
499381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    int level;
500381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    int strategy;
501381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes{
502381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    gz_statep state;
503381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    z_streamp strm;
504381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
505381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    /* get internal structure */
506381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    if (file == NULL)
507381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        return Z_STREAM_ERROR;
508381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    state = (gz_statep)file;
509381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    strm = &(state->strm);
510381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
511381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    /* check that we're writing and that there's no error */
512381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    if (state->mode != GZ_WRITE || state->err != Z_OK)
513381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        return Z_STREAM_ERROR;
514381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
515381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    /* if no change is requested, then do nothing */
516381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    if (level == state->level && strategy == state->strategy)
517381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        return Z_OK;
518381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
519381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    /* check for seek request */
520381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    if (state->seek) {
521381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        state->seek = 0;
522381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        if (gz_zero(state, state->skip) == -1)
523381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes            return -1;
524381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    }
525381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
526381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    /* change compression parameters for subsequent input */
527381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    if (state->size) {
528381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        /* flush previous input with previous parameters before changing */
529381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        if (strm->avail_in && gz_comp(state, Z_PARTIAL_FLUSH) == -1)
530381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes            return state->err;
531381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        deflateParams(strm, level, strategy);
532381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    }
533381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    state->level = level;
534381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    state->strategy = strategy;
535381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    return Z_OK;
536381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes}
537381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
538381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes/* -- see zlib.h -- */
539381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughesint ZEXPORT gzclose_w(file)
540381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    gzFile file;
541381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes{
542ee9e11d0d4e3361533860bf04896abb86a291bfbElliott Hughes    int ret = Z_OK;
543381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    gz_statep state;
544381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
545381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    /* get internal structure */
546381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    if (file == NULL)
547381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        return Z_STREAM_ERROR;
548381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    state = (gz_statep)file;
549381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
550381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    /* check that we're writing */
551381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    if (state->mode != GZ_WRITE)
552381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        return Z_STREAM_ERROR;
553381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
554381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    /* check for seek request */
555381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    if (state->seek) {
556381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        state->seek = 0;
557ee9e11d0d4e3361533860bf04896abb86a291bfbElliott Hughes        if (gz_zero(state, state->skip) == -1)
558ee9e11d0d4e3361533860bf04896abb86a291bfbElliott Hughes            ret = state->err;
559381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    }
560381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
561381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    /* flush, free memory, and close file */
56204351a92ecc8429c999acbfc5dfe5aa8bee1d19dElliott Hughes    if (gz_comp(state, Z_FINISH) == -1)
56304351a92ecc8429c999acbfc5dfe5aa8bee1d19dElliott Hughes        ret = state->err;
56409eb358bbbb9aad3fe48dd3368c8a7a481cbda1cElliott Hughes    if (state->size) {
56509eb358bbbb9aad3fe48dd3368c8a7a481cbda1cElliott Hughes        if (!state->direct) {
56609eb358bbbb9aad3fe48dd3368c8a7a481cbda1cElliott Hughes            (void)deflateEnd(&(state->strm));
56709eb358bbbb9aad3fe48dd3368c8a7a481cbda1cElliott Hughes            free(state->out);
56809eb358bbbb9aad3fe48dd3368c8a7a481cbda1cElliott Hughes        }
56909eb358bbbb9aad3fe48dd3368c8a7a481cbda1cElliott Hughes        free(state->in);
570ee9e11d0d4e3361533860bf04896abb86a291bfbElliott Hughes    }
571381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    gz_error(state, Z_OK, NULL);
572381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    free(state->path);
573ee9e11d0d4e3361533860bf04896abb86a291bfbElliott Hughes    if (close(state->fd) == -1)
574ee9e11d0d4e3361533860bf04896abb86a291bfbElliott Hughes        ret = Z_ERRNO;
575381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    free(state);
576ee9e11d0d4e3361533860bf04896abb86a291bfbElliott Hughes    return ret;
577ee9e11d0d4e3361533860bf04896abb86a291bfbElliott Hughes}
578