}
}
- switch (deflate(zs, flush)) {
+ 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_unreached();
+ i_panic("zlib.write(%s) failed with unexpected code %d",
+ o_stream_get_name(&zstream->ostream.ostream), ret);
}
}
size -= zs->avail_in;
return size;
}
-static int o_stream_zlib_send_flush(struct zlib_ostream *zstream)
+static int
+o_stream_zlib_send_flush(struct zlib_ostream *zstream, bool final)
{
z_stream *zs = &zstream->zs;
unsigned int len;
bool done = FALSE;
- int ret;
+ int ret, flush;
if (zs->avail_in != 0) {
i_assert(zstream->ostream.ostream.last_failed_errno != 0);
if ((ret = o_stream_zlib_send_outbuf(zstream)) <= 0)
return ret;
+ flush = !zstream->gz ? Z_SYNC_FLUSH :
+ (final ? Z_FINISH : Z_NO_FLUSH);
+
i_assert(zstream->outbuf_used == 0);
do {
len = sizeof(zstream->outbuf) - zs->avail_out;
break;
}
- switch (deflate(zs, zstream->gz ? Z_FINISH : Z_SYNC_FLUSH)) {
+ switch (deflate(zs, flush)) {
case Z_OK:
case Z_BUF_ERROR:
break;
}
} while (zs->avail_out != sizeof(zstream->outbuf));
- if (o_stream_zlib_send_gz_trailer(zstream) < 0)
- return -1;
- zstream->flushed = TRUE;
+ if (final) {
+ if (o_stream_zlib_send_gz_trailer(zstream) < 0)
+ return -1;
+ }
+ if (final || flush != Z_NO_FLUSH)
+ zstream->flushed = TRUE;
return 0;
}
struct zlib_ostream *zstream = (struct zlib_ostream *)stream;
int ret;
- if (o_stream_zlib_send_flush(zstream) < 0)
+ if (o_stream_zlib_send_flush(zstream, TRUE) < 0)
return -1;
ret = o_stream_flush(stream->parent);
stream->ostream.offset += bytes;
if (!zstream->ostream.corked && i == iov_count) {
- if (o_stream_zlib_send_flush(zstream) < 0)
+ if (o_stream_zlib_send_flush(zstream, FALSE) < 0)
return -1;
}
/* avail_in!=0 check is used to detect errors. if it's non-zero here