Coverage Report

Created: 2026-03-12 06:35

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/CMake/Utilities/cmzlib/gzwrite.c
Line
Count
Source
1
/* gzwrite.c -- zlib functions for writing gzip files
2
 * Copyright (C) 2004-2019 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
            put = strm->avail_in > max ? max : strm->avail_in;
78
0
            writ = write(state->fd, strm->next_in, put);
79
0
            if (writ < 0) {
80
0
                gz_error(state, Z_ERRNO, zstrerror());
81
0
                return -1;
82
0
            }
83
0
            strm->avail_in -= (unsigned)writ;
84
0
            strm->next_in += writ;
85
0
        }
86
0
        return 0;
87
0
    }
88
89
    /* check for a pending reset */
90
0
    if (state->reset) {
91
        /* don't start a new gzip member unless there is data to write */
92
0
        if (strm->avail_in == 0)
93
0
            return 0;
94
0
        deflateReset(strm);
95
0
        state->reset = 0;
96
0
    }
97
98
    /* run deflate() on provided input until it produces no more output */
99
0
    ret = Z_OK;
100
0
    do {
101
        /* write out current buffer contents if full, or if flushing, but if
102
           doing Z_FINISH then don't write until we get to Z_STREAM_END */
103
0
        if (strm->avail_out == 0 || (flush != Z_NO_FLUSH &&
104
0
            (flush != Z_FINISH || ret == Z_STREAM_END))) {
105
0
            while (strm->next_out > state->x.next) {
106
0
                put = strm->next_out - state->x.next > (int)max ? max :
107
0
                      (unsigned)(strm->next_out - state->x.next);
108
0
                writ = write(state->fd, state->x.next, put);
109
0
                if (writ < 0) {
110
0
                    gz_error(state, Z_ERRNO, zstrerror());
111
0
                    return -1;
112
0
                }
113
0
                state->x.next += writ;
114
0
            }
115
0
            if (strm->avail_out == 0) {
116
0
                strm->avail_out = state->size;
117
0
                strm->next_out = state->out;
118
0
                state->x.next = state->out;
119
0
            }
120
0
        }
121
122
        /* compress */
123
0
        have = strm->avail_out;
124
0
        ret = deflate(strm, flush);
125
0
        if (ret == Z_STREAM_ERROR) {
126
0
            gz_error(state, Z_STREAM_ERROR,
127
0
                      "internal error: deflate stream corrupt");
128
0
            return -1;
129
0
        }
130
0
        have -= strm->avail_out;
131
0
    } while (have);
132
133
    /* if that completed a deflate stream, allow another to start */
134
0
    if (flush == Z_FINISH)
135
0
        state->reset = 1;
136
137
    /* all done, no errors */
138
0
    return 0;
139
0
}
140
141
/* Compress len zeros to output.  Return -1 on a write error or memory
142
   allocation failure by gz_comp(), or 0 on success. */
143
0
local int gz_zero(gz_statep state, z_off64_t len) {
144
0
    int first;
145
0
    unsigned n;
146
0
    z_streamp strm = &(state->strm);
147
148
    /* consume whatever's left in the input buffer */
149
0
    if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1)
150
0
        return -1;
151
152
    /* compress len zeros (len guaranteed > 0) */
153
0
    first = 1;
154
0
    while (len) {
155
0
        n = GT_OFF(state->size) || (z_off64_t)state->size > len ?
156
0
            (unsigned)len : state->size;
157
0
        if (first) {
158
0
            memset(state->in, 0, n);
159
0
            first = 0;
160
0
        }
161
0
        strm->avail_in = n;
162
0
        strm->next_in = state->in;
163
0
        state->x.pos += n;
164
0
        if (gz_comp(state, Z_NO_FLUSH) == -1)
165
0
            return -1;
166
0
        len -= n;
167
0
    }
168
0
    return 0;
169
0
}
170
171
/* Write len bytes from buf to file.  Return the number of bytes written.  If
172
   the returned value is less than len, then there was an error. */
