Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sudo-project
GitHub Repository: sudo-project/sudo
Path: blob/main/lib/zlib/gzwrite.c
1532 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
/* write len bytes to buf, return the number of full items written */
283
return len ? gz_write(state, buf, len) / size : 0;
284
}
285
286
/* -- see zlib.h -- */
287
int ZEXPORT gzputc(gzFile file, int c) {
288
unsigned have;
289
unsigned char buf[1];
290
gz_statep state;
291
z_streamp strm;
292
293
/* get internal structure */
294
if (file == NULL)
295
return -1;
296
state = (gz_statep)file;
297
strm = &(state->strm);
298
299
/* check that we're writing and that there's no error */
300
if (state->mode != GZ_WRITE || state->err != Z_OK)
301
return -1;
302
303
/* check for seek request */
304
if (state->seek) {
305
state->seek = 0;
306
if (gz_zero(state, state->skip) == -1)
307
return -1;
308
}
309
310
/* try writing to input buffer for speed (state->size == 0 if buffer not
311
initialized) */
312
if (state->size) {
313
if (strm->avail_in == 0)
314
strm->next_in = state->in;
315
have = (unsigned)((strm->next_in + strm->avail_in) - state->in);
316
if (have < state->size) {
317
state->in[have] = (unsigned char)c;
318
strm->avail_in++;
319
state->x.pos++;
320
return c & 0xff;
321
}
322
}
323
324
/* no room in buffer or not initialized, use gz_write() */
325
buf[0] = (unsigned char)c;
326
if (gz_write(state, buf, 1) != 1)
327
return -1;
328
return c & 0xff;
329
}
330
331
/* -- see zlib.h -- */
332
int ZEXPORT gzputs(gzFile file, const char *s) {
333
z_size_t len, put;
334
gz_statep state;
335
336
/* get internal structure */
337
if (file == NULL)
338
return -1;
339
state = (gz_statep)file;
340
341
/* check that we're writing and that there's no error */
342
if (state->mode != GZ_WRITE || state->err != Z_OK)
343
return -1;
344
345
/* write string */
346
len = strlen(s);
347
if ((int)len < 0 || (unsigned)len != len) {
348
gz_error(state, Z_STREAM_ERROR, "string length does not fit in int");
349
return -1;
350
}
351
put = gz_write(state, s, len);
352
return put < len ? -1 : (int)len;
353
}
354
355
#if defined(STDC) || defined(Z_HAVE_STDARG_H)
356
#include <stdarg.h>
357
358
/* -- see zlib.h -- */
359
int ZEXPORTVA gzvprintf(gzFile file, const char *format, va_list va) {
360
int len;
361
unsigned left;
362
char *next;
363
gz_statep state;
364
z_streamp strm;
365
366
/* get internal structure */
367
if (file == NULL)
368
return Z_STREAM_ERROR;
369
state = (gz_statep)file;
370
strm = &(state->strm);
371
372
/* check that we're writing and that there's no error */
373
if (state->mode != GZ_WRITE || state->err != Z_OK)
374
return Z_STREAM_ERROR;
375
376
/* make sure we have some buffer space */
377
if (state->size == 0 && gz_init(state) == -1)
378
return state->err;
379
380
/* check for seek request */
381
if (state->seek) {
382
state->seek = 0;
383
if (gz_zero(state, state->skip) == -1)
384
return state->err;
385
}
386
387
/* do the printf() into the input buffer, put length in len -- the input
388
buffer is double-sized just for this function, so there is guaranteed to
389
be state->size bytes available after the current contents */
390
if (strm->avail_in == 0)
391
strm->next_in = state->in;
392
next = (char *)(state->in + (strm->next_in - state->in) + strm->avail_in);
393
next[state->size - 1] = 0;
394
#ifdef NO_vsnprintf
395
# ifdef HAS_vsprintf_void
396
(void)vsprintf(next, format, va);
397
for (len = 0; len < state->size; len++)
398
if (next[len] == 0) break;
399
# else
400
len = vsprintf(next, format, va);
401
# endif
402
#else
403
# ifdef HAS_vsnprintf_void
404
(void)vsnprintf(next, state->size, format, va);
405
len = strlen(next);
406
# else
407
len = vsnprintf(next, state->size, format, va);
408
# endif
409
#endif
410
411
/* check that printf() results fit in buffer */
412
if (len == 0 || (unsigned)len >= state->size || next[state->size - 1] != 0)
413
return 0;
414
415
/* update buffer and position, compress first half if past that */
416
strm->avail_in += (unsigned)len;
417
state->x.pos += len;
418
if (strm->avail_in >= state->size) {
419
left = strm->avail_in - state->size;
420
strm->avail_in = state->size;
421
if (gz_comp(state, Z_NO_FLUSH) == -1)
422
return state->err;
423
memmove(state->in, state->in + state->size, left);
424
strm->next_in = state->in;
425
strm->avail_in = left;
426
}
427
return len;
428
}
429
430
int ZEXPORTVA gzprintf(gzFile file, const char *format, ...) {
431
va_list va;
432
int ret;
433
434
va_start(va, format);
435
ret = gzvprintf(file, format, va);
436
va_end(va);
437
return ret;
438
}
439
440
#else /* !STDC && !Z_HAVE_STDARG_H */
441
442
/* -- see zlib.h -- */
443
int ZEXPORTVA gzprintf(gzFile file, const char *format, int a1, int a2, int a3,
444
int a4, int a5, int a6, int a7, int a8, int a9, int a10,
445
int a11, int a12, int a13, int a14, int a15, int a16,
446
int a17, int a18, int a19, int a20) {
447
unsigned len, left;
448
char *next;
449
gz_statep state;
450
z_streamp strm;
451
452
/* get internal structure */
453
if (file == NULL)
454
return Z_STREAM_ERROR;
455
state = (gz_statep)file;
456
strm = &(state->strm);
457
458
/* check that can really pass pointer in ints */
459
if (sizeof(int) != sizeof(void *))
460
return Z_STREAM_ERROR;
461
462
/* check that we're writing and that there's no error */
463
if (state->mode != GZ_WRITE || state->err != Z_OK)
464
return Z_STREAM_ERROR;
465
466
/* make sure we have some buffer space */
467
if (state->size == 0 && gz_init(state) == -1)
468
return state->error;
469
470
/* check for seek request */
471
if (state->seek) {
472
state->seek = 0;
473
if (gz_zero(state, state->skip) == -1)
474
return state->error;
475
}
476
477
/* do the printf() into the input buffer, put length in len -- the input
478
buffer is double-sized just for this function, so there is guaranteed to
479
be state->size bytes available after the current contents */
480
if (strm->avail_in == 0)
481
strm->next_in = state->in;
482
next = (char *)(strm->next_in + strm->avail_in);
483
next[state->size - 1] = 0;
484
#ifdef NO_snprintf
485
# ifdef HAS_sprintf_void
486
sprintf(next, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12,
487
a13, a14, a15, a16, a17, a18, a19, a20);
488
for (len = 0; len < size; len++)
489
if (next[len] == 0)
490
break;
491
# else
492
len = sprintf(next, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11,
493
a12, a13, a14, a15, a16, a17, a18, a19, a20);
494
# endif
495
#else
496
# ifdef HAS_snprintf_void
497
snprintf(next, state->size, format, a1, a2, a3, a4, a5, a6, a7, a8, a9,
498
a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20);
499
len = strlen(next);
500
# else
501
len = snprintf(next, state->size, format, a1, a2, a3, a4, a5, a6, a7, a8,
502
a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20);
503
# endif
504
#endif
505
506
/* check that printf() results fit in buffer */
507
if (len == 0 || len >= state->size || next[state->size - 1] != 0)
508
return 0;
509
510
/* update buffer and position, compress first half if past that */
511
strm->avail_in += len;
512
state->x.pos += len;
513
if (strm->avail_in >= state->size) {
514
left = strm->avail_in - state->size;
515
strm->avail_in = state->size;
516
if (gz_comp(state, Z_NO_FLUSH) == -1)
517
return state->err;
518
memmove(state->in, state->in + state->size, left);
519
strm->next_in = state->in;
520
strm->avail_in = left;
521
}
522
return (int)len;
523
}
524
525
#endif
526
527
/* -- see zlib.h -- */
528
int ZEXPORT gzflush(gzFile file, int flush) {
529
gz_statep state;
530
531
/* get internal structure */
532
if (file == NULL)
533
return Z_STREAM_ERROR;
534
state = (gz_statep)file;
535
536
/* check that we're writing and that there's no error */
537
if (state->mode != GZ_WRITE || state->err != Z_OK)
538
return Z_STREAM_ERROR;
539
540
/* check flush parameter */
541
if (flush < 0 || flush > Z_FINISH)
542
return Z_STREAM_ERROR;
543
544
/* check for seek request */
545
if (state->seek) {
546
state->seek = 0;
547
if (gz_zero(state, state->skip) == -1)
548
return state->err;
549
}
550
551
/* compress remaining data with requested flush */
552
(void)gz_comp(state, flush);
553
return state->err;
554
}
555
556
/* -- see zlib.h -- */
557
int ZEXPORT gzsetparams(gzFile file, int level, int strategy) {
558
gz_statep state;
559
z_streamp strm;
560
561
/* get internal structure */
562
if (file == NULL)
563
return Z_STREAM_ERROR;
564
state = (gz_statep)file;
565
strm = &(state->strm);
566
567
/* check that we're writing and that there's no error */
568
if (state->mode != GZ_WRITE || state->err != Z_OK || state->direct)
569
return Z_STREAM_ERROR;
570
571
/* if no change is requested, then do nothing */
572
if (level == state->level && strategy == state->strategy)
573
return Z_OK;
574
575
/* check for seek request */
576
if (state->seek) {
577
state->seek = 0;
578
if (gz_zero(state, state->skip) == -1)
579
return state->err;
580
}
581
582
/* change compression parameters for subsequent input */
583
if (state->size) {
584
/* flush previous input with previous parameters before changing */
585
if (strm->avail_in && gz_comp(state, Z_BLOCK) == -1)
586
return state->err;
587
deflateParams(strm, level, strategy);
588
}
589
state->level = level;
590
state->strategy = strategy;
591
return Z_OK;
592
}
593
594
/* -- see zlib.h -- */
595
int ZEXPORT gzclose_w(gzFile file) {
596
int ret = Z_OK;
597
gz_statep state;
598
599
/* get internal structure */
600
if (file == NULL)
601
return Z_STREAM_ERROR;
602
state = (gz_statep)file;
603
604
/* check that we're writing */
605
if (state->mode != GZ_WRITE)
606
return Z_STREAM_ERROR;
607
608
/* check for seek request */
609
if (state->seek) {
610
state->seek = 0;
611
if (gz_zero(state, state->skip) == -1)
612
ret = state->err;
613
}
614
615
/* flush, free memory, and close file */
616
if (gz_comp(state, Z_FINISH) == -1)
617
ret = state->err;
618
if (state->size) {
619
if (!state->direct) {
620
(void)deflateEnd(&(state->strm));
621
free(state->out);
622
}
623
free(state->in);
624
}
625
gz_error(state, Z_OK, NULL);
626
free(state->path);
627
if (close(state->fd) == -1)
628
ret = Z_ERRNO;
629
free(state);
630
return ret;
631
}
632
633