gzwrite.c revision 1.1.1.2 1 1.1 christos /* gzwrite.c -- zlib functions for writing gzip files
2 1.1.1.2 christos * Copyright (C) 2004, 2005, 2010, 2011, 2012, 2013 Mark Adler
3 1.1 christos * For conditions of distribution and use, see copyright notice in zlib.h
4 1.1 christos */
5 1.1 christos
6 1.1 christos #include "gzguts.h"
7 1.1 christos
8 1.1 christos /* Local functions */
9 1.1 christos local int gz_init OF((gz_statep));
10 1.1 christos local int gz_comp OF((gz_statep, int));
11 1.1 christos local int gz_zero OF((gz_statep, z_off64_t));
12 1.1 christos
13 1.1 christos /* Initialize state for writing a gzip file. Mark initialization by setting
14 1.1 christos state->size to non-zero. Return -1 on failure or 0 on success. */
15 1.1 christos local int gz_init(state)
16 1.1 christos gz_statep state;
17 1.1 christos {
18 1.1 christos int ret;
19 1.1 christos z_streamp strm = &(state->strm);
20 1.1 christos
21 1.1 christos /* allocate input buffer */
22 1.1.1.2 christos state->in = (unsigned char *)malloc(state->want);
23 1.1 christos if (state->in == NULL) {
24 1.1 christos gz_error(state, Z_MEM_ERROR, "out of memory");
25 1.1 christos return -1;
26 1.1 christos }
27 1.1 christos
28 1.1 christos /* only need output buffer and deflate state if compressing */
29 1.1 christos if (!state->direct) {
30 1.1 christos /* allocate output buffer */
31 1.1.1.2 christos state->out = (unsigned char *)malloc(state->want);
32 1.1 christos if (state->out == NULL) {
33 1.1 christos free(state->in);
34 1.1 christos gz_error(state, Z_MEM_ERROR, "out of memory");
35 1.1 christos return -1;
36 1.1 christos }
37 1.1 christos
38 1.1 christos /* allocate deflate memory, set up for gzip compression */
39 1.1 christos strm->zalloc = Z_NULL;
40 1.1 christos strm->zfree = Z_NULL;
41 1.1 christos strm->opaque = Z_NULL;
42 1.1 christos ret = deflateInit2(strm, state->level, Z_DEFLATED,
43 1.1 christos MAX_WBITS + 16, DEF_MEM_LEVEL, state->strategy);
44 1.1 christos if (ret != Z_OK) {
45 1.1 christos free(state->out);
46 1.1 christos free(state->in);
47 1.1 christos gz_error(state, Z_MEM_ERROR, "out of memory");
48 1.1 christos return -1;
49 1.1 christos }
50 1.1 christos }
51 1.1 christos
52 1.1 christos /* mark state as initialized */
53 1.1 christos state->size = state->want;
54 1.1 christos
55 1.1 christos /* initialize write buffer if compressing */
56 1.1 christos if (!state->direct) {
57 1.1 christos strm->avail_out = state->size;
58 1.1 christos strm->next_out = state->out;
59 1.1 christos state->x.next = strm->next_out;
60 1.1 christos }
61 1.1 christos return 0;
62 1.1 christos }
63 1.1 christos
64 1.1 christos /* Compress whatever is at avail_in and next_in and write to the output file.
65 1.1 christos Return -1 if there is an error writing to the output file, otherwise 0.
66 1.1 christos flush is assumed to be a valid deflate() flush value. If flush is Z_FINISH,
67 1.1 christos then the deflate() state is reset to start a new gzip stream. If gz->direct
68 1.1 christos is true, then simply write to the output file without compressing, and
69 1.1 christos ignore flush. */
70 1.1 christos local int gz_comp(state, flush)
71 1.1 christos gz_statep state;
72 1.1 christos int flush;
73 1.1 christos {
74 1.1 christos int ret, got;
75 1.1 christos unsigned have;
76 1.1 christos z_streamp strm = &(state->strm);
77 1.1 christos
78 1.1 christos /* allocate memory if this is the first time through */
79 1.1 christos if (state->size == 0 && gz_init(state) == -1)
80 1.1 christos return -1;
81 1.1 christos
82 1.1 christos /* write directly if requested */
83 1.1 christos if (state->direct) {
84 1.1 christos got = write(state->fd, strm->next_in, strm->avail_in);
85 1.1 christos if (got < 0 || (unsigned)got != strm->avail_in) {
86 1.1 christos gz_error(state, Z_ERRNO, zstrerror());
87 1.1 christos return -1;
88 1.1 christos }
89 1.1 christos strm->avail_in = 0;
90 1.1 christos return 0;
91 1.1 christos }
92 1.1 christos
93 1.1 christos /* run deflate() on provided input until it produces no more output */
94 1.1 christos ret = Z_OK;
95 1.1 christos do {
96 1.1 christos /* write out current buffer contents if full, or if flushing, but if
97 1.1 christos doing Z_FINISH then don't write until we get to Z_STREAM_END */
98 1.1 christos if (strm->avail_out == 0 || (flush != Z_NO_FLUSH &&
99 1.1 christos (flush != Z_FINISH || ret == Z_STREAM_END))) {
100 1.1 christos have = (unsigned)(strm->next_out - state->x.next);
101 1.1 christos if (have && ((got = write(state->fd, state->x.next, have)) < 0 ||
102 1.1 christos (unsigned)got != have)) {
103 1.1 christos gz_error(state, Z_ERRNO, zstrerror());
104 1.1 christos return -1;
105 1.1 christos }
106 1.1 christos if (strm->avail_out == 0) {
107 1.1 christos strm->avail_out = state->size;
108 1.1 christos strm->next_out = state->out;
109 1.1 christos }
110 1.1 christos state->x.next = strm->next_out;
111 1.1 christos }
112 1.1 christos
113 1.1 christos /* compress */
114 1.1 christos have = strm->avail_out;
115 1.1 christos ret = deflate(strm, flush);
116 1.1 christos if (ret == Z_STREAM_ERROR) {
117 1.1 christos gz_error(state, Z_STREAM_ERROR,
118 1.1 christos "internal error: deflate stream corrupt");
119 1.1 christos return -1;
120 1.1 christos }
121 1.1 christos have -= strm->avail_out;
122 1.1 christos } while (have);
123 1.1 christos
124 1.1 christos /* if that completed a deflate stream, allow another to start */
125 1.1 christos if (flush == Z_FINISH)
126 1.1 christos deflateReset(strm);
127 1.1 christos
128 1.1 christos /* all done, no errors */
129 1.1 christos return 0;
130 1.1 christos }
131 1.1 christos
132 1.1 christos /* Compress len zeros to output. Return -1 on error, 0 on success. */
133 1.1 christos local int gz_zero(state, len)
134 1.1 christos gz_statep state;
135 1.1 christos z_off64_t len;
136 1.1 christos {
137 1.1 christos int first;
138 1.1 christos unsigned n;
139 1.1 christos z_streamp strm = &(state->strm);
140 1.1 christos
141 1.1 christos /* consume whatever's left in the input buffer */
142 1.1 christos if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1)
143 1.1 christos return -1;
144 1.1 christos
145 1.1 christos /* compress len zeros (len guaranteed > 0) */
146 1.1 christos first = 1;
147 1.1 christos while (len) {
148 1.1 christos n = GT_OFF(state->size) || (z_off64_t)state->size > len ?
149 1.1 christos (unsigned)len : state->size;
150 1.1 christos if (first) {
151 1.1 christos memset(state->in, 0, n);
152 1.1 christos first = 0;
153 1.1 christos }
154 1.1 christos strm->avail_in = n;
155 1.1 christos strm->next_in = state->in;
156 1.1 christos state->x.pos += n;
157 1.1 christos if (gz_comp(state, Z_NO_FLUSH) == -1)
158 1.1 christos return -1;
159 1.1 christos len -= n;
160 1.1 christos }
161 1.1 christos return 0;
162 1.1 christos }
163 1.1 christos
164 1.1 christos /* -- see zlib.h -- */
165 1.1 christos int ZEXPORT gzwrite(file, buf, len)
166 1.1 christos gzFile file;
167 1.1 christos voidpc buf;
168 1.1 christos unsigned len;
169 1.1 christos {
170 1.1 christos unsigned put = len;
171 1.1 christos gz_statep state;
172 1.1 christos z_streamp strm;
173 1.1 christos
174 1.1 christos /* get internal structure */
175 1.1 christos if (file == NULL)
176 1.1 christos return 0;
177 1.1 christos state = (gz_statep)file;
178 1.1 christos strm = &(state->strm);
179 1.1 christos
180 1.1 christos /* check that we're writing and that there's no error */
181 1.1 christos if (state->mode != GZ_WRITE || state->err != Z_OK)
182 1.1 christos return 0;
183 1.1 christos
184 1.1 christos /* since an int is returned, make sure len fits in one, otherwise return
185 1.1 christos with an error (this avoids the flaw in the interface) */
186 1.1 christos if ((int)len < 0) {
187 1.1 christos gz_error(state, Z_DATA_ERROR, "requested length does not fit in int");
188 1.1 christos return 0;
189 1.1 christos }
190 1.1 christos
191 1.1 christos /* if len is zero, avoid unnecessary operations */
192 1.1 christos if (len == 0)
193 1.1 christos return 0;
194 1.1 christos
195 1.1 christos /* allocate memory if this is the first time through */
196 1.1 christos if (state->size == 0 && gz_init(state) == -1)
197 1.1 christos return 0;
198 1.1 christos
199 1.1 christos /* check for seek request */
200 1.1 christos if (state->seek) {
201 1.1 christos state->seek = 0;
202 1.1 christos if (gz_zero(state, state->skip) == -1)
203 1.1 christos return 0;
204 1.1 christos }
205 1.1 christos
206 1.1 christos /* for small len, copy to input buffer, otherwise compress directly */
207 1.1 christos if (len < state->size) {
208 1.1 christos /* copy to input buffer, compress when full */
209 1.1 christos do {
210 1.1.1.2 christos unsigned have, copy;
211 1.1.1.2 christos
212 1.1 christos if (strm->avail_in == 0)
213 1.1 christos strm->next_in = state->in;
214 1.1.1.2 christos have = (unsigned)((strm->next_in + strm->avail_in) - state->in);
215 1.1.1.2 christos copy = state->size - have;
216 1.1.1.2 christos if (copy > len)
217 1.1.1.2 christos copy = len;
218 1.1.1.2 christos memcpy(state->in + have, buf, copy);
219 1.1.1.2 christos strm->avail_in += copy;
220 1.1.1.2 christos state->x.pos += copy;
221 1.1.1.2 christos buf = (const char *)buf + copy;
222 1.1.1.2 christos len -= copy;
223 1.1 christos if (len && gz_comp(state, Z_NO_FLUSH) == -1)
224 1.1 christos return 0;
225 1.1 christos } while (len);
226 1.1 christos }
227 1.1 christos else {
228 1.1 christos /* consume whatever's left in the input buffer */
229 1.1 christos if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1)
230 1.1 christos return 0;
231 1.1 christos
232 1.1 christos /* directly compress user buffer to file */
233 1.1 christos strm->avail_in = len;
234 1.1.1.2 christos strm->next_in = (z_const Bytef *)buf;
235 1.1 christos state->x.pos += len;
236 1.1 christos if (gz_comp(state, Z_NO_FLUSH) == -1)
237 1.1 christos return 0;
238 1.1 christos }
239 1.1 christos
240 1.1 christos /* input was all buffered or compressed (put will fit in int) */
241 1.1 christos return (int)put;
242 1.1 christos }
243 1.1 christos
244 1.1 christos /* -- see zlib.h -- */
245 1.1 christos int ZEXPORT gzputc(file, c)
246 1.1 christos gzFile file;
247 1.1 christos int c;
248 1.1 christos {
249 1.1.1.2 christos unsigned have;
250 1.1 christos unsigned char buf[1];
251 1.1 christos gz_statep state;
252 1.1 christos z_streamp strm;
253 1.1 christos
254 1.1 christos /* get internal structure */
255 1.1 christos if (file == NULL)
256 1.1 christos return -1;
257 1.1 christos state = (gz_statep)file;
258 1.1 christos strm = &(state->strm);
259 1.1 christos
260 1.1 christos /* check that we're writing and that there's no error */
261 1.1 christos if (state->mode != GZ_WRITE || state->err != Z_OK)
262 1.1 christos return -1;
263 1.1 christos
264 1.1 christos /* check for seek request */
265 1.1 christos if (state->seek) {
266 1.1 christos state->seek = 0;
267 1.1 christos if (gz_zero(state, state->skip) == -1)
268 1.1 christos return -1;
269 1.1 christos }
270 1.1 christos
271 1.1 christos /* try writing to input buffer for speed (state->size == 0 if buffer not
272 1.1 christos initialized) */
273 1.1.1.2 christos if (state->size) {
274 1.1 christos if (strm->avail_in == 0)
275 1.1 christos strm->next_in = state->in;
276 1.1.1.2 christos have = (unsigned)((strm->next_in + strm->avail_in) - state->in);
277 1.1.1.2 christos if (have < state->size) {
278 1.1.1.2 christos state->in[have] = c;
279 1.1.1.2 christos strm->avail_in++;
280 1.1.1.2 christos state->x.pos++;
281 1.1.1.2 christos return c & 0xff;
282 1.1.1.2 christos }
283 1.1 christos }
284 1.1 christos
285 1.1 christos /* no room in buffer or not initialized, use gz_write() */
286 1.1 christos buf[0] = c;
287 1.1 christos if (gzwrite(file, buf, 1) != 1)
288 1.1 christos return -1;
289 1.1 christos return c & 0xff;
290 1.1 christos }
291 1.1 christos
292 1.1 christos /* -- see zlib.h -- */
293 1.1 christos int ZEXPORT gzputs(file, str)
294 1.1 christos gzFile file;
295 1.1 christos const char *str;
296 1.1 christos {
297 1.1 christos int ret;
298 1.1 christos unsigned len;
299 1.1 christos
300 1.1 christos /* write string */
301 1.1 christos len = (unsigned)strlen(str);
302 1.1 christos ret = gzwrite(file, str, len);
303 1.1 christos return ret == 0 && len != 0 ? -1 : ret;
304 1.1 christos }
305 1.1 christos
306 1.1 christos #if defined(STDC) || defined(Z_HAVE_STDARG_H)
307 1.1 christos #include <stdarg.h>
308 1.1 christos
309 1.1 christos /* -- see zlib.h -- */
310 1.1.1.2 christos int ZEXPORTVA gzvprintf(gzFile file, const char *format, va_list va)
311 1.1 christos {
312 1.1 christos int size, len;
313 1.1 christos gz_statep state;
314 1.1 christos z_streamp strm;
315 1.1 christos
316 1.1 christos /* get internal structure */
317 1.1 christos if (file == NULL)
318 1.1 christos return -1;
319 1.1 christos state = (gz_statep)file;
320 1.1 christos strm = &(state->strm);
321 1.1 christos
322 1.1 christos /* check that we're writing and that there's no error */
323 1.1 christos if (state->mode != GZ_WRITE || state->err != Z_OK)
324 1.1 christos return 0;
325 1.1 christos
326 1.1 christos /* make sure we have some buffer space */
327 1.1 christos if (state->size == 0 && gz_init(state) == -1)
328 1.1 christos return 0;
329 1.1 christos
330 1.1 christos /* check for seek request */
331 1.1 christos if (state->seek) {
332 1.1 christos state->seek = 0;
333 1.1 christos if (gz_zero(state, state->skip) == -1)
334 1.1 christos return 0;
335 1.1 christos }
336 1.1 christos
337 1.1 christos /* consume whatever's left in the input buffer */
338 1.1 christos if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1)
339 1.1 christos return 0;
340 1.1 christos
341 1.1 christos /* do the printf() into the input buffer, put length in len */
342 1.1 christos size = (int)(state->size);
343 1.1 christos state->in[size - 1] = 0;
344 1.1 christos #ifdef NO_vsnprintf
345 1.1 christos # ifdef HAS_vsprintf_void
346 1.1 christos (void)vsprintf((char *)(state->in), format, va);
347 1.1 christos for (len = 0; len < size; len++)
348 1.1 christos if (state->in[len] == 0) break;
349 1.1 christos # else
350 1.1 christos len = vsprintf((char *)(state->in), format, va);
351 1.1 christos # endif
352 1.1 christos #else
353 1.1 christos # ifdef HAS_vsnprintf_void
354 1.1 christos (void)vsnprintf((char *)(state->in), size, format, va);
355 1.1 christos len = strlen((char *)(state->in));
356 1.1 christos # else
357 1.1 christos len = vsnprintf((char *)(state->in), size, format, va);
358 1.1 christos # endif
359 1.1 christos #endif
360 1.1 christos
361 1.1 christos /* check that printf() results fit in buffer */
362 1.1 christos if (len <= 0 || len >= (int)size || state->in[size - 1] != 0)
363 1.1 christos return 0;
364 1.1 christos
365 1.1 christos /* update buffer and position, defer compression until needed */
366 1.1 christos strm->avail_in = (unsigned)len;
367 1.1 christos strm->next_in = state->in;
368 1.1 christos state->x.pos += len;
369 1.1 christos return len;
370 1.1 christos }
371 1.1 christos
372 1.1.1.2 christos int ZEXPORTVA gzprintf(gzFile file, const char *format, ...)
373 1.1.1.2 christos {
374 1.1.1.2 christos va_list va;
375 1.1.1.2 christos int ret;
376 1.1.1.2 christos
377 1.1.1.2 christos va_start(va, format);
378 1.1.1.2 christos ret = gzvprintf(file, format, va);
379 1.1.1.2 christos va_end(va);
380 1.1.1.2 christos return ret;
381 1.1.1.2 christos }
382 1.1.1.2 christos
383 1.1 christos #else /* !STDC && !Z_HAVE_STDARG_H */
384 1.1 christos
385 1.1 christos /* -- see zlib.h -- */
386 1.1 christos int ZEXPORTVA gzprintf (file, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10,
387 1.1 christos a11, a12, a13, a14, a15, a16, a17, a18, a19, a20)
388 1.1 christos gzFile file;
389 1.1 christos const char *format;
390 1.1 christos int a1, a2, a3, a4, a5, a6, a7, a8, a9, a10,
391 1.1 christos a11, a12, a13, a14, a15, a16, a17, a18, a19, a20;
392 1.1 christos {
393 1.1 christos int size, len;
394 1.1 christos gz_statep state;
395 1.1 christos z_streamp strm;
396 1.1 christos
397 1.1 christos /* get internal structure */
398 1.1 christos if (file == NULL)
399 1.1 christos return -1;
400 1.1 christos state = (gz_statep)file;
401 1.1 christos strm = &(state->strm);
402 1.1 christos
403 1.1 christos /* check that can really pass pointer in ints */
404 1.1 christos if (sizeof(int) != sizeof(void *))
405 1.1 christos return 0;
406 1.1 christos
407 1.1 christos /* check that we're writing and that there's no error */
408 1.1 christos if (state->mode != GZ_WRITE || state->err != Z_OK)
409 1.1 christos return 0;
410 1.1 christos
411 1.1 christos /* make sure we have some buffer space */
412 1.1 christos if (state->size == 0 && gz_init(state) == -1)
413 1.1 christos return 0;
414 1.1 christos
415 1.1 christos /* check for seek request */
416 1.1 christos if (state->seek) {
417 1.1 christos state->seek = 0;
418 1.1 christos if (gz_zero(state, state->skip) == -1)
419 1.1 christos return 0;
420 1.1 christos }
421 1.1 christos
422 1.1 christos /* consume whatever's left in the input buffer */
423 1.1 christos if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1)
424 1.1 christos return 0;
425 1.1 christos
426 1.1 christos /* do the printf() into the input buffer, put length in len */
427 1.1 christos size = (int)(state->size);
428 1.1 christos state->in[size - 1] = 0;
429 1.1 christos #ifdef NO_snprintf
430 1.1 christos # ifdef HAS_sprintf_void
431 1.1 christos sprintf((char *)(state->in), format, a1, a2, a3, a4, a5, a6, a7, a8,
432 1.1 christos a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20);
433 1.1 christos for (len = 0; len < size; len++)
434 1.1 christos if (state->in[len] == 0) break;
435 1.1 christos # else
436 1.1 christos len = sprintf((char *)(state->in), format, a1, a2, a3, a4, a5, a6, a7, a8,
437 1.1 christos a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20);
438 1.1 christos # endif
439 1.1 christos #else
440 1.1 christos # ifdef HAS_snprintf_void
441 1.1 christos snprintf((char *)(state->in), size, format, a1, a2, a3, a4, a5, a6, a7, a8,
442 1.1 christos a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20);
443 1.1 christos len = strlen((char *)(state->in));
444 1.1 christos # else
445 1.1 christos len = snprintf((char *)(state->in), size, format, a1, a2, a3, a4, a5, a6,
446 1.1 christos a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18,
447 1.1 christos a19, a20);
448 1.1 christos # endif
449 1.1 christos #endif
450 1.1 christos
451 1.1 christos /* check that printf() results fit in buffer */
452 1.1 christos if (len <= 0 || len >= (int)size || state->in[size - 1] != 0)
453 1.1 christos return 0;
454 1.1 christos
455 1.1 christos /* update buffer and position, defer compression until needed */
456 1.1 christos strm->avail_in = (unsigned)len;
457 1.1 christos strm->next_in = state->in;
458 1.1 christos state->x.pos += len;
459 1.1 christos return len;
460 1.1 christos }
461 1.1 christos
462 1.1 christos #endif
463 1.1 christos
464 1.1 christos /* -- see zlib.h -- */
465 1.1 christos int ZEXPORT gzflush(file, flush)
466 1.1 christos gzFile file;
467 1.1 christos int flush;
468 1.1 christos {
469 1.1 christos gz_statep state;
470 1.1 christos
471 1.1 christos /* get internal structure */
472 1.1 christos if (file == NULL)
473 1.1 christos return -1;
474 1.1 christos state = (gz_statep)file;
475 1.1 christos
476 1.1 christos /* check that we're writing and that there's no error */
477 1.1 christos if (state->mode != GZ_WRITE || state->err != Z_OK)
478 1.1 christos return Z_STREAM_ERROR;
479 1.1 christos
480 1.1 christos /* check flush parameter */
481 1.1 christos if (flush < 0 || flush > Z_FINISH)
482 1.1 christos return Z_STREAM_ERROR;
483 1.1 christos
484 1.1 christos /* check for seek request */
485 1.1 christos if (state->seek) {
486 1.1 christos state->seek = 0;
487 1.1 christos if (gz_zero(state, state->skip) == -1)
488 1.1 christos return -1;
489 1.1 christos }
490 1.1 christos
491 1.1 christos /* compress remaining data with requested flush */
492 1.1 christos gz_comp(state, flush);
493 1.1 christos return state->err;
494 1.1 christos }
495 1.1 christos
496 1.1 christos /* -- see zlib.h -- */
497 1.1 christos int ZEXPORT gzsetparams(file, level, strategy)
498 1.1 christos gzFile file;
499 1.1 christos int level;
500 1.1 christos int strategy;
501 1.1 christos {
502 1.1 christos gz_statep state;
503 1.1 christos z_streamp strm;
504 1.1 christos
505 1.1 christos /* get internal structure */
506 1.1 christos if (file == NULL)
507 1.1 christos return Z_STREAM_ERROR;
508 1.1 christos state = (gz_statep)file;
509 1.1 christos strm = &(state->strm);
510 1.1 christos
511 1.1 christos /* check that we're writing and that there's no error */
512 1.1 christos if (state->mode != GZ_WRITE || state->err != Z_OK)
513 1.1 christos return Z_STREAM_ERROR;
514 1.1 christos
515 1.1 christos /* if no change is requested, then do nothing */
516 1.1 christos if (level == state->level && strategy == state->strategy)
517 1.1 christos return Z_OK;
518 1.1 christos
519 1.1 christos /* check for seek request */
520 1.1 christos if (state->seek) {
521 1.1 christos state->seek = 0;
522 1.1 christos if (gz_zero(state, state->skip) == -1)
523 1.1 christos return -1;
524 1.1 christos }
525 1.1 christos
526 1.1 christos /* change compression parameters for subsequent input */
527 1.1 christos if (state->size) {
528 1.1 christos /* flush previous input with previous parameters before changing */
529 1.1 christos if (strm->avail_in && gz_comp(state, Z_PARTIAL_FLUSH) == -1)
530 1.1 christos return state->err;
531 1.1 christos deflateParams(strm, level, strategy);
532 1.1 christos }
533 1.1 christos state->level = level;
534 1.1 christos state->strategy = strategy;
535 1.1 christos return Z_OK;
536 1.1 christos }
537 1.1 christos
538 1.1 christos /* -- see zlib.h -- */
539 1.1 christos int ZEXPORT gzclose_w(file)
540 1.1 christos gzFile file;
541 1.1 christos {
542 1.1 christos int ret = Z_OK;
543 1.1 christos gz_statep state;
544 1.1 christos
545 1.1 christos /* get internal structure */
546 1.1 christos if (file == NULL)
547 1.1 christos return Z_STREAM_ERROR;
548 1.1 christos state = (gz_statep)file;
549 1.1 christos
550 1.1 christos /* check that we're writing */
551 1.1 christos if (state->mode != GZ_WRITE)
552 1.1 christos return Z_STREAM_ERROR;
553 1.1 christos
554 1.1 christos /* check for seek request */
555 1.1 christos if (state->seek) {
556 1.1 christos state->seek = 0;
557 1.1 christos if (gz_zero(state, state->skip) == -1)
558 1.1 christos ret = state->err;
559 1.1 christos }
560 1.1 christos
561 1.1 christos /* flush, free memory, and close file */
562 1.1.1.2 christos if (gz_comp(state, Z_FINISH) == -1)
563 1.1.1.2 christos ret = state->err;
564 1.1 christos if (state->size) {
565 1.1 christos if (!state->direct) {
566 1.1 christos (void)deflateEnd(&(state->strm));
567 1.1 christos free(state->out);
568 1.1 christos }
569 1.1 christos free(state->in);
570 1.1 christos }
571 1.1 christos gz_error(state, Z_OK, NULL);
572 1.1 christos free(state->path);
573 1.1 christos if (close(state->fd) == -1)
574 1.1 christos ret = Z_ERRNO;
575 1.1 christos free(state);
576 1.1 christos return ret;
577 1.1 christos }
578