File indexing completed on 2024-03-24 03:51:14
0001 /* gzwrite.c -- zlib functions for writing gzip files 0002 * Copyright (C) 2004, 2005, 2010, 2011, 2012, 2013 Mark Adler 0003 * For conditions of distribution and use, see copyright notice in zlib.h 0004 */ 0005 0006 #include "gzguts.h" 0007 0008 /* Local functions */ 0009 local int gz_init OF((gz_statep)); 0010 local int gz_comp OF((gz_statep, int)); 0011 local int gz_zero OF((gz_statep, z_off64_t)); 0012 0013 /* Initialize state for writing a gzip file. Mark initialization by setting 0014 state->size to non-zero. Return -1 on failure or 0 on success. */ 0015 local int gz_init(state) 0016 gz_statep state; 0017 { 0018 int ret; 0019 z_streamp strm = &(state->strm); 0020 0021 /* allocate input buffer */ 0022 state->in = (unsigned char *)malloc(state->want); 0023 if (state->in == NULL) { 0024 gz_error(state, Z_MEM_ERROR, "out of memory"); 0025 return -1; 0026 } 0027 0028 /* only need output buffer and deflate state if compressing */ 0029 if (!state->direct) { 0030 /* allocate output buffer */ 0031 state->out = (unsigned char *)malloc(state->want); 0032 if (state->out == NULL) { 0033 free(state->in); 0034 gz_error(state, Z_MEM_ERROR, "out of memory"); 0035 return -1; 0036 } 0037 0038 /* allocate deflate memory, set up for gzip compression */ 0039 strm->zalloc = Z_NULL; 0040 strm->zfree = Z_NULL; 0041 strm->opaque = Z_NULL; 0042 ret = deflateInit2(strm, state->level, Z_DEFLATED, 0043 MAX_WBITS + 16, DEF_MEM_LEVEL, state->strategy); 0044 if (ret != Z_OK) { 0045 free(state->out); 0046 free(state->in); 0047 gz_error(state, Z_MEM_ERROR, "out of memory"); 0048 return -1; 0049 } 0050 } 0051 0052 /* mark state as initialized */ 0053 state->size = state->want; 0054 0055 /* initialize write buffer if compressing */ 0056 if (!state->direct) { 0057 strm->avail_out = state->size; 0058 strm->next_out = state->out; 0059 state->x.next = strm->next_out; 0060 } 0061 return 0; 0062 } 0063 0064 /* Compress whatever is at avail_in and next_in and write to the output file. 0065 Return -1 if there is an error writing to the output file, otherwise 0. 0066 flush is assumed to be a valid deflate() flush value. If flush is Z_FINISH, 0067 then the deflate() state is reset to start a new gzip stream. If gz->direct 0068 is true, then simply write to the output file without compressing, and 0069 ignore flush. */ 0070 local int gz_comp(state, flush) 0071 gz_statep state; 0072 int flush; 0073 { 0074 int ret, got; 0075 unsigned have; 0076 z_streamp strm = &(state->strm); 0077 0078 /* allocate memory if this is the first time through */ 0079 if (state->size == 0 && gz_init(state) == -1) 0080 return -1; 0081 0082 /* write directly if requested */ 0083 if (state->direct) { 0084 got = write(state->fd, strm->next_in, strm->avail_in); 0085 if (got < 0 || (unsigned)got != strm->avail_in) { 0086 gz_error(state, Z_ERRNO, zstrerror()); 0087 return -1; 0088 } 0089 strm->avail_in = 0; 0090 return 0; 0091 } 0092 0093 /* run deflate() on provided input until it produces no more output */ 0094 ret = Z_OK; 0095 do { 0096 /* write out current buffer contents if full, or if flushing, but if 0097 doing Z_FINISH then don't write until we get to Z_STREAM_END */ 0098 if (strm->avail_out == 0 || (flush != Z_NO_FLUSH && 0099 (flush != Z_FINISH || ret == Z_STREAM_END))) { 0100 have = (unsigned)(strm->next_out - state->x.next); 0101 if (have && ((got = write(state->fd, state->x.next, have)) < 0 || 0102 (unsigned)got != have)) { 0103 gz_error(state, Z_ERRNO, zstrerror()); 0104 return -1; 0105 } 0106 if (strm->avail_out == 0) { 0107 strm->avail_out = state->size; 0108 strm->next_out = state->out; 0109 } 0110 state->x.next = strm->next_out; 0111 } 0112 0113 /* compress */ 0114 have = strm->avail_out; 0115 ret = deflate(strm, flush); 0116 if (ret == Z_STREAM_ERROR) { 0117 gz_error(state, Z_STREAM_ERROR, 0118 "internal error: deflate stream corrupt"); 0119 return -1; 0120 } 0121 have -= strm->avail_out; 0122 } while (have); 0123 0124 /* if that completed a deflate stream, allow another to start */ 0125 if (flush == Z_FINISH) 0126 deflateReset(strm); 0127 0128 /* all done, no errors */ 0129 return 0; 0130 } 0131 0132 /* Compress len zeros to output. Return -1 on error, 0 on success. */ 0133 local int gz_zero(state, len) 0134 gz_statep state; 0135 z_off64_t len; 0136 { 0137 int first; 0138 unsigned n; 0139 z_streamp strm = &(state->strm); 0140 0141 /* consume whatever's left in the input buffer */ 0142 if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1) 0143 return -1; 0144 0145 /* compress len zeros (len guaranteed > 0) */ 0146 first = 1; 0147 while (len) { 0148 n = GT_OFF(state->size) || (z_off64_t)state->size > len ? 0149 (unsigned)len : state->size; 0150 if (first) { 0151 memset(state->in, 0, n); 0152 first = 0; 0153 } 0154 strm->avail_in = n; 0155 strm->next_in = state->in; 0156 state->x.pos += n; 0157 if (gz_comp(state, Z_NO_FLUSH) == -1) 0158 return -1; 0159 len -= n; 0160 } 0161 return 0; 0162 } 0163 0164 /* -- see zlib.h -- */ 0165 int ZEXPORT gzwrite(file, buf, len) 0166 gzFile file; 0167 voidpc buf; 0168 unsigned len; 0169 { 0170 unsigned put = len; 0171 gz_statep state; 0172 z_streamp strm; 0173 0174 /* get internal structure */ 0175 if (file == NULL) 0176 return 0; 0177 state = (gz_statep)file; 0178 strm = &(state->strm); 0179 0180 /* check that we're writing and that there's no error */ 0181 if (state->mode != GZ_WRITE || state->err != Z_OK) 0182 return 0; 0183 0184 /* since an int is returned, make sure len fits in one, otherwise return 0185 with an error (this avoids the flaw in the interface) */ 0186 if ((int)len < 0) { 0187 gz_error(state, Z_DATA_ERROR, "requested length does not fit in int"); 0188 return 0; 0189 } 0190 0191 /* if len is zero, avoid unnecessary operations */ 0192 if (len == 0) 0193 return 0; 0194 0195 /* allocate memory if this is the first time through */ 0196 if (state->size == 0 && gz_init(state) == -1) 0197 return 0; 0198 0199 /* check for seek request */ 0200 if (state->seek) { 0201 state->seek = 0; 0202 if (gz_zero(state, state->skip) == -1) 0203 return 0; 0204 } 0205 0206 /* for small len, copy to input buffer, otherwise compress directly */ 0207 if (len < state->size) { 0208 /* copy to input buffer, compress when full */ 0209 do { 0210 unsigned have, copy; 0211 0212 if (strm->avail_in == 0) 0213 strm->next_in = state->in; 0214 have = (unsigned)((strm->next_in + strm->avail_in) - state->in); 0215 copy = state->size - have; 0216 if (copy > len) 0217 copy = len; 0218 memcpy(state->in + have, buf, copy); 0219 strm->avail_in += copy; 0220 state->x.pos += copy; 0221 buf = (const char *)buf + copy; 0222 len -= copy; 0223 if (len && gz_comp(state, Z_NO_FLUSH) == -1) 0224 return 0; 0225 } while (len); 0226 } 0227 else { 0228 /* consume whatever's left in the input buffer */ 0229 if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1) 0230 return 0; 0231 0232 /* directly compress user buffer to file */ 0233 strm->avail_in = len; 0234 strm->next_in = (z_const Bytef *)buf; 0235 state->x.pos += len; 0236 if (gz_comp(state, Z_NO_FLUSH) == -1) 0237 return 0; 0238 } 0239 0240 /* input was all buffered or compressed (put will fit in int) */ 0241 return (int)put; 0242 } 0243 0244 /* -- see zlib.h -- */ 0245 int ZEXPORT gzputc(file, c) 0246 gzFile file; 0247 int c; 0248 { 0249 unsigned have; 0250 unsigned char buf[1]; 0251 gz_statep state; 0252 z_streamp strm; 0253 0254 /* get internal structure */ 0255 if (file == NULL) 0256 return -1; 0257 state = (gz_statep)file; 0258 strm = &(state->strm); 0259 0260 /* check that we're writing and that there's no error */ 0261 if (state->mode != GZ_WRITE || state->err != Z_OK) 0262 return -1; 0263 0264 /* check for seek request */ 0265 if (state->seek) { 0266 state->seek = 0; 0267 if (gz_zero(state, state->skip) == -1) 0268 return -1; 0269 } 0270 0271 /* try writing to input buffer for speed (state->size == 0 if buffer not 0272 initialized) */ 0273 if (state->size) { 0274 if (strm->avail_in == 0) 0275 strm->next_in = state->in; 0276 have = (unsigned)((strm->next_in + strm->avail_in) - state->in); 0277 if (have < state->size) { 0278 state->in[have] = c; 0279 strm->avail_in++; 0280 state->x.pos++; 0281 return c & 0xff; 0282 } 0283 } 0284 0285 /* no room in buffer or not initialized, use gz_write() */ 0286 buf[0] = c; 0287 if (gzwrite(file, buf, 1) != 1) 0288 return -1; 0289 return c & 0xff; 0290 } 0291 0292 /* -- see zlib.h -- */ 0293 int ZEXPORT gzputs(file, str) 0294 gzFile file; 0295 const char *str; 0296 { 0297 int ret; 0298 unsigned len; 0299 0300 /* write string */ 0301 len = (unsigned)strlen(str); 0302 ret = gzwrite(file, str, len); 0303 return ret == 0 && len != 0 ? -1 : ret; 0304 } 0305 0306 #if defined(STDC) || defined(Z_HAVE_STDARG_H) 0307 #include <stdarg.h> 0308 0309 /* -- see zlib.h -- */ 0310 int ZEXPORTVA gzvprintf(gzFile file, const char *format, va_list va) 0311 { 0312 int size, len; 0313 gz_statep state; 0314 z_streamp strm; 0315 0316 /* get internal structure */ 0317 if (file == NULL) 0318 return -1; 0319 state = (gz_statep)file; 0320 strm = &(state->strm); 0321 0322 /* check that we're writing and that there's no error */ 0323 if (state->mode != GZ_WRITE || state->err != Z_OK) 0324 return 0; 0325 0326 /* make sure we have some buffer space */ 0327 if (state->size == 0 && gz_init(state) == -1) 0328 return 0; 0329 0330 /* check for seek request */ 0331 if (state->seek) { 0332 state->seek = 0; 0333 if (gz_zero(state, state->skip) == -1) 0334 return 0; 0335 } 0336 0337 /* consume whatever's left in the input buffer */ 0338 if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1) 0339 return 0; 0340 0341 /* do the printf() into the input buffer, put length in len */ 0342 size = (int)(state->size); 0343 state->in[size - 1] = 0; 0344 #ifdef NO_vsnprintf 0345 # ifdef HAS_vsprintf_void 0346 (void)vsprintf((char *)(state->in), format, va); 0347 for (len = 0; len < size; len++) 0348 if (state->in[len] == 0) break; 0349 # else 0350 len = vsprintf((char *)(state->in), format, va); 0351 # endif 0352 #else 0353 # ifdef HAS_vsnprintf_void 0354 (void)vsnprintf((char *)(state->in), size, format, va); 0355 len = strlen((char *)(state->in)); 0356 # else 0357 len = vsnprintf((char *)(state->in), size, format, va); 0358 # endif 0359 #endif 0360 0361 /* check that printf() results fit in buffer */ 0362 if (len <= 0 || len >= (int)size || state->in[size - 1] != 0) 0363 return 0; 0364 0365 /* update buffer and position, defer compression until needed */ 0366 strm->avail_in = (unsigned)len; 0367 strm->next_in = state->in; 0368 state->x.pos += len; 0369 return len; 0370 } 0371 0372 int ZEXPORTVA gzprintf(gzFile file, const char *format, ...) 0373 { 0374 va_list va; 0375 int ret; 0376 0377 va_start(va, format); 0378 ret = gzvprintf(file, format, va); 0379 va_end(va); 0380 return ret; 0381 } 0382 0383 #else /* !STDC && !Z_HAVE_STDARG_H */ 0384 0385 /* -- see zlib.h -- */ 0386 int ZEXPORTVA gzprintf (file, format, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, 0387 a11, a12, a13, a14, a15, a16, a17, a18, a19, a20) 0388 gzFile file; 0389 const char *format; 0390 int a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, 0391 a11, a12, a13, a14, a15, a16, a17, a18, a19, a20; 0392 { 0393 int size, len; 0394 gz_statep state; 0395 z_streamp strm; 0396 0397 /* get internal structure */ 0398 if (file == NULL) 0399 return -1; 0400 state = (gz_statep)file; 0401 strm = &(state->strm); 0402 0403 /* check that can really pass pointer in ints */ 0404 if (sizeof(int) != sizeof(void *)) 0405 return 0; 0406 0407 /* check that we're writing and that there's no error */ 0408 if (state->mode != GZ_WRITE || state->err != Z_OK) 0409 return 0; 0410 0411 /* make sure we have some buffer space */ 0412 if (state->size == 0 && gz_init(state) == -1) 0413 return 0; 0414 0415 /* check for seek request */ 0416 if (state->seek) { 0417 state->seek = 0; 0418 if (gz_zero(state, state->skip) == -1) 0419 return 0; 0420 } 0421 0422 /* consume whatever's left in the input buffer */ 0423 if (strm->avail_in && gz_comp(state, Z_NO_FLUSH) == -1) 0424 return 0; 0425 0426 /* do the printf() into the input buffer, put length in len */ 0427 size = (int)(state->size); 0428 state->in[size - 1] = 0; 0429 #ifdef NO_snprintf 0430 # ifdef HAS_sprintf_void 0431 sprintf((char *)(state->in), format, a1, a2, a3, a4, a5, a6, a7, a8, 0432 a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20); 0433 for (len = 0; len < size; len++) 0434 if (state->in[len] == 0) break; 0435 # else 0436 len = sprintf((char *)(state->in), format, a1, a2, a3, a4, a5, a6, a7, a8, 0437 a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20); 0438 # endif 0439 #else 0440 # ifdef HAS_snprintf_void 0441 snprintf((char *)(state->in), size, format, a1, a2, a3, a4, a5, a6, a7, a8, 0442 a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20); 0443 len = strlen((char *)(state->in)); 0444 # else 0445 len = snprintf((char *)(state->in), size, format, a1, a2, a3, a4, a5, a6, 0446 a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, 0447 a19, a20); 0448 # endif 0449 #endif 0450 0451 /* check that printf() results fit in buffer */ 0452 if (len <= 0 || len >= (int)size || state->in[size - 1] != 0) 0453 return 0; 0454 0455 /* update buffer and position, defer compression until needed */ 0456 strm->avail_in = (unsigned)len; 0457 strm->next_in = state->in; 0458 state->x.pos += len; 0459 return len; 0460 } 0461 0462 #endif 0463 0464 /* -- see zlib.h -- */ 0465 int ZEXPORT gzflush(file, flush) 0466 gzFile file; 0467 int flush; 0468 { 0469 gz_statep state; 0470 0471 /* get internal structure */ 0472 if (file == NULL) 0473 return -1; 0474 state = (gz_statep)file; 0475 0476 /* check that we're writing and that there's no error */ 0477 if (state->mode != GZ_WRITE || state->err != Z_OK) 0478 return Z_STREAM_ERROR; 0479 0480 /* check flush parameter */ 0481 if (flush < 0 || flush > Z_FINISH) 0482 return Z_STREAM_ERROR; 0483 0484 /* check for seek request */ 0485 if (state->seek) { 0486 state->seek = 0; 0487 if (gz_zero(state, state->skip) == -1) 0488 return -1; 0489 } 0490 0491 /* compress remaining data with requested flush */ 0492 gz_comp(state, flush); 0493 return state->err; 0494 } 0495 0496 /* -- see zlib.h -- */ 0497 int ZEXPORT gzsetparams(file, level, strategy) 0498 gzFile file; 0499 int level; 0500 int strategy; 0501 { 0502 gz_statep state; 0503 z_streamp strm; 0504 0505 /* get internal structure */ 0506 if (file == NULL) 0507 return Z_STREAM_ERROR; 0508 state = (gz_statep)file; 0509 strm = &(state->strm); 0510 0511 /* check that we're writing and that there's no error */ 0512 if (state->mode != GZ_WRITE || state->err != Z_OK) 0513 return Z_STREAM_ERROR; 0514 0515 /* if no change is requested, then do nothing */ 0516 if (level == state->level && strategy == state->strategy) 0517 return Z_OK; 0518 0519 /* check for seek request */ 0520 if (state->seek) { 0521 state->seek = 0; 0522 if (gz_zero(state, state->skip) == -1) 0523 return -1; 0524 } 0525 0526 /* change compression parameters for subsequent input */ 0527 if (state->size) { 0528 /* flush previous input with previous parameters before changing */ 0529 if (strm->avail_in && gz_comp(state, Z_PARTIAL_FLUSH) == -1) 0530 return state->err; 0531 deflateParams(strm, level, strategy); 0532 } 0533 state->level = level; 0534 state->strategy = strategy; 0535 return Z_OK; 0536 } 0537 0538 /* -- see zlib.h -- */ 0539 int ZEXPORT gzclose_w(file) 0540 gzFile file; 0541 { 0542 int ret = Z_OK; 0543 gz_statep state; 0544 0545 /* get internal structure */ 0546 if (file == NULL) 0547 return Z_STREAM_ERROR; 0548 state = (gz_statep)file; 0549 0550 /* check that we're writing */ 0551 if (state->mode != GZ_WRITE) 0552 return Z_STREAM_ERROR; 0553 0554 /* check for seek request */ 0555 if (state->seek) { 0556 state->seek = 0; 0557 if (gz_zero(state, state->skip) == -1) 0558 ret = state->err; 0559 } 0560 0561 /* flush, free memory, and close file */ 0562 if (gz_comp(state, Z_FINISH) == -1) 0563 ret = state->err; 0564 if (state->size) { 0565 if (!state->direct) { 0566 (void)deflateEnd(&(state->strm)); 0567 free(state->out); 0568 } 0569 free(state->in); 0570 } 0571 gz_error(state, Z_OK, NULL); 0572 free(state->path); 0573 if (close(state->fd) == -1) 0574 ret = Z_ERRNO; 0575 free(state); 0576 return ret; 0577 }