Coverage Report

Created: 2026-10-17 07:03

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