Coverage Report

Created: 2026-11-12 07:18

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
1.66k
local int gz_init(gz_statep state) {
12
1.66k
    int ret;
13
1.66k
    z_streamp strm = &(state->strm);
14
15
    /* allocate input buffer (double size for gzprintf) */
16
1.66k
    state->in = (unsigned char *)malloc(state->want << 1);
17
1.66k
    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
1.66k
    if (!state->direct) {
24
        /* allocate output buffer */
25
1.64k
        state->out = (unsigned char *)malloc(state->want);
26
1.64k
        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
1.64k
        strm->zalloc = Z_NULL;
34
1.64k
        strm->zfree = Z_NULL;
35
1.64k
        strm->opaque = Z_NULL;
36
1.64k
        ret = deflateInit2(strm, state->level, Z_DEFLATED,
37
1.64k
                           MAX_WBITS + 16, DEF_MEM_LEVEL, state->strategy);
38
1.64k
        if (ret != Z_OK) {
39
88
            free(state->out);
40
88
            free(state->in);
41
88
            gz_error(state, Z_MEM_ERROR, "out of memory");
42
88
            return -1;
43
88
        }
44
1.64k
    }
45
1.57k
    strm->next_in = NULL;
46
47
    /* mark state as initialized */
48
1.57k
    state->size = state->want;
49
50
    /* initialize write buffer if compressing */
51
1.57k
    if (!state->direct) {
52
1.55k
        strm->avail_out = state->size;
53
1.55k
        strm->next_out = state->out;
54
1.55k
        state->x.next = strm->next_out;
55
1.55k
    }
56
1.57k
    return 0;
57
1.66k
}
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
2.94k
local int gz_comp(gz_statep state, int flush) {
66
2.94k
    int ret, writ;
67
2.94k
    unsigned have, put, max = ((unsigned)-1 >> 2) + 1;
68
2.94k
    z_streamp strm = &(state->strm);
69
70
    /* allocate memory if this is the first time through */
71
2.94k
    if (state->size == 0 && gz_init(state) == -1)
72
76
        return -1;
73
74
    /* write directly if requested */
75
2.86k
    if (state->direct) {
76
186
        while (strm->avail_in) {
77
87
            errno = 0;
78
87
            state->again = 0;
79
87
            put = strm->avail_in > max ? max : strm->avail_in;
80
87
            writ = (int)write(state->fd, strm->next_in, put);
81
87
            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
87
            strm->avail_in -= (unsigned)writ;
88
87
            strm->next_in += writ;
89
87
        }
90
99
        return 0;
91
99
    }
92
93
    /* check for a pending reset */
94
2.76k
    if (state->reset) {
95
        /* don't start a new gzip member unless there is data to write and
96
           we're not flushing */
97
44
        if (strm->avail_in == 0 && flush == Z_NO_FLUSH)
98
0
            return 0;
99
44
        deflateReset(strm);
100
44
        state->reset = 0;
101
44
    }
102
103
    /* run deflate() on provided input until it produces no more output */
104
2.76k
    ret = Z_OK;
105
5.80k
    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
5.80k
        if (strm->avail_out == 0 || (flush != Z_NO_FLUSH &&
109
3.55k
            (flush != Z_FINISH || ret == Z_STREAM_END))) {
110
5.59k
            while (strm->next_out > state->x.next) {
111
2.70k
                errno = 0;
112
2.70k
                state->again = 0;
113
2.70k
                put = strm->next_out - state->x.next > (int)max ? max :
114
2.70k
                      (unsigned)(strm->next_out - state->x.next);
115
2.70k
                writ = (int)write(state->fd, state->x.next, put);
116
2.70k
                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
2.70k
                state->x.next += writ;
123
2.70k
            }
124
2.88k
            if (strm->avail_out == 0) {
125
933
                strm->avail_out = state->size;
126
933
                strm->next_out = state->out;
127
933
                state->x.next = state->out;
128
933
            }
129
2.88k
        }
130
131
        /* compress */
132
5.80k
        have = strm->avail_out;
133
5.80k
        ret = deflate(strm, flush);
134
5.80k
        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
5.80k
        have -= strm->avail_out;
140
5.80k
    } while (have);
141
142
    /* if that completed a deflate stream, allow another to start */
