Coverage Report

Created: 2026-01-10 06:21

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