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