1275793eaSopenharmony_ci/* gzwrite.c -- zlib functions for writing gzip files
2275793eaSopenharmony_ci * Copyright (C) 2004-2019 Mark Adler
3275793eaSopenharmony_ci * For conditions of distribution and use, see copyright notice in zlib.h
4275793eaSopenharmony_ci */
5275793eaSopenharmony_ci
6275793eaSopenharmony_ci#include "gzguts.h"
7275793eaSopenharmony_ci#include <sys/types.h>
8275793eaSopenharmony_ci#include <unistd.h>
9275793eaSopenharmony_ci
10275793eaSopenharmony_ci/* Initialize state for writing a gzip file.  Mark initialization by setting
11275793eaSopenharmony_ci   state->size to non-zero.  Return -1 on a memory allocation failure, or 0 on
12275793eaSopenharmony_ci   success. */
13275793eaSopenharmony_cilocal int gz_init(gz_statep state)
14275793eaSopenharmony_ci{
15275793eaSopenharmony_ci    int ret;
16275793eaSopenharmony_ci    z_streamp strm = &(state->strm);
17275793eaSopenharmony_ci
18275793eaSopenharmony_ci    /* allocate input buffer (double size for gzprintf) */
19275793eaSopenharmony_ci    state->in = (unsigned char *)malloc(state->want << 1);
20275793eaSopenharmony_ci    if (state->in == NULL) {
21275793eaSopenharmony_ci        gz_error(state, Z_MEM_ERROR, "out of memory");
22275793eaSopenharmony_ci        return -1;
23275793eaSopenharmony_ci    }
24275793eaSopenharmony_ci
25275793eaSopenharmony_ci    /* only need output buffer and deflate state if compressing */
26275793eaSopenharmony_ci    if (!state->direct) {
27275793eaSopenharmony_ci        /* allocate output buffer */
28275793eaSopenharmony_ci        state->out = (unsigned char *)malloc(state->want);
29275793eaSopenharmony_ci        if (state->out == NULL) {
30275793eaSopenharmony_ci            free(state->in);
31275793eaSopenharmony_ci            gz_error(state, Z_MEM_ERROR, "out of memory");
32275793eaSopenharmony_ci            return -1;
33275793eaSopenharmony_ci        }
34275793eaSopenharmony_ci
35275793eaSopenharmony_ci        /* allocate deflate memory, set up for gzip compression */
36275793eaSopenharmony_ci        strm->zalloc = Z_NULL;
37275793eaSopenharmony_ci        strm->zfree = Z_NULL;
38275793eaSopenharmony_ci        strm->opaque = Z_NULL;
39275793eaSopenharmony_ci        ret = deflateInit2(strm, state->level, Z_DEFLATED,
40275793eaSopenharmony_ci                           MAX_WBITS + 16, DEF_MEM_LEVEL, state->strategy);
41275793eaSopenharmony_ci        if (ret != Z_OK) {
42275793eaSopenharmony_ci            free(state->out);
43275793eaSopenharmony_ci            free(state->in);
44275793eaSopenharmony_ci            gz_error(state, Z_MEM_ERROR, "out of memory");
45275793eaSopenharmony_ci            return -1;
46275793eaSopenharmony_ci        }
47275793eaSopenharmony_ci        strm->next_in = NULL;
48275793eaSopenharmony_ci    }
49275793eaSopenharmony_ci
50275793eaSopenharmony_ci    /* mark state as initialized */
51275793eaSopenharmony_ci    state->size = state->want;
52275793eaSopenharmony_ci
53275793eaSopenharmony_ci    /* initialize write buffer if compressing */
54275793eaSopenharmony_ci    if (!state->direct) {
55275793eaSopenharmony_ci        strm->avail_out = state->size;
56275793eaSopenharmony_ci        strm->next_out = state->out;
57275793eaSopenharmony_ci        state->x.next = strm->next_out;
58275793eaSopenharmony_ci    }
59275793eaSopenharmony_ci    return 0;
60275793eaSopenharmony_ci}
61275793eaSopenharmony_ci
62275793eaSopenharmony_ci/* Compress whatever is at avail_in and next_in and write to the output file.
63275793eaSopenharmony_ci   Return -1 if there is an error writing to the output file or if gz_init()
64275793eaSopenharmony_ci   fails to allocate memory, otherwise 0.  flush is assumed to be a valid
65275793eaSopenharmony_ci   deflate() flush value.  If flush is Z_FINISH, then the deflate() state is
66275793eaSopenharmony_ci   reset to start a new gzip stream.  If gz->direct is true, then simply write
67275793eaSopenharmony_ci   to the output file without compressing, and ignore flush. */
68275793eaSopenharmony_cilocal int gz_comp(gz_statep state, int flush)
69275793eaSopenharmony_ci{
70275793eaSopenharmony_ci    int ret, writ;
71275793eaSopenharmony_ci    unsigned have, put, max = ((unsigned)-1 >> 2) + 1;
72275793eaSopenharmony_ci    z_streamp strm = &(state->strm);
73275793eaSopenharmony_ci
74275793eaSopenharmony_ci    /* allocate memory if this is the first time through */
75275793eaSopenharmony_ci    if (state->size == 0 && gz_init(state) == -1)
76275793eaSopenharmony_ci        return -1;
77275793eaSopenharmony_ci
78275793eaSopenharmony_ci    /* write directly if requested */
79275793eaSopenharmony_ci    if (state->direct) {
80275793eaSopenharmony_ci        while (strm->avail_in) {
81275793eaSopenharmony_ci            put = strm->avail_in > max ? max : strm->avail_in;
82275793eaSopenharmony_ci            writ = write(state->fd, strm->next_in, put);
83275793eaSopenharmony_ci            if (writ < 0) {
84275793eaSopenharmony_ci                gz_error(state, Z_ERRNO, zstrerror());
85275793eaSopenharmony_ci                return -1;
86275793eaSopenharmony_ci            }
87275793eaSopenharmony_ci            strm->avail_in -= (unsigned)writ;
88275793eaSopenharmony_ci            strm->next_in += writ;
89275793eaSopenharmony_ci        }
90275793eaSopenharmony_ci        return 0;
91275793eaSopenharmony_ci    }
92275793eaSopenharmony_ci
93275793eaSopenharmony_ci    /* check for a pending reset */
94275793eaSopenharmony_ci    if (state->reset) {
95275793eaSopenharmony_ci        /* don't start a new gzip member unless there is data to write */
96275793eaSopenharmony_ci        if (strm->avail_in == 0)
97275793eaSopenharmony_ci            return 0;
98275793eaSopenharmony_ci        deflateReset(strm);
99275793eaSopenharmony_ci        state->reset = 0;
100275793eaSopenharmony_ci    }
101275793eaSopenharmony_ci
102275793eaSopenharmony_ci    /* run deflate() on provided input until it produces no more output */
103275793eaSopenharmony_ci    ret = Z_OK;
104275793eaSopenharmony_ci    do {
105275793eaSopenharmony_ci        /* write out current buffer contents if full, or if flushing, but if
106275793eaSopenharmony_ci           doing Z_FINISH then don't write until we get to Z_STREAM_END */
107275793eaSopenharmony_ci        if (strm->avail_out == 0 || (flush != Z_NO_FLUSH &&
108275793eaSopenharmony_ci            (flush != Z_FINISH || ret == Z_STREAM_END))) {
109275793eaSopenharmony_ci            while (strm->next_out > state->x.next) {
110275793eaSopenharmony_ci                put = strm->next_out - state->x.next > (int)max ? max :
111275793eaSopenharmony_ci                      (unsigned)(strm->next_out - state->x.next);
112275793eaSopenharmony_ci                writ = write(state->fd, state->x.next, put);
113275793eaSopenharmony_ci                if (writ < 0) {
114275793eaSopenharmony_ci                    gz_error(state, Z_ERRNO, zstrerror());
115275793eaSopenharmony_ci                    return -1;
116275793eaSopenharmony_ci                }
117275793eaSopenharmony_ci                state->x.next += writ;
118275793eaSopenharmony_ci            }
119275793eaSopenharmony_ci            if (strm->avail_out == 0) {
120275793eaSopenharmony_ci                strm->avail_out = state->size;
121275793eaSopenharmony_ci                strm->next_out = state->out;
122275793eaSopenharmony_ci                state->x.next = state->out;
123275793eaSopenharmony_ci            }
124275793eaSopenharmony_ci        }
125275793eaSopenharmony_ci
126275793eaSopenharmony_ci        /* compress */
127275793eaSopenharmony_ci        have = strm->avail_out;
128275793eaSopenharmony_ci        ret = deflate(strm, flush);
129275793eaSopenharmony_ci        if (ret == Z_STREAM_ERROR) {
130275793eaSopenharmony_ci            gz_error(state, Z_STREAM_ERROR,
131275793eaSopenharmony_ci                      "internal error: deflate stream corrupt");
132275793eaSopenharmony_ci            return -1;
133275793eaSopenharmony_ci        }
134275793eaSopenharmony_ci        have -= strm->avail_out;
135275793eaSopenharmony_ci    } while (have);
136275793eaSopenharmony_ci
137275793eaSopenharmony_ci    /* if that completed a deflate stream, allow another to start */
138275793eaSopenharmony_ci    if (flush == Z_FINISH)
139275793eaSopenharmony_ci        state->reset = 1;
140275793eaSopenharmony_ci
141275793eaSopenharmony_ci    /* all done, no errors */
142275793eaSopenharmony_ci    return 0;
143275793eaSopenharmony_ci}
144275793eaSopenharmony_ci
145275793eaSopenharmony_ci/* Compress len zeros to output.  Return -1 on a write error or memory
146275793eaSopenharmony_ci   allocation failure by gz_comp(), or 0 on success. */
147275793eaSopenharmony_cilocal int gz_zero(gz_statep state, z_off64_t len)
148275793eaSopenharmony_ci{
149275793eaSopenharmony_ci    int first;
150275793eaSopenharmony_ci    unsigned n;
151275793eaSopenharmony_ci    z_streamp strm = &(state->strm);
152275793eaSopenharmony_ci
153275793eaSopenharmony_ci    /* consume whatever's left in the input buffer */
154275793eaSopenharmony_ci    if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1)
155275793eaSopenharmony_ci        return -1;
156275793eaSopenharmony_ci
157275793eaSopenharmony_ci    /* compress len zeros (len guaranteed > 0) */
158275793eaSopenharmony_ci    first = 1;
159275793eaSopenharmony_ci    while (len) {
160275793eaSopenharmony_ci        n = GT_OFF(state->size) || (z_off64_t)state->size > len ?
161275793eaSopenharmony_ci            (unsigned)len : state->size;
162275793eaSopenharmony_ci        if (first) {
163275793eaSopenharmony_ci            memset(state->in, 0, n);
164275793eaSopenharmony_ci            first = 0;
165275793eaSopenharmony_ci        }
166275793eaSopenharmony_ci        strm->avail_in = n;
167275793eaSopenharmony_ci        strm->next_in = state->in;
168275793eaSopenharmony_ci        state->x.pos += n;
169275793eaSopenharmony_ci        if (gz_comp(state, Z_NO_FLUSH) == -1)
170275793eaSopenharmony_ci            return -1;
171275793eaSopenharmony_ci        len -= n;
172275793eaSopenharmony_ci    }
173275793eaSopenharmony_ci    return 0;
174275793eaSopenharmony_ci}
175275793eaSopenharmony_ci
176275793eaSopenharmony_ci/* Write len bytes from buf to file.  Return the number of bytes written.  If
177275793eaSopenharmony_ci   the returned value is less than len, then there was an error. */
178275793eaSopenharmony_cilocal z_size_t gz_write(gz_statep state, voidpc buf, z_size_t len)
179275793eaSopenharmony_ci{
180275793eaSopenharmony_ci    z_size_t put = len;
181275793eaSopenharmony_ci
182275793eaSopenharmony_ci    /* if len is zero, avoid unnecessary operations */
183275793eaSopenharmony_ci    if (len == 0)
184275793eaSopenharmony_ci        return 0;
185275793eaSopenharmony_ci
186275793eaSopenharmony_ci    /* allocate memory if this is the first time through */
187275793eaSopenharmony_ci    if (state->size == 0 && gz_init(state) == -1)
188275793eaSopenharmony_ci        return 0;
189275793eaSopenharmony_ci
190275793eaSopenharmony_ci    /* check for seek request */
191275793eaSopenharmony_ci    if (state->seek) {
192275793eaSopenharmony_ci        state->seek = 0;
193275793eaSopenharmony_ci        if (gz_zero(state, state->skip) == -1)
194275793eaSopenharmony_ci            return 0;
195275793eaSopenharmony_ci    }
196275793eaSopenharmony_ci
197275793eaSopenharmony_ci    /* for small len, copy to input buffer, otherwise compress directly */
198275793eaSopenharmony_ci    if (len < state->size) {
199275793eaSopenharmony_ci        /* copy to input buffer, compress when full */
200275793eaSopenharmony_ci        do {
201275793eaSopenharmony_ci            unsigned have, copy;
202275793eaSopenharmony_ci
203275793eaSopenharmony_ci            if (state->strm.avail_in == 0)
204275793eaSopenharmony_ci                state->strm.next_in = state->in;
205275793eaSopenharmony_ci            have = (unsigned)((state->strm.next_in + state->strm.avail_in) -
206275793eaSopenharmony_ci                              state->in);
207275793eaSopenharmony_ci            copy = state->size - have;
208275793eaSopenharmony_ci            if (copy > len)
209275793eaSopenharmony_ci                copy = (unsigned)len;
210275793eaSopenharmony_ci            memcpy(state->in + have, buf, copy);
211275793eaSopenharmony_ci            state->strm.avail_in += copy;
212275793eaSopenharmony_ci            state->x.pos += copy;
213275793eaSopenharmony_ci            buf = (const char *)buf + copy;
214275793eaSopenharmony_ci            len -= copy;
215275793eaSopenharmony_ci            if (len && gz_comp(state, Z_NO_FLUSH) == -1)
216275793eaSopenharmony_ci                return 0;
217275793eaSopenharmony_ci        } while (len);
218275793eaSopenharmony_ci    }
219275793eaSopenharmony_ci    else {
220275793eaSopenharmony_ci        /* consume whatever's left in the input buffer */
221275793eaSopenharmony_ci        if (state->strm.avail_in && gz_comp(state, Z_NO_FLUSH) == -1)
222275793eaSopenharmony_ci            return 0;
223275793eaSopenharmony_ci
224275793eaSopenharmony_ci        /* directly compress user buffer to file */
225275793eaSopenharmony_ci        state->strm.next_in = (z_const Bytef *)buf;
226275793eaSopenharmony_ci        do {
227275793eaSopenharmony_ci            unsigned n = (unsigned)-1;
228275793eaSopenharmony_ci            if (n > len)
229275793eaSopenharmony_ci                n = (unsigned)len;
230275793eaSopenharmony_ci            state->strm.avail_in = n;
231275793eaSopenharmony_ci            state->x.pos += n;
232275793eaSopenharmony_ci            if (gz_comp(state, Z_NO_FLUSH) == -1)
233275793eaSopenharmony_ci                return 0;
234275793eaSopenharmony_ci            len -= n;
235275793eaSopenharmony_ci        } while (len);
236275793eaSopenharmony_ci    }
237275793eaSopenharmony_ci
238275793eaSopenharmony_ci    /* input was all buffered or compressed */
239275793eaSopenharmony_ci    return put;
240275793eaSopenharmony_ci}
241275793eaSopenharmony_ci
242275793eaSopenharmony_ci/* -- see zlib.h -- */
243275793eaSopenharmony_ciint ZEXPORT gzwrite(gzFile file, voidpc buf, unsigned len) {
244275793eaSopenharmony_ci    gz_statep state;
245275793eaSopenharmony_ci
246275793eaSopenharmony_ci    /* get internal structure */
247275793eaSopenharmony_ci    if (file == NULL)
248275793eaSopenharmony_ci        return 0;
249275793eaSopenharmony_ci    state = (gz_statep)file;
250275793eaSopenharmony_ci
251275793eaSopenharmony_ci    /* check that we're writing and that there's no error */
252275793eaSopenharmony_ci    if (state->mode != GZ_WRITE || state->err != Z_OK)
253275793eaSopenharmony_ci        return 0;
254275793eaSopenharmony_ci
255275793eaSopenharmony_ci    /* since an int is returned, make sure len fits in one, otherwise return
256275793eaSopenharmony_ci       with an error (this avoids a flaw in the interface) */
257275793eaSopenharmony_ci    if ((int)len < 0) {
258275793eaSopenharmony_ci        gz_error(state, Z_DATA_ERROR, "requested length does not fit in int");
259275793eaSopenharmony_ci        return 0;
260275793eaSopenharmony_ci    }
261275793eaSopenharmony_ci
262275793eaSopenharmony_ci    /* write len bytes from buf (the return value will fit in an int) */
263275793eaSopenharmony_ci    return (int)gz_write(state, buf, len);
264275793eaSopenharmony_ci}
265275793eaSopenharmony_ci
266275793eaSopenharmony_ci/* -- see zlib.h -- */
267275793eaSopenharmony_ciz_size_t ZEXPORT gzfwrite(voidpc buf, z_size_t size, z_size_t nitems,
268275793eaSopenharmony_ci                          gzFile file)
269275793eaSopenharmony_ci{
270275793eaSopenharmony_ci    z_size_t len;
271275793eaSopenharmony_ci    gz_statep state;
272275793eaSopenharmony_ci
273275793eaSopenharmony_ci    /* get internal structure */
274275793eaSopenharmony_ci    if (file == NULL)
275275793eaSopenharmony_ci        return 0;
276275793eaSopenharmony_ci    state = (gz_statep)file;
277275793eaSopenharmony_ci
278275793eaSopenharmony_ci    /* check that we're writing and that there's no error */
279275793eaSopenharmony_ci    if (state->mode != GZ_WRITE || state->err != Z_OK)
280275793eaSopenharmony_ci        return 0;
281275793eaSopenharmony_ci
282275793eaSopenharmony_ci    /* compute bytes to read -- error on overflow */
283275793eaSopenharmony_ci    len = nitems * size;
284275793eaSopenharmony_ci    if (size && len / size != nitems) {
285275793eaSopenharmony_ci        gz_error(state, Z_STREAM_ERROR, "request does not fit in a size_t");
286275793eaSopenharmony_ci        return 0;
287275793eaSopenharmony_ci    }
288275793eaSopenharmony_ci
289275793eaSopenharmony_ci    /* write len bytes to buf, return the number of full items written */
290275793eaSopenharmony_ci    return len ? gz_write(state, buf, len) / size : 0;
291275793eaSopenharmony_ci}
292275793eaSopenharmony_ci
293275793eaSopenharmony_ci/* -- see zlib.h -- */
294275793eaSopenharmony_ciint ZEXPORT gzputc(gzFile file, int c) {
295275793eaSopenharmony_ci    unsigned have;
296275793eaSopenharmony_ci    unsigned char buf[1];
297275793eaSopenharmony_ci    gz_statep state;
298275793eaSopenharmony_ci    z_streamp strm;
299275793eaSopenharmony_ci
300275793eaSopenharmony_ci    /* get internal structure */
301275793eaSopenharmony_ci    if (file == NULL)
302275793eaSopenharmony_ci        return -1;
303275793eaSopenharmony_ci    state = (gz_statep)file;
304275793eaSopenharmony_ci    strm = &(state->strm);
305275793eaSopenharmony_ci
306275793eaSopenharmony_ci    /* check that we're writing and that there's no error */
307275793eaSopenharmony_ci    if (state->mode != GZ_WRITE || state->err != Z_OK)
308275793eaSopenharmony_ci        return -1;
309275793eaSopenharmony_ci
310275793eaSopenharmony_ci    /* check for seek request */
311275793eaSopenharmony_ci    if (state->seek) {
312275793eaSopenharmony_ci        state->seek = 0;
313275793eaSopenharmony_ci        if (gz_zero(state, state->skip) == -1)
314275793eaSopenharmony_ci            return -1;
315275793eaSopenharmony_ci    }
316275793eaSopenharmony_ci
317275793eaSopenharmony_ci    /* try writing to input buffer for speed (state->size == 0 if buffer not
318275793eaSopenharmony_ci       initialized) */
319275793eaSopenharmony_ci    if (state->size) {
320275793eaSopenharmony_ci        if (strm->avail_in == 0)
321275793eaSopenharmony_ci            strm->next_in = state->in;
322275793eaSopenharmony_ci        have = (unsigned)((strm->next_in + strm->avail_in) - state->in);
323275793eaSopenharmony_ci        if (have < state->size) {
324275793eaSopenharmony_ci            state->in[have] = (unsigned char)c;
325275793eaSopenharmony_ci            strm->avail_in++;
326275793eaSopenharmony_ci            state->x.pos++;
327275793eaSopenharmony_ci            return c & 0xff;
328275793eaSopenharmony_ci        }
329275793eaSopenharmony_ci    }
330275793eaSopenharmony_ci
331275793eaSopenharmony_ci    /* no room in buffer or not initialized, use gz_write() */
332275793eaSopenharmony_ci    buf[0] = (unsigned char)c;
333275793eaSopenharmony_ci    if (gz_write(state, buf, 1) != 1)
334275793eaSopenharmony_ci        return -1;
335275793eaSopenharmony_ci    return c & 0xff;
336275793eaSopenharmony_ci}
337275793eaSopenharmony_ci
338275793eaSopenharmony_ci/* -- see zlib.h -- */
339275793eaSopenharmony_ciint ZEXPORT gzputs(gzFile file, const char *s) {
340275793eaSopenharmony_ci    z_size_t len, put;
341275793eaSopenharmony_ci    gz_statep state;
342275793eaSopenharmony_ci
343275793eaSopenharmony_ci    /* get internal structure */
344275793eaSopenharmony_ci    if (file == NULL)
345275793eaSopenharmony_ci        return -1;
346275793eaSopenharmony_ci    state = (gz_statep)file;
347275793eaSopenharmony_ci
348275793eaSopenharmony_ci    /* check that we're writing and that there's no error */
349275793eaSopenharmony_ci    if (state->mode != GZ_WRITE || state->err != Z_OK)
350275793eaSopenharmony_ci        return -1;
351275793eaSopenharmony_ci
352275793eaSopenharmony_ci    /* write string */
353275793eaSopenharmony_ci    len = strlen(s);
354275793eaSopenharmony_ci    if ((int)len < 0 || (unsigned)len != len) {
355275793eaSopenharmony_ci        gz_error(state, Z_STREAM_ERROR, "string length does not fit in int");
356275793eaSopenharmony_ci        return -1;
357275793eaSopenharmony_ci    }
358275793eaSopenharmony_ci    put = gz_write(state, s, len);
359275793eaSopenharmony_ci    return put < len ? -1 : (int)len;
360275793eaSopenharmony_ci}
361275793eaSopenharmony_ci
362275793eaSopenharmony_ci#if defined(STDC) || defined(Z_HAVE_STDARG_H)
363275793eaSopenharmony_ci#include <stdarg.h>
364275793eaSopenharmony_ci
365275793eaSopenharmony_ci/* -- see zlib.h -- */
366275793eaSopenharmony_ciint ZEXPORTVA gzvprintf(gzFile file, const char *format, va_list va) {
367275793eaSopenharmony_ci    int len;
368275793eaSopenharmony_ci    unsigned left;
369275793eaSopenharmony_ci    char *next;
370275793eaSopenharmony_ci    gz_statep state;
371275793eaSopenharmony_ci    z_streamp strm;
372275793eaSopenharmony_ci
373275793eaSopenharmony_ci    /* get internal structure */
374275793eaSopenharmony_ci    if (file == NULL)
375275793eaSopenharmony_ci        return Z_STREAM_ERROR;
376275793eaSopenharmony_ci    state = (gz_statep)file;
377275793eaSopenharmony_ci    strm = &(state->strm);
378275793eaSopenharmony_ci
379275793eaSopenharmony_ci    /* check that we're writing and that there's no error */
380275793eaSopenharmony_ci    if (state->mode != GZ_WRITE || state->err != Z_OK)
381275793eaSopenharmony_ci        return Z_STREAM_ERROR;
382275793eaSopenharmony_ci
383275793eaSopenharmony_ci    /* make sure we have some buffer space */
384275793eaSopenharmony_ci    if (state->size == 0 && gz_init(state) == -1)
385275793eaSopenharmony_ci        return state->err;
386275793eaSopenharmony_ci
387275793eaSopenharmony_ci    /* check for seek request */
388275793eaSopenharmony_ci    if (state->seek) {
389275793eaSopenharmony_ci        state->seek = 0;
390275793eaSopenharmony_ci        if (gz_zero(state, state->skip) == -1)
391275793eaSopenharmony_ci            return state->err;
392275793eaSopenharmony_ci    }
393275793eaSopenharmony_ci
394275793eaSopenharmony_ci    /* do the printf() into the input buffer, put length in len -- the input
395275793eaSopenharmony_ci       buffer is double-sized just for this function, so there is guaranteed to
396275793eaSopenharmony_ci       be state->size bytes available after the current contents */
397275793eaSopenharmony_ci    if (strm->avail_in == 0)
398275793eaSopenharmony_ci        strm->next_in = state->in;
399275793eaSopenharmony_ci    next = (char *)(state->in + (strm->next_in - state->in) + strm->avail_in);
400275793eaSopenharmony_ci    next[state->size - 1] = 0;
401275793eaSopenharmony_ci#ifdef NO_vsnprintf
402275793eaSopenharmony_ci#  ifdef HAS_vsprintf_void
403275793eaSopenharmony_ci    (void)vsprintf(next, format, va);
404275793eaSopenharmony_ci    for (len = 0; len < state->size; len++)
405275793eaSopenharmony_ci        if (next[len] == 0) break;
406275793eaSopenharmony_ci#  else
407275793eaSopenharmony_ci    len = vsprintf(next, format, va);
408275793eaSopenharmony_ci#  endif
409275793eaSopenharmony_ci#else
410275793eaSopenharmony_ci#  ifdef HAS_vsnprintf_void
411275793eaSopenharmony_ci    (void)vsnprintf(next, state->size, format, va);
412275793eaSopenharmony_ci    len = strlen(next);
413275793eaSopenharmony_ci#  else
414275793eaSopenharmony_ci    len = vsnprintf(next, state->size, format, va);
415275793eaSopenharmony_ci#  endif
416275793eaSopenharmony_ci#endif
417275793eaSopenharmony_ci
418275793eaSopenharmony_ci    /* check that printf() results fit in buffer */
419275793eaSopenharmony_ci    if (len == 0 || (unsigned)len >= state->size || next[state->size - 1] != 0)
420275793eaSopenharmony_ci        return 0;
421275793eaSopenharmony_ci
422275793eaSopenharmony_ci    /* update buffer and position, compress first half if past that */
423275793eaSopenharmony_ci    strm->avail_in += (unsigned)len;
424275793eaSopenharmony_ci    state->x.pos += len;
425275793eaSopenharmony_ci    if (strm->avail_in >= state->size) {
426275793eaSopenharmony_ci        left = strm->avail_in - state->size;
427275793eaSopenharmony_ci        strm->avail_in = state->size;
428275793eaSopenharmony_ci        if (gz_comp(state, Z_NO_FLUSH) == -1)
429275793eaSopenharmony_ci            return state->err;
430275793eaSopenharmony_ci        memmove(state->in, state->in + state->size, left);
431275793eaSopenharmony_ci        strm->next_in = state->in;
432275793eaSopenharmony_ci        strm->avail_in = left;
433275793eaSopenharmony_ci    }
434275793eaSopenharmony_ci    return len;
435275793eaSopenharmony_ci}
436275793eaSopenharmony_ci
437275793eaSopenharmony_ciint ZEXPORTVA gzprintf(gzFile file, const char *format, ...) {
438275793eaSopenharmony_ci    va_list va;
439275793eaSopenharmony_ci    int ret;
440275793eaSopenharmony_ci
441275793eaSopenharmony_ci    va_start(va, format);
442275793eaSopenharmony_ci    ret = gzvprintf(file, format, va);
443275793eaSopenharmony_ci    va_end(va);
444275793eaSopenharmony_ci    return ret;
445275793eaSopenharmony_ci}
446275793eaSopenharmony_ci
447275793eaSopenharmony_ci#else /* !STDC && !Z_HAVE_STDARG_H */
448275793eaSopenharmony_ci
449275793eaSopenharmony_ci/* -- see zlib.h -- */
450275793eaSopenharmony_ciint ZEXPORTVA gzprintf(gzFile file, const char *format, int a1, int a2, int a3,
451275793eaSopenharmony_ci                       int a4, int a5, int a6, int a7, int a8, int a9, int a10,
452275793eaSopenharmony_ci                       int a11, int a12, int a13, int a14, int a15, int a16,
453275793eaSopenharmony_ci                       int a17, int a18, int a19, int a20) {
454275793eaSopenharmony_ci    unsigned len, left;
455275793eaSopenharmony_ci    char *next;
456275793eaSopenharmony_ci    gz_statep state;
457275793eaSopenharmony_ci    z_streamp strm;
458275793eaSopenharmony_ci
459275793eaSopenharmony_ci    /* get internal structure */
460275793eaSopenharmony_ci    if (file == NULL)
461275793eaSopenharmony_ci        return Z_STREAM_ERROR;
462275793eaSopenharmony_ci    state = (gz_statep)file;
463275793eaSopenharmony_ci    strm = &(state->strm);
464275793eaSopenharmony_ci
465275793eaSopenharmony_ci    /* check that can really pass pointer in ints */
466275793eaSopenharmony_ci    if (sizeof(int) != sizeof(void *))
467275793eaSopenharmony_ci        return Z_STREAM_ERROR;
468275793eaSopenharmony_ci
469275793eaSopenharmony_ci    /* check that we're writing and that there's no error */
470275793eaSopenharmony_ci    if (state->mode != GZ_WRITE || state->err != Z_OK)
471275793eaSopenharmony_ci        return Z_STREAM_ERROR;
472275793eaSopenharmony_ci
473275793eaSopenharmony_ci    /* make sure we have some buffer space */
474275793eaSopenharmony_ci    if (state->size == 0 && gz_init(state) == -1)
475275793eaSopenharmony_ci        return state->error;
476275793eaSopenharmony_ci
477275793eaSopenharmony_ci    /* check for seek request */
478275793eaSopenharmony_ci    if (state->seek) {
479275793eaSopenharmony_ci        state->seek = 0;
480275793eaSopenharmony_ci        if (gz_zero(state, state->skip) == -1)
481275793eaSopenharmony_ci            return state->error;
482275793eaSopenharmony_ci    }
483275793eaSopenharmony_ci
484275793eaSopenharmony_ci    /* do the printf() into the input buffer, put length in len -- the input
485275793eaSopenharmony_ci       buffer is double-sized just for this function, so there is guaranteed to
486275793eaSopenharmony_ci       be state->size bytes available after the current contents */
487275793eaSopenharmony_ci    if (strm->avail_in == 0)
488275793eaSopenharmony_ci        strm->next_in = state->in;
489275793eaSopenharmony_ci    next = (char *)(strm->next_in + strm->avail_in);
490275793eaSopenharmony_ci    next[state->size - 1] = 0;
491275793eaSopenharmony_ci#ifdef NO_snprintf
492275793eaSopenharmony_ci#  ifdef HAS_sprintf_void
493275793eaSopenharmony_ci    sprintf(next, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12,
494275793eaSopenharmony_ci            a13, a14, a15, a16, a17, a18, a19, a20);
495275793eaSopenharmony_ci    for (len = 0; len < size; len++)
496275793eaSopenharmony_ci        if (next[len] == 0)
497275793eaSopenharmony_ci            break;
498275793eaSopenharmony_ci#  else
499275793eaSopenharmony_ci    len = sprintf(next, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11,
500275793eaSopenharmony_ci                  a12, a13, a14, a15, a16, a17, a18, a19, a20);
501275793eaSopenharmony_ci#  endif
502275793eaSopenharmony_ci#else
503275793eaSopenharmony_ci#  ifdef HAS_snprintf_void
504275793eaSopenharmony_ci    snprintf(next, state->size, format, a1, a2, a3, a4, a5, a6, a7, a8, a9,
505275793eaSopenharmony_ci             a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20);
506275793eaSopenharmony_ci    len = strlen(next);
507275793eaSopenharmony_ci#  else
508275793eaSopenharmony_ci    len = snprintf(next, state->size, format, a1, a2, a3, a4, a5, a6, a7, a8,
509275793eaSopenharmony_ci                   a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20);
510275793eaSopenharmony_ci#  endif
511275793eaSopenharmony_ci#endif
512275793eaSopenharmony_ci
513275793eaSopenharmony_ci    /* check that printf() results fit in buffer */
514275793eaSopenharmony_ci    if (len == 0 || len >= state->size || next[state->size - 1] != 0)
515275793eaSopenharmony_ci        return 0;
516275793eaSopenharmony_ci
517275793eaSopenharmony_ci    /* update buffer and position, compress first half if past that */
518275793eaSopenharmony_ci    strm->avail_in += len;
519275793eaSopenharmony_ci    state->x.pos += len;
520275793eaSopenharmony_ci    if (strm->avail_in >= state->size) {
521275793eaSopenharmony_ci        left = strm->avail_in - state->size;
522275793eaSopenharmony_ci        strm->avail_in = state->size;
523275793eaSopenharmony_ci        if (gz_comp(state, Z_NO_FLUSH) == -1)
524275793eaSopenharmony_ci            return state->err;
525275793eaSopenharmony_ci        memmove(state->in, state->in + state->size, left);
526275793eaSopenharmony_ci        strm->next_in = state->in;
527275793eaSopenharmony_ci        strm->avail_in = left;
528275793eaSopenharmony_ci    }
529275793eaSopenharmony_ci    return (int)len;
530275793eaSopenharmony_ci}
531275793eaSopenharmony_ci
532275793eaSopenharmony_ci#endif
533275793eaSopenharmony_ci
534275793eaSopenharmony_ci/* -- see zlib.h -- */
535275793eaSopenharmony_ciint ZEXPORT gzflush(gzFile file, int flush) {
536275793eaSopenharmony_ci    gz_statep state;
537275793eaSopenharmony_ci
538275793eaSopenharmony_ci    /* get internal structure */
539275793eaSopenharmony_ci    if (file == NULL)
540275793eaSopenharmony_ci        return Z_STREAM_ERROR;
541275793eaSopenharmony_ci    state = (gz_statep)file;
542275793eaSopenharmony_ci
543275793eaSopenharmony_ci    /* check that we're writing and that there's no error */
544275793eaSopenharmony_ci    if (state->mode != GZ_WRITE || state->err != Z_OK)
545275793eaSopenharmony_ci        return Z_STREAM_ERROR;
546275793eaSopenharmony_ci
547275793eaSopenharmony_ci    /* check flush parameter */
548275793eaSopenharmony_ci    if (flush < 0 || flush > Z_FINISH)
549275793eaSopenharmony_ci        return Z_STREAM_ERROR;
550275793eaSopenharmony_ci
551275793eaSopenharmony_ci    /* check for seek request */
552275793eaSopenharmony_ci    if (state->seek) {
553275793eaSopenharmony_ci        state->seek = 0;
554275793eaSopenharmony_ci        if (gz_zero(state, state->skip) == -1)
555275793eaSopenharmony_ci            return state->err;
556275793eaSopenharmony_ci    }
557275793eaSopenharmony_ci
558275793eaSopenharmony_ci    /* compress remaining data with requested flush */
559275793eaSopenharmony_ci    (void)gz_comp(state, flush);
560275793eaSopenharmony_ci    return state->err;
561275793eaSopenharmony_ci}
562275793eaSopenharmony_ci
563275793eaSopenharmony_ci/* -- see zlib.h -- */
564275793eaSopenharmony_ciint ZEXPORT gzsetparams(gzFile file, int level, int strategy) {
565275793eaSopenharmony_ci    gz_statep state;
566275793eaSopenharmony_ci    z_streamp strm;
567275793eaSopenharmony_ci
568275793eaSopenharmony_ci    /* get internal structure */
569275793eaSopenharmony_ci    if (file == NULL)
570275793eaSopenharmony_ci        return Z_STREAM_ERROR;
571275793eaSopenharmony_ci    state = (gz_statep)file;
572275793eaSopenharmony_ci    strm = &(state->strm);
573275793eaSopenharmony_ci
574275793eaSopenharmony_ci    /* check that we're writing and that there's no error */
575275793eaSopenharmony_ci    if (state->mode != GZ_WRITE || state->err != Z_OK || state->direct)
576275793eaSopenharmony_ci        return Z_STREAM_ERROR;
577275793eaSopenharmony_ci
578275793eaSopenharmony_ci    /* if no change is requested, then do nothing */
579275793eaSopenharmony_ci    if (level == state->level && strategy == state->strategy)
580275793eaSopenharmony_ci        return Z_OK;
581275793eaSopenharmony_ci
582275793eaSopenharmony_ci    /* check for seek request */
583275793eaSopenharmony_ci    if (state->seek) {
584275793eaSopenharmony_ci        state->seek = 0;
585275793eaSopenharmony_ci        if (gz_zero(state, state->skip) == -1)
586275793eaSopenharmony_ci            return state->err;
587275793eaSopenharmony_ci    }
588275793eaSopenharmony_ci
589275793eaSopenharmony_ci    /* change compression parameters for subsequent input */
590275793eaSopenharmony_ci    if (state->size) {
591275793eaSopenharmony_ci        /* flush previous input with previous parameters before changing */
592275793eaSopenharmony_ci        if (strm->avail_in && gz_comp(state, Z_BLOCK) == -1)
593275793eaSopenharmony_ci            return state->err;
594275793eaSopenharmony_ci        deflateParams(strm, level, strategy);
595275793eaSopenharmony_ci    }
596275793eaSopenharmony_ci    state->level = level;
597275793eaSopenharmony_ci    state->strategy = strategy;
598275793eaSopenharmony_ci    return Z_OK;
599275793eaSopenharmony_ci}
600275793eaSopenharmony_ci
601275793eaSopenharmony_ci/* -- see zlib.h -- */
602275793eaSopenharmony_ciint ZEXPORT gzclose_w(gzFile file) {
603275793eaSopenharmony_ci    int ret = Z_OK;
604275793eaSopenharmony_ci    gz_statep state;
605275793eaSopenharmony_ci
606275793eaSopenharmony_ci    /* get internal structure */
607275793eaSopenharmony_ci    if (file == NULL)
608275793eaSopenharmony_ci        return Z_STREAM_ERROR;
609275793eaSopenharmony_ci    state = (gz_statep)file;
610275793eaSopenharmony_ci
611275793eaSopenharmony_ci    /* check that we're writing */
612275793eaSopenharmony_ci    if (state->mode != GZ_WRITE)
613275793eaSopenharmony_ci        return Z_STREAM_ERROR;
614275793eaSopenharmony_ci
615275793eaSopenharmony_ci    /* check for seek request */
616275793eaSopenharmony_ci    if (state->seek) {
617275793eaSopenharmony_ci        state->seek = 0;
618275793eaSopenharmony_ci        if (gz_zero(state, state->skip) == -1)
619275793eaSopenharmony_ci            ret = state->err;
620275793eaSopenharmony_ci    }
621275793eaSopenharmony_ci
622275793eaSopenharmony_ci    /* flush, free memory, and close file */
623275793eaSopenharmony_ci    if (gz_comp(state, Z_FINISH) == -1)
624275793eaSopenharmony_ci        ret = state->err;
625275793eaSopenharmony_ci    if (state->size) {
626275793eaSopenharmony_ci        if (!state->direct) {
627275793eaSopenharmony_ci            (void)deflateEnd(&(state->strm));
628275793eaSopenharmony_ci            free(state->out);
629275793eaSopenharmony_ci        }
630275793eaSopenharmony_ci        free(state->in);
631275793eaSopenharmony_ci    }
632275793eaSopenharmony_ci    gz_error(state, Z_OK, NULL);
633275793eaSopenharmony_ci    free(state->path);
634275793eaSopenharmony_ci    if (close(state->fd) == -1)
635275793eaSopenharmony_ci        ret = Z_ERRNO;
636275793eaSopenharmony_ci    free(state);
637275793eaSopenharmony_ci    return ret;
638275793eaSopenharmony_ci}
639