Coverage Report

Created: 2026-10-28 07:26

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