bcb4e51a409d94ae670de96afb8483a4f7855294Stephan Bosch/* Copyright (c) 2013-2018 Dovecot authors, see the included COPYING file */
a49d1c2ca3c134c0c62b37a94936c78e9849e044Timo Sirainen /* chunk size, followed by compressed data */
efd203f312659a7ce82644fb2a39d791ac198b77Teemu Huovila unsigned char outbuf[IOSTREAM_LZ4_CHUNK_PREFIX_LEN +
a49d1c2ca3c134c0c62b37a94936c78e9849e044Timo Sirainenstatic void o_stream_lz4_close(struct iostream_private *stream,
a49d1c2ca3c134c0c62b37a94936c78e9849e044Timo Sirainen struct lz4_ostream *zstream = (struct lz4_ostream *)stream;
a49d1c2ca3c134c0c62b37a94936c78e9849e044Timo Sirainenstatic int o_stream_lz4_send_outbuf(struct lz4_ostream *zstream)
a49d1c2ca3c134c0c62b37a94936c78e9849e044Timo Sirainen size = zstream->outbuf_used - zstream->outbuf_offset;
a49d1c2ca3c134c0c62b37a94936c78e9849e044Timo Sirainen zstream->outbuf + zstream->outbuf_offset, size);
a49d1c2ca3c134c0c62b37a94936c78e9849e044Timo Sirainen o_stream_copy_error_from_parent(&zstream->ostream);
a49d1c2ca3c134c0c62b37a94936c78e9849e044Timo Sirainenstatic int o_stream_lz4_compress(struct lz4_ostream *zstream)
a49d1c2ca3c134c0c62b37a94936c78e9849e044Timo Sirainen if ((ret = o_stream_lz4_send_outbuf(zstream)) <= 0)
d31a407872fb93f907fc2587daaa780ffa9a6f56Martti Rannanjärvi int max_dest_size = LZ4_compressBound(zstream->compressbuf_offset);
d31a407872fb93f907fc2587daaa780ffa9a6f56Martti Rannanjärvi io_stream_set_error(&zstream->ostream.iostream,
d31a407872fb93f907fc2587daaa780ffa9a6f56Martti Rannanjärvi "lz4-compress: input size %u too large (> %u)",
d31a407872fb93f907fc2587daaa780ffa9a6f56Martti Rannanjärvi zstream->compressbuf_offset, LZ4_MAX_INPUT_SIZE);
d31a407872fb93f907fc2587daaa780ffa9a6f56Martti Rannanjärvi zstream->ostream.ostream.stream_errno = EINVAL;
d31a407872fb93f907fc2587daaa780ffa9a6f56Martti Rannanjärvi ret = LZ4_compress_default((void *)zstream->compressbuf,
efd203f312659a7ce82644fb2a39d791ac198b77Teemu Huovila ret = LZ4_compress((void *)zstream->compressbuf,
d31a407872fb93f907fc2587daaa780ffa9a6f56Martti Rannanjärvi#endif /* defined(HAVE_LZ4_COMPRESS_DEFAULT) */
efd203f312659a7ce82644fb2a39d791ac198b77Teemu Huovila i_assert(ret > 0 && (unsigned int)ret <= sizeof(zstream->outbuf) -
efd203f312659a7ce82644fb2a39d791ac198b77Teemu Huovila zstream->outbuf_used = IOSTREAM_LZ4_CHUNK_PREFIX_LEN + ret;
a49d1c2ca3c134c0c62b37a94936c78e9849e044Timo Sirainen chunk_size = zstream->outbuf_used - IOSTREAM_LZ4_CHUNK_PREFIX_LEN;
a49d1c2ca3c134c0c62b37a94936c78e9849e044Timo Sirainen zstream->outbuf[0] = (chunk_size & 0xff000000) >> 24;
a49d1c2ca3c134c0c62b37a94936c78e9849e044Timo Sirainen zstream->outbuf[1] = (chunk_size & 0x00ff0000) >> 16;
a49d1c2ca3c134c0c62b37a94936c78e9849e044Timo Sirainen zstream->outbuf[2] = (chunk_size & 0x0000ff00) >> 8;
a49d1c2ca3c134c0c62b37a94936c78e9849e044Timo Sirainen zstream->outbuf[3] = (chunk_size & 0x000000ff);
a49d1c2ca3c134c0c62b37a94936c78e9849e044Timo Siraineno_stream_lz4_send_chunk(struct lz4_ostream *zstream,
a49d1c2ca3c134c0c62b37a94936c78e9849e044Timo Sirainen max_size = I_MIN(size, sizeof(zstream->compressbuf) -
a49d1c2ca3c134c0c62b37a94936c78e9849e044Timo Sirainen memcpy(zstream->compressbuf + zstream->compressbuf_offset,
a49d1c2ca3c134c0c62b37a94936c78e9849e044Timo Sirainen if (zstream->compressbuf_offset == sizeof(zstream->compressbuf)) {
a49d1c2ca3c134c0c62b37a94936c78e9849e044Timo Sirainen } while (size > 0);
a49d1c2ca3c134c0c62b37a94936c78e9849e044Timo Sirainenstatic int o_stream_lz4_flush(struct ostream_private *stream)
a49d1c2ca3c134c0c62b37a94936c78e9849e044Timo Sirainen struct lz4_ostream *zstream = (struct lz4_ostream *)stream;
a49d1c2ca3c134c0c62b37a94936c78e9849e044Timo Siraineno_stream_lz4_sendv(struct ostream_private *stream,
a49d1c2ca3c134c0c62b37a94936c78e9849e044Timo Sirainen const struct const_iovec *iov, unsigned int iov_count)
a49d1c2ca3c134c0c62b37a94936c78e9849e044Timo Sirainen struct lz4_ostream *zstream = (struct lz4_ostream *)stream;
a49d1c2ca3c134c0c62b37a94936c78e9849e044Timo Sirainen unsigned int i;
a49d1c2ca3c134c0c62b37a94936c78e9849e044Timo Sirainen if ((ret = o_stream_lz4_send_outbuf(zstream)) <= 0) {
a49d1c2ca3c134c0c62b37a94936c78e9849e044Timo Sirainen /* error / we still couldn't flush existing data to
a49d1c2ca3c134c0c62b37a94936c78e9849e044Timo Sirainen parent stream. */
a49d1c2ca3c134c0c62b37a94936c78e9849e044Timo Sirainen for (i = 0; i < iov_count; i++) {
a49d1c2ca3c134c0c62b37a94936c78e9849e044Timo Sirainen ret = o_stream_lz4_send_chunk(zstream, iov[i].iov_base,
a49d1c2ca3c134c0c62b37a94936c78e9849e044Timo Sirainenstruct ostream *o_stream_create_lz4(struct ostream *output, int level)
a49d1c2ca3c134c0c62b37a94936c78e9849e044Timo Sirainen zstream->ostream.iostream.close = o_stream_lz4_close;
a49d1c2ca3c134c0c62b37a94936c78e9849e044Timo Sirainen i_assert(sizeof(zstream->outbuf) >= sizeof(*hdr));
a49d1c2ca3c134c0c62b37a94936c78e9849e044Timo Sirainen memcpy(hdr->magic, IOSTREAM_LZ4_MAGIC, sizeof(hdr->magic));