gzwrite.c revision 205305
1205194Sdelphij/* gzwrite.c -- zlib functions for writing gzip files
2205194Sdelphij * Copyright (C) 2004, 2005, 2010 Mark Adler
3205194Sdelphij * For conditions of distribution and use, see copyright notice in zlib.h
4205194Sdelphij */
5205194Sdelphij
6205194Sdelphij#include "gzguts.h"
7205305Sdelphij#include <unistd.h>
8205194Sdelphij
9205194Sdelphij/* Local functions */
10205194Sdelphijlocal int gz_init OF((gz_statep));
11205194Sdelphijlocal int gz_comp OF((gz_statep, int));
12205194Sdelphijlocal int gz_zero OF((gz_statep, z_off64_t));
13205194Sdelphij
14205194Sdelphij/* Initialize state for writing a gzip file.  Mark initialization by setting
15205194Sdelphij   state->size to non-zero.  Return -1 on failure or 0 on success. */
16205194Sdelphijlocal int gz_init(state)
17205194Sdelphij    gz_statep state;
18205194Sdelphij{
19205194Sdelphij    int ret;
20205194Sdelphij    z_streamp strm = &(state->strm);
21205194Sdelphij
22205194Sdelphij    /* allocate input and output buffers */
23205194Sdelphij    state->in = malloc(state->want);
24205194Sdelphij    state->out = malloc(state->want);
25205194Sdelphij    if (state->in == NULL || state->out == NULL) {
26205194Sdelphij        if (state->out != NULL)
27205194Sdelphij            free(state->out);
28205194Sdelphij        if (state->in != NULL)
29205194Sdelphij            free(state->in);
30205194Sdelphij        gz_error(state, Z_MEM_ERROR, "out of memory");
31205194Sdelphij        return -1;
32205194Sdelphij    }
33205194Sdelphij
34205194Sdelphij    /* allocate deflate memory, set up for gzip compression */
35205194Sdelphij    strm->zalloc = Z_NULL;
36205194Sdelphij    strm->zfree = Z_NULL;
37205194Sdelphij    strm->opaque = Z_NULL;
38205194Sdelphij    ret = deflateInit2(strm, state->level, Z_DEFLATED,
39205194Sdelphij                       15 + 16, 8, state->strategy);
40205194Sdelphij    if (ret != Z_OK) {
41205194Sdelphij        free(state->in);
42205194Sdelphij        gz_error(state, Z_MEM_ERROR, "out of memory");
43205194Sdelphij        return -1;
44205194Sdelphij    }
45205194Sdelphij
46205194Sdelphij    /* mark state as initialized */
47205194Sdelphij    state->size = state->want;
48205194Sdelphij
49205194Sdelphij    /* initialize write buffer */
50205194Sdelphij    strm->avail_out = state->size;
51205194Sdelphij    strm->next_out = state->out;
52205194Sdelphij    state->next = strm->next_out;
53205194Sdelphij    return 0;
54205194Sdelphij}
55205194Sdelphij
56205194Sdelphij/* Compress whatever is at avail_in and next_in and write to the output file.
57205194Sdelphij   Return -1 if there is an error writing to the output file, otherwise 0.
58205194Sdelphij   flush is assumed to be a valid deflate() flush value.  If flush is Z_FINISH,
59205194Sdelphij   then the deflate() state is reset to start a new gzip stream. */
60205194Sdelphijlocal int gz_comp(state, flush)
61205194Sdelphij    gz_statep state;
62205194Sdelphij    int flush;
63205194Sdelphij{
64205194Sdelphij    int ret, got;
65205194Sdelphij    unsigned have;
66205194Sdelphij    z_streamp strm = &(state->strm);
67205194Sdelphij
68205194Sdelphij    /* allocate memory if this is the first time through */
69205194Sdelphij    if (state->size == 0 && gz_init(state) == -1)
70205194Sdelphij        return -1;
71205194Sdelphij
72205194Sdelphij    /* run deflate() on provided input until it produces no more output */
73205194Sdelphij    ret = Z_OK;
74205194Sdelphij    do {
75205194Sdelphij        /* write out current buffer contents if full, or if flushing, but if
76205194Sdelphij           doing Z_FINISH then don't write until we get to Z_STREAM_END */
77205194Sdelphij        if (strm->avail_out == 0 || (flush != Z_NO_FLUSH &&
78205194Sdelphij            (flush != Z_FINISH || ret == Z_STREAM_END))) {
79205194Sdelphij            have = (unsigned)(strm->next_out - state->next);
80205194Sdelphij            if (have && ((got = write(state->fd, state->next, have)) < 0 ||
81205194Sdelphij                         (unsigned)got != have)) {
82205194Sdelphij                gz_error(state, Z_ERRNO, zstrerror());
83205194Sdelphij                return -1;
84205194Sdelphij            }
85205194Sdelphij            if (strm->avail_out == 0) {
86205194Sdelphij                strm->avail_out = state->size;
87205194Sdelphij                strm->next_out = state->out;
88205194Sdelphij            }
89205194Sdelphij            state->next = strm->next_out;
90205194Sdelphij        }
91205194Sdelphij
92205194Sdelphij        /* compress */
93205194Sdelphij        have = strm->avail_out;
94205194Sdelphij        ret = deflate(strm, flush);
95205194Sdelphij        if (ret == Z_STREAM_ERROR) {
96205194Sdelphij            gz_error(state, Z_STREAM_ERROR,
97205194Sdelphij                      "internal error: deflate stream corrupt");
98205194Sdelphij            return -1;
99205194Sdelphij        }
100205194Sdelphij        have -= strm->avail_out;
101205194Sdelphij    } while (have);
102205194Sdelphij
103205194Sdelphij    /* if that completed a deflate stream, allow another to start */
104205194Sdelphij    if (flush == Z_FINISH)
105205194Sdelphij        deflateReset(strm);
106205194Sdelphij
107205194Sdelphij    /* all done, no errors */
108205194Sdelphij    return 0;
109205194Sdelphij}
110205194Sdelphij
111205194Sdelphij/* Compress len zeros to output.  Return -1 on error, 0 on success. */
112205194Sdelphijlocal int gz_zero(state, len)
113205194Sdelphij    gz_statep state;
114205194Sdelphij    z_off64_t len;
115205194Sdelphij{
116205194Sdelphij    int first;
117205194Sdelphij    unsigned n;
118205194Sdelphij    z_streamp strm = &(state->strm);
119205194Sdelphij
120205194Sdelphij    /* consume whatever's left in the input buffer */
121205194Sdelphij    if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1)
122205194Sdelphij        return -1;
123205194Sdelphij
124205194Sdelphij    /* compress len zeros (len guaranteed > 0) */
125205194Sdelphij    first = 1;
126205194Sdelphij    while (len) {
127205194Sdelphij        n = GT_OFF(state->size) || (z_off64_t)state->size > len ?
128205194Sdelphij            (unsigned)len : state->size;
129205194Sdelphij        if (first) {
130205194Sdelphij            memset(state->in, 0, n);
131205194Sdelphij            first = 0;
132205194Sdelphij        }
133205194Sdelphij        strm->avail_in = n;
134205194Sdelphij        strm->next_in = state->in;
135205194Sdelphij        state->pos += n;
136205194Sdelphij        if (gz_comp(state, Z_NO_FLUSH) == -1)
137205194Sdelphij            return -1;
138205194Sdelphij        len -= n;
139205194Sdelphij    }
140205194Sdelphij    return 0;
141205194Sdelphij}
142205194Sdelphij
143205194Sdelphij/* -- see zlib.h -- */
144205194Sdelphijint ZEXPORT gzwrite(file, buf, len)
145205194Sdelphij    gzFile file;
146205194Sdelphij    voidpc buf;
147205194Sdelphij    unsigned len;
148205194Sdelphij{
149205194Sdelphij    unsigned put = len;
150205194Sdelphij    unsigned n;
151205194Sdelphij    gz_statep state;
152205194Sdelphij    z_streamp strm;
153205194Sdelphij
154205194Sdelphij    /* get internal structure */
155205194Sdelphij    if (file == NULL)
156205194Sdelphij        return 0;
157205194Sdelphij    state = (gz_statep)file;
158205194Sdelphij    strm = &(state->strm);
159205194Sdelphij
160205194Sdelphij    /* check that we're writing and that there's no error */
161205194Sdelphij    if (state->mode != GZ_WRITE || state->err != Z_OK)
162205194Sdelphij        return 0;
163205194Sdelphij
164205194Sdelphij    /* since an int is returned, make sure len fits in one, otherwise return
165205194Sdelphij       with an error (this avoids the flaw in the interface) */
166205194Sdelphij    if ((int)len < 0) {
167205194Sdelphij        gz_error(state, Z_BUF_ERROR, "requested length does not fit in int");
168205194Sdelphij        return 0;
169205194Sdelphij    }
170205194Sdelphij
171205194Sdelphij    /* if len is zero, avoid unnecessary operations */
172205194Sdelphij    if (len == 0)
173205194Sdelphij        return 0;
174205194Sdelphij
175205194Sdelphij    /* allocate memory if this is the first time through */
176205194Sdelphij    if (state->size == 0 && gz_init(state) == -1)
177205194Sdelphij        return 0;
178205194Sdelphij
179205194Sdelphij    /* check for seek request */
180205194Sdelphij    if (state->seek) {
181205194Sdelphij        state->seek = 0;
182205194Sdelphij        if (gz_zero(state, state->skip) == -1)
183205194Sdelphij            return 0;
184205194Sdelphij    }
185205194Sdelphij
186205194Sdelphij    /* for small len, copy to input buffer, otherwise compress directly */
187205194Sdelphij    if (len < state->size) {
188205194Sdelphij        /* copy to input buffer, compress when full */
189205194Sdelphij        do {
190205194Sdelphij            if (strm->avail_in == 0)
191205194Sdelphij                strm->next_in = state->in;
192205194Sdelphij            n = state->size - strm->avail_in;
193205194Sdelphij            if (n > len)
194205194Sdelphij                n = len;
195205194Sdelphij            memcpy(strm->next_in + strm->avail_in, buf, n);
196205194Sdelphij            strm->avail_in += n;
197205194Sdelphij            state->pos += n;
198205194Sdelphij            buf = (char *)buf + n;
199205194Sdelphij            len -= n;
200205194Sdelphij            if (len && gz_comp(state, Z_NO_FLUSH) == -1)
201205194Sdelphij                return 0;
202205194Sdelphij        } while (len);
203205194Sdelphij    }
204205194Sdelphij    else {
205205194Sdelphij        /* consume whatever's left in the input buffer */
206205194Sdelphij        if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1)
207205194Sdelphij            return 0;
208205194Sdelphij
209205194Sdelphij        /* directly compress user buffer to file */
210205194Sdelphij        strm->avail_in = len;
211205194Sdelphij        strm->next_in = (voidp)buf;
212205194Sdelphij        state->pos += len;
213205194Sdelphij        if (gz_comp(state, Z_NO_FLUSH) == -1)
214205194Sdelphij            return 0;
215205194Sdelphij    }
216205194Sdelphij
217205194Sdelphij    /* input was all buffered or compressed (put will fit in int) */
218205194Sdelphij    return (int)put;
219205194Sdelphij}
220205194Sdelphij
221205194Sdelphij/* -- see zlib.h -- */
222205194Sdelphijint ZEXPORT gzputc(file, c)
223205194Sdelphij    gzFile file;
224205194Sdelphij    int c;
225205194Sdelphij{
226205194Sdelphij    unsigned char buf[1];
227205194Sdelphij    gz_statep state;
228205194Sdelphij    z_streamp strm;
229205194Sdelphij
230205194Sdelphij    /* get internal structure */
231205194Sdelphij    if (file == NULL)
232205194Sdelphij        return -1;
233205194Sdelphij    state = (gz_statep)file;
234205194Sdelphij    strm = &(state->strm);
235205194Sdelphij
236205194Sdelphij    /* check that we're writing and that there's no error */
237205194Sdelphij    if (state->mode != GZ_WRITE || state->err != Z_OK)
238205194Sdelphij        return -1;
239205194Sdelphij
240205194Sdelphij    /* check for seek request */
241205194Sdelphij    if (state->seek) {
242205194Sdelphij        state->seek = 0;
243205194Sdelphij        if (gz_zero(state, state->skip) == -1)
244205194Sdelphij            return -1;
245205194Sdelphij    }
246205194Sdelphij
247205194Sdelphij    /* try writing to input buffer for speed (state->size == 0 if buffer not
248205194Sdelphij       initialized) */
249205194Sdelphij    if (strm->avail_in < state->size) {
250205194Sdelphij        if (strm->avail_in == 0)
251205194Sdelphij            strm->next_in = state->in;
252205194Sdelphij        strm->next_in[strm->avail_in++] = c;
253205194Sdelphij        state->pos++;
254205194Sdelphij        return c;
255205194Sdelphij    }
256205194Sdelphij
257205194Sdelphij    /* no room in buffer or not initialized, use gz_write() */
258205194Sdelphij    buf[0] = c;
259205194Sdelphij    if (gzwrite(file, buf, 1) != 1)
260205194Sdelphij        return -1;
261205194Sdelphij    return c;
262205194Sdelphij}
263205194Sdelphij
264205194Sdelphij/* -- see zlib.h -- */
265205194Sdelphijint ZEXPORT gzputs(file, str)
266205194Sdelphij    gzFile file;
267205194Sdelphij    const char *str;
268205194Sdelphij{
269205194Sdelphij    int ret;
270205194Sdelphij    unsigned len;
271205194Sdelphij
272205194Sdelphij    /* write string */
273205194Sdelphij    len = (unsigned)strlen(str);
274205194Sdelphij    ret = gzwrite(file, str, len);
275205194Sdelphij    return ret == 0 && len != 0 ? -1 : ret;
276205194Sdelphij}
277205194Sdelphij
278205194Sdelphij#ifdef STDC
279205194Sdelphij#include <stdarg.h>
280205194Sdelphij
281205194Sdelphij/* -- see zlib.h -- */
282205194Sdelphijint ZEXPORTVA gzprintf (gzFile file, const char *format, ...)
283205194Sdelphij{
284205194Sdelphij    int size, len;
285205194Sdelphij    gz_statep state;
286205194Sdelphij    z_streamp strm;
287205194Sdelphij    va_list va;
288205194Sdelphij
289205194Sdelphij    /* get internal structure */
290205194Sdelphij    if (file == NULL)
291205194Sdelphij        return -1;
292205194Sdelphij    state = (gz_statep)file;
293205194Sdelphij    strm = &(state->strm);
294205194Sdelphij
295205194Sdelphij    /* check that we're writing and that there's no error */
296205194Sdelphij    if (state->mode != GZ_WRITE || state->err != Z_OK)
297205194Sdelphij        return 0;
298205194Sdelphij
299205194Sdelphij    /* make sure we have some buffer space */
300205194Sdelphij    if (state->size == 0 && gz_init(state) == -1)
301205194Sdelphij        return 0;
302205194Sdelphij
303205194Sdelphij    /* check for seek request */
304205194Sdelphij    if (state->seek) {
305205194Sdelphij        state->seek = 0;
306205194Sdelphij        if (gz_zero(state, state->skip) == -1)
307205194Sdelphij            return 0;
308205194Sdelphij    }
309205194Sdelphij
310205194Sdelphij    /* consume whatever's left in the input buffer */
311205194Sdelphij    if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1)
312205194Sdelphij        return 0;
313205194Sdelphij
314205194Sdelphij    /* do the printf() into the input buffer, put length in len */
315205194Sdelphij    size = (int)(state->size);
316205194Sdelphij    state->in[size - 1] = 0;
317205194Sdelphij    va_start(va, format);
318205194Sdelphij#ifdef NO_vsnprintf
319205194Sdelphij#  ifdef HAS_vsprintf_void
320205194Sdelphij    (void)vsprintf(state->in, format, va);
321205194Sdelphij    va_end(va);
322205194Sdelphij    for (len = 0; len < size; len++)
323205194Sdelphij        if (state->in[len] == 0) break;
324205194Sdelphij#  else
325205194Sdelphij    len = vsprintf(state->in, format, va);
326205194Sdelphij    va_end(va);
327205194Sdelphij#  endif
328205194Sdelphij#else
329205194Sdelphij#  ifdef HAS_vsnprintf_void
330205194Sdelphij    (void)vsnprintf(state->in, size, format, va);
331205194Sdelphij    va_end(va);
332205194Sdelphij    len = strlen(state->in);
333205194Sdelphij#  else
334205194Sdelphij    len = vsnprintf((char *)(state->in), size, format, va);
335205194Sdelphij    va_end(va);
336205194Sdelphij#  endif
337205194Sdelphij#endif
338205194Sdelphij
339205194Sdelphij    /* check that printf() results fit in buffer */
340205194Sdelphij    if (len <= 0 || len >= (int)size || state->in[size - 1] != 0)
341205194Sdelphij        return 0;
342205194Sdelphij
343205194Sdelphij    /* update buffer and position, defer compression until needed */
344205194Sdelphij    strm->avail_in = (unsigned)len;
345205194Sdelphij    strm->next_in = state->in;
346205194Sdelphij    state->pos += len;
347205194Sdelphij    return len;
348205194Sdelphij}
349205194Sdelphij
350205194Sdelphij#else /* !STDC */
351205194Sdelphij
352205194Sdelphij/* -- see zlib.h -- */
353205194Sdelphijint ZEXPORTVA gzprintf (file, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10,
354205194Sdelphij                       a11, a12, a13, a14, a15, a16, a17, a18, a19, a20)
355205194Sdelphij    gzFile file;
356205194Sdelphij    const char *format;
357205194Sdelphij    int a1, a2, a3, a4, a5, a6, a7, a8, a9, a10,
358205194Sdelphij        a11, a12, a13, a14, a15, a16, a17, a18, a19, a20;
359205194Sdelphij{
360205194Sdelphij    int size, len;
361205194Sdelphij    gz_statep state;
362205194Sdelphij    z_streamp strm;
363205194Sdelphij
364205194Sdelphij    /* get internal structure */
365205194Sdelphij    if (file == NULL)
366205194Sdelphij        return -1;
367205194Sdelphij    state = (gz_statep)file;
368205194Sdelphij    strm = &(state->strm);
369205194Sdelphij
370205194Sdelphij    /* check that we're writing and that there's no error */
371205194Sdelphij    if (state->mode != GZ_WRITE || state->err != Z_OK)
372205194Sdelphij        return 0;
373205194Sdelphij
374205194Sdelphij    /* make sure we have some buffer space */
375205194Sdelphij    if (state->size == 0 && gz_init(state) == -1)
376205194Sdelphij        return 0;
377205194Sdelphij
378205194Sdelphij    /* check for seek request */
379205194Sdelphij    if (state->seek) {
380205194Sdelphij        state->seek = 0;
381205194Sdelphij        if (gz_zero(state, state->skip) == -1)
382205194Sdelphij            return 0;
383205194Sdelphij    }
384205194Sdelphij
385205194Sdelphij    /* consume whatever's left in the input buffer */
386205194Sdelphij    if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1)
387205194Sdelphij        return 0;
388205194Sdelphij
389205194Sdelphij    /* do the printf() into the input buffer, put length in len */
390205194Sdelphij    size = (int)(state->size);
391205194Sdelphij    state->in[size - 1] = 0;
392205194Sdelphij#ifdef NO_snprintf
393205194Sdelphij#  ifdef HAS_sprintf_void
394205194Sdelphij    sprintf(state->in, format, a1, a2, a3, a4, a5, a6, a7, a8,
395205194Sdelphij            a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20);
396205194Sdelphij    for (len = 0; len < size; len++)
397205194Sdelphij        if (state->in[len] == 0) break;
398205194Sdelphij#  else
399205194Sdelphij    len = sprintf(state->in, format, a1, a2, a3, a4, a5, a6, a7, a8,
400205194Sdelphij                a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20);
401205194Sdelphij#  endif
402205194Sdelphij#else
403205194Sdelphij#  ifdef HAS_snprintf_void
404205194Sdelphij    snprintf(state->in, size, format, a1, a2, a3, a4, a5, a6, a7, a8,
405205194Sdelphij             a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20);
406205194Sdelphij    len = strlen(state->in);
407205194Sdelphij#  else
408205194Sdelphij    len = snprintf(state->in, size, format, a1, a2, a3, a4, a5, a6, a7, a8,
409205194Sdelphij                 a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20);
410205194Sdelphij#  endif
411205194Sdelphij#endif
412205194Sdelphij
413205194Sdelphij    /* check that printf() results fit in buffer */
414205194Sdelphij    if (len <= 0 || len >= (int)size || state->in[size - 1] != 0)
415205194Sdelphij        return 0;
416205194Sdelphij
417205194Sdelphij    /* update buffer and position, defer compression until needed */
418205194Sdelphij    strm->avail_in = (unsigned)len;
419205194Sdelphij    strm->next_in = state->in;
420205194Sdelphij    state->pos += len;
421205194Sdelphij    return len;
422205194Sdelphij}
423205194Sdelphij
424205194Sdelphij#endif
425205194Sdelphij
426205194Sdelphij/* -- see zlib.h -- */
427205194Sdelphijint ZEXPORT gzflush(file, flush)
428205194Sdelphij    gzFile file;
429205194Sdelphij    int flush;
430205194Sdelphij{
431205194Sdelphij    gz_statep state;
432205194Sdelphij
433205194Sdelphij    /* get internal structure */
434205194Sdelphij    if (file == NULL)
435205194Sdelphij        return -1;
436205194Sdelphij    state = (gz_statep)file;
437205194Sdelphij
438205194Sdelphij    /* check that we're writing and that there's no error */
439205194Sdelphij    if (state->mode != GZ_WRITE || state->err != Z_OK)
440205194Sdelphij        return Z_STREAM_ERROR;
441205194Sdelphij
442205194Sdelphij    /* check flush parameter */
443205194Sdelphij    if (flush < 0 || flush > Z_FINISH)
444205194Sdelphij        return Z_STREAM_ERROR;
445205194Sdelphij
446205194Sdelphij    /* check for seek request */
447205194Sdelphij    if (state->seek) {
448205194Sdelphij        state->seek = 0;
449205194Sdelphij        if (gz_zero(state, state->skip) == -1)
450205194Sdelphij            return -1;
451205194Sdelphij    }
452205194Sdelphij
453205194Sdelphij    /* compress remaining data with requested flush */
454205194Sdelphij    gz_comp(state, flush);
455205194Sdelphij    return state->err;
456205194Sdelphij}
457205194Sdelphij
458205194Sdelphij/* -- see zlib.h -- */
459205194Sdelphijint ZEXPORT gzsetparams(file, level, strategy)
460205194Sdelphij    gzFile file;
461205194Sdelphij    int level;
462205194Sdelphij    int strategy;
463205194Sdelphij{
464205194Sdelphij    gz_statep state;
465205194Sdelphij    z_streamp strm;
466205194Sdelphij
467205194Sdelphij    /* get internal structure */
468205194Sdelphij    if (file == NULL)
469205194Sdelphij        return Z_STREAM_ERROR;
470205194Sdelphij    state = (gz_statep)file;
471205194Sdelphij    strm = &(state->strm);
472205194Sdelphij
473205194Sdelphij    /* check that we're writing and that there's no error */
474205194Sdelphij    if (state->mode != GZ_WRITE || state->err != Z_OK)
475205194Sdelphij        return Z_STREAM_ERROR;
476205194Sdelphij
477205194Sdelphij    /* if no change is requested, then do nothing */
478205194Sdelphij    if (level == state->level && strategy == state->strategy)
479205194Sdelphij        return Z_OK;
480205194Sdelphij
481205194Sdelphij    /* check for seek request */
482205194Sdelphij    if (state->seek) {
483205194Sdelphij        state->seek = 0;
484205194Sdelphij        if (gz_zero(state, state->skip) == -1)
485205194Sdelphij            return -1;
486205194Sdelphij    }
487205194Sdelphij
488205194Sdelphij    /* change compression parameters for subsequent input */
489205194Sdelphij    if (state->size) {
490205194Sdelphij        /* flush previous input with previous parameters before changing */
491205194Sdelphij        if (strm->avail_in && gz_comp(state, Z_PARTIAL_FLUSH) == -1)
492205194Sdelphij            return state->err;
493205194Sdelphij        deflateParams(strm, level, strategy);
494205194Sdelphij    }
495205194Sdelphij    state->level = level;
496205194Sdelphij    state->strategy = strategy;
497205194Sdelphij    return Z_OK;
498205194Sdelphij}
499205194Sdelphij
500205194Sdelphij/* -- see zlib.h -- */
501205194Sdelphijint ZEXPORT gzclose_w(file)
502205194Sdelphij    gzFile file;
503205194Sdelphij{
504205194Sdelphij    int ret = 0;
505205194Sdelphij    gz_statep state;
506205194Sdelphij
507205194Sdelphij    /* get internal structure */
508205194Sdelphij    if (file == NULL)
509205194Sdelphij        return Z_STREAM_ERROR;
510205194Sdelphij    state = (gz_statep)file;
511205194Sdelphij
512205194Sdelphij    /* check that we're writing */
513205194Sdelphij    if (state->mode != GZ_WRITE)
514205194Sdelphij        return Z_STREAM_ERROR;
515205194Sdelphij
516205194Sdelphij    /* check for seek request */
517205194Sdelphij    if (state->seek) {
518205194Sdelphij        state->seek = 0;
519205194Sdelphij        ret += gz_zero(state, state->skip);
520205194Sdelphij    }
521205194Sdelphij
522205194Sdelphij    /* flush, free memory, and close file */
523205194Sdelphij    ret += gz_comp(state, Z_FINISH);
524205194Sdelphij    (void)deflateEnd(&(state->strm));
525205194Sdelphij    free(state->out);
526205194Sdelphij    free(state->in);
527205194Sdelphij    gz_error(state, Z_OK, NULL);
528205194Sdelphij    free(state->path);
529205194Sdelphij    ret += close(state->fd);
530205194Sdelphij    free(state);
531205194Sdelphij    return ret ? Z_ERRNO : Z_OK;
532205194Sdelphij}
533