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