Coverage Report

Created: 2026-09-01 06:34

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