1205194Sdelphij/* gzwrite.c -- zlib functions for writing gzip files 2312335Sdelphij * Copyright (C) 2004-2017 Mark Adler 3205194Sdelphij * For conditions of distribution and use, see copyright notice in zlib.h 4205194Sdelphij */ 5205194Sdelphij 6311275Sdelphij/* $FreeBSD: stable/11/sys/contrib/zlib/gzwrite.c 312335 2017-01-17 05:55:47Z delphij $ */ 7311275Sdelphij 8205194Sdelphij#include "gzguts.h" 9311275Sdelphij#include <unistd.h> 10205194Sdelphij 11205194Sdelphij/* Local functions */ 12205194Sdelphijlocal int gz_init OF((gz_statep)); 13205194Sdelphijlocal int gz_comp OF((gz_statep, int)); 14205194Sdelphijlocal int gz_zero OF((gz_statep, z_off64_t)); 15311285Sdelphijlocal z_size_t gz_write OF((gz_statep, voidpc, z_size_t)); 16205194Sdelphij 17205194Sdelphij/* Initialize state for writing a gzip file. Mark initialization by setting 18311285Sdelphij state->size to non-zero. Return -1 on a memory allocation failure, or 0 on 19311285Sdelphij success. */ 20205194Sdelphijlocal int gz_init(state) 21205194Sdelphij gz_statep state; 22205194Sdelphij{ 23205194Sdelphij int ret; 24205194Sdelphij z_streamp strm = &(state->strm); 25205194Sdelphij 26311285Sdelphij /* allocate input buffer (double size for gzprintf) */ 27311285Sdelphij state->in = (unsigned char *)malloc(state->want << 1); 28230837Sdelphij if (state->in == NULL) { 29205194Sdelphij gz_error(state, Z_MEM_ERROR, "out of memory"); 30205194Sdelphij return -1; 31205194Sdelphij } 32205194Sdelphij 33230837Sdelphij /* only need output buffer and deflate state if compressing */ 34230837Sdelphij if (!state->direct) { 35230837Sdelphij /* allocate output buffer */ 36250224Sdelphij state->out = (unsigned char *)malloc(state->want); 37230837Sdelphij if (state->out == NULL) { 38230837Sdelphij free(state->in); 39230837Sdelphij gz_error(state, Z_MEM_ERROR, "out of memory"); 40230837Sdelphij return -1; 41230837Sdelphij } 42230837Sdelphij 43230837Sdelphij /* allocate deflate memory, set up for gzip compression */ 44230837Sdelphij strm->zalloc = Z_NULL; 45230837Sdelphij strm->zfree = Z_NULL; 46230837Sdelphij strm->opaque = Z_NULL; 47230837Sdelphij ret = deflateInit2(strm, state->level, Z_DEFLATED, 48230837Sdelphij MAX_WBITS + 16, DEF_MEM_LEVEL, state->strategy); 49230837Sdelphij if (ret != Z_OK) { 50230837Sdelphij free(state->out); 51230837Sdelphij free(state->in); 52230837Sdelphij gz_error(state, Z_MEM_ERROR, "out of memory"); 53230837Sdelphij return -1; 54230837Sdelphij } 55311285Sdelphij strm->next_in = NULL; 56205194Sdelphij } 57205194Sdelphij 58205194Sdelphij /* mark state as initialized */ 59205194Sdelphij state->size = state->want; 60205194Sdelphij 61230837Sdelphij /* initialize write buffer if compressing */ 62230837Sdelphij if (!state->direct) { 63230837Sdelphij strm->avail_out = state->size; 64230837Sdelphij strm->next_out = state->out; 65230837Sdelphij state->x.next = strm->next_out; 66230837Sdelphij } 67205194Sdelphij return 0; 68205194Sdelphij} 69205194Sdelphij 70205194Sdelphij/* Compress whatever is at avail_in and next_in and write to the output file. 71311285Sdelphij Return -1 if there is an error writing to the output file or if gz_init() 72311285Sdelphij fails to allocate memory, otherwise 0. flush is assumed to be a valid 73311285Sdelphij deflate() flush value. If flush is Z_FINISH, then the deflate() state is 74311285Sdelphij reset to start a new gzip stream. If gz->direct is true, then simply write 75311285Sdelphij to the output file without compressing, and ignore flush. */ 76205194Sdelphijlocal int gz_comp(state, flush) 77205194Sdelphij gz_statep state; 78205194Sdelphij int flush; 79205194Sdelphij{ 80311285Sdelphij int ret, writ; 81311285Sdelphij unsigned have, put, max = ((unsigned)-1 >> 2) + 1; 82205194Sdelphij z_streamp strm = &(state->strm); 83205194Sdelphij 84205194Sdelphij /* allocate memory if this is the first time through */ 85205194Sdelphij if (state->size == 0 && gz_init(state) == -1) 86205194Sdelphij return -1; 87205194Sdelphij 88230837Sdelphij /* write directly if requested */ 89230837Sdelphij if (state->direct) { 90311285Sdelphij while (strm->avail_in) { 91311285Sdelphij put = strm->avail_in > max ? max : strm->avail_in; 92311285Sdelphij writ = write(state->fd, strm->next_in, put); 93311285Sdelphij if (writ < 0) { 94311285Sdelphij gz_error(state, Z_ERRNO, zstrerror()); 95311285Sdelphij return -1; 96311285Sdelphij } 97311285Sdelphij strm->avail_in -= (unsigned)writ; 98311285Sdelphij strm->next_in += writ; 99230837Sdelphij } 100230837Sdelphij return 0; 101230837Sdelphij } 102230837Sdelphij 103205194Sdelphij /* run deflate() on provided input until it produces no more output */ 104205194Sdelphij ret = Z_OK; 105205194Sdelphij do { 106205194Sdelphij /* write out current buffer contents if full, or if flushing, but if 107205194Sdelphij doing Z_FINISH then don't write until we get to Z_STREAM_END */ 108205194Sdelphij if (strm->avail_out == 0 || (flush != Z_NO_FLUSH && 109205194Sdelphij (flush != Z_FINISH || ret == Z_STREAM_END))) { 110311285Sdelphij while (strm->next_out > state->x.next) { 111311285Sdelphij put = strm->next_out - state->x.next > (int)max ? max : 112311285Sdelphij (unsigned)(strm->next_out - state->x.next); 113311285Sdelphij writ = write(state->fd, state->x.next, put); 114311285Sdelphij if (writ < 0) { 115311285Sdelphij gz_error(state, Z_ERRNO, zstrerror()); 116311285Sdelphij return -1; 117311285Sdelphij } 118311285Sdelphij state->x.next += writ; 119205194Sdelphij } 120205194Sdelphij if (strm->avail_out == 0) { 121205194Sdelphij strm->avail_out = state->size; 122205194Sdelphij strm->next_out = state->out; 123311285Sdelphij state->x.next = state->out; 124205194Sdelphij } 125205194Sdelphij } 126205194Sdelphij 127205194Sdelphij /* compress */ 128205194Sdelphij have = strm->avail_out; 129205194Sdelphij ret = deflate(strm, flush); 130205194Sdelphij if (ret == Z_STREAM_ERROR) { 131205194Sdelphij gz_error(state, Z_STREAM_ERROR, 132205194Sdelphij "internal error: deflate stream corrupt"); 133205194Sdelphij return -1; 134205194Sdelphij } 135205194Sdelphij have -= strm->avail_out; 136205194Sdelphij } while (have); 137205194Sdelphij 138205194Sdelphij /* if that completed a deflate stream, allow another to start */ 139205194Sdelphij if (flush == Z_FINISH) 140205194Sdelphij deflateReset(strm); 141205194Sdelphij 142205194Sdelphij /* all done, no errors */ 143205194Sdelphij return 0; 144205194Sdelphij} 145205194Sdelphij 146311285Sdelphij/* Compress len zeros to output. Return -1 on a write error or memory 147311285Sdelphij allocation failure by gz_comp(), or 0 on success. */ 148205194Sdelphijlocal int gz_zero(state, len) 149205194Sdelphij gz_statep state; 150205194Sdelphij z_off64_t len; 151205194Sdelphij{ 152205194Sdelphij int first; 153205194Sdelphij unsigned n; 154205194Sdelphij z_streamp strm = &(state->strm); 155205194Sdelphij 156205194Sdelphij /* consume whatever's left in the input buffer */ 157205194Sdelphij if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1) 158205194Sdelphij return -1; 159205194Sdelphij 160205194Sdelphij /* compress len zeros (len guaranteed > 0) */ 161205194Sdelphij first = 1; 162205194Sdelphij while (len) { 163205194Sdelphij n = GT_OFF(state->size) || (z_off64_t)state->size > len ? 164205194Sdelphij (unsigned)len : state->size; 165205194Sdelphij if (first) { 166205194Sdelphij memset(state->in, 0, n); 167205194Sdelphij first = 0; 168205194Sdelphij } 169205194Sdelphij strm->avail_in = n; 170205194Sdelphij strm->next_in = state->in; 171230837Sdelphij state->x.pos += n; 172205194Sdelphij if (gz_comp(state, Z_NO_FLUSH) == -1) 173205194Sdelphij return -1; 174205194Sdelphij len -= n; 175205194Sdelphij } 176205194Sdelphij return 0; 177205194Sdelphij} 178205194Sdelphij 179311285Sdelphij/* Write len bytes from buf to file. Return the number of bytes written. If 180311285Sdelphij the returned value is less than len, then there was an error. */ 181311285Sdelphijlocal z_size_t gz_write(state, buf, len) 182311285Sdelphij gz_statep state; 183205194Sdelphij voidpc buf; 184311285Sdelphij z_size_t len; 185205194Sdelphij{ 186311285Sdelphij z_size_t put = len; 187205194Sdelphij 188205194Sdelphij /* if len is zero, avoid unnecessary operations */ 189205194Sdelphij if (len == 0) 190205194Sdelphij return 0; 191205194Sdelphij 192205194Sdelphij /* allocate memory if this is the first time through */ 193205194Sdelphij if (state->size == 0 && gz_init(state) == -1) 194205194Sdelphij return 0; 195205194Sdelphij 196205194Sdelphij /* check for seek request */ 197205194Sdelphij if (state->seek) { 198205194Sdelphij state->seek = 0; 199205194Sdelphij if (gz_zero(state, state->skip) == -1) 200205194Sdelphij return 0; 201205194Sdelphij } 202205194Sdelphij 203205194Sdelphij /* for small len, copy to input buffer, otherwise compress directly */ 204205194Sdelphij if (len < state->size) { 205205194Sdelphij /* copy to input buffer, compress when full */ 206205194Sdelphij do { 207250224Sdelphij unsigned have, copy; 208250224Sdelphij 209311285Sdelphij if (state->strm.avail_in == 0) 210311285Sdelphij state->strm.next_in = state->in; 211311285Sdelphij have = (unsigned)((state->strm.next_in + state->strm.avail_in) - 212311285Sdelphij state->in); 213250224Sdelphij copy = state->size - have; 214250224Sdelphij if (copy > len) 215250224Sdelphij copy = len; 216250224Sdelphij memcpy(state->in + have, buf, copy); 217311285Sdelphij state->strm.avail_in += copy; 218250224Sdelphij state->x.pos += copy; 219250224Sdelphij buf = (const char *)buf + copy; 220250224Sdelphij len -= copy; 221205194Sdelphij if (len && gz_comp(state, Z_NO_FLUSH) == -1) 222205194Sdelphij return 0; 223205194Sdelphij } while (len); 224205194Sdelphij } 225205194Sdelphij else { 226205194Sdelphij /* consume whatever's left in the input buffer */ 227311285Sdelphij if (state->strm.avail_in && gz_comp(state, Z_NO_FLUSH) == -1) 228205194Sdelphij return 0; 229205194Sdelphij 230205194Sdelphij /* directly compress user buffer to file */ 231311285Sdelphij state->strm.next_in = (z_const Bytef *)buf; 232311285Sdelphij do { 233311285Sdelphij unsigned n = (unsigned)-1; 234311285Sdelphij if (n > len) 235311285Sdelphij n = len; 236311285Sdelphij state->strm.avail_in = n; 237311285Sdelphij state->x.pos += n; 238311285Sdelphij if (gz_comp(state, Z_NO_FLUSH) == -1) 239311285Sdelphij return 0; 240311285Sdelphij len -= n; 241311285Sdelphij } while (len); 242205194Sdelphij } 243205194Sdelphij 244311285Sdelphij /* input was all buffered or compressed */ 245311285Sdelphij return put; 246205194Sdelphij} 247205194Sdelphij 248205194Sdelphij/* -- see zlib.h -- */ 249311285Sdelphijint ZEXPORT gzwrite(file, buf, len) 250311285Sdelphij gzFile file; 251311285Sdelphij voidpc buf; 252311285Sdelphij unsigned len; 253311285Sdelphij{ 254311285Sdelphij gz_statep state; 255311285Sdelphij 256311285Sdelphij /* get internal structure */ 257311285Sdelphij if (file == NULL) 258311285Sdelphij return 0; 259311285Sdelphij state = (gz_statep)file; 260311285Sdelphij 261311285Sdelphij /* check that we're writing and that there's no error */ 262311285Sdelphij if (state->mode != GZ_WRITE || state->err != Z_OK) 263311285Sdelphij return 0; 264311285Sdelphij 265311285Sdelphij /* since an int is returned, make sure len fits in one, otherwise return 266311285Sdelphij with an error (this avoids a flaw in the interface) */ 267311285Sdelphij if ((int)len < 0) { 268311285Sdelphij gz_error(state, Z_DATA_ERROR, "requested length does not fit in int"); 269311285Sdelphij return 0; 270311285Sdelphij } 271311285Sdelphij 272311285Sdelphij /* write len bytes from buf (the return value will fit in an int) */ 273311285Sdelphij return (int)gz_write(state, buf, len); 274311285Sdelphij} 275311285Sdelphij 276311285Sdelphij/* -- see zlib.h -- */ 277311285Sdelphijz_size_t ZEXPORT gzfwrite(buf, size, nitems, file) 278311285Sdelphij voidpc buf; 279311285Sdelphij z_size_t size; 280311285Sdelphij z_size_t nitems; 281311285Sdelphij gzFile file; 282311285Sdelphij{ 283311285Sdelphij z_size_t len; 284311285Sdelphij gz_statep state; 285311285Sdelphij 286311285Sdelphij /* get internal structure */ 287311285Sdelphij if (file == NULL) 288311285Sdelphij return 0; 289311285Sdelphij state = (gz_statep)file; 290311285Sdelphij 291311285Sdelphij /* check that we're writing and that there's no error */ 292311285Sdelphij if (state->mode != GZ_WRITE || state->err != Z_OK) 293311285Sdelphij return 0; 294311285Sdelphij 295311285Sdelphij /* compute bytes to read -- error on overflow */ 296311285Sdelphij len = nitems * size; 297311285Sdelphij if (size && len / size != nitems) { 298311285Sdelphij gz_error(state, Z_STREAM_ERROR, "request does not fit in a size_t"); 299311285Sdelphij return 0; 300311285Sdelphij } 301311285Sdelphij 302311285Sdelphij /* write len bytes to buf, return the number of full items written */ 303311285Sdelphij return len ? gz_write(state, buf, len) / size : 0; 304311285Sdelphij} 305311285Sdelphij 306311285Sdelphij/* -- see zlib.h -- */ 307205194Sdelphijint ZEXPORT gzputc(file, c) 308205194Sdelphij gzFile file; 309205194Sdelphij int c; 310205194Sdelphij{ 311250224Sdelphij unsigned have; 312205194Sdelphij unsigned char buf[1]; 313205194Sdelphij gz_statep state; 314205194Sdelphij z_streamp strm; 315205194Sdelphij 316205194Sdelphij /* get internal structure */ 317205194Sdelphij if (file == NULL) 318205194Sdelphij return -1; 319205194Sdelphij state = (gz_statep)file; 320205194Sdelphij strm = &(state->strm); 321205194Sdelphij 322205194Sdelphij /* check that we're writing and that there's no error */ 323205194Sdelphij if (state->mode != GZ_WRITE || state->err != Z_OK) 324205194Sdelphij return -1; 325205194Sdelphij 326205194Sdelphij /* check for seek request */ 327205194Sdelphij if (state->seek) { 328205194Sdelphij state->seek = 0; 329205194Sdelphij if (gz_zero(state, state->skip) == -1) 330205194Sdelphij return -1; 331205194Sdelphij } 332205194Sdelphij 333205194Sdelphij /* try writing to input buffer for speed (state->size == 0 if buffer not 334205194Sdelphij initialized) */ 335250224Sdelphij if (state->size) { 336205194Sdelphij if (strm->avail_in == 0) 337205194Sdelphij strm->next_in = state->in; 338250224Sdelphij have = (unsigned)((strm->next_in + strm->avail_in) - state->in); 339250224Sdelphij if (have < state->size) { 340311285Sdelphij state->in[have] = (unsigned char)c; 341250224Sdelphij strm->avail_in++; 342250224Sdelphij state->x.pos++; 343250224Sdelphij return c & 0xff; 344250224Sdelphij } 345205194Sdelphij } 346205194Sdelphij 347205194Sdelphij /* no room in buffer or not initialized, use gz_write() */ 348311285Sdelphij buf[0] = (unsigned char)c; 349311285Sdelphij if (gz_write(state, buf, 1) != 1) 350205194Sdelphij return -1; 351230837Sdelphij return c & 0xff; 352205194Sdelphij} 353205194Sdelphij 354205194Sdelphij/* -- see zlib.h -- */ 355205194Sdelphijint ZEXPORT gzputs(file, str) 356205194Sdelphij gzFile file; 357205194Sdelphij const char *str; 358205194Sdelphij{ 359205194Sdelphij int ret; 360311285Sdelphij z_size_t len; 361311285Sdelphij gz_statep state; 362205194Sdelphij 363311285Sdelphij /* get internal structure */ 364311285Sdelphij if (file == NULL) 365311285Sdelphij return -1; 366311285Sdelphij state = (gz_statep)file; 367311285Sdelphij 368311285Sdelphij /* check that we're writing and that there's no error */ 369311285Sdelphij if (state->mode != GZ_WRITE || state->err != Z_OK) 370311285Sdelphij return -1; 371311285Sdelphij 372205194Sdelphij /* write string */ 373311285Sdelphij len = strlen(str); 374311285Sdelphij ret = gz_write(state, str, len); 375205194Sdelphij return ret == 0 && len != 0 ? -1 : ret; 376205194Sdelphij} 377205194Sdelphij 378230837Sdelphij#if defined(STDC) || defined(Z_HAVE_STDARG_H) 379205194Sdelphij#include <stdarg.h> 380205194Sdelphij 381205194Sdelphij/* -- see zlib.h -- */ 382250224Sdelphijint ZEXPORTVA gzvprintf(gzFile file, const char *format, va_list va) 383205194Sdelphij{ 384311285Sdelphij int len; 385311285Sdelphij unsigned left; 386311285Sdelphij char *next; 387205194Sdelphij gz_statep state; 388205194Sdelphij z_streamp strm; 389205194Sdelphij 390205194Sdelphij /* get internal structure */ 391205194Sdelphij if (file == NULL) 392311285Sdelphij return Z_STREAM_ERROR; 393205194Sdelphij state = (gz_statep)file; 394205194Sdelphij strm = &(state->strm); 395205194Sdelphij 396205194Sdelphij /* check that we're writing and that there's no error */ 397205194Sdelphij if (state->mode != GZ_WRITE || state->err != Z_OK) 398311285Sdelphij return Z_STREAM_ERROR; 399205194Sdelphij 400205194Sdelphij /* make sure we have some buffer space */ 401205194Sdelphij if (state->size == 0 && gz_init(state) == -1) 402311285Sdelphij return state->err; 403205194Sdelphij 404205194Sdelphij /* check for seek request */ 405205194Sdelphij if (state->seek) { 406205194Sdelphij state->seek = 0; 407205194Sdelphij if (gz_zero(state, state->skip) == -1) 408311285Sdelphij return state->err; 409205194Sdelphij } 410205194Sdelphij 411311285Sdelphij /* do the printf() into the input buffer, put length in len -- the input 412311285Sdelphij buffer is double-sized just for this function, so there is guaranteed to 413311285Sdelphij be state->size bytes available after the current contents */ 414311285Sdelphij if (strm->avail_in == 0) 415311285Sdelphij strm->next_in = state->in; 416311285Sdelphij next = (char *)(state->in + (strm->next_in - state->in) + strm->avail_in); 417311285Sdelphij next[state->size - 1] = 0; 418205194Sdelphij#ifdef NO_vsnprintf 419205194Sdelphij# ifdef HAS_vsprintf_void 420311285Sdelphij (void)vsprintf(next, format, va); 421311285Sdelphij for (len = 0; len < state->size; len++) 422311285Sdelphij if (next[len] == 0) break; 423205194Sdelphij# else 424311285Sdelphij len = vsprintf(next, format, va); 425205194Sdelphij# endif 426205194Sdelphij#else 427205194Sdelphij# ifdef HAS_vsnprintf_void 428311285Sdelphij (void)vsnprintf(next, state->size, format, va); 429311285Sdelphij len = strlen(next); 430205194Sdelphij# else 431311285Sdelphij len = vsnprintf(next, state->size, format, va); 432205194Sdelphij# endif 433205194Sdelphij#endif 434205194Sdelphij 435205194Sdelphij /* check that printf() results fit in buffer */ 436311285Sdelphij if (len == 0 || (unsigned)len >= state->size || next[state->size - 1] != 0) 437205194Sdelphij return 0; 438205194Sdelphij 439311285Sdelphij /* update buffer and position, compress first half if past that */ 440311285Sdelphij strm->avail_in += (unsigned)len; 441230837Sdelphij state->x.pos += len; 442311285Sdelphij if (strm->avail_in >= state->size) { 443311285Sdelphij left = strm->avail_in - state->size; 444311285Sdelphij strm->avail_in = state->size; 445311285Sdelphij if (gz_comp(state, Z_NO_FLUSH) == -1) 446311285Sdelphij return state->err; 447311285Sdelphij memcpy(state->in, state->in + state->size, left); 448311285Sdelphij strm->next_in = state->in; 449311285Sdelphij strm->avail_in = left; 450311285Sdelphij } 451205194Sdelphij return len; 452205194Sdelphij} 453205194Sdelphij 454250224Sdelphijint ZEXPORTVA gzprintf(gzFile file, const char *format, ...) 455250224Sdelphij{ 456250224Sdelphij va_list va; 457250224Sdelphij int ret; 458250224Sdelphij 459250224Sdelphij va_start(va, format); 460250224Sdelphij ret = gzvprintf(file, format, va); 461250224Sdelphij va_end(va); 462250224Sdelphij return ret; 463250224Sdelphij} 464250224Sdelphij 465230837Sdelphij#else /* !STDC && !Z_HAVE_STDARG_H */ 466205194Sdelphij 467205194Sdelphij/* -- see zlib.h -- */ 468205194Sdelphijint ZEXPORTVA gzprintf (file, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, 469205194Sdelphij a11, a12, a13, a14, a15, a16, a17, a18, a19, a20) 470205194Sdelphij gzFile file; 471205194Sdelphij const char *format; 472205194Sdelphij int a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, 473205194Sdelphij a11, a12, a13, a14, a15, a16, a17, a18, a19, a20; 474205194Sdelphij{ 475311285Sdelphij unsigned len, left; 476311285Sdelphij char *next; 477205194Sdelphij gz_statep state; 478205194Sdelphij z_streamp strm; 479205194Sdelphij 480205194Sdelphij /* get internal structure */ 481205194Sdelphij if (file == NULL) 482311285Sdelphij return Z_STREAM_ERROR; 483205194Sdelphij state = (gz_statep)file; 484205194Sdelphij strm = &(state->strm); 485205194Sdelphij 486230837Sdelphij /* check that can really pass pointer in ints */ 487230837Sdelphij if (sizeof(int) != sizeof(void *)) 488311285Sdelphij return Z_STREAM_ERROR; 489230837Sdelphij 490205194Sdelphij /* check that we're writing and that there's no error */ 491205194Sdelphij if (state->mode != GZ_WRITE || state->err != Z_OK) 492311285Sdelphij return Z_STREAM_ERROR; 493205194Sdelphij 494205194Sdelphij /* make sure we have some buffer space */ 495205194Sdelphij if (state->size == 0 && gz_init(state) == -1) 496311285Sdelphij return state->error; 497205194Sdelphij 498205194Sdelphij /* check for seek request */ 499205194Sdelphij if (state->seek) { 500205194Sdelphij state->seek = 0; 501205194Sdelphij if (gz_zero(state, state->skip) == -1) 502311285Sdelphij return state->error; 503205194Sdelphij } 504205194Sdelphij 505311285Sdelphij /* do the printf() into the input buffer, put length in len -- the input 506311285Sdelphij buffer is double-sized just for this function, so there is guaranteed to 507311285Sdelphij be state->size bytes available after the current contents */ 508311285Sdelphij if (strm->avail_in == 0) 509311285Sdelphij strm->next_in = state->in; 510311285Sdelphij next = (char *)(strm->next_in + strm->avail_in); 511311285Sdelphij next[state->size - 1] = 0; 512205194Sdelphij#ifdef NO_snprintf 513205194Sdelphij# ifdef HAS_sprintf_void 514311285Sdelphij sprintf(next, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, 515311285Sdelphij a13, a14, a15, a16, a17, a18, a19, a20); 516205194Sdelphij for (len = 0; len < size; len++) 517311285Sdelphij if (next[len] == 0) 518311285Sdelphij break; 519205194Sdelphij# else 520311285Sdelphij len = sprintf(next, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, 521311285Sdelphij a12, a13, a14, a15, a16, a17, a18, a19, a20); 522205194Sdelphij# endif 523205194Sdelphij#else 524205194Sdelphij# ifdef HAS_snprintf_void 525311285Sdelphij snprintf(next, state->size, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, 526311285Sdelphij a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20); 527311285Sdelphij len = strlen(next); 528205194Sdelphij# else 529311285Sdelphij len = snprintf(next, state->size, format, a1, a2, a3, a4, a5, a6, a7, a8, 530311285Sdelphij a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20); 531205194Sdelphij# endif 532205194Sdelphij#endif 533205194Sdelphij 534205194Sdelphij /* check that printf() results fit in buffer */ 535311285Sdelphij if (len == 0 || len >= state->size || next[state->size - 1] != 0) 536205194Sdelphij return 0; 537205194Sdelphij 538311285Sdelphij /* update buffer and position, compress first half if past that */ 539311285Sdelphij strm->avail_in += len; 540230837Sdelphij state->x.pos += len; 541311285Sdelphij if (strm->avail_in >= state->size) { 542311285Sdelphij left = strm->avail_in - state->size; 543311285Sdelphij strm->avail_in = state->size; 544311285Sdelphij if (gz_comp(state, Z_NO_FLUSH) == -1) 545311285Sdelphij return state->err; 546311285Sdelphij memcpy(state->in, state->in + state->size, left); 547311285Sdelphij strm->next_in = state->in; 548311285Sdelphij strm->avail_in = left; 549311285Sdelphij } 550311285Sdelphij return (int)len; 551205194Sdelphij} 552205194Sdelphij 553205194Sdelphij#endif 554205194Sdelphij 555205194Sdelphij/* -- see zlib.h -- */ 556205194Sdelphijint ZEXPORT gzflush(file, flush) 557205194Sdelphij gzFile file; 558205194Sdelphij int flush; 559205194Sdelphij{ 560205194Sdelphij gz_statep state; 561205194Sdelphij 562205194Sdelphij /* get internal structure */ 563205194Sdelphij if (file == NULL) 564311285Sdelphij return Z_STREAM_ERROR; 565205194Sdelphij state = (gz_statep)file; 566205194Sdelphij 567205194Sdelphij /* check that we're writing and that there's no error */ 568205194Sdelphij if (state->mode != GZ_WRITE || state->err != Z_OK) 569205194Sdelphij return Z_STREAM_ERROR; 570205194Sdelphij 571205194Sdelphij /* check flush parameter */ 572205194Sdelphij if (flush < 0 || flush > Z_FINISH) 573205194Sdelphij return Z_STREAM_ERROR; 574205194Sdelphij 575205194Sdelphij /* check for seek request */ 576205194Sdelphij if (state->seek) { 577205194Sdelphij state->seek = 0; 578205194Sdelphij if (gz_zero(state, state->skip) == -1) 579311285Sdelphij return state->err; 580205194Sdelphij } 581205194Sdelphij 582205194Sdelphij /* compress remaining data with requested flush */ 583311285Sdelphij (void)gz_comp(state, flush); 584205194Sdelphij return state->err; 585205194Sdelphij} 586205194Sdelphij 587205194Sdelphij/* -- see zlib.h -- */ 588205194Sdelphijint ZEXPORT gzsetparams(file, level, strategy) 589205194Sdelphij gzFile file; 590205194Sdelphij int level; 591205194Sdelphij int strategy; 592205194Sdelphij{ 593205194Sdelphij gz_statep state; 594205194Sdelphij z_streamp strm; 595205194Sdelphij 596205194Sdelphij /* get internal structure */ 597205194Sdelphij if (file == NULL) 598205194Sdelphij return Z_STREAM_ERROR; 599205194Sdelphij state = (gz_statep)file; 600205194Sdelphij strm = &(state->strm); 601205194Sdelphij 602205194Sdelphij /* check that we're writing and that there's no error */ 603205194Sdelphij if (state->mode != GZ_WRITE || state->err != Z_OK) 604205194Sdelphij return Z_STREAM_ERROR; 605205194Sdelphij 606205194Sdelphij /* if no change is requested, then do nothing */ 607205194Sdelphij if (level == state->level && strategy == state->strategy) 608205194Sdelphij return Z_OK; 609205194Sdelphij 610205194Sdelphij /* check for seek request */ 611205194Sdelphij if (state->seek) { 612205194Sdelphij state->seek = 0; 613205194Sdelphij if (gz_zero(state, state->skip) == -1) 614311285Sdelphij return state->err; 615205194Sdelphij } 616205194Sdelphij 617205194Sdelphij /* change compression parameters for subsequent input */ 618205194Sdelphij if (state->size) { 619205194Sdelphij /* flush previous input with previous parameters before changing */ 620311285Sdelphij if (strm->avail_in && gz_comp(state, Z_BLOCK) == -1) 621205194Sdelphij return state->err; 622205194Sdelphij deflateParams(strm, level, strategy); 623205194Sdelphij } 624205194Sdelphij state->level = level; 625205194Sdelphij state->strategy = strategy; 626205194Sdelphij return Z_OK; 627205194Sdelphij} 628205194Sdelphij 629205194Sdelphij/* -- see zlib.h -- */ 630205194Sdelphijint ZEXPORT gzclose_w(file) 631205194Sdelphij gzFile file; 632205194Sdelphij{ 633230837Sdelphij int ret = Z_OK; 634205194Sdelphij gz_statep state; 635205194Sdelphij 636205194Sdelphij /* get internal structure */ 637205194Sdelphij if (file == NULL) 638205194Sdelphij return Z_STREAM_ERROR; 639205194Sdelphij state = (gz_statep)file; 640205194Sdelphij 641205194Sdelphij /* check that we're writing */ 642205194Sdelphij if (state->mode != GZ_WRITE) 643205194Sdelphij return Z_STREAM_ERROR; 644205194Sdelphij 645205194Sdelphij /* check for seek request */ 646205194Sdelphij if (state->seek) { 647205194Sdelphij state->seek = 0; 648230837Sdelphij if (gz_zero(state, state->skip) == -1) 649230837Sdelphij ret = state->err; 650205194Sdelphij } 651205194Sdelphij 652205194Sdelphij /* flush, free memory, and close file */ 653250224Sdelphij if (gz_comp(state, Z_FINISH) == -1) 654250224Sdelphij ret = state->err; 655237248Sdelphij if (state->size) { 656237248Sdelphij if (!state->direct) { 657237248Sdelphij (void)deflateEnd(&(state->strm)); 658237248Sdelphij free(state->out); 659237248Sdelphij } 660237248Sdelphij free(state->in); 661230837Sdelphij } 662205194Sdelphij gz_error(state, Z_OK, NULL); 663205194Sdelphij free(state->path); 664230837Sdelphij if (close(state->fd) == -1) 665230837Sdelphij ret = Z_ERRNO; 666205194Sdelphij free(state); 667230837Sdelphij return ret; 668205194Sdelphij} 669