1205194Sdelphij/* gzwrite.c -- zlib functions for writing gzip files 2254069Sdelphij * Copyright (C) 2004, 2005, 2010, 2011, 2012, 2013 Mark Adler 3205194Sdelphij * For conditions of distribution and use, see copyright notice in zlib.h 4205194Sdelphij */ 5205194Sdelphij 6237691Sdelphij/* $FreeBSD$ */ 7237691Sdelphij 8205194Sdelphij#include "gzguts.h" 9205305Sdelphij#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)); 15205194Sdelphij 16205194Sdelphij/* Initialize state for writing a gzip file. Mark initialization by setting 17205194Sdelphij state->size to non-zero. Return -1 on failure or 0 on success. */ 18205194Sdelphijlocal int gz_init(state) 19205194Sdelphij gz_statep state; 20205194Sdelphij{ 21205194Sdelphij int ret; 22205194Sdelphij z_streamp strm = &(state->strm); 23205194Sdelphij 24237691Sdelphij /* allocate input buffer */ 25254069Sdelphij state->in = (unsigned char *)malloc(state->want); 26237691Sdelphij if (state->in == NULL) { 27205194Sdelphij gz_error(state, Z_MEM_ERROR, "out of memory"); 28205194Sdelphij return -1; 29205194Sdelphij } 30205194Sdelphij 31237691Sdelphij /* only need output buffer and deflate state if compressing */ 32237691Sdelphij if (!state->direct) { 33237691Sdelphij /* allocate output buffer */ 34254069Sdelphij state->out = (unsigned char *)malloc(state->want); 35237691Sdelphij if (state->out == NULL) { 36237691Sdelphij free(state->in); 37237691Sdelphij gz_error(state, Z_MEM_ERROR, "out of memory"); 38237691Sdelphij return -1; 39237691Sdelphij } 40237691Sdelphij 41237691Sdelphij /* allocate deflate memory, set up for gzip compression */ 42237691Sdelphij strm->zalloc = Z_NULL; 43237691Sdelphij strm->zfree = Z_NULL; 44237691Sdelphij strm->opaque = Z_NULL; 45237691Sdelphij ret = deflateInit2(strm, state->level, Z_DEFLATED, 46237691Sdelphij MAX_WBITS + 16, DEF_MEM_LEVEL, state->strategy); 47237691Sdelphij if (ret != Z_OK) { 48237691Sdelphij free(state->out); 49237691Sdelphij free(state->in); 50237691Sdelphij gz_error(state, Z_MEM_ERROR, "out of memory"); 51237691Sdelphij return -1; 52237691Sdelphij } 53205194Sdelphij } 54205194Sdelphij 55205194Sdelphij /* mark state as initialized */ 56205194Sdelphij state->size = state->want; 57205194Sdelphij 58237691Sdelphij /* initialize write buffer if compressing */ 59237691Sdelphij if (!state->direct) { 60237691Sdelphij strm->avail_out = state->size; 61237691Sdelphij strm->next_out = state->out; 62237691Sdelphij state->x.next = strm->next_out; 63237691Sdelphij } 64205194Sdelphij return 0; 65205194Sdelphij} 66205194Sdelphij 67205194Sdelphij/* Compress whatever is at avail_in and next_in and write to the output file. 68205194Sdelphij Return -1 if there is an error writing to the output file, otherwise 0. 69205194Sdelphij flush is assumed to be a valid deflate() flush value. If flush is Z_FINISH, 70237691Sdelphij then the deflate() state is reset to start a new gzip stream. If gz->direct 71237691Sdelphij is true, then simply write to the output file without compressing, and 72237691Sdelphij ignore flush. */ 73205194Sdelphijlocal int gz_comp(state, flush) 74205194Sdelphij gz_statep state; 75205194Sdelphij int flush; 76205194Sdelphij{ 77205194Sdelphij int ret, got; 78205194Sdelphij unsigned have; 79205194Sdelphij z_streamp strm = &(state->strm); 80205194Sdelphij 81205194Sdelphij /* allocate memory if this is the first time through */ 82205194Sdelphij if (state->size == 0 && gz_init(state) == -1) 83205194Sdelphij return -1; 84205194Sdelphij 85237691Sdelphij /* write directly if requested */ 86237691Sdelphij if (state->direct) { 87237691Sdelphij got = write(state->fd, strm->next_in, strm->avail_in); 88237691Sdelphij if (got < 0 || (unsigned)got != strm->avail_in) { 89237691Sdelphij gz_error(state, Z_ERRNO, zstrerror()); 90237691Sdelphij return -1; 91237691Sdelphij } 92237691Sdelphij strm->avail_in = 0; 93237691Sdelphij return 0; 94237691Sdelphij } 95237691Sdelphij 96205194Sdelphij /* run deflate() on provided input until it produces no more output */ 97205194Sdelphij ret = Z_OK; 98205194Sdelphij do { 99205194Sdelphij /* write out current buffer contents if full, or if flushing, but if 100205194Sdelphij doing Z_FINISH then don't write until we get to Z_STREAM_END */ 101205194Sdelphij if (strm->avail_out == 0 || (flush != Z_NO_FLUSH && 102205194Sdelphij (flush != Z_FINISH || ret == Z_STREAM_END))) { 103237691Sdelphij have = (unsigned)(strm->next_out - state->x.next); 104237691Sdelphij if (have && ((got = write(state->fd, state->x.next, have)) < 0 || 105205194Sdelphij (unsigned)got != have)) { 106205194Sdelphij gz_error(state, Z_ERRNO, zstrerror()); 107205194Sdelphij return -1; 108205194Sdelphij } 109205194Sdelphij if (strm->avail_out == 0) { 110205194Sdelphij strm->avail_out = state->size; 111205194Sdelphij strm->next_out = state->out; 112205194Sdelphij } 113237691Sdelphij state->x.next = strm->next_out; 114205194Sdelphij } 115205194Sdelphij 116205194Sdelphij /* compress */ 117205194Sdelphij have = strm->avail_out; 118205194Sdelphij ret = deflate(strm, flush); 119205194Sdelphij if (ret == Z_STREAM_ERROR) { 120205194Sdelphij gz_error(state, Z_STREAM_ERROR, 121205194Sdelphij "internal error: deflate stream corrupt"); 122205194Sdelphij return -1; 123205194Sdelphij } 124205194Sdelphij have -= strm->avail_out; 125205194Sdelphij } while (have); 126205194Sdelphij 127205194Sdelphij /* if that completed a deflate stream, allow another to start */ 128205194Sdelphij if (flush == Z_FINISH) 129205194Sdelphij deflateReset(strm); 130205194Sdelphij 131205194Sdelphij /* all done, no errors */ 132205194Sdelphij return 0; 133205194Sdelphij} 134205194Sdelphij 135205194Sdelphij/* Compress len zeros to output. Return -1 on error, 0 on success. */ 136205194Sdelphijlocal int gz_zero(state, len) 137205194Sdelphij gz_statep state; 138205194Sdelphij z_off64_t len; 139205194Sdelphij{ 140205194Sdelphij int first; 141205194Sdelphij unsigned n; 142205194Sdelphij z_streamp strm = &(state->strm); 143205194Sdelphij 144205194Sdelphij /* consume whatever's left in the input buffer */ 145205194Sdelphij if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1) 146205194Sdelphij return -1; 147205194Sdelphij 148205194Sdelphij /* compress len zeros (len guaranteed > 0) */ 149205194Sdelphij first = 1; 150205194Sdelphij while (len) { 151205194Sdelphij n = GT_OFF(state->size) || (z_off64_t)state->size > len ? 152205194Sdelphij (unsigned)len : state->size; 153205194Sdelphij if (first) { 154205194Sdelphij memset(state->in, 0, n); 155205194Sdelphij first = 0; 156205194Sdelphij } 157205194Sdelphij strm->avail_in = n; 158205194Sdelphij strm->next_in = state->in; 159237691Sdelphij state->x.pos += n; 160205194Sdelphij if (gz_comp(state, Z_NO_FLUSH) == -1) 161205194Sdelphij return -1; 162205194Sdelphij len -= n; 163205194Sdelphij } 164205194Sdelphij return 0; 165205194Sdelphij} 166205194Sdelphij 167205194Sdelphij/* -- see zlib.h -- */ 168205194Sdelphijint ZEXPORT gzwrite(file, buf, len) 169205194Sdelphij gzFile file; 170205194Sdelphij voidpc buf; 171205194Sdelphij unsigned len; 172205194Sdelphij{ 173205194Sdelphij unsigned put = len; 174205194Sdelphij gz_statep state; 175205194Sdelphij z_streamp strm; 176205194Sdelphij 177205194Sdelphij /* get internal structure */ 178205194Sdelphij if (file == NULL) 179205194Sdelphij return 0; 180205194Sdelphij state = (gz_statep)file; 181205194Sdelphij strm = &(state->strm); 182205194Sdelphij 183205194Sdelphij /* check that we're writing and that there's no error */ 184205194Sdelphij if (state->mode != GZ_WRITE || state->err != Z_OK) 185205194Sdelphij return 0; 186205194Sdelphij 187205194Sdelphij /* since an int is returned, make sure len fits in one, otherwise return 188205194Sdelphij with an error (this avoids the flaw in the interface) */ 189205194Sdelphij if ((int)len < 0) { 190237691Sdelphij gz_error(state, Z_DATA_ERROR, "requested length does not fit in int"); 191205194Sdelphij return 0; 192205194Sdelphij } 193205194Sdelphij 194205194Sdelphij /* if len is zero, avoid unnecessary operations */ 195205194Sdelphij if (len == 0) 196205194Sdelphij return 0; 197205194Sdelphij 198205194Sdelphij /* allocate memory if this is the first time through */ 199205194Sdelphij if (state->size == 0 && gz_init(state) == -1) 200205194Sdelphij return 0; 201205194Sdelphij 202205194Sdelphij /* check for seek request */ 203205194Sdelphij if (state->seek) { 204205194Sdelphij state->seek = 0; 205205194Sdelphij if (gz_zero(state, state->skip) == -1) 206205194Sdelphij return 0; 207205194Sdelphij } 208205194Sdelphij 209205194Sdelphij /* for small len, copy to input buffer, otherwise compress directly */ 210205194Sdelphij if (len < state->size) { 211205194Sdelphij /* copy to input buffer, compress when full */ 212205194Sdelphij do { 213254069Sdelphij unsigned have, copy; 214254069Sdelphij 215205194Sdelphij if (strm->avail_in == 0) 216205194Sdelphij strm->next_in = state->in; 217254069Sdelphij have = (unsigned)((strm->next_in + strm->avail_in) - state->in); 218254069Sdelphij copy = state->size - have; 219254069Sdelphij if (copy > len) 220254069Sdelphij copy = len; 221254069Sdelphij memcpy(state->in + have, buf, copy); 222254069Sdelphij strm->avail_in += copy; 223254069Sdelphij state->x.pos += copy; 224254069Sdelphij buf = (const char *)buf + copy; 225254069Sdelphij len -= copy; 226205194Sdelphij if (len && gz_comp(state, Z_NO_FLUSH) == -1) 227205194Sdelphij return 0; 228205194Sdelphij } while (len); 229205194Sdelphij } 230205194Sdelphij else { 231205194Sdelphij /* consume whatever's left in the input buffer */ 232205194Sdelphij if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1) 233205194Sdelphij return 0; 234205194Sdelphij 235205194Sdelphij /* directly compress user buffer to file */ 236205194Sdelphij strm->avail_in = len; 237254069Sdelphij strm->next_in = (z_const Bytef *)buf; 238237691Sdelphij state->x.pos += len; 239205194Sdelphij if (gz_comp(state, Z_NO_FLUSH) == -1) 240205194Sdelphij return 0; 241205194Sdelphij } 242205194Sdelphij 243205194Sdelphij /* input was all buffered or compressed (put will fit in int) */ 244205194Sdelphij return (int)put; 245205194Sdelphij} 246205194Sdelphij 247205194Sdelphij/* -- see zlib.h -- */ 248205194Sdelphijint ZEXPORT gzputc(file, c) 249205194Sdelphij gzFile file; 250205194Sdelphij int c; 251205194Sdelphij{ 252254069Sdelphij unsigned have; 253205194Sdelphij unsigned char buf[1]; 254205194Sdelphij gz_statep state; 255205194Sdelphij z_streamp strm; 256205194Sdelphij 257205194Sdelphij /* get internal structure */ 258205194Sdelphij if (file == NULL) 259205194Sdelphij return -1; 260205194Sdelphij state = (gz_statep)file; 261205194Sdelphij strm = &(state->strm); 262205194Sdelphij 263205194Sdelphij /* check that we're writing and that there's no error */ 264205194Sdelphij if (state->mode != GZ_WRITE || state->err != Z_OK) 265205194Sdelphij return -1; 266205194Sdelphij 267205194Sdelphij /* check for seek request */ 268205194Sdelphij if (state->seek) { 269205194Sdelphij state->seek = 0; 270205194Sdelphij if (gz_zero(state, state->skip) == -1) 271205194Sdelphij return -1; 272205194Sdelphij } 273205194Sdelphij 274205194Sdelphij /* try writing to input buffer for speed (state->size == 0 if buffer not 275205194Sdelphij initialized) */ 276254069Sdelphij if (state->size) { 277205194Sdelphij if (strm->avail_in == 0) 278205194Sdelphij strm->next_in = state->in; 279254069Sdelphij have = (unsigned)((strm->next_in + strm->avail_in) - state->in); 280254069Sdelphij if (have < state->size) { 281254069Sdelphij state->in[have] = c; 282254069Sdelphij strm->avail_in++; 283254069Sdelphij state->x.pos++; 284254069Sdelphij return c & 0xff; 285254069Sdelphij } 286205194Sdelphij } 287205194Sdelphij 288205194Sdelphij /* no room in buffer or not initialized, use gz_write() */ 289205194Sdelphij buf[0] = c; 290205194Sdelphij if (gzwrite(file, buf, 1) != 1) 291205194Sdelphij return -1; 292237691Sdelphij return c & 0xff; 293205194Sdelphij} 294205194Sdelphij 295205194Sdelphij/* -- see zlib.h -- */ 296205194Sdelphijint ZEXPORT gzputs(file, str) 297205194Sdelphij gzFile file; 298205194Sdelphij const char *str; 299205194Sdelphij{ 300205194Sdelphij int ret; 301205194Sdelphij unsigned len; 302205194Sdelphij 303205194Sdelphij /* write string */ 304205194Sdelphij len = (unsigned)strlen(str); 305205194Sdelphij ret = gzwrite(file, str, len); 306205194Sdelphij return ret == 0 && len != 0 ? -1 : ret; 307205194Sdelphij} 308205194Sdelphij 309237691Sdelphij#if defined(STDC) || defined(Z_HAVE_STDARG_H) 310205194Sdelphij#include <stdarg.h> 311205194Sdelphij 312205194Sdelphij/* -- see zlib.h -- */ 313254069Sdelphijint ZEXPORTVA gzvprintf(gzFile file, const char *format, va_list va) 314205194Sdelphij{ 315205194Sdelphij int size, len; 316205194Sdelphij gz_statep state; 317205194Sdelphij z_streamp strm; 318205194Sdelphij 319205194Sdelphij /* get internal structure */ 320205194Sdelphij if (file == NULL) 321205194Sdelphij return -1; 322205194Sdelphij state = (gz_statep)file; 323205194Sdelphij strm = &(state->strm); 324205194Sdelphij 325205194Sdelphij /* check that we're writing and that there's no error */ 326205194Sdelphij if (state->mode != GZ_WRITE || state->err != Z_OK) 327205194Sdelphij return 0; 328205194Sdelphij 329205194Sdelphij /* make sure we have some buffer space */ 330205194Sdelphij if (state->size == 0 && gz_init(state) == -1) 331205194Sdelphij return 0; 332205194Sdelphij 333205194Sdelphij /* check for seek request */ 334205194Sdelphij if (state->seek) { 335205194Sdelphij state->seek = 0; 336205194Sdelphij if (gz_zero(state, state->skip) == -1) 337205194Sdelphij return 0; 338205194Sdelphij } 339205194Sdelphij 340205194Sdelphij /* consume whatever's left in the input buffer */ 341205194Sdelphij if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1) 342205194Sdelphij return 0; 343205194Sdelphij 344205194Sdelphij /* do the printf() into the input buffer, put length in len */ 345205194Sdelphij size = (int)(state->size); 346205194Sdelphij state->in[size - 1] = 0; 347205194Sdelphij#ifdef NO_vsnprintf 348205194Sdelphij# ifdef HAS_vsprintf_void 349237691Sdelphij (void)vsprintf((char *)(state->in), format, va); 350205194Sdelphij for (len = 0; len < size; len++) 351205194Sdelphij if (state->in[len] == 0) break; 352205194Sdelphij# else 353237691Sdelphij len = vsprintf((char *)(state->in), format, va); 354205194Sdelphij# endif 355205194Sdelphij#else 356205194Sdelphij# ifdef HAS_vsnprintf_void 357237691Sdelphij (void)vsnprintf((char *)(state->in), size, format, va); 358237691Sdelphij len = strlen((char *)(state->in)); 359205194Sdelphij# else 360205194Sdelphij len = vsnprintf((char *)(state->in), size, format, va); 361205194Sdelphij# endif 362205194Sdelphij#endif 363205194Sdelphij 364205194Sdelphij /* check that printf() results fit in buffer */ 365205194Sdelphij if (len <= 0 || len >= (int)size || state->in[size - 1] != 0) 366205194Sdelphij return 0; 367205194Sdelphij 368205194Sdelphij /* update buffer and position, defer compression until needed */ 369205194Sdelphij strm->avail_in = (unsigned)len; 370205194Sdelphij strm->next_in = state->in; 371237691Sdelphij state->x.pos += len; 372205194Sdelphij return len; 373205194Sdelphij} 374205194Sdelphij 375254069Sdelphijint ZEXPORTVA gzprintf(gzFile file, const char *format, ...) 376254069Sdelphij{ 377254069Sdelphij va_list va; 378254069Sdelphij int ret; 379254069Sdelphij 380254069Sdelphij va_start(va, format); 381254069Sdelphij ret = gzvprintf(file, format, va); 382254069Sdelphij va_end(va); 383254069Sdelphij return ret; 384254069Sdelphij} 385254069Sdelphij 386237691Sdelphij#else /* !STDC && !Z_HAVE_STDARG_H */ 387205194Sdelphij 388205194Sdelphij/* -- see zlib.h -- */ 389205194Sdelphijint ZEXPORTVA gzprintf (file, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, 390205194Sdelphij a11, a12, a13, a14, a15, a16, a17, a18, a19, a20) 391205194Sdelphij gzFile file; 392205194Sdelphij const char *format; 393205194Sdelphij int a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, 394205194Sdelphij a11, a12, a13, a14, a15, a16, a17, a18, a19, a20; 395205194Sdelphij{ 396205194Sdelphij int size, len; 397205194Sdelphij gz_statep state; 398205194Sdelphij z_streamp strm; 399205194Sdelphij 400205194Sdelphij /* get internal structure */ 401205194Sdelphij if (file == NULL) 402205194Sdelphij return -1; 403205194Sdelphij state = (gz_statep)file; 404205194Sdelphij strm = &(state->strm); 405205194Sdelphij 406237691Sdelphij /* check that can really pass pointer in ints */ 407237691Sdelphij if (sizeof(int) != sizeof(void *)) 408237691Sdelphij return 0; 409237691Sdelphij 410205194Sdelphij /* check that we're writing and that there's no error */ 411205194Sdelphij if (state->mode != GZ_WRITE || state->err != Z_OK) 412205194Sdelphij return 0; 413205194Sdelphij 414205194Sdelphij /* make sure we have some buffer space */ 415205194Sdelphij if (state->size == 0 && gz_init(state) == -1) 416205194Sdelphij return 0; 417205194Sdelphij 418205194Sdelphij /* check for seek request */ 419205194Sdelphij if (state->seek) { 420205194Sdelphij state->seek = 0; 421205194Sdelphij if (gz_zero(state, state->skip) == -1) 422205194Sdelphij return 0; 423205194Sdelphij } 424205194Sdelphij 425205194Sdelphij /* consume whatever's left in the input buffer */ 426205194Sdelphij if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1) 427205194Sdelphij return 0; 428205194Sdelphij 429205194Sdelphij /* do the printf() into the input buffer, put length in len */ 430205194Sdelphij size = (int)(state->size); 431205194Sdelphij state->in[size - 1] = 0; 432205194Sdelphij#ifdef NO_snprintf 433205194Sdelphij# ifdef HAS_sprintf_void 434237691Sdelphij sprintf((char *)(state->in), format, a1, a2, a3, a4, a5, a6, a7, a8, 435205194Sdelphij a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20); 436205194Sdelphij for (len = 0; len < size; len++) 437205194Sdelphij if (state->in[len] == 0) break; 438205194Sdelphij# else 439237691Sdelphij len = sprintf((char *)(state->in), format, a1, a2, a3, a4, a5, a6, a7, a8, 440237691Sdelphij a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20); 441205194Sdelphij# endif 442205194Sdelphij#else 443205194Sdelphij# ifdef HAS_snprintf_void 444237691Sdelphij snprintf((char *)(state->in), size, format, a1, a2, a3, a4, a5, a6, a7, a8, 445205194Sdelphij a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20); 446237691Sdelphij len = strlen((char *)(state->in)); 447205194Sdelphij# else 448237691Sdelphij len = snprintf((char *)(state->in), size, format, a1, a2, a3, a4, a5, a6, 449237691Sdelphij a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, 450237691Sdelphij a19, a20); 451205194Sdelphij# endif 452205194Sdelphij#endif 453205194Sdelphij 454205194Sdelphij /* check that printf() results fit in buffer */ 455205194Sdelphij if (len <= 0 || len >= (int)size || state->in[size - 1] != 0) 456205194Sdelphij return 0; 457205194Sdelphij 458205194Sdelphij /* update buffer and position, defer compression until needed */ 459205194Sdelphij strm->avail_in = (unsigned)len; 460205194Sdelphij strm->next_in = state->in; 461237691Sdelphij state->x.pos += len; 462205194Sdelphij return len; 463205194Sdelphij} 464205194Sdelphij 465205194Sdelphij#endif 466205194Sdelphij 467205194Sdelphij/* -- see zlib.h -- */ 468205194Sdelphijint ZEXPORT gzflush(file, flush) 469205194Sdelphij gzFile file; 470205194Sdelphij int flush; 471205194Sdelphij{ 472205194Sdelphij gz_statep state; 473205194Sdelphij 474205194Sdelphij /* get internal structure */ 475205194Sdelphij if (file == NULL) 476205194Sdelphij return -1; 477205194Sdelphij state = (gz_statep)file; 478205194Sdelphij 479205194Sdelphij /* check that we're writing and that there's no error */ 480205194Sdelphij if (state->mode != GZ_WRITE || state->err != Z_OK) 481205194Sdelphij return Z_STREAM_ERROR; 482205194Sdelphij 483205194Sdelphij /* check flush parameter */ 484205194Sdelphij if (flush < 0 || flush > Z_FINISH) 485205194Sdelphij return Z_STREAM_ERROR; 486205194Sdelphij 487205194Sdelphij /* check for seek request */ 488205194Sdelphij if (state->seek) { 489205194Sdelphij state->seek = 0; 490205194Sdelphij if (gz_zero(state, state->skip) == -1) 491205194Sdelphij return -1; 492205194Sdelphij } 493205194Sdelphij 494205194Sdelphij /* compress remaining data with requested flush */ 495205194Sdelphij gz_comp(state, flush); 496205194Sdelphij return state->err; 497205194Sdelphij} 498205194Sdelphij 499205194Sdelphij/* -- see zlib.h -- */ 500205194Sdelphijint ZEXPORT gzsetparams(file, level, strategy) 501205194Sdelphij gzFile file; 502205194Sdelphij int level; 503205194Sdelphij int strategy; 504205194Sdelphij{ 505205194Sdelphij gz_statep state; 506205194Sdelphij z_streamp strm; 507205194Sdelphij 508205194Sdelphij /* get internal structure */ 509205194Sdelphij if (file == NULL) 510205194Sdelphij return Z_STREAM_ERROR; 511205194Sdelphij state = (gz_statep)file; 512205194Sdelphij strm = &(state->strm); 513205194Sdelphij 514205194Sdelphij /* check that we're writing and that there's no error */ 515205194Sdelphij if (state->mode != GZ_WRITE || state->err != Z_OK) 516205194Sdelphij return Z_STREAM_ERROR; 517205194Sdelphij 518205194Sdelphij /* if no change is requested, then do nothing */ 519205194Sdelphij if (level == state->level && strategy == state->strategy) 520205194Sdelphij return Z_OK; 521205194Sdelphij 522205194Sdelphij /* check for seek request */ 523205194Sdelphij if (state->seek) { 524205194Sdelphij state->seek = 0; 525205194Sdelphij if (gz_zero(state, state->skip) == -1) 526205194Sdelphij return -1; 527205194Sdelphij } 528205194Sdelphij 529205194Sdelphij /* change compression parameters for subsequent input */ 530205194Sdelphij if (state->size) { 531205194Sdelphij /* flush previous input with previous parameters before changing */ 532205194Sdelphij if (strm->avail_in && gz_comp(state, Z_PARTIAL_FLUSH) == -1) 533205194Sdelphij return state->err; 534205194Sdelphij deflateParams(strm, level, strategy); 535205194Sdelphij } 536205194Sdelphij state->level = level; 537205194Sdelphij state->strategy = strategy; 538205194Sdelphij return Z_OK; 539205194Sdelphij} 540205194Sdelphij 541205194Sdelphij/* -- see zlib.h -- */ 542205194Sdelphijint ZEXPORT gzclose_w(file) 543205194Sdelphij gzFile file; 544205194Sdelphij{ 545237691Sdelphij int ret = Z_OK; 546205194Sdelphij gz_statep state; 547205194Sdelphij 548205194Sdelphij /* get internal structure */ 549205194Sdelphij if (file == NULL) 550205194Sdelphij return Z_STREAM_ERROR; 551205194Sdelphij state = (gz_statep)file; 552205194Sdelphij 553205194Sdelphij /* check that we're writing */ 554205194Sdelphij if (state->mode != GZ_WRITE) 555205194Sdelphij return Z_STREAM_ERROR; 556205194Sdelphij 557205194Sdelphij /* check for seek request */ 558205194Sdelphij if (state->seek) { 559205194Sdelphij state->seek = 0; 560237691Sdelphij if (gz_zero(state, state->skip) == -1) 561237691Sdelphij ret = state->err; 562205194Sdelphij } 563205194Sdelphij 564205194Sdelphij /* flush, free memory, and close file */ 565254069Sdelphij if (gz_comp(state, Z_FINISH) == -1) 566254069Sdelphij ret = state->err; 567237691Sdelphij if (state->size) { 568237691Sdelphij if (!state->direct) { 569237691Sdelphij (void)deflateEnd(&(state->strm)); 570237691Sdelphij free(state->out); 571237691Sdelphij } 572237691Sdelphij free(state->in); 573237691Sdelphij } 574205194Sdelphij gz_error(state, Z_OK, NULL); 575205194Sdelphij free(state->path); 576237691Sdelphij if (close(state->fd) == -1) 577237691Sdelphij ret = Z_ERRNO; 578205194Sdelphij free(state); 579237691Sdelphij return ret; 580205194Sdelphij} 581