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