gzwrite.c revision 381716e9396b55b1adb8235b020c37344f60ab07
1381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes/* gzwrite.c -- zlib functions for writing gzip files
2381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes * Copyright (C) 2004, 2005, 2010 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
21381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    /* allocate input and output buffers */
22381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    state->in = malloc(state->want);
23381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    state->out = malloc(state->want);
24381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    if (state->in == NULL || state->out == NULL) {
25381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        if (state->out != NULL)
26381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes            free(state->out);
27381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        if (state->in != NULL)
28381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes            free(state->in);
29381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        gz_error(state, Z_MEM_ERROR, "out of memory");
30381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        return -1;
31381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    }
32381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
33381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    /* allocate deflate memory, set up for gzip compression */
34381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    strm->zalloc = Z_NULL;
35381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    strm->zfree = Z_NULL;
36381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    strm->opaque = Z_NULL;
37381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    ret = deflateInit2(strm, state->level, Z_DEFLATED,
38381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes                       15 + 16, 8, state->strategy);
39381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    if (ret != Z_OK) {
40381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        free(state->in);
41381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        gz_error(state, Z_MEM_ERROR, "out of memory");
42381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        return -1;
43381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    }
44381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
45381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    /* mark state as initialized */
46381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    state->size = state->want;
47381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
48381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    /* initialize write buffer */
49381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    strm->avail_out = state->size;
50381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    strm->next_out = state->out;
51381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    state->next = strm->next_out;
52381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    return 0;
53381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes}
54381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
55381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes/* Compress whatever is at avail_in and next_in and write to the output file.
56381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes   Return -1 if there is an error writing to the output file, otherwise 0.
57381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes   flush is assumed to be a valid deflate() flush value.  If flush is Z_FINISH,
58381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes   then the deflate() state is reset to start a new gzip stream. */
59381716e9396b55b1adb8235b020c37344f60ab07Elliott Hugheslocal int gz_comp(state, flush)
60381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    gz_statep state;
61381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    int flush;
62381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes{
63381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    int ret, got;
64381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    unsigned have;
65381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    z_streamp strm = &(state->strm);
66381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
67381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    /* allocate memory if this is the first time through */
68381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    if (state->size == 0 && gz_init(state) == -1)
69381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        return -1;
70381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
71381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    /* run deflate() on provided input until it produces no more output */
72381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    ret = Z_OK;
73381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    do {
74381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        /* write out current buffer contents if full, or if flushing, but if
75381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes           doing Z_FINISH then don't write until we get to Z_STREAM_END */
76381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        if (strm->avail_out == 0 || (flush != Z_NO_FLUSH &&
77381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes            (flush != Z_FINISH || ret == Z_STREAM_END))) {
78381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes            have = (unsigned)(strm->next_out - state->next);
79381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes            if (have && ((got = write(state->fd, state->next, have)) < 0 ||
80381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes                         (unsigned)got != have)) {
81381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes                gz_error(state, Z_ERRNO, zstrerror());
82381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes                return -1;
83381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes            }
84381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes            if (strm->avail_out == 0) {
85381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes                strm->avail_out = state->size;
86381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes                strm->next_out = state->out;
87381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes            }
88381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes            state->next = strm->next_out;
89381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        }
90381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
91381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        /* compress */
92381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        have = strm->avail_out;
93381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        ret = deflate(strm, flush);
94381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        if (ret == Z_STREAM_ERROR) {
95381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes            gz_error(state, Z_STREAM_ERROR,
96381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes                      "internal error: deflate stream corrupt");
97381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes            return -1;
98381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        }
99381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        have -= strm->avail_out;
100381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    } while (have);
101381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
102381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    /* if that completed a deflate stream, allow another to start */
103381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    if (flush == Z_FINISH)
104381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        deflateReset(strm);
105381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
106381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    /* all done, no errors */
107381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    return 0;
108381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes}
109381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
110381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes/* Compress len zeros to output.  Return -1 on error, 0 on success. */
111381716e9396b55b1adb8235b020c37344f60ab07Elliott Hugheslocal int gz_zero(state, len)
112381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    gz_statep state;
113381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    z_off64_t len;
114381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes{
115381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    int first;
116381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    unsigned n;
117381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    z_streamp strm = &(state->strm);
118381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
119381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    /* consume whatever's left in the input buffer */
120381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1)
121381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        return -1;
122381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
123381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    /* compress len zeros (len guaranteed > 0) */
124381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    first = 1;
125381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    while (len) {
126381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        n = GT_OFF(state->size) || (z_off64_t)state->size > len ?
127381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes            (unsigned)len : state->size;
128381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        if (first) {
129381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes            memset(state->in, 0, n);
130381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes            first = 0;
131381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        }
132381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        strm->avail_in = n;
133381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        strm->next_in = state->in;
134381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        state->pos += n;
135381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        if (gz_comp(state, Z_NO_FLUSH) == -1)
136381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes            return -1;
137381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        len -= n;
138381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    }
139381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    return 0;
140381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes}
141381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
142381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes/* -- see zlib.h -- */
143381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughesint ZEXPORT gzwrite(file, buf, len)
144381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    gzFile file;
145381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    voidpc buf;
146381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    unsigned len;
147381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes{
148381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    unsigned put = len;
149381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    unsigned n;
150381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    gz_statep state;
151381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    z_streamp strm;
152381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
153381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    /* get internal structure */
154381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    if (file == NULL)
155381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        return 0;
156381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    state = (gz_statep)file;
157381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    strm = &(state->strm);
158381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
159381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    /* check that we're writing and that there's no error */
160381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    if (state->mode != GZ_WRITE || state->err != Z_OK)
161381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        return 0;
162381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
163381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    /* since an int is returned, make sure len fits in one, otherwise return
164381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes       with an error (this avoids the flaw in the interface) */
165381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    if ((int)len < 0) {
166381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        gz_error(state, Z_BUF_ERROR, "requested length does not fit in int");
167381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        return 0;
168381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    }
169381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
170381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    /* if len is zero, avoid unnecessary operations */
171381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    if (len == 0)
172381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        return 0;
173381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
174381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    /* allocate memory if this is the first time through */
175381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    if (state->size == 0 && gz_init(state) == -1)
176381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        return 0;
177381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
178381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    /* check for seek request */
179381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    if (state->seek) {
180381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        state->seek = 0;
181381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        if (gz_zero(state, state->skip) == -1)
182381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes            return 0;
183381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    }
184381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
185381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    /* for small len, copy to input buffer, otherwise compress directly */
186381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    if (len < state->size) {
187381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        /* copy to input buffer, compress when full */
188381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        do {
189381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes            if (strm->avail_in == 0)
190381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes                strm->next_in = state->in;
191381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes            n = state->size - strm->avail_in;
192381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes            if (n > len)
193381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes                n = len;
194381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes            memcpy(strm->next_in + strm->avail_in, buf, n);
195381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes            strm->avail_in += n;
196381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes            state->pos += n;
197381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes            buf = (char *)buf + n;
198381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes            len -= n;
199381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes            if (len && gz_comp(state, Z_NO_FLUSH) == -1)
200381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes                return 0;
201381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        } while (len);
202381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    }
203381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    else {
204381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        /* consume whatever's left in the input buffer */
205381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1)
206381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes            return 0;
207381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
208381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        /* directly compress user buffer to file */
209381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        strm->avail_in = len;
210381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        strm->next_in = (voidp)buf;
211381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        state->pos += len;
212381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        if (gz_comp(state, Z_NO_FLUSH) == -1)
213381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes            return 0;
214381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    }
215381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
216381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    /* input was all buffered or compressed (put will fit in int) */
217381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    return (int)put;
218381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes}
219381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
220381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes/* -- see zlib.h -- */
221381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughesint ZEXPORT gzputc(file, c)
222381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    gzFile file;
223381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    int c;
224381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes{
225381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    unsigned char buf[1];
226381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    gz_statep state;
227381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    z_streamp strm;
228381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
229381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    /* get internal structure */
230381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    if (file == NULL)
231381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        return -1;
232381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    state = (gz_statep)file;
233381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    strm = &(state->strm);
234381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
235381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    /* check that we're writing and that there's no error */
236381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    if (state->mode != GZ_WRITE || state->err != Z_OK)
237381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        return -1;
238381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
239381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    /* check for seek request */
240381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    if (state->seek) {
241381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        state->seek = 0;
242381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        if (gz_zero(state, state->skip) == -1)
243381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes            return -1;
244381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    }
245381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
246381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    /* try writing to input buffer for speed (state->size == 0 if buffer not
247381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes       initialized) */
248381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    if (strm->avail_in < state->size) {
249381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        if (strm->avail_in == 0)
250381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes            strm->next_in = state->in;
251381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        strm->next_in[strm->avail_in++] = c;
252381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        state->pos++;
253381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        return c;
254381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    }
255381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
256381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    /* no room in buffer or not initialized, use gz_write() */
257381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    buf[0] = c;
258381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    if (gzwrite(file, buf, 1) != 1)
259381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        return -1;
260381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    return c;
261381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes}
262381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
263381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes/* -- see zlib.h -- */
264381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughesint ZEXPORT gzputs(file, str)
265381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    gzFile file;
266381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    const char *str;
267381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes{
268381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    int ret;
269381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    unsigned len;
270381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
271381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    /* write string */
272381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    len = (unsigned)strlen(str);
273381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    ret = gzwrite(file, str, len);
274381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    return ret == 0 && len != 0 ? -1 : ret;
275381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes}
276381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
277381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes#ifdef STDC
278381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes#include <stdarg.h>
279381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
280381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes/* -- see zlib.h -- */
281381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughesint ZEXPORTVA gzprintf (gzFile file, const char *format, ...)
282381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes{
283381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    int size, len;
284381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    gz_statep state;
285381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    z_streamp strm;
286381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    va_list va;
287381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
288381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    /* get internal structure */
289381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    if (file == NULL)
290381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        return -1;
291381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    state = (gz_statep)file;
292381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    strm = &(state->strm);
293381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
294381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    /* check that we're writing and that there's no error */
295381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    if (state->mode != GZ_WRITE || state->err != Z_OK)
296381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        return 0;
297381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
298381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    /* make sure we have some buffer space */
299381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    if (state->size == 0 && gz_init(state) == -1)
300381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        return 0;
301381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
302381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    /* check for seek request */
303381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    if (state->seek) {
304381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        state->seek = 0;
305381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        if (gz_zero(state, state->skip) == -1)
306381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes            return 0;
307381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    }
308381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
309381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    /* consume whatever's left in the input buffer */
310381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1)
311381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        return 0;
312381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
313381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    /* do the printf() into the input buffer, put length in len */
314381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    size = (int)(state->size);
315381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    state->in[size - 1] = 0;
316381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    va_start(va, format);
317381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes#ifdef NO_vsnprintf
318381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes#  ifdef HAS_vsprintf_void
319381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    (void)vsprintf(state->in, format, va);
320381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    va_end(va);
321381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    for (len = 0; len < size; len++)
322381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        if (state->in[len] == 0) break;
323381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes#  else
324381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    len = vsprintf(state->in, format, va);
325381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    va_end(va);
326381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes#  endif
327381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes#else
328381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes#  ifdef HAS_vsnprintf_void
329381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    (void)vsnprintf(state->in, size, format, va);
330381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    va_end(va);
331381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    len = strlen(state->in);
332381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes#  else
333381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    len = vsnprintf((char *)(state->in), size, format, va);
334381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    va_end(va);
335381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes#  endif
336381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes#endif
337381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
338381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    /* check that printf() results fit in buffer */
339381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    if (len <= 0 || len >= (int)size || state->in[size - 1] != 0)
340381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        return 0;
341381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
342381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    /* update buffer and position, defer compression until needed */
343381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    strm->avail_in = (unsigned)len;
344381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    strm->next_in = state->in;
345381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    state->pos += len;
346381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    return len;
347381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes}
348381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
349381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes#else /* !STDC */
350381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
351381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes/* -- see zlib.h -- */
352381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughesint ZEXPORTVA gzprintf (file, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10,
353381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes                       a11, a12, a13, a14, a15, a16, a17, a18, a19, a20)
354381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    gzFile file;
355381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    const char *format;
356381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    int a1, a2, a3, a4, a5, a6, a7, a8, a9, a10,
357381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        a11, a12, a13, a14, a15, a16, a17, a18, a19, a20;
358381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes{
359381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    int size, len;
360381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    gz_statep state;
361381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    z_streamp strm;
362381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
363381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    /* get internal structure */
364381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    if (file == NULL)
365381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        return -1;
366381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    state = (gz_statep)file;
367381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    strm = &(state->strm);
368381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
369381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    /* check that we're writing and that there's no error */
370381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    if (state->mode != GZ_WRITE || state->err != Z_OK)
371381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        return 0;
372381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
373381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    /* make sure we have some buffer space */
374381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    if (state->size == 0 && gz_init(state) == -1)
375381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        return 0;
376381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
377381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    /* check for seek request */
378381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    if (state->seek) {
379381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        state->seek = 0;
380381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        if (gz_zero(state, state->skip) == -1)
381381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes            return 0;
382381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    }
383381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
384381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    /* consume whatever's left in the input buffer */
385381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1)
386381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        return 0;
387381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
388381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    /* do the printf() into the input buffer, put length in len */
389381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    size = (int)(state->size);
390381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    state->in[size - 1] = 0;
391381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes#ifdef NO_snprintf
392381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes#  ifdef HAS_sprintf_void
393381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    sprintf(state->in, format, a1, a2, a3, a4, a5, a6, a7, a8,
394381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes            a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20);
395381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    for (len = 0; len < size; len++)
396381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        if (state->in[len] == 0) break;
397381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes#  else
398381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    len = sprintf(state->in, format, a1, a2, a3, a4, a5, a6, a7, a8,
399381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes                a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20);
400381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes#  endif
401381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes#else
402381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes#  ifdef HAS_snprintf_void
403381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    snprintf(state->in, size, format, a1, a2, a3, a4, a5, a6, a7, a8,
404381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes             a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20);
405381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    len = strlen(state->in);
406381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes#  else
407381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    len = snprintf(state->in, size, format, a1, a2, a3, a4, a5, a6, a7, a8,
408381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes                 a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20);
409381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes#  endif
410381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes#endif
411381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
412381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    /* check that printf() results fit in buffer */
413381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    if (len <= 0 || len >= (int)size || state->in[size - 1] != 0)
414381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        return 0;
415381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
416381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    /* update buffer and position, defer compression until needed */
417381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    strm->avail_in = (unsigned)len;
418381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    strm->next_in = state->in;
419381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    state->pos += len;
420381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    return len;
421381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes}
422381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
423381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes#endif
424381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
425381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes/* -- see zlib.h -- */
426381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughesint ZEXPORT gzflush(file, flush)
427381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    gzFile file;
428381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    int flush;
429381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes{
430381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    gz_statep state;
431381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
432381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    /* get internal structure */
433381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    if (file == NULL)
434381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        return -1;
435381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    state = (gz_statep)file;
436381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
437381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    /* check that we're writing and that there's no error */
438381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    if (state->mode != GZ_WRITE || state->err != Z_OK)
439381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        return Z_STREAM_ERROR;
440381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
441381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    /* check flush parameter */
442381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    if (flush < 0 || flush > Z_FINISH)
443381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        return Z_STREAM_ERROR;
444381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
445381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    /* check for seek request */
446381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    if (state->seek) {
447381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        state->seek = 0;
448381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        if (gz_zero(state, state->skip) == -1)
449381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes            return -1;
450381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    }
451381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
452381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    /* compress remaining data with requested flush */
453381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    gz_comp(state, flush);
454381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    return state->err;
455381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes}
456381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
457381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes/* -- see zlib.h -- */
458381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughesint ZEXPORT gzsetparams(file, level, strategy)
459381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    gzFile file;
460381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    int level;
461381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    int strategy;
462381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes{
463381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    gz_statep state;
464381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    z_streamp strm;
465381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
466381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    /* get internal structure */
467381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    if (file == NULL)
468381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        return Z_STREAM_ERROR;
469381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    state = (gz_statep)file;
470381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    strm = &(state->strm);
471381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
472381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    /* check that we're writing and that there's no error */
473381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    if (state->mode != GZ_WRITE || state->err != Z_OK)
474381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        return Z_STREAM_ERROR;
475381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
476381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    /* if no change is requested, then do nothing */
477381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    if (level == state->level && strategy == state->strategy)
478381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        return Z_OK;
479381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
480381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    /* check for seek request */
481381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    if (state->seek) {
482381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        state->seek = 0;
483381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        if (gz_zero(state, state->skip) == -1)
484381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes            return -1;
485381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    }
486381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
487381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    /* change compression parameters for subsequent input */
488381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    if (state->size) {
489381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        /* flush previous input with previous parameters before changing */
490381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        if (strm->avail_in && gz_comp(state, Z_PARTIAL_FLUSH) == -1)
491381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes            return state->err;
492381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        deflateParams(strm, level, strategy);
493381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    }
494381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    state->level = level;
495381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    state->strategy = strategy;
496381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    return Z_OK;
497381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes}
498381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
499381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes/* -- see zlib.h -- */
500381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughesint ZEXPORT gzclose_w(file)
501381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    gzFile file;
502381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes{
503381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    int ret = 0;
504381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    gz_statep state;
505381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
506381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    /* get internal structure */
507381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    if (file == NULL)
508381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        return Z_STREAM_ERROR;
509381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    state = (gz_statep)file;
510381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
511381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    /* check that we're writing */
512381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    if (state->mode != GZ_WRITE)
513381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        return Z_STREAM_ERROR;
514381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
515381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    /* check for seek request */
516381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    if (state->seek) {
517381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        state->seek = 0;
518381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes        ret += gz_zero(state, state->skip);
519381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    }
520381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes
521381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    /* flush, free memory, and close file */
522381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    ret += gz_comp(state, Z_FINISH);
523381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    (void)deflateEnd(&(state->strm));
524381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    free(state->out);
525381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    free(state->in);
526381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    gz_error(state, Z_OK, NULL);
527381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    free(state->path);
528381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    ret += close(state->fd);
529381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    free(state);
530381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes    return ret ? Z_ERRNO : Z_OK;
531381716e9396b55b1adb8235b020c37344f60ab07Elliott Hughes}
532