static ssize_t o_stream_zlib_send_chunk(struct zlib_ostream *zstream, const void *data, size_t size) { z_stream *zs = &zstream->zs; int ret, flush; i_assert(zstream->outbuf_used == 0); flush = zstream->ostream.corked || zstream->gz ? Z_NO_FLUSH : Z_SYNC_FLUSH; if (!zstream->header_sent) { if (o_stream_zlib_send_gz_header(zstream) < 0) return -1; } zs->next_in = (void *)data; zs->avail_in = size; while (zs->avail_in > 0) { if (zs->avail_out == 0) { /* previous block was compressed. send it and start compression for a new block. */ zs->next_out = zstream->outbuf; zs->avail_out = sizeof(zstream->outbuf); zstream->outbuf_used = sizeof(zstream->outbuf); if ((ret = o_stream_zlib_send_outbuf(zstream)) < 0) return -1; if (ret == 0) { /* parent stream's buffer full */ break; } } ret = deflate(zs, flush); switch (ret) { case Z_OK: case Z_BUF_ERROR: break; case Z_STREAM_ERROR: i_assert(zstream->gz); i_panic("zlib.write(%s) failed: Can't write more data to .gz after flushing", o_stream_get_name(&zstream->ostream.ostream)); default: i_panic("zlib.write(%s) failed with unexpected code %d", o_stream_get_name(&zstream->ostream.ostream), ret); } } size -= zs->avail_in; zstream->crc = crc32_data_more(zstream->crc, data, size); zstream->bytes32 += size; zstream->flushed = flush == Z_SYNC_FLUSH && zs->avail_in == 0 && zs->avail_out == sizeof(zstream->outbuf); return size; }
static int o_stream_zlib_send_flush(struct zlib_ostream *zstream) { z_stream *zs = &zstream->zs; unsigned int len; bool done = FALSE; int ret; i_assert(zs->avail_in == 0); if (zstream->flushed) return 0; if (!zstream->header_sent) o_stream_zlib_send_gz_header(zstream); do { len = sizeof(zstream->outbuf) - zs->avail_out; if (len != 0) { zs->next_out = zstream->outbuf; zs->avail_out = sizeof(zstream->outbuf); ret = o_stream_send(zstream->output, zstream->outbuf, len); if (ret != (int)len) { zstream_copy_error(zstream); return -1; } if (done) break; } switch (deflate(zs, zstream->gz ? Z_FINISH : Z_SYNC_FLUSH)) { case Z_OK: case Z_BUF_ERROR: break; case Z_STREAM_END: done = TRUE; break; default: i_unreached(); } } while (zs->avail_out != sizeof(zstream->outbuf)); if (o_stream_zlib_send_gz_trailer(zstream) < 0) return -1; zstream->flushed = TRUE; return 0; }
static int o_stream_zlib_send_chunk(struct zlib_ostream *zstream, const void *data, size_t size) { z_stream *zs = &zstream->zs; ssize_t ret; int flush; flush = zstream->ostream.corked || zstream->gz ? Z_NO_FLUSH : Z_SYNC_FLUSH; if (!zstream->header_sent) o_stream_zlib_send_gz_header(zstream); zs->next_in = (void *)data; zs->avail_in = size; while (zs->avail_in > 0) { if (zs->avail_out == 0) { zs->next_out = zstream->outbuf; zs->avail_out = sizeof(zstream->outbuf); ret = o_stream_send(zstream->output, zstream->outbuf, sizeof(zstream->outbuf)); if (ret != (ssize_t)sizeof(zstream->outbuf)) { zstream_copy_error(zstream); return -1; } } switch (deflate(zs, flush)) { case Z_OK: case Z_BUF_ERROR: break; default: i_unreached(); } } zstream->crc = crc32_data_more(zstream->crc, data, size); zstream->bytes32 += size; zstream->flushed = FALSE; return 0; }