Coverage Report

Created: 2026-09-28 06:47

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
        strm->next_in = NULL;
45
0
    }
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
    /* consume whatever's left in the input buffer */
160
0
    if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1)
161
0
        return -1;
162
163
    /* compress state->skip zeros */
164
0
    first = 1;
165
0
    do {
166
0
        n = GT_OFF(state->size) || (z_off64_t)state->size > state->skip ?
167
0
            (unsigned)state->skip : state->size;
168
0
        if (first) {
169
0
            memset(state->in, 0, n);
170
0
            first = 0;
171
0
        }
172
0
        strm->avail_in = n;
173
0
        strm->next_in = state->in;
174
0
        ret = gz_comp(state, Z_NO_FLUSH);
175
0
        n -= strm->avail_in;
176
0
        state->x.pos += n;
177
0
        state->skip -= n;
178
0
        if (ret == -1)
179
0
            return -1;
180
0
    } while (state->skip);
181
0
    return 0;
182
0
}
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
0
local z_size_t gz_write(gz_statep state, voidpc buf, z_size_t len) {
189
0
    z_size_t put = len;
190
0
    int ret;
191
192
    /* if len is zero, avoid unnecessary operations */
193
0
    if (len == 0)
194
0
        return 0;
195
196
    /* allocate memory if this is the first time through */
197
0
    if (state->size == 0 && gz_init(state) == -1)
198
0
        return 0;
199
200
    /* check for seek request */
201
0
    if (state->skip && gz_zero(state) == -1)
202
0
        return 0;
203
204
    /* for small len, copy to input buffer, otherwise compress directly */
205
0
    if (len < state->size) {
206
        /* copy to input buffer, compress when full */
207
0
        for (;;) {
208
0
            unsigned have, copy;
209
210
0
            if (state->strm.avail_in == 0)
211
0
                state->strm.next_in = state->in;
212
0
            have = (unsigned)((state->strm.next_in + state->strm.avail_in) -
213
0
                              state->in);
214
0
            copy = state->size - have;
215
0
            if (copy > len)
216
0
                copy = (unsigned)len;
217
0
            memcpy(state->in + have, buf, copy);
218
0
            state->strm.avail_in += copy;
219
0
            state->x.pos += copy;
220
0
            buf = (const char *)buf + copy;
221
0
            len -= copy;
222
0
            if (len == 0)
223
0
                break;
224
0
            if (gz_comp(state, Z_NO_FLUSH) == -1)
225
0
                return state->again ? put - len : 0;
226
0
        }
227
0
    }
228
0
    else {
229
        /* consume whatever's left in the input buffer */
230
0
        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
0
        state->strm.next_in = (z_const Bytef *)buf;
235
0
        do {
236
0
            unsigned n = (unsigned)-1;
237
238
0
            if (n > len)
239
0
                n = (unsigned)len;
240
0
            state->strm.avail_in = n;
241
0
            ret = gz_comp(state, Z_NO_FLUSH);
242
0
            n -= state->strm.avail_in;
243
0
            state->x.pos += n;
244
0
            len -= n;
245
0
            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
0
        } while (len);
251
0
    }
252
253
    /* input was all buffered or compressed */
254
0
    return put;
255
0
}
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
0
                          gzFile file) {
285
0
    z_size_t len;
286
0
    gz_statep state;
287
288
    /* get internal structure */
289
0
    if (file == NULL)
290
0
        return 0;
291
0
    state = (gz_statep)file;
292
293
    /* check that we're writing and that there's no (serious) error */
294
0
    if (state->mode != GZ_WRITE || (state->err != Z_OK && !state->again))
295
0
        return 0;
296
0
    gz_error(state, Z_OK, NULL);
297
298
    /* compute bytes to read -- error on overflow */
299
0
    len = nitems * size;
300
0
    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
0
    return len ? gz_write(state, buf, len) / size : 0;
307
0
}
308
309
/* -- see zlib.h -- */
310
0
int ZEXPORT gzputc(gzFile file, int c) {
311
0
    unsigned have;
312
0
    unsigned char buf[1];
313
0
    gz_statep state;
314
0
    z_streamp strm;
315
316
    /* get internal structure */
317
0
    if (file == NULL)
318
0
        return -1;
319
0
    state = (gz_statep)file;
320
0
    strm = &(state->strm);
321
322
    /* check that we're writing and that there's no (serious) error */
323
0
    if (state->mode != GZ_WRITE || (state->err != Z_OK && !state->again))
324
0
        return -1;
325
0
    gz_error(state, Z_OK, NULL);
326
327
    /* check for seek request */
328
0
    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
0
    if (state->size) {
334
0
        if (strm->avail_in == 0)
335
0
            strm->next_in = state->in;
336
0
        have = (unsigned)((strm->next_in + strm->avail_in) - state->in);
337
0
        if (have < state->size) {
338
0
            state->in[have] = (unsigned char)c;
339
0
            strm->avail_in++;
340
0
            state->x.pos++;
341
0
            return c & 0xff;
342
0
        }
343
0
    }
344
345
    /* no room in buffer or not initialized, use gz_write() */
346
0
    buf[0] = (unsigned char)c;
347
0
    if (gz_write(state, buf, 1) != 1)
348
0
        return -1;
349
0
    return c & 0xff;
350
0
}
351
352
/* -- see zlib.h -- */
353
0
int ZEXPORT gzputs(gzFile file, const char *s) {
354
0
    z_size_t len, put;
355
0
    gz_statep state;
356
357
    /* get internal structure */
358
0
    if (file == NULL)
359
0
        return -1;
360
0
    state = (gz_statep)file;
361
362
    /* check that we're writing and that there's no (serious) error */
363
0
    if (state->mode != GZ_WRITE || (state->err != Z_OK && !state->again))
364
0
        return -1;
365
0
    gz_error(state, Z_OK, NULL);
366
367
    /* write string */
368
0
    len = strlen(s);
369
0
    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
0
    put = gz_write(state, s, len);
374
0
    return len && put == 0 ? -1 : (int)put;
375
0
}
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
0
local int gz_vacate(gz_statep state) {
386
0
    z_streamp strm;
387
388
0
    strm = &(state->strm);
389
0
    if (strm->next_in == NULL ||
390
0
        strm->next_in + strm->avail_in <= state->in + state->size)
391
0
        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
0
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
0
    int len, ret;
416
0
    char *next;
417
0
    gz_statep state;
418
0
    z_streamp strm;
419
420
    /* get internal structure */
421
0
    if (file == NULL)
422
0
        return Z_STREAM_ERROR;
423
0
    state = (gz_statep)file;
424
0
    strm = &(state->strm);
425
426
    /* check that we're writing and that there's no (serious) error */
427
0
    if (state->mode != GZ_WRITE || (state->err != Z_OK && !state->again))
428
0
        return Z_STREAM_ERROR;
429
0
    gz_error(state, Z_OK, NULL);
430
431
    /* make sure we have some buffer space */
432
0
    if (state->size == 0 && gz_init(state) == -1)
433
0
        return state->err;
434
435
    /* check for seek request */
436
0
    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
0
    ret = gz_vacate(state);
443
0
    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
0
    if (strm->avail_in == 0)
456
0
        strm->next_in = state->in;
457
0
    next = (char *)(state->in + (strm->next_in - state->in) + strm->avail_in);
458
0
    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
0
    len = vsnprintf(next, state->size, format, va);
473
0
#  endif
474
0
#endif
475
476
    /* check that printf() results fit in buffer */
477
0
    if (len == 0 || (unsigned)len >= state->size || next[state->size - 1] != 0)
478
0
        return 0;
479
480
    /* update buffer and position */
481
0
    strm->avail_in += (unsigned)len;
482
0
    state->x.pos += len;
483
484
    /* write out buffer if more than half is occupied */
485
0
    ret = gz_vacate(state);
486
0
    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
0
    if (state->err && !state->again)
495
0
        return state->err;
496
0
    return len;
497
0
#endif
498
0
}
499
500
0
int ZEXPORTVA gzprintf(gzFile file, const char *format, ...) {
501
0
    va_list va;
502
0
    int ret;
503
504
0
    va_start(va, format);
505
0
    ret = gzvprintf(file, format, va);
506
0
    va_end(va);
507
0
    return ret;
508
0
}
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
23.2k
int ZEXPORT gzflush(gzFile file, int flush) {
626
23.2k
    gz_statep state;
627
628
    /* get internal structure */
629
23.2k
    if (file == NULL)
630
0
        return Z_STREAM_ERROR;
631
23.2k
    state = (gz_statep)file;
632
633
    /* check that we're writing and that there's no (serious) error */
634
23.2k
    if (state->mode != GZ_WRITE || (state->err != Z_OK && !state->again))
635
23.2k
        return Z_STREAM_ERROR;
636
0
    gz_error(state, Z_OK, NULL);
637
638
    /* check flush parameter */
639
0
    if (flush < 0 || flush > Z_FINISH)
640
0
        return Z_STREAM_ERROR;
641
642
    /* check for seek request */
643
0
    if (state->skip && gz_zero(state) == -1)
644
0
        return state->err;
645
646
    /* compress remaining data with requested flush */
647
0
    (void)gz_comp(state, flush);
648
0
    return state->err;
649
0
}
650
651
/* -- see zlib.h -- */
652
0
int ZEXPORT gzsetparams(gzFile file, int level, int strategy) {
653
0
    gz_statep state;
654
0
    z_streamp strm;
655
656
    /* get internal structure */
657
0
    if (file == NULL)
658
0
        return Z_STREAM_ERROR;
659
0
    state = (gz_statep)file;
660
0
    strm = &(state->strm);
661
662
    /* check that we're compressing and that there's no (serious) error */
663
0
    if (state->mode != GZ_WRITE || (state->err != Z_OK && !state->again) ||
664
0
            state->direct)
665
0
        return Z_STREAM_ERROR;
666
0
    gz_error(state, Z_OK, NULL);
667
668
    /* if no change is requested, then do nothing */
669
0
    if (level == state->level && strategy == state->strategy)
670
0
        return Z_OK;
671
672
    /* check for seek request */
673
0
    if (state->skip && gz_zero(state) == -1)
674
0
        return state->err;
675
676
    /* change compression parameters for subsequent input */
677
0
    if (state->size) {
678
        /* flush previous input with previous parameters before changing */
679
0
        if (strm->avail_in && gz_comp(state, Z_BLOCK) == -1)
680
0
            return state->err;
681
0
        deflateParams(strm, level, strategy);
682
0
    }
683
0
    state->level = level;
684
0
    state->strategy = strategy;
685
0
    return Z_OK;
686
0
}
687
688
/* -- see zlib.h -- */
689
0
int ZEXPORT gzclose_w(gzFile file) {
690
0
    int ret = Z_OK;
691
0
    gz_statep state;
692
693
    /* get internal structure */
694
0
    if (file == NULL)
695
0
        return Z_STREAM_ERROR;
696
0
    state = (gz_statep)file;
697
698
    /* check that we're writing */
699
0
    if (state->mode != GZ_WRITE)
700
0
        return Z_STREAM_ERROR;
701
702
    /* check for seek request */
703
0
    if (state->skip && gz_zero(state) == -1)
704
0
        ret = state->err;
705
706
    /* flush, free memory, and close file */
707
0
    if (gz_comp(state, Z_FINISH) == -1)
708
0
        ret = state->err;
709
0
    if (state->size) {
710
0
        if (!state->direct) {
711
0
            (void)deflateEnd(&(state->strm));
712
0
            free(state->out);
713
0
        }
714
0
        free(state->in);
715
0
    }
716
0
    gz_error(state, Z_OK, NULL);
717
0
    free(state->path);
718
0
    if (close(state->fd) == -1)
719
0
        ret = Z_ERRNO;
720
0
    free(state);
721
0
    return ret;
722
0
}