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