gzwrite.c revision 272461
1160994Ssam/* gzwrite.c -- zlib functions for writing gzip files 2160994Ssam * Copyright (C) 2004, 2005, 2010, 2011, 2012, 2013 Mark Adler 3160994Ssam * For conditions of distribution and use, see copyright notice in zlib.h 4160994Ssam */ 5160994Ssam 6160994Ssam/* $FreeBSD: releng/10.1/lib/libz/gzwrite.c 250261 2013-05-05 06:20:49Z delphij $ */ 7160994Ssam 8160994Ssam#include "gzguts.h" 9160994Ssam#include <unistd.h> 10160994Ssam 11160994Ssam/* Local functions */ 12160994Ssamlocal int gz_init OF((gz_statep)); 13160994Ssamlocal int gz_comp OF((gz_statep, int)); 14160994Ssamlocal int gz_zero OF((gz_statep, z_off64_t)); 15160994Ssam 16160994Ssam/* Initialize state for writing a gzip file. Mark initialization by setting 17160994Ssam state->size to non-zero. Return -1 on failure or 0 on success. */ 18160994Ssamlocal int gz_init(state) 19160994Ssam gz_statep state; 20160994Ssam{ 21160994Ssam int ret; 22160994Ssam z_streamp strm = &(state->strm); 23160994Ssam 24160994Ssam /* allocate input buffer */ 25160994Ssam state->in = (unsigned char *)malloc(state->want); 26160994Ssam if (state->in == NULL) { 27160994Ssam gz_error(state, Z_MEM_ERROR, "out of memory"); 28160994Ssam return -1; 29160994Ssam } 30160994Ssam 31160994Ssam /* only need output buffer and deflate state if compressing */ 32160994Ssam if (!state->direct) { 33160994Ssam /* allocate output buffer */ 34160994Ssam state->out = (unsigned char *)malloc(state->want); 35160994Ssam if (state->out == NULL) { 36160994Ssam free(state->in); 37160994Ssam gz_error(state, Z_MEM_ERROR, "out of memory"); 38160994Ssam return -1; 39160994Ssam } 40160994Ssam 41160994Ssam /* allocate deflate memory, set up for gzip compression */ 42160994Ssam strm->zalloc = Z_NULL; 43160994Ssam strm->zfree = Z_NULL; 44160994Ssam strm->opaque = Z_NULL; 45160994Ssam ret = deflateInit2(strm, state->level, Z_DEFLATED, 46160994Ssam MAX_WBITS + 16, DEF_MEM_LEVEL, state->strategy); 47160994Ssam if (ret != Z_OK) { 48160994Ssam free(state->out); 49160994Ssam free(state->in); 50160994Ssam gz_error(state, Z_MEM_ERROR, "out of memory"); 51160994Ssam return -1; 52160994Ssam } 53160994Ssam } 54160994Ssam 55160994Ssam /* mark state as initialized */ 56160994Ssam state->size = state->want; 57160994Ssam 58160994Ssam /* initialize write buffer if compressing */ 59160994Ssam if (!state->direct) { 60160994Ssam strm->avail_out = state->size; 61160994Ssam strm->next_out = state->out; 62160994Ssam state->x.next = strm->next_out; 63160994Ssam } 64160994Ssam return 0; 65160994Ssam} 66160994Ssam 67160994Ssam/* Compress whatever is at avail_in and next_in and write to the output file. 68160994Ssam Return -1 if there is an error writing to the output file, otherwise 0. 69160994Ssam flush is assumed to be a valid deflate() flush value. If flush is Z_FINISH, 70160994Ssam then the deflate() state is reset to start a new gzip stream. If gz->direct 71160994Ssam is true, then simply write to the output file without compressing, and 72160994Ssam ignore flush. */ 73160994Ssamlocal int gz_comp(state, flush) 74160994Ssam gz_statep state; 75160994Ssam int flush; 76160994Ssam{ 77160994Ssam int ret, got; 78160994Ssam unsigned have; 79160994Ssam z_streamp strm = &(state->strm); 80160994Ssam 81160994Ssam /* allocate memory if this is the first time through */ 82160994Ssam if (state->size == 0 && gz_init(state) == -1) 83160994Ssam return -1; 84160994Ssam 85160994Ssam /* write directly if requested */ 86160994Ssam if (state->direct) { 87160994Ssam got = write(state->fd, strm->next_in, strm->avail_in); 88160994Ssam if (got < 0 || (unsigned)got != strm->avail_in) { 89160994Ssam gz_error(state, Z_ERRNO, zstrerror()); 90160994Ssam return -1; 91160994Ssam } 92160994Ssam strm->avail_in = 0; 93160994Ssam return 0; 94160994Ssam } 95160994Ssam 96160994Ssam /* run deflate() on provided input until it produces no more output */ 97160994Ssam ret = Z_OK; 98160994Ssam do { 99160994Ssam /* write out current buffer contents if full, or if flushing, but if 100160994Ssam doing Z_FINISH then don't write until we get to Z_STREAM_END */ 101160994Ssam if (strm->avail_out == 0 || (flush != Z_NO_FLUSH && 102160994Ssam (flush != Z_FINISH || ret == Z_STREAM_END))) { 103160994Ssam have = (unsigned)(strm->next_out - state->x.next); 104160994Ssam if (have && ((got = write(state->fd, state->x.next, have)) < 0 || 105160994Ssam (unsigned)got != have)) { 106160994Ssam gz_error(state, Z_ERRNO, zstrerror()); 107160994Ssam return -1; 108160994Ssam } 109160994Ssam if (strm->avail_out == 0) { 110160994Ssam strm->avail_out = state->size; 111160994Ssam strm->next_out = state->out; 112160994Ssam } 113160994Ssam state->x.next = strm->next_out; 114160994Ssam } 115160994Ssam 116160994Ssam /* compress */ 117160994Ssam have = strm->avail_out; 118160994Ssam ret = deflate(strm, flush); 119160994Ssam if (ret == Z_STREAM_ERROR) { 120160994Ssam gz_error(state, Z_STREAM_ERROR, 121160994Ssam "internal error: deflate stream corrupt"); 122160994Ssam return -1; 123160994Ssam } 124160994Ssam have -= strm->avail_out; 125160994Ssam } while (have); 126160994Ssam 127160994Ssam /* if that completed a deflate stream, allow another to start */ 128160994Ssam if (flush == Z_FINISH) 129160994Ssam deflateReset(strm); 130160994Ssam 131160994Ssam /* all done, no errors */ 132160994Ssam return 0; 133160994Ssam} 134160994Ssam 135160994Ssam/* Compress len zeros to output. Return -1 on error, 0 on success. */ 136160994Ssamlocal int gz_zero(state, len) 137160994Ssam gz_statep state; 138160994Ssam z_off64_t len; 139160994Ssam{ 140160994Ssam int first; 141160994Ssam unsigned n; 142160994Ssam z_streamp strm = &(state->strm); 143160994Ssam 144160994Ssam /* consume whatever's left in the input buffer */ 145160994Ssam if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1) 146160994Ssam return -1; 147160994Ssam 148160994Ssam /* compress len zeros (len guaranteed > 0) */ 149160994Ssam first = 1; 150160994Ssam while (len) { 151160994Ssam n = GT_OFF(state->size) || (z_off64_t)state->size > len ? 152160994Ssam (unsigned)len : state->size; 153160994Ssam if (first) { 154160994Ssam memset(state->in, 0, n); 155160994Ssam first = 0; 156160994Ssam } 157160994Ssam strm->avail_in = n; 158160994Ssam strm->next_in = state->in; 159160994Ssam state->x.pos += n; 160160994Ssam if (gz_comp(state, Z_NO_FLUSH) == -1) 161160994Ssam return -1; 162160994Ssam len -= n; 163160994Ssam } 164160994Ssam return 0; 165160994Ssam} 166160994Ssam 167160994Ssam/* -- see zlib.h -- */ 168160994Ssamint ZEXPORT gzwrite(file, buf, len) 169160994Ssam gzFile file; 170160994Ssam voidpc buf; 171160994Ssam unsigned len; 172160994Ssam{ 173160994Ssam unsigned put = len; 174160994Ssam gz_statep state; 175160994Ssam z_streamp strm; 176160994Ssam 177160994Ssam /* get internal structure */ 178160994Ssam if (file == NULL) 179160994Ssam return 0; 180160994Ssam state = (gz_statep)file; 181160994Ssam strm = &(state->strm); 182160994Ssam 183160994Ssam /* check that we're writing and that there's no error */ 184160994Ssam if (state->mode != GZ_WRITE || state->err != Z_OK) 185160994Ssam return 0; 186160994Ssam 187160994Ssam /* since an int is returned, make sure len fits in one, otherwise return 188160994Ssam with an error (this avoids the flaw in the interface) */ 189160994Ssam if ((int)len < 0) { 190160994Ssam gz_error(state, Z_DATA_ERROR, "requested length does not fit in int"); 191160994Ssam return 0; 192160994Ssam } 193160994Ssam 194160994Ssam /* if len is zero, avoid unnecessary operations */ 195160994Ssam if (len == 0) 196160994Ssam return 0; 197160994Ssam 198160994Ssam /* allocate memory if this is the first time through */ 199160994Ssam if (state->size == 0 && gz_init(state) == -1) 200160994Ssam return 0; 201160994Ssam 202160994Ssam /* check for seek request */ 203160994Ssam if (state->seek) { 204160994Ssam state->seek = 0; 205160994Ssam if (gz_zero(state, state->skip) == -1) 206160994Ssam return 0; 207160994Ssam } 208160994Ssam 209160994Ssam /* for small len, copy to input buffer, otherwise compress directly */ 210160994Ssam if (len < state->size) { 211160994Ssam /* copy to input buffer, compress when full */ 212160994Ssam do { 213160994Ssam unsigned have, copy; 214160994Ssam 215160994Ssam if (strm->avail_in == 0) 216160994Ssam strm->next_in = state->in; 217160994Ssam have = (unsigned)((strm->next_in + strm->avail_in) - state->in); 218160994Ssam copy = state->size - have; 219160994Ssam if (copy > len) 220160994Ssam copy = len; 221160994Ssam memcpy(state->in + have, buf, copy); 222160994Ssam strm->avail_in += copy; 223160994Ssam state->x.pos += copy; 224160994Ssam buf = (const char *)buf + copy; 225160994Ssam len -= copy; 226160994Ssam if (len && gz_comp(state, Z_NO_FLUSH) == -1) 227160994Ssam return 0; 228160994Ssam } while (len); 229160994Ssam } 230160994Ssam else { 231160994Ssam /* consume whatever's left in the input buffer */ 232160994Ssam if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1) 233160994Ssam return 0; 234160994Ssam 235160994Ssam /* directly compress user buffer to file */ 236160994Ssam strm->avail_in = len; 237160994Ssam strm->next_in = (z_const Bytef *)buf; 238160994Ssam state->x.pos += len; 239160994Ssam if (gz_comp(state, Z_NO_FLUSH) == -1) 240160994Ssam return 0; 241160994Ssam } 242160994Ssam 243160994Ssam /* input was all buffered or compressed (put will fit in int) */ 244160994Ssam return (int)put; 245160994Ssam} 246160994Ssam 247160994Ssam/* -- see zlib.h -- */ 248160994Ssamint ZEXPORT gzputc(file, c) 249160994Ssam gzFile file; 250160994Ssam int c; 251160994Ssam{ 252160994Ssam unsigned have; 253160994Ssam unsigned char buf[1]; 254160994Ssam gz_statep state; 255160994Ssam z_streamp strm; 256160994Ssam 257160994Ssam /* get internal structure */ 258160994Ssam if (file == NULL) 259160994Ssam return -1; 260160994Ssam state = (gz_statep)file; 261160994Ssam strm = &(state->strm); 262160994Ssam 263160994Ssam /* check that we're writing and that there's no error */ 264160994Ssam if (state->mode != GZ_WRITE || state->err != Z_OK) 265160994Ssam return -1; 266160994Ssam 267160994Ssam /* check for seek request */ 268160994Ssam if (state->seek) { 269160994Ssam state->seek = 0; 270160994Ssam if (gz_zero(state, state->skip) == -1) 271160994Ssam return -1; 272160994Ssam } 273160994Ssam 274160994Ssam /* try writing to input buffer for speed (state->size == 0 if buffer not 275160994Ssam initialized) */ 276160994Ssam if (state->size) { 277160994Ssam if (strm->avail_in == 0) 278195848Ssam strm->next_in = state->in; 279195848Ssam have = (unsigned)((strm->next_in + strm->avail_in) - state->in); 280195848Ssam if (have < state->size) { 281195848Ssam state->in[have] = c; 282195848Ssam strm->avail_in++; 283195848Ssam state->x.pos++; 284195848Ssam return c & 0xff; 285195848Ssam } 286160994Ssam } 287160994Ssam 288160994Ssam /* no room in buffer or not initialized, use gz_write() */ 289160994Ssam buf[0] = c; 290160994Ssam if (gzwrite(file, buf, 1) != 1) 291160994Ssam return -1; 292160994Ssam return c & 0xff; 293160994Ssam} 294160994Ssam 295160994Ssam/* -- see zlib.h -- */ 296160994Ssamint ZEXPORT gzputs(file, str) 297160994Ssam gzFile file; 298160994Ssam const char *str; 299160994Ssam{ 300160994Ssam int ret; 301160994Ssam unsigned len; 302160994Ssam 303160994Ssam /* write string */ 304160994Ssam len = (unsigned)strlen(str); 305160994Ssam ret = gzwrite(file, str, len); 306160994Ssam return ret == 0 && len != 0 ? -1 : ret; 307160994Ssam} 308160994Ssam 309160994Ssam#if defined(STDC) || defined(Z_HAVE_STDARG_H) 310160994Ssam#include <stdarg.h> 311160994Ssam 312160994Ssam/* -- see zlib.h -- */ 313160994Ssamint ZEXPORTVA gzvprintf(gzFile file, const char *format, va_list va) 314160994Ssam{ 315160994Ssam int size, len; 316160994Ssam gz_statep state; 317160994Ssam z_streamp strm; 318160994Ssam 319160994Ssam /* get internal structure */ 320160994Ssam if (file == NULL) 321160994Ssam return -1; 322160994Ssam state = (gz_statep)file; 323160994Ssam strm = &(state->strm); 324160994Ssam 325160994Ssam /* check that we're writing and that there's no error */ 326160994Ssam if (state->mode != GZ_WRITE || state->err != Z_OK) 327160994Ssam return 0; 328160994Ssam 329160994Ssam /* make sure we have some buffer space */ 330160994Ssam if (state->size == 0 && gz_init(state) == -1) 331160994Ssam return 0; 332160994Ssam 333160994Ssam /* check for seek request */ 334160994Ssam if (state->seek) { 335160994Ssam state->seek = 0; 336160994Ssam if (gz_zero(state, state->skip) == -1) 337160994Ssam return 0; 338160994Ssam } 339160994Ssam 340160994Ssam /* consume whatever's left in the input buffer */ 341160994Ssam if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1) 342160994Ssam return 0; 343160994Ssam 344160994Ssam /* do the printf() into the input buffer, put length in len */ 345160994Ssam size = (int)(state->size); 346160994Ssam state->in[size - 1] = 0; 347160994Ssam#ifdef NO_vsnprintf 348160994Ssam# ifdef HAS_vsprintf_void 349160994Ssam (void)vsprintf((char *)(state->in), format, va); 350160994Ssam for (len = 0; len < size; len++) 351160994Ssam if (state->in[len] == 0) break; 352160994Ssam# else 353160994Ssam len = vsprintf((char *)(state->in), format, va); 354160994Ssam# endif 355160994Ssam#else 356160994Ssam# ifdef HAS_vsnprintf_void 357160994Ssam (void)vsnprintf((char *)(state->in), size, format, va); 358160994Ssam len = strlen((char *)(state->in)); 359160994Ssam# else 360160994Ssam len = vsnprintf((char *)(state->in), size, format, va); 361160994Ssam# endif 362160994Ssam#endif 363160994Ssam 364160994Ssam /* check that printf() results fit in buffer */ 365160994Ssam if (len <= 0 || len >= (int)size || state->in[size - 1] != 0) 366160994Ssam return 0; 367160994Ssam 368160994Ssam /* update buffer and position, defer compression until needed */ 369160994Ssam strm->avail_in = (unsigned)len; 370160994Ssam strm->next_in = state->in; 371160994Ssam state->x.pos += len; 372160994Ssam return len; 373160994Ssam} 374160994Ssam 375160994Ssamint ZEXPORTVA gzprintf(gzFile file, const char *format, ...) 376160994Ssam{ 377160994Ssam va_list va; 378160994Ssam int ret; 379160994Ssam 380160994Ssam va_start(va, format); 381160994Ssam ret = gzvprintf(file, format, va); 382160994Ssam va_end(va); 383160994Ssam return ret; 384160994Ssam} 385160994Ssam 386160994Ssam#else /* !STDC && !Z_HAVE_STDARG_H */ 387160994Ssam 388160994Ssam/* -- see zlib.h -- */ 389160994Ssamint ZEXPORTVA gzprintf (file, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, 390160994Ssam a11, a12, a13, a14, a15, a16, a17, a18, a19, a20) 391160994Ssam gzFile file; 392160994Ssam const char *format; 393160994Ssam int a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, 394160994Ssam a11, a12, a13, a14, a15, a16, a17, a18, a19, a20; 395160994Ssam{ 396160994Ssam int size, len; 397160994Ssam gz_statep state; 398160994Ssam z_streamp strm; 399160994Ssam 400160994Ssam /* get internal structure */ 401160994Ssam if (file == NULL) 402160994Ssam return -1; 403160994Ssam state = (gz_statep)file; 404160994Ssam strm = &(state->strm); 405160994Ssam 406160994Ssam /* check that can really pass pointer in ints */ 407160994Ssam if (sizeof(int) != sizeof(void *)) 408160994Ssam return 0; 409160994Ssam 410160994Ssam /* check that we're writing and that there's no error */ 411160994Ssam if (state->mode != GZ_WRITE || state->err != Z_OK) 412160994Ssam return 0; 413160994Ssam 414160994Ssam /* make sure we have some buffer space */ 415160994Ssam if (state->size == 0 && gz_init(state) == -1) 416160994Ssam return 0; 417160994Ssam 418160994Ssam /* check for seek request */ 419160994Ssam if (state->seek) { 420160994Ssam state->seek = 0; 421160994Ssam if (gz_zero(state, state->skip) == -1) 422160994Ssam return 0; 423160994Ssam } 424160994Ssam 425160994Ssam /* consume whatever's left in the input buffer */ 426160994Ssam if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1) 427160994Ssam return 0; 428160994Ssam 429160994Ssam /* do the printf() into the input buffer, put length in len */ 430160994Ssam size = (int)(state->size); 431160994Ssam state->in[size - 1] = 0; 432160994Ssam#ifdef NO_snprintf 433160994Ssam# ifdef HAS_sprintf_void 434160994Ssam sprintf((char *)(state->in), format, a1, a2, a3, a4, a5, a6, a7, a8, 435160994Ssam a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20); 436160994Ssam for (len = 0; len < size; len++) 437160994Ssam if (state->in[len] == 0) break; 438160994Ssam# else 439160994Ssam len = sprintf((char *)(state->in), format, a1, a2, a3, a4, a5, a6, a7, a8, 440160994Ssam a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20); 441160994Ssam# endif 442160994Ssam#else 443160994Ssam# ifdef HAS_snprintf_void 444160994Ssam snprintf((char *)(state->in), size, format, a1, a2, a3, a4, a5, a6, a7, a8, 445160994Ssam a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20); 446160994Ssam len = strlen((char *)(state->in)); 447160994Ssam# else 448160994Ssam len = snprintf((char *)(state->in), size, format, a1, a2, a3, a4, a5, a6, 449160994Ssam a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, 450160994Ssam a19, a20); 451160994Ssam# endif 452160994Ssam#endif 453160994Ssam 454160994Ssam /* check that printf() results fit in buffer */ 455160994Ssam if (len <= 0 || len >= (int)size || state->in[size - 1] != 0) 456160994Ssam return 0; 457160994Ssam 458160994Ssam /* update buffer and position, defer compression until needed */ 459160994Ssam strm->avail_in = (unsigned)len; 460160994Ssam strm->next_in = state->in; 461160994Ssam state->x.pos += len; 462160994Ssam return len; 463160994Ssam} 464160994Ssam 465160994Ssam#endif 466160994Ssam 467160994Ssam/* -- see zlib.h -- */ 468160994Ssamint ZEXPORT gzflush(file, flush) 469160994Ssam gzFile file; 470160994Ssam int flush; 471160994Ssam{ 472160994Ssam gz_statep state; 473160994Ssam 474160994Ssam /* get internal structure */ 475160994Ssam if (file == NULL) 476160994Ssam return -1; 477160994Ssam state = (gz_statep)file; 478160994Ssam 479160994Ssam /* check that we're writing and that there's no error */ 480160994Ssam if (state->mode != GZ_WRITE || state->err != Z_OK) 481160994Ssam return Z_STREAM_ERROR; 482160994Ssam 483160994Ssam /* check flush parameter */ 484160994Ssam if (flush < 0 || flush > Z_FINISH) 485160994Ssam return Z_STREAM_ERROR; 486160994Ssam 487160994Ssam /* check for seek request */ 488160994Ssam if (state->seek) { 489160994Ssam state->seek = 0; 490160994Ssam if (gz_zero(state, state->skip) == -1) 491160994Ssam return -1; 492160994Ssam } 493160994Ssam 494160994Ssam /* compress remaining data with requested flush */ 495160994Ssam gz_comp(state, flush); 496160994Ssam return state->err; 497160994Ssam} 498160994Ssam 499160994Ssam/* -- see zlib.h -- */ 500160994Ssamint ZEXPORT gzsetparams(file, level, strategy) 501160994Ssam gzFile file; 502160994Ssam int level; 503160994Ssam int strategy; 504160994Ssam{ 505160994Ssam gz_statep state; 506160994Ssam z_streamp strm; 507160994Ssam 508160994Ssam /* get internal structure */ 509160994Ssam if (file == NULL) 510160994Ssam return Z_STREAM_ERROR; 511160994Ssam state = (gz_statep)file; 512160994Ssam strm = &(state->strm); 513160994Ssam 514160994Ssam /* check that we're writing and that there's no error */ 515160994Ssam if (state->mode != GZ_WRITE || state->err != Z_OK) 516160994Ssam return Z_STREAM_ERROR; 517160994Ssam 518160994Ssam /* if no change is requested, then do nothing */ 519160994Ssam if (level == state->level && strategy == state->strategy) 520160994Ssam return Z_OK; 521160994Ssam 522160994Ssam /* check for seek request */ 523160994Ssam if (state->seek) { 524160994Ssam state->seek = 0; 525160994Ssam if (gz_zero(state, state->skip) == -1) 526160994Ssam return -1; 527160994Ssam } 528160994Ssam 529160994Ssam /* change compression parameters for subsequent input */ 530160994Ssam if (state->size) { 531160994Ssam /* flush previous input with previous parameters before changing */ 532160994Ssam if (strm->avail_in && gz_comp(state, Z_PARTIAL_FLUSH) == -1) 533160994Ssam return state->err; 534160994Ssam deflateParams(strm, level, strategy); 535160994Ssam } 536160994Ssam state->level = level; 537160994Ssam state->strategy = strategy; 538160994Ssam return Z_OK; 539160994Ssam} 540160994Ssam 541160994Ssam/* -- see zlib.h -- */ 542160994Ssamint ZEXPORT gzclose_w(file) 543160994Ssam gzFile file; 544160994Ssam{ 545160994Ssam int ret = Z_OK; 546160994Ssam gz_statep state; 547160994Ssam 548160994Ssam /* get internal structure */ 549160994Ssam if (file == NULL) 550160994Ssam return Z_STREAM_ERROR; 551160994Ssam state = (gz_statep)file; 552160994Ssam 553160994Ssam /* check that we're writing */ 554160994Ssam if (state->mode != GZ_WRITE) 555160994Ssam return Z_STREAM_ERROR; 556160994Ssam 557160994Ssam /* check for seek request */ 558160994Ssam if (state->seek) { 559160994Ssam state->seek = 0; 560160994Ssam if (gz_zero(state, state->skip) == -1) 561160994Ssam ret = state->err; 562160994Ssam } 563160994Ssam 564160994Ssam /* flush, free memory, and close file */ 565160994Ssam if (gz_comp(state, Z_FINISH) == -1) 566160994Ssam ret = state->err; 567160994Ssam if (state->size) { 568160994Ssam if (!state->direct) { 569160994Ssam (void)deflateEnd(&(state->strm)); 570160994Ssam free(state->out); 571160994Ssam } 572160994Ssam free(state->in); 573160994Ssam } 574160994Ssam gz_error(state, Z_OK, NULL); 575160994Ssam free(state->path); 576160994Ssam if (close(state->fd) == -1) 577160994Ssam ret = Z_ERRNO; 578160994Ssam free(state); 579160994Ssam return ret; 580160994Ssam} 581160994Ssam