143
2.76k
    if (flush == Z_FINISH)
144
1.59k
        state->reset = 1;
145
146
    /* all done, no errors */
147
2.76k
    return 0;
148
2.76k
}
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
261
local int gz_zero(gz_statep state) {
155
261
    int first, ret;
156
261
    unsigned n;
157
261
    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
261
    if (state->size == 0 && gz_init(state) == -1)
162
4
        return -1;
163
164
    /* consume whatever's left in the input buffer */
165
257
    if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1)
166
0
        return -1;
167
168
    /* compress state->skip zeros */
169
257
    first = 1;
170
925
    do {
171
925
        n = GT_OFF(state->size) || (z_off64_t)state->size > state->skip ?
172
670
            (unsigned)state->skip : state->size;
173
925
        if (first) {
174
257
            memset(state->in, 0, n);
175
257
            first = 0;
176
257
        }
177
925
        strm->avail_in = n;
178
925
        strm->next_in = state->in;
179
925
        ret = gz_comp(state, Z_NO_FLUSH);
180
925
        n -= strm->avail_in;
181
925
        state->x.pos += n;
182
925
        state->skip -= n;
183
925
        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
925
    } while (state->skip);
192
257
    return 0;
193
257
}
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
1.45k
local z_size_t gz_write(gz_statep state, voidpc buf, z_size_t len) {
200
1.45k
    z_size_t put = len;
201
1.45k
    int ret;
202
203
    /* if len is zero, avoid unnecessary operations */
204
1.45k
    if (len == 0)
205
26
        return 0;
206
207
    /* allocate memory if this is the first time through */
208
1.43k
    if (state->size == 0 && gz_init(state) == -1)
209
2
        return 0;
210
211
    /* check for seek request */
212
1.43k
    if (state->skip && gz_zero(state) == -1)
213
0
        return 0;
214
215
    /* for small len, copy to input buffer, otherwise compress directly */
216
1.43k
    if (len < state->size) {
217
        /* copy to input buffer, compress when full */
218
1.35k
        for (;;) {
219
1.35k
            unsigned have, copy;
220
221
1.35k
            if (state->strm.avail_in == 0)
222
945
                state->strm.next_in = state->in;
223
1.35k
            have = (unsigned)((state->strm.next_in + state->strm.avail_in) -
224
1.35k
                              state->in);
225
1.35k
            copy = state->size - have;
226
1.35k
            if (copy > len)
227
1.35k
                copy = (unsigned)len;
228
1.35k
            memcpy(state->in + have, buf, copy);
229
1.35k
            state->strm.avail_in += copy;
230
1.35k
            state->x.pos += copy;
231
1.35k
            buf = (const char *)buf + copy;
232
1.35k
            len -= copy;
233
1.35k
            if (len == 0)
234
1.35k
                break;
235
0
            if (gz_comp(state, Z_NO_FLUSH) == -1)
236
0
                return state->again ? put - len : 0;
237
0
        }
238
1.35k
    }
239
78
    else {
240
        /* consume whatever's left in the input buffer */
241
78
        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
78
        state->strm.next_in = (z_const Bytef *)buf;
246
78
        do {
247
78
            unsigned n = (unsigned)-1;
248
249
78
            if (n > len)
250
78
                n = (unsigned)len;
251
78
            state->strm.avail_in = n;
252
78
            ret = gz_comp(state, Z_NO_FLUSH);
253
78
            n -= state->strm.avail_in;
254
78
            state->x.pos += n;
255
78
            len -= n;
256
78
            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
78
        } while (len);
262
78
        state->strm.next_in = state->in;
263
78
    }
264
265
    /* input was all buffered or compressed */
266
1.43k
    return put;
267
1.43k
}
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
1.26k
                          gzFile file) {
297
1.26k
    z_size_t len;
298
1.26k
    gz_statep state;
299
300
    /* get internal structure */
301
1.26k
    if (file == NULL)
302
13
        return 0;
303
1.25k
    state = (gz_statep)file;
304
305
    /* check that we're writing and that there's no (serious) error */
306
1.25k
    if (state->mode != GZ_WRITE || (state->err != Z_OK && !state->again))
307
1
        return 0;
308
1.24k
    gz_error(state, Z_OK, NULL);
309
310
    /* compute bytes to read -- error on overflow */
311
1.24k
    len = nitems * size;
312
1.24k
    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
1.24k
    return len ? gz_write(state, buf, len) / size : 0;
319
1.24k
}
320
321
/* -- see zlib.h -- */
322
104
int ZEXPORT gzputc(gzFile file, int c) {
323
104
    unsigned have;
324
104
    unsigned char buf[1];
325
104
    gz_statep state;
326
104
    z_streamp strm;
327
328
    /* get internal structure */
329
104
    if (file == NULL)
330
16
        return -1;
331
88
    state = (gz_statep)file;
332
88
    strm = &(state->strm);
333
334
    /* check that we're writing and that there's no (serious) error */
335
88
    if (state->mode != GZ_WRITE || (state->err != Z_OK && !state->again))
336
1
        return -1;
337
87
    gz_error(state, Z_OK, NULL);
338
339
    /* check for seek request */
340
87
    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
87
    if (state->size) {
346
18
        if (strm->avail_in == 0)
347
5
            strm->next_in = state->in;
348
18
        have = (unsigned)((strm->next_in + strm->avail_in) - state->in);
349
18
        if (have < state->size) {
350
18
            state->in[have] = (unsigned char)c;
351
18
            strm->avail_in++;
352
18
            state->x.pos++;
353
18
            return c & 0xff;
354
18
        }
355
18
    }
356
357
    /* no room in buffer or not initialized, use gz_write() */
358
69
    buf[0] = (unsigned char)c;
359
69
    if (gz_write(state, buf, 1) != 1)
360
1
        return -1;
361
68
    return c & 0xff;
362
69
}
363
364
/* -- see zlib.h -- */
365
146
int ZEXPORT gzputs(gzFile file, const char *s) {
366
146
    z_size_t len, put;
367
146
    gz_statep state;
368
369
    /* get internal structure */
370
146
    if (file == NULL)
371
5
        return -1;
372
141
    state = (gz_statep)file;
373
374
    /* check that we're writing and that there's no (serious) error */
375
141
    if (state->mode != GZ_WRITE || (state->err != Z_OK && !state->again))
376
1
        return -1;
377
140
    gz_error(state, Z_OK, NULL);
378
379
    /* write string */
380
140
    len = strlen(s);
381
140
    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
140
    put = gz_write(state, s, len);
386
140
    return len && put == 0 ? -1 : (int)put;
387
140
}
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
566
local int gz_vacate(gz_statep state) {
399
566
    z_streamp strm;
400
401
566
    strm = &(state->strm);
402
566
    if (strm->next_in == NULL ||
403
333
        strm->next_in + strm->avail_in <= state->in + state->size)
404
566
        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
477
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
477
    int len, ret;
429
477
    char *next;
430
477
    gz_statep state;
431
477
    z_streamp strm;
432
433
    /* get internal structure */
434
477
    if (file == NULL)
435
151
        return Z_STREAM_ERROR;
436
326
    state = (gz_statep)file;
437
326
    strm = &(state->strm);
438
439
    /* check that we're writing and that there's no (serious) error */
440
326
    if (state->mode != GZ_WRITE || (state->err != Z_OK && !state->again))
441
14
        return Z_STREAM_ERROR;
442
312
    gz_error(state, Z_OK, NULL);
443
444
    /* make sure we have some buffer space */
445
312
    if (state->size == 0 && gz_init(state) == -1)
446
6
        return state->err;
447
448
    /* check for seek request */
449
306
    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
306
    ret = gz_vacate(state);
456
306
    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
306
    if (strm->avail_in == 0)
469
265
        strm->next_in = state->in;
470
306
    next = (char *)(state->in + (strm->next_in - state->in) + strm->avail_in);
471
306
    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
306
    len = vsnprintf(next, state->size, format, va);
486
306
#  endif
487
306
#endif
488
489
    /* check that printf() results fit in buffer */
490
306
    if (len == 0 || (unsigned)len >= state->size || next[state->size - 1] != 0)
491
46
        return 0;
492
493
    /* update buffer and position */
494
260
    strm->avail_in += (unsigned)len;
495
260
    state->x.pos += len;
496
497
    /* write out buffer if more than half is occupied */
498
260
    ret = gz_vacate(state);
499
260
    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
260
    if (state->err && !state->again)
508
0
        return state->err;
509
260
    return len;
510
260
#endif
511
260
}
512
513
477
int ZEXPORTVA gzprintf(gzFile file, const char *format, ...) {
514
477
    va_list va;
515
477
    int ret;
516
517
477
    va_start(va, format);
518
477
    ret = gzvprintf(file, format, va);
519
477
    va_end(va);
520
477
    return ret;
521
477
}
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
223
int ZEXPORT gzflush(gzFile file, int flush) {
639
223
    gz_statep state;
640
641
    /* get internal structure */
642
223
    if (file == NULL)
643
17
        return Z_STREAM_ERROR;
644
206
    state = (gz_statep)file;
645
646
    /* check that we're writing and that there's no (serious) error */
647
206
    if (state->mode != GZ_WRITE || (state->err != Z_OK && !state->again))
648
59
        return Z_STREAM_ERROR;
649
147
    gz_error(state, Z_OK, NULL);
650
651
    /* check flush parameter */
652
147
    if (flush < 0 || flush > Z_FINISH)
653
33
        return Z_STREAM_ERROR;
654
655
    /* check for seek request */
656
114
    if (state->skip && gz_zero(state) == -1)
657
0
        return state->err;
658
659
    /* compress remaining data with requested flush */
660
114
    (void)gz_comp(state, flush);
661
114
    return state->err;
662
114
}
663
664
/* -- see zlib.h -- */
665
248
int ZEXPORT gzsetparams(gzFile file, int level, int strategy) {
666
248
    gz_statep state;
667
248
    z_streamp strm;
668
669
    /* get internal structure */
670
248
    if (file == NULL)
671
4
        return Z_STREAM_ERROR;
672
244
    state = (gz_statep)file;
673
244
    strm = &(state->strm);
674
675
    /* check that we're compressing and that there's no (serious) error */
676
244
    if (state->mode != GZ_WRITE || (state->err != Z_OK && !state->again) ||
677
242
            state->direct)
678
3
        return Z_STREAM_ERROR;
679
241
    gz_error(state, Z_OK, NULL);
680
681
    /* if no change is requested, then do nothing */
682
241
    if (level == state->level && strategy == state->strategy)
683
3
        return Z_OK;
684
685
    /* check for seek request */
686
238
    if (state->skip && gz_zero(state) == -1)
687
0
        return state->err;
688
689
    /* change compression parameters for subsequent input */
690
238
    if (state->size) {
691
        /* flush previous input with previous parameters before changing */
692
152
        if (strm->avail_in && gz_comp(state, Z_BLOCK) == -1)
693
0
            return state->err;
694
152
        deflateParams(strm, level, strategy);
695
152
    }
696
238
    state->level = level;
697
238
    state->strategy = strategy;
698
238
    return Z_OK;
699
238
}
700
701
/* -- see zlib.h -- */
702
1.64k
int ZEXPORT gzclose_w(gzFile file) {
703
1.64k
    int ret = Z_OK;
704
1.64k
    gz_statep state;
705
706
    /* get internal structure */
707
1.64k
    if (file == NULL)
708
0
        return Z_STREAM_ERROR;
709
1.64k
    state = (gz_statep)file;
710
711
    /* check that we're writing */
712
1.64k
    if (state->mode != GZ_WRITE)
713
0
        return Z_STREAM_ERROR;
714
715
    /* check for seek request */
716
1.64k
    if (state->skip && gz_zero(state) == -1)
717
4
        ret = state->err;
718
719
    /* flush, free memory, and close file */
720
1.64k
    if (gz_comp(state, Z_FINISH) == -1)
721
73
        ret = state->err;
722
1.64k
    if (state->size) {
723
1.57k
        if (!state->direct) {
724
1.55k
            (void)deflateEnd(&(state->strm));
725
1.55k
            free(state->out);
726
1.55k
        }
727
1.57k
        free(state->in);
728
1.57k
    }
729
1.64k
    gz_error(state, Z_OK, NULL);
730
1.64k
    free(state->path);
731
1.64k
    if (close(state->fd) == -1)
732
0
        ret = Z_ERRNO;
733
1.64k
    free(state);
734
1.64k
    return ret;
735
1.64k
}