173
0
local z_size_t gz_write(gz_statep state, voidpc buf, z_size_t len) {
174
0
    z_size_t put = len;
175
176
    /* if len is zero, avoid unnecessary operations */
177
0
    if (len == 0)
178
0
        return 0;
179
180
    /* allocate memory if this is the first time through */
181
0
    if (state->size == 0 && gz_init(state) == -1)
182
0
        return 0;
183
184
    /* check for seek request */
185
0
    if (state->seek) {
186
0
        state->seek = 0;
187
0
        if (gz_zero(state, state->skip) == -1)
188
0
            return 0;
189
0
    }
190
191
    /* for small len, copy to input buffer, otherwise compress directly */
192
0
    if (len < state->size) {
193
        /* copy to input buffer, compress when full */
194
0
        do {
195
0
            unsigned have, copy;
196
197
0
            if (state->strm.avail_in == 0)
198
0
                state->strm.next_in = state->in;
199
0
            have = (unsigned)((state->strm.next_in + state->strm.avail_in) -
200
0
                              state->in);
201
0
            copy = state->size - have;
202
0
            if (copy > len)
203
0
                copy = (unsigned)len;
204
0
            memcpy(state->in + have, buf, copy);
205
0
            state->strm.avail_in += copy;
206
0
            state->x.pos += copy;
207
0
            buf = (const char *)buf + copy;
208
0
            len -= copy;
209
0
            if (len && gz_comp(state, Z_NO_FLUSH) == -1)
210
0
                return 0;
211
0
        } while (len);
212
0
    }
213
0
    else {
214
        /* consume whatever's left in the input buffer */
215
0
        if (state->strm.avail_in && gz_comp(state, Z_NO_FLUSH) == -1)
216
0
            return 0;
217
218
        /* directly compress user buffer to file */
219
0
        state->strm.next_in = (z_const Bytef *)buf;
220
0
        do {
221
0
            unsigned n = (unsigned)-1;
222
0
            if (n > len)
223
0
                n = (unsigned)len;
224
0
            state->strm.avail_in = n;
225
0
            state->x.pos += n;
226
0
            if (gz_comp(state, Z_NO_FLUSH) == -1)
227
0
                return 0;
228
0
            len -= n;
229
0
        } while (len);
230
0
    }
231
232
    /* input was all buffered or compressed */
233
0
    return put;
234
0
}
235
236
/* -- see zlib.h -- */
237
0
int ZEXPORT gzwrite(gzFile file, voidpc buf, unsigned len) {
238
0
    gz_statep state;
239
240
    /* get internal structure */
241
0
    if (file == NULL)
242
0
        return 0;
243
0
    state = (gz_statep)file;
244
245
    /* check that we're writing and that there's no error */
246
0
    if (state->mode != GZ_WRITE || state->err != Z_OK)
247
0
        return 0;
248
249
    /* since an int is returned, make sure len fits in one, otherwise return
250
       with an error (this avoids a flaw in the interface) */
251
0
    if ((int)len < 0) {
252
0
        gz_error(state, Z_DATA_ERROR, "requested length does not fit in int");
253
0
        return 0;
254
0
    }
255
256
    /* write len bytes from buf (the return value will fit in an int) */
257
0
    return (int)gz_write(state, buf, len);
258
0
}
259
260
/* -- see zlib.h -- */
261
z_size_t ZEXPORT gzfwrite(voidpc buf, z_size_t size, z_size_t nitems,
262
0
                          gzFile file) {
263
0
    z_size_t len;
264
0
    gz_statep state;
265
266
    /* get internal structure */
267
0
    if (file == NULL)
268
0
        return 0;
269
0
    state = (gz_statep)file;
270
271
    /* check that we're writing and that there's no error */
272
0
    if (state->mode != GZ_WRITE || state->err != Z_OK)
273
0
        return 0;
274
275
    /* compute bytes to read -- error on overflow */
276
0
    len = nitems * size;
277
0
    if (size && len / size != nitems) {
278
0
        gz_error(state, Z_STREAM_ERROR, "request does not fit in a size_t");
279
0
        return 0;
280
0
    }
281
282
#ifdef __clang_analyzer__
283
    /* clang-analyzer does not see size==0 through len==0 below. */
284
    if (!size)
285
        return 0;
286
#endif
287
288
    /* write len bytes to buf, return the number of full items written */
289
0
    return len ? gz_write(state, buf, len) / size : 0;
290
0
}
291
292
/* -- see zlib.h -- */
293
0
int ZEXPORT gzputc(gzFile file, int c) {
294
0
    unsigned have;
295
0
    unsigned char buf[1];
296
0
    gz_statep state;
297
0
    z_streamp strm;
298
299
    /* get internal structure */
300
0
    if (file == NULL)
301
0
        return -1;
302
0
    state = (gz_statep)file;
303
0
    strm = &(state->strm);
304
305
    /* check that we're writing and that there's no error */
306
0
    if (state->mode != GZ_WRITE || state->err != Z_OK)
307
0
        return -1;
308
309
    /* check for seek request */
310
0
    if (state->seek) {
311
0
        state->seek = 0;
312
0
        if (gz_zero(state, state->skip) == -1)
313
0
            return -1;
314
0
    }
315
316
    /* try writing to input buffer for speed (state->size == 0 if buffer not
317
       initialized) */
318
0
    if (state->size) {
319
0
        if (strm->avail_in == 0)
320
0
            strm->next_in = state->in;
321
0
        have = (unsigned)((strm->next_in + strm->avail_in) - state->in);
322
0
        if (have < state->size) {
323
0
            state->in[have] = (unsigned char)c;
324
0
            strm->avail_in++;
325
0
            state->x.pos++;
326
0
            return c & 0xff;
327
0
        }
328
0
    }
329
330
    /* no room in buffer or not initialized, use gz_write() */
331
0
    buf[0] = (unsigned char)c;
332
0
    if (gz_write(state, buf, 1) != 1)
333
0
        return -1;
334
0
    return c & 0xff;
335
0
}
336
337
/* -- see zlib.h -- */
338
0
int ZEXPORT gzputs(gzFile file, const char *s) {
339
0
    z_size_t len, put;
340
0
    gz_statep state;
341
342
    /* get internal structure */
343
0
    if (file == NULL)
344
0
        return -1;
345
0
    state = (gz_statep)file;
346
347
    /* check that we're writing and that there's no error */
348
0
    if (state->mode != GZ_WRITE || state->err != Z_OK)
349
0
        return -1;
350
351
    /* write string */
352
0
    len = strlen(s);
353
0
    if ((int)len < 0 || (unsigned)len != len) {
354
0
        gz_error(state, Z_STREAM_ERROR, "string length does not fit in int");
355
0
        return -1;
356
0
    }
357
0
    put = gz_write(state, s, len);
358
0
    return put < len ? -1 : (int)len;
359
0
}
360
361
#if defined(STDC) || defined(Z_HAVE_STDARG_H)
362
#include <stdarg.h>
363
364
/* -- see zlib.h -- */
365
0
int ZEXPORTVA gzvprintf(gzFile file, const char *format, va_list va) {
366
0
    int len;
367
0
    unsigned left;
368
0
    char *next;
369
0
    gz_statep state;
370
0
    z_streamp strm;
371
372
    /* get internal structure */
373
0
    if (file == NULL)
374
0
        return Z_STREAM_ERROR;
375
0
    state = (gz_statep)file;
376
0
    strm = &(state->strm);
377
378
    /* check that we're writing and that there's no error */
379
0
    if (state->mode != GZ_WRITE || state->err != Z_OK)
380
0
        return Z_STREAM_ERROR;
381
382
    /* make sure we have some buffer space */
383
0
    if (state->size == 0 && gz_init(state) == -1)
384
0
        return state->err;
385
386
    /* check for seek request */
387
0
    if (state->seek) {
388
0
        state->seek = 0;
389
0
        if (gz_zero(state, state->skip) == -1)
390
0
            return state->err;
391
0
    }
392
393
    /* do the printf() into the input buffer, put length in len -- the input
394
       buffer is double-sized just for this function, so there is guaranteed to
395
       be state->size bytes available after the current contents */
396
0
    if (strm->avail_in == 0)
397
0
        strm->next_in = state->in;
398
0
    next = (char *)(state->in + (strm->next_in - state->in) + strm->avail_in);
399
0
    next[state->size - 1] = 0;
400
#ifdef NO_vsnprintf
401
#  ifdef HAS_vsprintf_void
402
    (void)vsprintf(next, format, va);
403
    for (len = 0; len < state->size; len++)
404
        if (next[len] == 0) break;
405
#  else
406
    len = vsprintf(next, format, va);
407
#  endif
408
#else
409
#  ifdef HAS_vsnprintf_void
410
    (void)vsnprintf(next, state->size, format, va);
411
    len = strlen(next);
412
#  else
413
0
    len = vsnprintf(next, state->size, format, va);
414
0
#  endif
415
0
#endif
416
417
    /* check that printf() results fit in buffer */
418
0
    if (len == 0 || (unsigned)len >= state->size || next[state->size - 1] != 0)
419
0
        return 0;
420
421
    /* update buffer and position, compress first half if past that */
422
0
    strm->avail_in += (unsigned)len;
423
0
    state->x.pos += len;
424
0
    if (strm->avail_in >= state->size) {
425
0
        left = strm->avail_in - state->size;
426
0
        strm->avail_in = state->size;
427
0
        if (gz_comp(state, Z_NO_FLUSH) == -1)
428
0
            return state->err;
429
0
        memmove(state->in, state->in + state->size, left);
430
0
        strm->next_in = state->in;
431
0
        strm->avail_in = left;
432
0
    }
433
0
    return len;
434
0
}
435
436
0
int ZEXPORTVA gzprintf(gzFile file, const char *format, ...) {
437
0
    va_list va;
438
0
    int ret;
439
440
0
    va_start(va, format);
441
0
    ret = gzvprintf(file, format, va);
442
0
    va_end(va);
443
0
    return ret;
444
0
}
445
446
#else /* !STDC && !Z_HAVE_STDARG_H */
447
448
/* -- see zlib.h -- */
449
int ZEXPORTVA gzprintf(gzFile file, const char *format, int a1, int a2, int a3,
450
                       int a4, int a5, int a6, int a7, int a8, int a9, int a10,
451
                       int a11, int a12, int a13, int a14, int a15, int a16,
452
                       int a17, int a18, int a19, int a20) {
453
    unsigned len, left;
454
    char *next;
455
    gz_statep state;
456
    z_streamp strm;
457
458
    /* get internal structure */
459
    if (file == NULL)
460
        return Z_STREAM_ERROR;
461
    state = (gz_statep)file;
462
    strm = &(state->strm);
463
464
    /* check that can really pass pointer in ints */
465
    if (sizeof(int) != sizeof(void *))
466
        return Z_STREAM_ERROR;
467
468
    /* check that we're writing and that there's no error */
469
    if (state->mode != GZ_WRITE || state->err != Z_OK)
470
        return Z_STREAM_ERROR;
471
472
    /* make sure we have some buffer space */
473
    if (state->size == 0 && gz_init(state) == -1)
474
        return state->error;
475
476
    /* check for seek request */
477
    if (state->seek) {
478
        state->seek = 0;
479
        if (gz_zero(state, state->skip) == -1)
480
            return state->error;
481
    }
482
483
    /* do the printf() into the input buffer, put length in len -- the input
484
       buffer is double-sized just for this function, so there is guaranteed to
485
       be state->size bytes available after the current contents */
486
    if (strm->avail_in == 0)
487
        strm->next_in = state->in;
488
    next = (char *)(strm->next_in + strm->avail_in);
489
    next[state->size - 1] = 0;
490
#ifdef NO_snprintf
491
#  ifdef HAS_sprintf_void
492
    sprintf(next, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12,
493
            a13, a14, a15, a16, a17, a18, a19, a20);
494
    for (len = 0; len < size; len++)
495
        if (next[len] == 0)
496
            break;
497
#  else
498
    len = sprintf(next, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11,
499
                  a12, a13, a14, a15, a16, a17, a18, a19, a20);
500
#  endif
501
#else
502
#  ifdef HAS_snprintf_void
503
    snprintf(next, state->size, format, a1, a2, a3, a4, a5, a6, a7, a8, a9,
504
             a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20);
505
    len = strlen(next);
506
#  else
507
    len = snprintf(next, state->size, format, a1, a2, a3, a4, a5, a6, a7, a8,
508
                   a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20);
509
#  endif
510
#endif
511
512
    /* check that printf() results fit in buffer */
513
    if (len == 0 || len >= state->size || next[state->size - 1] != 0)
514
        return 0;
515
516
    /* update buffer and position, compress first half if past that */
517
    strm->avail_in += len;
518
    state->x.pos += len;
519
    if (strm->avail_in >= state->size) {
520
        left = strm->avail_in - state->size;
521
        strm->avail_in = state->size;
522
        if (gz_comp(state, Z_NO_FLUSH) == -1)
523
            return state->err;
524
        memmove(state->in, state->in + state->size, left);
525
        strm->next_in = state->in;
526
        strm->avail_in = left;
527
    }
528
    return (int)len;
529
}
530
531
#endif
532
533
/* -- see zlib.h -- */
534
0
int ZEXPORT gzflush(gzFile file, int flush) {
535
0
    gz_statep state;
536
537
    /* get internal structure */
538
0
    if (file == NULL)
539
0
        return Z_STREAM_ERROR;
540
0
    state = (gz_statep)file;
541
542
    /* check that we're writing and that there's no error */
543
0
    if (state->mode != GZ_WRITE || state->err != Z_OK)
544
0
        return Z_STREAM_ERROR;
545
546
    /* check flush parameter */
547
0
    if (flush < 0 || flush > Z_FINISH)
548
0
        return Z_STREAM_ERROR;
549
550
    /* check for seek request */
551
0
    if (state->seek) {
552
0
        state->seek = 0;
553
0
        if (gz_zero(state, state->skip) == -1)
554
0
            return state->err;
555
0
    }
556
557
    /* compress remaining data with requested flush */
558
0
    (void)gz_comp(state, flush);
559
0
    return state->err;
560
0
}
561
562
/* -- see zlib.h -- */
563
0
int ZEXPORT gzsetparams(gzFile file, int level, int strategy) {
564
0
    gz_statep state;
565
0
    z_streamp strm;
566
567
    /* get internal structure */
568
0
    if (file == NULL)
569
0
        return Z_STREAM_ERROR;
570
0
    state = (gz_statep)file;
571
0
    strm = &(state->strm);
572
573
    /* check that we're writing and that there's no error */
574
0
    if (state->mode != GZ_WRITE || state->err != Z_OK || state->direct)
575
0
        return Z_STREAM_ERROR;
576
577
    /* if no change is requested, then do nothing */
578
0
    if (level == state->level && strategy == state->strategy)
579
0
        return Z_OK;
580
581
    /* check for seek request */
582
0
    if (state->seek) {
583
0
        state->seek = 0;
584
0
        if (gz_zero(state, state->skip) == -1)
585
0
            return state->err;
586
0
    }
587
588
    /* change compression parameters for subsequent input */
589
0
    if (state->size) {
590
        /* flush previous input with previous parameters before changing */
591
0
        if (strm->avail_in && gz_comp(state, Z_BLOCK) == -1)
592
0
            return state->err;
593
0
        deflateParams(strm, level, strategy);
594
0
    }
595
0
    state->level = level;
596
0
    state->strategy = strategy;
597
0
    return Z_OK;
598
0
}
599
600
/* -- see zlib.h -- */
601
0
int ZEXPORT gzclose_w(gzFile file) {
602
0
    int ret = Z_OK;
603
0
    gz_statep state;
604
605
    /* get internal structure */
606
0
    if (file == NULL)
607
0
        return Z_STREAM_ERROR;
608
0
    state = (gz_statep)file;
609
610
    /* check that we're writing */
611
0
    if (state->mode != GZ_WRITE)
612
0
        return Z_STREAM_ERROR;
613
614
    /* check for seek request */
615
0
    if (state->seek) {
616
0
        state->seek = 0;
617
0
        if (gz_zero(state, state->skip) == -1)
618
0
            ret = state->err;
619
0
    }
620
621
    /* flush, free memory, and close file */
622
0
    if (gz_comp(state, Z_FINISH) == -1)
623
0
        ret = state->err;
624
0
    if (state->size) {
625
0
        if (!state->direct) {
626
0
            (void)deflateEnd(&(state->strm));
627
0
            free(state->out);
628
0
        }
629
0
        free(state->in);
630
0
    }
631
0
    gz_error(state, Z_OK, NULL);
632
0
    free(state->path);
633
0
    if (close(state->fd) == -1)
634
0
        ret = Z_ERRNO;
635
0
    free(state);
636
0
    return ret;
637
0
}