blob: 85b776a94f784c0dc08e47432e5842bc3febb336 [file] [log] [blame]
Przemyslaw Skibinskif0d7da72016-11-29 18:02:34 +01001/* gzwrite.c contains minimal changes required to be compiled with zlibWrapper:
Yann Collet32fb4072017-08-18 16:52:05 -07002 * - gz_statep was converted to union to work with -Wstrict-aliasing=1 */
3
Przemyslaw Skibinski3805a002017-01-18 12:47:32 +01004 /* gzwrite.c -- zlib functions for writing gzip files
5 * Copyright (C) 2004-2017 Mark Adler
Danielle Rozenblit4dffc352022-12-14 06:58:35 -08006 * For conditions of distribution and use, see https://www.zlib.net/zlib_license.html
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +01007 */
8
Yann Colletda558652018-08-15 16:43:13 -07009#include <assert.h>
10
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +010011#include "gzguts.h"
12
13/* Local functions */
orbea1e09cff2022-07-29 12:22:10 -070014local int gz_init _Z_OF((gz_statep));
15local int gz_comp _Z_OF((gz_statep, int));
16local int gz_zero _Z_OF((gz_statep, z_off64_t));
17local z_size_t gz_write _Z_OF((gz_statep, voidpc, z_size_t));
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +010018
19/* Initialize state for writing a gzip file. Mark initialization by setting
Przemyslaw Skibinski3805a002017-01-18 12:47:32 +010020 state.state->size to non-zero. Return -1 on a memory allocation failure, or 0 on
21 success. */
Ed Maste2ce02902023-12-13 19:54:29 -050022local int gz_init(gz_statep state) {
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +010023 int ret;
Przemyslaw Skibinski0feb24a2016-11-29 16:05:52 +010024 z_streamp strm = &(state.state->strm);
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +010025
Przemyslaw Skibinski3805a002017-01-18 12:47:32 +010026 /* allocate input buffer (double size for gzprintf) */
Yann Colletda558652018-08-15 16:43:13 -070027 state.state->in = (unsigned char*)malloc(state.state->want << 1);
Przemyslaw Skibinski0feb24a2016-11-29 16:05:52 +010028 if (state.state->in == NULL) {
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +010029 gz_error(state, Z_MEM_ERROR, "out of memory");
30 return -1;
31 }
32
33 /* only need output buffer and deflate state if compressing */
Przemyslaw Skibinski0feb24a2016-11-29 16:05:52 +010034 if (!state.state->direct) {
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +010035 /* allocate output buffer */
Yann Colletda558652018-08-15 16:43:13 -070036 state.state->out = (unsigned char*)malloc(state.state->want);
Przemyslaw Skibinski0feb24a2016-11-29 16:05:52 +010037 if (state.state->out == NULL) {
38 free(state.state->in);
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +010039 gz_error(state, Z_MEM_ERROR, "out of memory");
40 return -1;
41 }
42
43 /* allocate deflate memory, set up for gzip compression */
44 strm->zalloc = Z_NULL;
45 strm->zfree = Z_NULL;
46 strm->opaque = Z_NULL;
Przemyslaw Skibinski0feb24a2016-11-29 16:05:52 +010047 ret = deflateInit2(strm, state.state->level, Z_DEFLATED,
48 MAX_WBITS + 16, DEF_MEM_LEVEL, state.state->strategy);
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +010049 if (ret != Z_OK) {
Przemyslaw Skibinski0feb24a2016-11-29 16:05:52 +010050 free(state.state->out);
51 free(state.state->in);
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +010052 gz_error(state, Z_MEM_ERROR, "out of memory");
53 return -1;
54 }
Przemyslaw Skibinski3805a002017-01-18 12:47:32 +010055 strm->next_in = NULL;
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +010056 }
57
58 /* mark state as initialized */
Przemyslaw Skibinski0feb24a2016-11-29 16:05:52 +010059 state.state->size = state.state->want;
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +010060
61 /* initialize write buffer if compressing */
Przemyslaw Skibinski0feb24a2016-11-29 16:05:52 +010062 if (!state.state->direct) {
63 strm->avail_out = state.state->size;
64 strm->next_out = state.state->out;
65 state.state->x.next = strm->next_out;
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +010066 }
Alex Murkoff1d5e9702024-04-13 02:24:14 +070067
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +010068 return 0;
69}
70
71/* Compress whatever is at avail_in and next_in and write to the output file.
Przemyslaw Skibinski3805a002017-01-18 12:47:32 +010072 Return -1 if there is an error writing to the output file or if gz_init()
73 fails to allocate memory, otherwise 0. flush is assumed to be a valid
74 deflate() flush value. If flush is Z_FINISH, then the deflate() state is
75 reset to start a new gzip stream. If gz->direct is true, then simply write
76 to the output file without compressing, and ignore flush. */
Ed Maste2ce02902023-12-13 19:54:29 -050077local int gz_comp(gz_statep state, int flush) {
Przemyslaw Skibinski3805a002017-01-18 12:47:32 +010078 int ret, writ;
79 unsigned have, put, max = ((unsigned)-1 >> 2) + 1;
Przemyslaw Skibinski0feb24a2016-11-29 16:05:52 +010080 z_streamp strm = &(state.state->strm);
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +010081
82 /* allocate memory if this is the first time through */
Przemyslaw Skibinski0feb24a2016-11-29 16:05:52 +010083 if (state.state->size == 0 && gz_init(state) == -1)
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +010084 return -1;
85
86 /* write directly if requested */
Przemyslaw Skibinski0feb24a2016-11-29 16:05:52 +010087 if (state.state->direct) {
Przemyslaw Skibinski3805a002017-01-18 12:47:32 +010088 while (strm->avail_in) {
89 put = strm->avail_in > max ? max : strm->avail_in;
Przemyslaw Skibinskic3a04de2017-01-18 14:36:10 +010090 writ = (int)write(state.state->fd, strm->next_in, put);
Przemyslaw Skibinski3805a002017-01-18 12:47:32 +010091 if (writ < 0) {
92 gz_error(state, Z_ERRNO, zstrerror());
93 return -1;
94 }
95 strm->avail_in -= (unsigned)writ;
96 strm->next_in += writ;
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +010097 }
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +010098 return 0;
99 }
100
101 /* run deflate() on provided input until it produces no more output */
102 ret = Z_OK;
103 do {
104 /* write out current buffer contents if full, or if flushing, but if
105 doing Z_FINISH then don't write until we get to Z_STREAM_END */
106 if (strm->avail_out == 0 || (flush != Z_NO_FLUSH &&
107 (flush != Z_FINISH || ret == Z_STREAM_END))) {
Przemyslaw Skibinski3805a002017-01-18 12:47:32 +0100108 while (strm->next_out > state.state->x.next) {
109 put = strm->next_out - state.state->x.next > (int)max ? max :
110 (unsigned)(strm->next_out - state.state->x.next);
Przemyslaw Skibinskic3a04de2017-01-18 14:36:10 +0100111 writ = (int)write(state.state->fd, state.state->x.next, put);
Przemyslaw Skibinski3805a002017-01-18 12:47:32 +0100112 if (writ < 0) {
113 gz_error(state, Z_ERRNO, zstrerror());
114 return -1;
115 }
116 state.state->x.next += writ;
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100117 }
118 if (strm->avail_out == 0) {
Przemyslaw Skibinski0feb24a2016-11-29 16:05:52 +0100119 strm->avail_out = state.state->size;
120 strm->next_out = state.state->out;
Przemyslaw Skibinski3805a002017-01-18 12:47:32 +0100121 state.state->x.next = state.state->out;
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100122 }
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100123 }
124
125 /* compress */
126 have = strm->avail_out;
127 ret = deflate(strm, flush);
128 if (ret == Z_STREAM_ERROR) {
129 gz_error(state, Z_STREAM_ERROR,
130 "internal error: deflate stream corrupt");
131 return -1;
132 }
133 have -= strm->avail_out;
134 } while (have);
135
136 /* if that completed a deflate stream, allow another to start */
137 if (flush == Z_FINISH)
138 deflateReset(strm);
139
140 /* all done, no errors */
141 return 0;
142}
143
Przemyslaw Skibinski3805a002017-01-18 12:47:32 +0100144/* Compress len zeros to output. Return -1 on a write error or memory
145 allocation failure by gz_comp(), or 0 on success. */
Ed Maste2ce02902023-12-13 19:54:29 -0500146local int gz_zero(gz_statep state, z_off64_t len) {
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100147 int first;
148 unsigned n;
Przemyslaw Skibinski0feb24a2016-11-29 16:05:52 +0100149 z_streamp strm = &(state.state->strm);
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100150
151 /* consume whatever's left in the input buffer */
152 if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1)
153 return -1;
154
155 /* compress len zeros (len guaranteed > 0) */
156 first = 1;
157 while (len) {
Przemyslaw Skibinski0feb24a2016-11-29 16:05:52 +0100158 n = GT_OFF(state.state->size) || (z_off64_t)state.state->size > len ?
159 (unsigned)len : state.state->size;
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100160 if (first) {
Przemyslaw Skibinski0feb24a2016-11-29 16:05:52 +0100161 memset(state.state->in, 0, n);
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100162 first = 0;
163 }
164 strm->avail_in = n;
Przemyslaw Skibinski0feb24a2016-11-29 16:05:52 +0100165 strm->next_in = state.state->in;
166 state.state->x.pos += n;
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100167 if (gz_comp(state, Z_NO_FLUSH) == -1)
168 return -1;
169 len -= n;
170 }
171 return 0;
172}
173
Przemyslaw Skibinski3805a002017-01-18 12:47:32 +0100174/* Write len bytes from buf to file. Return the number of bytes written. If
175 the returned value is less than len, then there was an error. */
Ed Maste2ce02902023-12-13 19:54:29 -0500176local z_size_t gz_write(gz_statep state, voidpc buf, z_size_t len) {
Przemyslaw Skibinski3805a002017-01-18 12:47:32 +0100177 z_size_t put = len;
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100178
179 /* if len is zero, avoid unnecessary operations */
180 if (len == 0)
181 return 0;
182
183 /* allocate memory if this is the first time through */
Przemyslaw Skibinski0feb24a2016-11-29 16:05:52 +0100184 if (state.state->size == 0 && gz_init(state) == -1)
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100185 return 0;
186
187 /* check for seek request */
Przemyslaw Skibinski0feb24a2016-11-29 16:05:52 +0100188 if (state.state->seek) {
189 state.state->seek = 0;
190 if (gz_zero(state, state.state->skip) == -1)
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100191 return 0;
192 }
193
194 /* for small len, copy to input buffer, otherwise compress directly */
Przemyslaw Skibinski0feb24a2016-11-29 16:05:52 +0100195 if (len < state.state->size) {
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100196 /* copy to input buffer, compress when full */
197 do {
Przemyslaw Skibinskic3a04de2017-01-18 14:36:10 +0100198 z_size_t have, copy;
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100199
Przemyslaw Skibinski3805a002017-01-18 12:47:32 +0100200 if (state.state->strm.avail_in == 0)
201 state.state->strm.next_in = state.state->in;
202 have = (unsigned)((state.state->strm.next_in + state.state->strm.avail_in) -
203 state.state->in);
Przemyslaw Skibinski0feb24a2016-11-29 16:05:52 +0100204 copy = state.state->size - have;
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100205 if (copy > len)
206 copy = len;
Przemyslaw Skibinski0feb24a2016-11-29 16:05:52 +0100207 memcpy(state.state->in + have, buf, copy);
Przemyslaw Skibinski3805a002017-01-18 12:47:32 +0100208 state.state->strm.avail_in += copy;
Przemyslaw Skibinski0feb24a2016-11-29 16:05:52 +0100209 state.state->x.pos += copy;
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100210 buf = (const char *)buf + copy;
211 len -= copy;
212 if (len && gz_comp(state, Z_NO_FLUSH) == -1)
213 return 0;
214 } while (len);
215 }
216 else {
217 /* consume whatever's left in the input buffer */
Przemyslaw Skibinski3805a002017-01-18 12:47:32 +0100218 if (state.state->strm.avail_in && gz_comp(state, Z_NO_FLUSH) == -1)
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100219 return 0;
220
221 /* directly compress user buffer to file */
Przemyslaw Skibinski3805a002017-01-18 12:47:32 +0100222 state.state->strm.next_in = (z_const Bytef *)buf;
223 do {
Przemyslaw Skibinskic3a04de2017-01-18 14:36:10 +0100224 z_size_t n = (unsigned)-1;
Przemyslaw Skibinski3805a002017-01-18 12:47:32 +0100225 if (n > len)
226 n = len;
Piotr Paweł Stefaniak71def592024-04-07 13:04:26 +0200227 state.state->strm.avail_in = (uInt)n;
Przemyslaw Skibinski3805a002017-01-18 12:47:32 +0100228 state.state->x.pos += n;
229 if (gz_comp(state, Z_NO_FLUSH) == -1)
230 return 0;
231 len -= n;
232 } while (len);
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100233 }
234
Przemyslaw Skibinski3805a002017-01-18 12:47:32 +0100235 /* input was all buffered or compressed */
236 return put;
237}
238
239/* -- see zlib.h -- */
Ed Maste2ce02902023-12-13 19:54:29 -0500240int ZEXPORT gzwrite(gzFile file, voidpc buf, unsigned len) {
Przemyslaw Skibinski3805a002017-01-18 12:47:32 +0100241 gz_statep state;
242
243 /* get internal structure */
244 if (file == NULL)
245 return 0;
Yann Colletcb18fff2019-09-24 17:50:58 -0700246 state.file = file;
Przemyslaw Skibinski3805a002017-01-18 12:47:32 +0100247
248 /* check that we're writing and that there's no error */
249 if (state.state->mode != GZ_WRITE || state.state->err != Z_OK)
250 return 0;
251
252 /* since an int is returned, make sure len fits in one, otherwise return
253 with an error (this avoids a flaw in the interface) */
254 if ((int)len < 0) {
255 gz_error(state, Z_DATA_ERROR, "requested length does not fit in int");
256 return 0;
257 }
258
259 /* write len bytes from buf (the return value will fit in an int) */
260 return (int)gz_write(state, buf, len);
261}
262
263/* -- see zlib.h -- */
Ed Maste2ce02902023-12-13 19:54:29 -0500264z_size_t ZEXPORT gzfwrite(voidpc buf, z_size_t size, z_size_t nitems,
265 gzFile file) {
Przemyslaw Skibinski3805a002017-01-18 12:47:32 +0100266 z_size_t len;
267 gz_statep state;
268
269 /* get internal structure */
Yann Colletda558652018-08-15 16:43:13 -0700270 assert(size != 0);
Przemyslaw Skibinski3805a002017-01-18 12:47:32 +0100271 if (file == NULL)
272 return 0;
Yann Colletcb18fff2019-09-24 17:50:58 -0700273 state.file = file;
Przemyslaw Skibinski3805a002017-01-18 12:47:32 +0100274
275 /* check that we're writing and that there's no error */
276 if (state.state->mode != GZ_WRITE || state.state->err != Z_OK)
277 return 0;
278
279 /* compute bytes to read -- error on overflow */
280 len = nitems * size;
Yann Colletda558652018-08-15 16:43:13 -0700281 if (size && (len / size != nitems)) {
Przemyslaw Skibinski3805a002017-01-18 12:47:32 +0100282 gz_error(state, Z_STREAM_ERROR, "request does not fit in a size_t");
283 return 0;
284 }
285
286 /* write len bytes to buf, return the number of full items written */
287 return len ? gz_write(state, buf, len) / size : 0;
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100288}
289
290/* -- see zlib.h -- */
Ed Maste2ce02902023-12-13 19:54:29 -0500291int ZEXPORT gzputc(gzFile file, int c) {
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100292 unsigned have;
293 unsigned char buf[1];
294 gz_statep state;
295 z_streamp strm;
296
297 /* get internal structure */
298 if (file == NULL)
299 return -1;
Yann Colletcb18fff2019-09-24 17:50:58 -0700300 state.file = file;
Przemyslaw Skibinski0feb24a2016-11-29 16:05:52 +0100301 strm = &(state.state->strm);
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100302
303 /* check that we're writing and that there's no error */
Przemyslaw Skibinski0feb24a2016-11-29 16:05:52 +0100304 if (state.state->mode != GZ_WRITE || state.state->err != Z_OK)
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100305 return -1;
306
307 /* check for seek request */
Przemyslaw Skibinski0feb24a2016-11-29 16:05:52 +0100308 if (state.state->seek) {
309 state.state->seek = 0;
310 if (gz_zero(state, state.state->skip) == -1)
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100311 return -1;
312 }
313
Przemyslaw Skibinski3805a002017-01-18 12:47:32 +0100314 /* try writing to input buffer for speed (state.state->size == 0 if buffer not
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100315 initialized) */
Przemyslaw Skibinski0feb24a2016-11-29 16:05:52 +0100316 if (state.state->size) {
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100317 if (strm->avail_in == 0)
Przemyslaw Skibinski0feb24a2016-11-29 16:05:52 +0100318 strm->next_in = state.state->in;
319 have = (unsigned)((strm->next_in + strm->avail_in) - state.state->in);
320 if (have < state.state->size) {
Yann Collet9ceb49e2016-12-22 15:26:33 +0100321 state.state->in[have] = (unsigned char)c;
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100322 strm->avail_in++;
Przemyslaw Skibinski0feb24a2016-11-29 16:05:52 +0100323 state.state->x.pos++;
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100324 return c & 0xff;
325 }
326 }
327
328 /* no room in buffer or not initialized, use gz_write() */
Yann Collet9ceb49e2016-12-22 15:26:33 +0100329 buf[0] = (unsigned char)c;
Przemyslaw Skibinski3805a002017-01-18 12:47:32 +0100330 if (gz_write(state, buf, 1) != 1)
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100331 return -1;
332 return c & 0xff;
333}
334
335/* -- see zlib.h -- */
Ed Maste2ce02902023-12-13 19:54:29 -0500336int ZEXPORT gzputs(gzFile file, const char *str) {
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100337 int ret;
Przemyslaw Skibinski3805a002017-01-18 12:47:32 +0100338 z_size_t len;
339 gz_statep state;
340
341 /* get internal structure */
342 if (file == NULL)
343 return -1;
Yann Colletcb18fff2019-09-24 17:50:58 -0700344 state.file = file;
Przemyslaw Skibinski3805a002017-01-18 12:47:32 +0100345
346 /* check that we're writing and that there's no error */
347 if (state.state->mode != GZ_WRITE || state.state->err != Z_OK)
348 return -1;
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100349
350 /* write string */
Przemyslaw Skibinski3805a002017-01-18 12:47:32 +0100351 len = strlen(str);
Przemyslaw Skibinskic3a04de2017-01-18 14:36:10 +0100352 ret = (int)gz_write(state, str, len);
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100353 return ret == 0 && len != 0 ? -1 : ret;
354}
355
356#if defined(STDC) || defined(Z_HAVE_STDARG_H)
357#include <stdarg.h>
358
359/* -- see zlib.h -- */
Ed Maste2ce02902023-12-13 19:54:29 -0500360int ZEXPORTVA gzvprintf(gzFile file, const char *format, va_list va) {
Przemyslaw Skibinski3805a002017-01-18 12:47:32 +0100361 int len;
362 unsigned left;
363 char *next;
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100364 gz_statep state;
365 z_streamp strm;
366
367 /* get internal structure */
368 if (file == NULL)
Przemyslaw Skibinski3805a002017-01-18 12:47:32 +0100369 return Z_STREAM_ERROR;
Yann Colletcb18fff2019-09-24 17:50:58 -0700370 state.file = file;
Przemyslaw Skibinski0feb24a2016-11-29 16:05:52 +0100371 strm = &(state.state->strm);
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100372
373 /* check that we're writing and that there's no error */
Przemyslaw Skibinski0feb24a2016-11-29 16:05:52 +0100374 if (state.state->mode != GZ_WRITE || state.state->err != Z_OK)
Przemyslaw Skibinski3805a002017-01-18 12:47:32 +0100375 return Z_STREAM_ERROR;
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100376
377 /* make sure we have some buffer space */
Przemyslaw Skibinski0feb24a2016-11-29 16:05:52 +0100378 if (state.state->size == 0 && gz_init(state) == -1)
Przemyslaw Skibinski3805a002017-01-18 12:47:32 +0100379 return state.state->err;
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100380
381 /* check for seek request */
Przemyslaw Skibinski0feb24a2016-11-29 16:05:52 +0100382 if (state.state->seek) {
383 state.state->seek = 0;
384 if (gz_zero(state, state.state->skip) == -1)
Przemyslaw Skibinski3805a002017-01-18 12:47:32 +0100385 return state.state->err;
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100386 }
387
Przemyslaw Skibinski3805a002017-01-18 12:47:32 +0100388 /* do the printf() into the input buffer, put length in len -- the input
389 buffer is double-sized just for this function, so there is guaranteed to
390 be state.state->size bytes available after the current contents */
391 if (strm->avail_in == 0)
392 strm->next_in = state.state->in;
393 next = (char *)(state.state->in + (strm->next_in - state.state->in) + strm->avail_in);
394 next[state.state->size - 1] = 0;
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100395#ifdef NO_vsnprintf
396# ifdef HAS_vsprintf_void
Przemyslaw Skibinski3805a002017-01-18 12:47:32 +0100397 (void)vsprintf(next, format, va);
398 for (len = 0; len < state.state->size; len++)
399 if (next[len] == 0) break;
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100400# else
Przemyslaw Skibinski3805a002017-01-18 12:47:32 +0100401 len = vsprintf(next, format, va);
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100402# endif
403#else
404# ifdef HAS_vsnprintf_void
Przemyslaw Skibinski3805a002017-01-18 12:47:32 +0100405 (void)vsnprintf(next, state.state->size, format, va);
406 len = strlen(next);
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100407# else
Przemyslaw Skibinski3805a002017-01-18 12:47:32 +0100408 len = vsnprintf(next, state.state->size, format, va);
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100409# endif
410#endif
411
412 /* check that printf() results fit in buffer */
Przemyslaw Skibinski3805a002017-01-18 12:47:32 +0100413 if (len == 0 || (unsigned)len >= state.state->size || next[state.state->size - 1] != 0)
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100414 return 0;
415
Przemyslaw Skibinski3805a002017-01-18 12:47:32 +0100416 /* update buffer and position, compress first half if past that */
417 strm->avail_in += (unsigned)len;
Przemyslaw Skibinski0feb24a2016-11-29 16:05:52 +0100418 state.state->x.pos += len;
Przemyslaw Skibinski3805a002017-01-18 12:47:32 +0100419 if (strm->avail_in >= state.state->size) {
420 left = strm->avail_in - state.state->size;
421 strm->avail_in = state.state->size;
422 if (gz_comp(state, Z_NO_FLUSH) == -1)
423 return state.state->err;
424 memcpy(state.state->in, state.state->in + state.state->size, left);
425 strm->next_in = state.state->in;
426 strm->avail_in = left;
427 }
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100428 return len;
429}
430
Ed Maste2ce02902023-12-13 19:54:29 -0500431int ZEXPORTVA gzprintf(gzFile file, const char *format, ...) {
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100432 va_list va;
433 int ret;
434
435 va_start(va, format);
436 ret = gzvprintf(file, format, va);
437 va_end(va);
438 return ret;
439}
440
441#else /* !STDC && !Z_HAVE_STDARG_H */
442
443/* -- see zlib.h -- */
Ed Maste2ce02902023-12-13 19:54:29 -0500444int ZEXPORTVA gzprintf(gzFile file, const char *format, int a1, int a2, int a3,
445 int a4, int a5, int a6, int a7, int a8, int a9, int a10,
446 int a11, int a12, int a13, int a14, int a15, int a16,
447 int a17, int a18, int a19, int a20) {
Przemyslaw Skibinski3805a002017-01-18 12:47:32 +0100448 unsigned len, left;
449 char *next;
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100450 gz_statep state;
451 z_streamp strm;
452
453 /* get internal structure */
454 if (file == NULL)
Przemyslaw Skibinski3805a002017-01-18 12:47:32 +0100455 return Z_STREAM_ERROR;
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100456 state = (gz_statep)file;
Przemyslaw Skibinski0feb24a2016-11-29 16:05:52 +0100457 strm = &(state.state->strm);
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100458
459 /* check that can really pass pointer in ints */
460 if (sizeof(int) != sizeof(void *))
Przemyslaw Skibinski3805a002017-01-18 12:47:32 +0100461 return Z_STREAM_ERROR;
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100462
463 /* check that we're writing and that there's no error */
Przemyslaw Skibinski0feb24a2016-11-29 16:05:52 +0100464 if (state.state->mode != GZ_WRITE || state.state->err != Z_OK)
Przemyslaw Skibinski3805a002017-01-18 12:47:32 +0100465 return Z_STREAM_ERROR;
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100466
467 /* make sure we have some buffer space */
Przemyslaw Skibinski0feb24a2016-11-29 16:05:52 +0100468 if (state.state->size == 0 && gz_init(state) == -1)
Przemyslaw Skibinski3805a002017-01-18 12:47:32 +0100469 return state.state->error;
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100470
471 /* check for seek request */
Przemyslaw Skibinski0feb24a2016-11-29 16:05:52 +0100472 if (state.state->seek) {
473 state.state->seek = 0;
474 if (gz_zero(state, state.state->skip) == -1)
Przemyslaw Skibinski3805a002017-01-18 12:47:32 +0100475 return state.state->error;
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100476 }
477
Przemyslaw Skibinski3805a002017-01-18 12:47:32 +0100478 /* do the printf() into the input buffer, put length in len -- the input
479 buffer is double-sized just for this function, so there is guaranteed to
480 be state.state->size bytes available after the current contents */
481 if (strm->avail_in == 0)
482 strm->next_in = state.state->in;
483 next = (char *)(strm->next_in + strm->avail_in);
484 next[state.state->size - 1] = 0;
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100485#ifdef NO_snprintf
486# ifdef HAS_sprintf_void
Przemyslaw Skibinski3805a002017-01-18 12:47:32 +0100487 sprintf(next, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12,
488 a13, a14, a15, a16, a17, a18, a19, a20);
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100489 for (len = 0; len < size; len++)
Przemyslaw Skibinski3805a002017-01-18 12:47:32 +0100490 if (next[len] == 0)
491 break;
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100492# else
Przemyslaw Skibinski3805a002017-01-18 12:47:32 +0100493 len = sprintf(next, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11,
494 a12, a13, a14, a15, a16, a17, a18, a19, a20);
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100495# endif
496#else
497# ifdef HAS_snprintf_void
Przemyslaw Skibinski3805a002017-01-18 12:47:32 +0100498 snprintf(next, state.state->size, format, a1, a2, a3, a4, a5, a6, a7, a8, a9,
499 a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20);
500 len = strlen(next);
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100501# else
Przemyslaw Skibinski3805a002017-01-18 12:47:32 +0100502 len = snprintf(next, state.state->size, format, a1, a2, a3, a4, a5, a6, a7, a8,
503 a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20);
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100504# endif
505#endif
506
507 /* check that printf() results fit in buffer */
Przemyslaw Skibinski3805a002017-01-18 12:47:32 +0100508 if (len == 0 || len >= state.state->size || next[state.state->size - 1] != 0)
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100509 return 0;
510
Przemyslaw Skibinski3805a002017-01-18 12:47:32 +0100511 /* update buffer and position, compress first half if past that */
512 strm->avail_in += len;
Przemyslaw Skibinski0feb24a2016-11-29 16:05:52 +0100513 state.state->x.pos += len;
Przemyslaw Skibinski3805a002017-01-18 12:47:32 +0100514 if (strm->avail_in >= state.state->size) {
515 left = strm->avail_in - state.state->size;
516 strm->avail_in = state.state->size;
517 if (gz_comp(state, Z_NO_FLUSH) == -1)
518 return state.state->err;
519 memcpy(state.state->in, state.state->in + state.state->size, left);
520 strm->next_in = state.state->in;
521 strm->avail_in = left;
522 }
523 return (int)len;
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100524}
525
526#endif
527
528/* -- see zlib.h -- */
Ed Maste2ce02902023-12-13 19:54:29 -0500529int ZEXPORT gzflush(gzFile file, int flush) {
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100530 gz_statep state;
531
532 /* get internal structure */
533 if (file == NULL)
Przemyslaw Skibinski3805a002017-01-18 12:47:32 +0100534 return Z_STREAM_ERROR;
Yann Colletcb18fff2019-09-24 17:50:58 -0700535 state.file = file;
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100536
537 /* check that we're writing and that there's no error */
Przemyslaw Skibinski0feb24a2016-11-29 16:05:52 +0100538 if (state.state->mode != GZ_WRITE || state.state->err != Z_OK)
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100539 return Z_STREAM_ERROR;
540
541 /* check flush parameter */
542 if (flush < 0 || flush > Z_FINISH)
543 return Z_STREAM_ERROR;
544
545 /* check for seek request */
Przemyslaw Skibinski0feb24a2016-11-29 16:05:52 +0100546 if (state.state->seek) {
547 state.state->seek = 0;
548 if (gz_zero(state, state.state->skip) == -1)
Przemyslaw Skibinski3805a002017-01-18 12:47:32 +0100549 return state.state->err;
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100550 }
551
552 /* compress remaining data with requested flush */
Przemyslaw Skibinski3805a002017-01-18 12:47:32 +0100553 (void)gz_comp(state, flush);
Przemyslaw Skibinski0feb24a2016-11-29 16:05:52 +0100554 return state.state->err;
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100555}
556
557/* -- see zlib.h -- */
Ed Maste2ce02902023-12-13 19:54:29 -0500558int ZEXPORT gzsetparams(gzFile file, int level, int strategy) {
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100559 gz_statep state;
560 z_streamp strm;
561
562 /* get internal structure */
563 if (file == NULL)
564 return Z_STREAM_ERROR;
Yann Colletcb18fff2019-09-24 17:50:58 -0700565 state.file = file;
Przemyslaw Skibinski0feb24a2016-11-29 16:05:52 +0100566 strm = &(state.state->strm);
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100567
568 /* check that we're writing and that there's no error */
Przemyslaw Skibinski0feb24a2016-11-29 16:05:52 +0100569 if (state.state->mode != GZ_WRITE || state.state->err != Z_OK)
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100570 return Z_STREAM_ERROR;
571
572 /* if no change is requested, then do nothing */
Przemyslaw Skibinski0feb24a2016-11-29 16:05:52 +0100573 if (level == state.state->level && strategy == state.state->strategy)
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100574 return Z_OK;
575
576 /* check for seek request */
Przemyslaw Skibinski0feb24a2016-11-29 16:05:52 +0100577 if (state.state->seek) {
578 state.state->seek = 0;
579 if (gz_zero(state, state.state->skip) == -1)
Przemyslaw Skibinski3805a002017-01-18 12:47:32 +0100580 return state.state->err;
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100581 }
582
583 /* change compression parameters for subsequent input */
Przemyslaw Skibinski0feb24a2016-11-29 16:05:52 +0100584 if (state.state->size) {
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100585 /* flush previous input with previous parameters before changing */
Przemyslaw Skibinski3805a002017-01-18 12:47:32 +0100586 if (strm->avail_in && gz_comp(state, Z_BLOCK) == -1)
Przemyslaw Skibinski0feb24a2016-11-29 16:05:52 +0100587 return state.state->err;
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100588 deflateParams(strm, level, strategy);
589 }
Przemyslaw Skibinski0feb24a2016-11-29 16:05:52 +0100590 state.state->level = level;
591 state.state->strategy = strategy;
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100592 return Z_OK;
593}
594
595/* -- see zlib.h -- */
Ed Maste2ce02902023-12-13 19:54:29 -0500596int ZEXPORT gzclose_w(gzFile file) {
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100597 int ret = Z_OK;
598 gz_statep state;
599
600 /* get internal structure */
601 if (file == NULL)
602 return Z_STREAM_ERROR;
Yann Colletcb18fff2019-09-24 17:50:58 -0700603 state.file = file;
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100604
605 /* check that we're writing */
Przemyslaw Skibinski0feb24a2016-11-29 16:05:52 +0100606 if (state.state->mode != GZ_WRITE)
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100607 return Z_STREAM_ERROR;
608
609 /* check for seek request */
Przemyslaw Skibinski0feb24a2016-11-29 16:05:52 +0100610 if (state.state->seek) {
611 state.state->seek = 0;
612 if (gz_zero(state, state.state->skip) == -1)
613 ret = state.state->err;
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100614 }
615
616 /* flush, free memory, and close file */
617 if (gz_comp(state, Z_FINISH) == -1)
Przemyslaw Skibinski0feb24a2016-11-29 16:05:52 +0100618 ret = state.state->err;
619 if (state.state->size) {
620 if (!state.state->direct) {
621 (void)deflateEnd(&(state.state->strm));
622 free(state.state->out);
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100623 }
Przemyslaw Skibinski0feb24a2016-11-29 16:05:52 +0100624 free(state.state->in);
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100625 }
626 gz_error(state, Z_OK, NULL);
Przemyslaw Skibinski0feb24a2016-11-29 16:05:52 +0100627 free(state.state->path);
628 if (close(state.state->fd) == -1)
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100629 ret = Z_ERRNO;
Przemyslaw Skibinski0feb24a2016-11-29 16:05:52 +0100630 free(state.state);
Przemyslaw Skibinski3bf9a722016-11-24 18:26:30 +0100631 return ret;
632}