Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Kitware
GitHub Repository: Kitware/CMake
Path: blob/master/Utilities/cmzlib/gzwrite.c
3150 views
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
local int gz_init(gz_statep state) {
12
int ret;
13
z_streamp strm = &(state->strm);
14
15
/* allocate input buffer (double size for gzprintf) */
16
state->in = (unsigned char *)malloc(state->want << 1);
17
if (state->in == NULL) {
18
gz_error(state, Z_MEM_ERROR, "out of memory");
19
return -1;
20
}
21
22
/* only need output buffer and deflate state if compressing */
23
if (!state->direct) {
24
/* allocate output buffer */
25
state->out = (unsigned char *)malloc(state->want);
26
if (state->out == NULL) {
27
free(state->in);
28
gz_error(state, Z_MEM_ERROR, "out of memory");
29
return -1;
30
}
31
32
/* allocate deflate memory, set up for gzip compression */
33
strm->zalloc = Z_NULL;
34
strm->zfree = Z_NULL;
35
strm->opaque = Z_NULL;
36
ret = deflateInit2(strm, state->level, Z_DEFLATED,
37
MAX_WBITS + 16, DEF_MEM_LEVEL, state->strategy);
38
if (ret != Z_OK) {
39
free(state->out);
40
free(state->in);
41
gz_error(state, Z_MEM_ERROR, "out of memory");
42
return -1;
43
}
44
strm->next_in = NULL;
45
}
46
47
/* mark state as initialized */
48
state->size = state->want;
49
50
/* initialize write buffer if compressing */
51
if (!state->direct) {
52
strm->avail_out = state->size;
53
strm->next_out = state->out;
54
state->x.next = strm->next_out;
55
}
56
return 0;
57
}
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
local int gz_comp(gz_statep state, int flush) {
66
int ret, writ;
67
unsigned have, put, max = ((unsigned)-1 >> 2) + 1;
68
z_streamp strm = &(state->strm);
69
70
/* allocate memory if this is the first time through */
71
if (state->size == 0 && gz_init(state) == -1)
72
return -1;
73
74
/* write directly if requested */
75
if (state->direct) {
76
while (strm->avail_in) {
77
put = strm->avail_in > max ? max : strm->avail_in;
78
writ = write(state->fd, strm->next_in, put);
79
if (writ < 0) {
80
gz_error(state, Z_ERRNO, zstrerror());
81
return -1;
82
}
83
strm->avail_in -= (unsigned)writ;
84
strm->next_in += writ;
85
}
86
return 0;
87
}
88
89
/* check for a pending reset */
90
if (state->reset) {
91
/* don't start a new gzip member unless there is data to write */
92
if (strm->avail_in == 0)
93
return 0;
94
deflateReset(strm);
95
state->reset = 0;
96
}
97
98
/* run deflate() on provided input until it produces no more output */
99
ret = Z_OK;
100
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
if (strm->avail_out == 0 || (flush != Z_NO_FLUSH &&
104
(flush != Z_FINISH || ret == Z_STREAM_END))) {
105
while (strm->next_out > state->x.next) {
106
put = strm->next_out - state->x.next > (int)max ? max :
107
(unsigned)(strm->next_out - state->x.next);
108
writ = write(state->fd, state->x.next, put);
109
if (writ < 0) {
110
gz_error(state, Z_ERRNO, zstrerror());
111
return -1;
112
}
113
state->x.next += writ;
114
}
115
if (strm->avail_out == 0) {
116
strm->avail_out = state->size;
117
strm->next_out = state->out;
118
state->x.next = state->out;
119
}
120
}
121
122
/* compress */
123
have = strm->avail_out;
124
ret = deflate(strm, flush);
125
if (ret == Z_STREAM_ERROR) {
126
gz_error(state, Z_STREAM_ERROR,
127
"internal error: deflate stream corrupt");
128
return -1;
129
}
130
have -= strm->avail_out;
131
} while (have);
132
133
/* if that completed a deflate stream, allow another to start */
134
if (flush == Z_FINISH)
135
state->reset = 1;
136
137
/* all done, no errors */
138
return 0;
139
}
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
local int gz_zero(gz_statep state, z_off64_t len) {
144
int first;
145
unsigned n;
146
z_streamp strm = &(state->strm);
147
148
/* consume whatever's left in the input buffer */
149
if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1)
150
return -1;
151
152
/* compress len zeros (len guaranteed > 0) */
153
first = 1;
154
while (len) {
155
n = GT_OFF(state->size) || (z_off64_t)state->size > len ?
156
(unsigned)len : state->size;
157
if (first) {
158
memset(state->in, 0, n);
159
first = 0;
160
}
161
strm->avail_in = n;
162
strm->next_in = state->in;
163
state->x.pos += n;
164
if (gz_comp(state, Z_NO_FLUSH) == -1)
165
return -1;
166
len -= n;
167
}
168
return 0;
169
}
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
local z_size_t gz_write(gz_statep state, voidpc buf, z_size_t len) {
174
z_size_t put = len;
175
176
/* if len is zero, avoid unnecessary operations */
177
if (len == 0)
178
return 0;
179
180
/* allocate memory if this is the first time through */
181
if (state->size == 0 && gz_init(state) == -1)
182
return 0;
183
184
/* check for seek request */
185
if (state->seek) {
186
state->seek = 0;
187
if (gz_zero(state, state->skip) == -1)
188
return 0;
189
}
190
191
/* for small len, copy to input buffer, otherwise compress directly */
192
if (len < state->size) {
193
/* copy to input buffer, compress when full */
194
do {
195
unsigned have, copy;
196
197
if (state->strm.avail_in == 0)
198
state->strm.next_in = state->in;
199
have = (unsigned)((state->strm.next_in + state->strm.avail_in) -
200
state->in);
201
copy = state->size - have;
202
if (copy > len)
203
copy = (unsigned)len;
204
memcpy(state->in + have, buf, copy);
205
state->strm.avail_in += copy;
206
state->x.pos += copy;
207
buf = (const char *)buf + copy;
208
len -= copy;
209
if (len && gz_comp(state, Z_NO_FLUSH) == -1)
210
return 0;
211
} while (len);
212
}
213
else {
214
/* consume whatever's left in the input buffer */
215
if (state->strm.avail_in && gz_comp(state, Z_NO_FLUSH) == -1)
216
return 0;
217
218
/* directly compress user buffer to file */
219
state->strm.next_in = (z_const Bytef *)buf;
220
do {
221
unsigned n = (unsigned)-1;
222
if (n > len)
223
n = (unsigned)len;
224
state->strm.avail_in = n;
225
state->x.pos += n;
226
if (gz_comp(state, Z_NO_FLUSH) == -1)
227
return 0;
228
len -= n;
229
} while (len);
230
}
231
232
/* input was all buffered or compressed */
233
return put;
234
}
235
236
/* -- see zlib.h -- */
237
int ZEXPORT gzwrite(gzFile file, voidpc buf, unsigned len) {
238
gz_statep state;
239
240
/* get internal structure */
241
if (file == NULL)
242
return 0;
243
state = (gz_statep)file;
244
245
/* check that we're writing and that there's no error */
246
if (state->mode != GZ_WRITE || state->err != Z_OK)
247
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
if ((int)len < 0) {
252
gz_error(state, Z_DATA_ERROR, "requested length does not fit in int");
253
return 0;
254
}
255
256
/* write len bytes from buf (the return value will fit in an int) */
257
return (int)gz_write(state, buf, len);
258
}
259
260
/* -- see zlib.h -- */
261
z_size_t ZEXPORT gzfwrite(voidpc buf, z_size_t size, z_size_t nitems,
262
gzFile file) {
263
z_size_t len;
264
gz_statep state;
265
266
/* get internal structure */
267
if (file == NULL)
268
return 0;
269
state = (gz_statep)file;
270
271
/* check that we're writing and that there's no error */
272
if (state->mode != GZ_WRITE || state->err != Z_OK)
273
return 0;
274
275
/* compute bytes to read -- error on overflow */
276
len = nitems * size;
277
if (size && len / size != nitems) {
278
gz_error(state, Z_STREAM_ERROR, "request does not fit in a size_t");
279
return 0;
280
}
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
return len ? gz_write(state, buf, len) / size : 0;
290
}
291
292
/* -- see zlib.h -- */
293
int ZEXPORT gzputc(gzFile file, int c) {
294
unsigned have;
295
unsigned char buf[1];
296
gz_statep state;
297
z_streamp strm;
298
299
/* get internal structure */
300
if (file == NULL)
301
return -1;
302
state = (gz_statep)file;
303
strm = &(state->strm);
304
305
/* check that we're writing and that there's no error */
306
if (state->mode != GZ_WRITE || state->err != Z_OK)
307
return -1;
308
309
/* check for seek request */
310
if (state->seek) {
311
state->seek = 0;
312
if (gz_zero(state, state->skip) == -1)
313
return -1;
314
}
315
316
/* try writing to input buffer for speed (state->size == 0 if buffer not
317
initialized) */
318
if (state->size) {
319
if (strm->avail_in == 0)
320
strm->next_in = state->in;
321
have = (unsigned)((strm->next_in + strm->avail_in) - state->in);
322
if (have < state->size) {
323
state->in[have] = (unsigned char)c;
324
strm->avail_in++;
325
state->x.pos++;
326
return c & 0xff;
327
}
328
}
329
330
/* no room in buffer or not initialized, use gz_write() */
331
buf[0] = (unsigned char)c;
332
if (gz_write(state, buf, 1) != 1)
333
return -1;
334
return c & 0xff;
335
}
336
337
/* -- see zlib.h -- */
338
int ZEXPORT gzputs(gzFile file, const char *s) {
339
z_size_t len, put;
340
gz_statep state;
341
342
/* get internal structure */
343
if (file == NULL)
344
return -1;
345
state = (gz_statep)file;
346
347
/* check that we're writing and that there's no error */
348
if (state->mode != GZ_WRITE || state->err != Z_OK)
349
return -1;
350
351
/* write string */
352
len = strlen(s);
353
if ((int)len < 0 || (unsigned)len != len) {
354
gz_error(state, Z_STREAM_ERROR, "string length does not fit in int");
355
return -1;
356
}
357
put = gz_write(state, s, len);
358
return put < len ? -1 : (int)len;
359
}
360
361
#if defined(STDC) || defined(Z_HAVE_STDARG_H)
362
#include <stdarg.h>
363
364
/* -- see zlib.h -- */
365
int ZEXPORTVA gzvprintf(gzFile file, const char *format, va_list va) {
366
int len;
367
unsigned left;
368
char *next;
369
gz_statep state;
370
z_streamp strm;
371
372
/* get internal structure */
373
if (file == NULL)
374
return Z_STREAM_ERROR;
375
state = (gz_statep)file;
376
strm = &(state->strm);
377
378
/* check that we're writing and that there's no error */
379
if (state->mode != GZ_WRITE || state->err != Z_OK)
380
return Z_STREAM_ERROR;
381
382
/* make sure we have some buffer space */
383
if (state->size == 0 && gz_init(state) == -1)
384
return state->err;
385
386
/* check for seek request */
387
if (state->seek) {
388
state->seek = 0;
389
if (gz_zero(state, state->skip) == -1)
390
return state->err;
391
}
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
if (strm->avail_in == 0)
397
strm->next_in = state->in;
398
next = (char *)(state->in + (strm->next_in - state->in) + strm->avail_in);
399
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
len = vsnprintf(next, state->size, format, va);
414
# endif
415
#endif
416
417
/* check that printf() results fit in buffer */
418
if (len == 0 || (unsigned)len >= state->size || next[state->size - 1] != 0)
419
return 0;
420
421
/* update buffer and position, compress first half if past that */
422
strm->avail_in += (unsigned)len;
423
state->x.pos += len;
424
if (strm->avail_in >= state->size) {
425
left = strm->avail_in - state->size;
426
strm->avail_in = state->size;
427
if (gz_comp(state, Z_NO_FLUSH) == -1)
428
return state->err;
429
memmove(state->in, state->in + state->size, left);
430
strm->next_in = state->in;
431
strm->avail_in = left;
432
}
433
return len;
434
}
435
436
int ZEXPORTVA gzprintf(gzFile file, const char *format, ...) {
437
va_list va;
438
int ret;
439
440
va_start(va, format);
441
ret = gzvprintf(file, format, va);
442
va_end(va);
443
return ret;
444
}
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
int ZEXPORT gzflush(gzFile file, int flush) {
535
gz_statep state;
536
537
/* get internal structure */
538
if (file == NULL)
539
return Z_STREAM_ERROR;
540
state = (gz_statep)file;
541
542
/* check that we're writing and that there's no error */
543
if (state->mode != GZ_WRITE || state->err != Z_OK)
544
return Z_STREAM_ERROR;
545
546
/* check flush parameter */
547
if (flush < 0 || flush > Z_FINISH)
548
return Z_STREAM_ERROR;
549
550
/* check for seek request */
551
if (state->seek) {
552
state->seek = 0;
553
if (gz_zero(state, state->skip) == -1)
554
return state->err;
555
}
556
557
/* compress remaining data with requested flush */
558
(void)gz_comp(state, flush);
559
return state->err;
560
}
561
562
/* -- see zlib.h -- */
563
int ZEXPORT gzsetparams(gzFile file, int level, int strategy) {
564
gz_statep state;
565
z_streamp strm;
566
567
/* get internal structure */
568
if (file == NULL)
569
return Z_STREAM_ERROR;
570
state = (gz_statep)file;
571
strm = &(state->strm);
572
573
/* check that we're writing and that there's no error */
574
if (state->mode != GZ_WRITE || state->err != Z_OK || state->direct)
575
return Z_STREAM_ERROR;
576
577
/* if no change is requested, then do nothing */
578
if (level == state->level && strategy == state->strategy)
579
return Z_OK;
580
581
/* check for seek request */
582
if (state->seek) {
583
state->seek = 0;
584
if (gz_zero(state, state->skip) == -1)
585
return state->err;
586
}
587
588
/* change compression parameters for subsequent input */
589
if (state->size) {
590
/* flush previous input with previous parameters before changing */
591
if (strm->avail_in && gz_comp(state, Z_BLOCK) == -1)
592
return state->err;
593
deflateParams(strm, level, strategy);
594
}
595
state->level = level;
596
state->strategy = strategy;
597
return Z_OK;
598
}
599
600
/* -- see zlib.h -- */
601
int ZEXPORT gzclose_w(gzFile file) {
602
int ret = Z_OK;
603
gz_statep state;
604
605
/* get internal structure */
606
if (file == NULL)
607
return Z_STREAM_ERROR;
608
state = (gz_statep)file;
609
610
/* check that we're writing */
611
if (state->mode != GZ_WRITE)
612
return Z_STREAM_ERROR;
613
614
/* check for seek request */
615
if (state->seek) {
616
state->seek = 0;
617
if (gz_zero(state, state->skip) == -1)
618
ret = state->err;
619
}
620
621
/* flush, free memory, and close file */
622
if (gz_comp(state, Z_FINISH) == -1)
623
ret = state->err;
624
if (state->size) {
625
if (!state->direct) {
626
(void)deflateEnd(&(state->strm));
627
free(state->out);
628
}
629
free(state->in);
630
}
631
gz_error(state, Z_OK, NULL);
632
free(state->path);
633
if (close(state->fd) == -1)
634
ret = Z_ERRNO;
635
free(state);
636
return ret;
637
}
638
639