dovecot-2.0: zlib plugin: Added support for compressing Maildir ...

dovecot at dovecot.org dovecot at dovecot.org
Sat Feb 6 01:07:48 EET 2010


details:   http://hg.dovecot.org/dovecot-2.0/rev/9f0e01905171
changeset: 10642:9f0e01905171
user:      Timo Sirainen <tss at iki.fi>
date:      Sat Feb 06 01:07:44 2010 +0200
description:
zlib plugin: Added support for compressing Maildir mails while saving.

diffstat:

5 files changed, 569 insertions(+), 6 deletions(-)
src/plugins/zlib/Makefile.am     |    3 
src/plugins/zlib/ostream-bzlib.c |  188 +++++++++++++++++++++++++
src/plugins/zlib/ostream-zlib.c  |  278 ++++++++++++++++++++++++++++++++++++++
src/plugins/zlib/ostream-zlib.h  |    8 +
src/plugins/zlib/zlib-plugin.c   |   98 ++++++++++++-

diffs (truncated from 673 to 300 lines):

diff -r 174275bcb1a5 -r 9f0e01905171 src/plugins/zlib/Makefile.am
--- a/src/plugins/zlib/Makefile.am	Sat Feb 06 01:06:47 2010 +0200
+++ b/src/plugins/zlib/Makefile.am	Sat Feb 06 01:07:44 2010 +0200
@@ -23,8 +23,11 @@ lib20_zlib_plugin_la_SOURCES = \
 lib20_zlib_plugin_la_SOURCES = \
 	istream-bzlib.c \
 	istream-zlib.c \
+	ostream-zlib.c \
+	ostream-bzlib.c \
 	zlib-plugin.c
 
 noinst_HEADERS = \
 	istream-zlib.h \
+	ostream-zlib.h \
 	zlib-plugin.h
diff -r 174275bcb1a5 -r 9f0e01905171 src/plugins/zlib/ostream-bzlib.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/plugins/zlib/ostream-bzlib.c	Sat Feb 06 01:07:44 2010 +0200
@@ -0,0 +1,188 @@
+/* Copyright (c) 2010 Dovecot authors, see the included COPYING file */
+
+#include "lib.h"
+
+#ifdef HAVE_BZLIB
+
+#include "ostream-internal.h"
+#include "ostream-zlib.h"
+#include <bzlib.h>
+
+#define CHUNK_SIZE (1024*64)
+
+struct bzlib_ostream {
+	struct ostream_private ostream;
+	bz_stream zs;
+
+	char outbuf[CHUNK_SIZE];
+	struct ostream *output;
+
+	unsigned int flushed:1;
+};
+
+static void zstream_copy_error(struct bzlib_ostream *zstream)
+{
+	struct ostream *src = zstream->output;
+	struct ostream *dest = &zstream->ostream.ostream;
+
+	dest->stream_errno = src->stream_errno;
+	dest->last_failed_errno = src->last_failed_errno;
+	dest->overflow = src->overflow;
+}
+
+static void o_stream_bzlib_close(struct iostream_private *stream)
+{
+	struct bzlib_ostream *zstream = (struct bzlib_ostream *)stream;
+
+	if (zstream->output == NULL)
+		return;
+
+	o_stream_flush(&zstream->ostream.ostream);
+	o_stream_unref(&zstream->output);
+	(void)BZ2_bzCompressEnd(&zstream->zs);
+}
+
+static ssize_t
+o_stream_bzlib_send_chunk(struct bzlib_ostream *zstream,
+			  const void *data, size_t size)
+{
+	bz_stream *zs = &zstream->zs;
+	ssize_t ret;
+
+	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 (BZ2_bzCompress(zs, BZ_RUN)) {
+		case BZ_RUN_OK:
+			break;
+		default:
+			i_unreached();
+		}
+	}
+	zstream->flushed = FALSE;
+	return 0;
+}
+
+static int o_stream_bzlib_send_flush(struct bzlib_ostream *zstream)
+{
+	bz_stream *zs = &zstream->zs;
+	unsigned int len;
+	bool done = FALSE;
+	int ret;
+
+	i_assert(zs->avail_in == 0);
+
+	if (zstream->flushed)
+		return 0;
+
+	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;
+		}
+
+		ret = BZ2_bzCompress(zs, BZ_FINISH);
+		switch (ret) {
+		case BZ_STREAM_END:
+			done = TRUE;
+			break;
+		case BZ_FINISH_OK:
+			break;
+		default:
+			i_unreached();
+		}
+	} while (zs->avail_out != sizeof(zstream->outbuf));
+
+	zstream->flushed = TRUE;
+	return 0;
+}
+
+static int o_stream_bzlib_flush(struct ostream_private *stream)
+{
+	struct bzlib_ostream *zstream = (struct bzlib_ostream *)stream;
+
+	if (o_stream_bzlib_send_flush(zstream) < 0)
+		return -1;
+
+	if (o_stream_flush(zstream->output) < 0) {
+		zstream_copy_error(zstream);
+		return -1;
+	}
+	return 0;
+}
+
+static ssize_t
+o_stream_bzlib_sendv(struct ostream_private *stream,
+		    const struct const_iovec *iov, unsigned int iov_count)
+{
+	struct bzlib_ostream *zstream = (struct bzlib_ostream *)stream;
+	ssize_t bytes = 0;
+	unsigned int i;
+
+	for (i = 0; i < iov_count; i++) {
+		if (o_stream_bzlib_send_chunk(zstream, iov[i].iov_base,
+					      iov[i].iov_len) < 0)
+			return -1;
+		bytes += iov[i].iov_len;
+	}
+
+	stream->ostream.offset += bytes;
+	return bytes;
+}
+
+struct ostream *o_stream_create_bz2(struct ostream *output, int level)
+{
+	struct bzlib_ostream *zstream;
+	int ret;
+
+	i_assert(level >= 1 && level <= 9);
+
+	zstream = i_new(struct bzlib_ostream, 1);
+	zstream->ostream.sendv = o_stream_bzlib_sendv;
+	zstream->ostream.flush = o_stream_bzlib_flush;
+	zstream->ostream.iostream.close = o_stream_bzlib_close;
+	zstream->output = output;
+	o_stream_ref(output);
+
+	ret = BZ2_bzCompressInit(&zstream->zs, level, 0, 0);
+	switch (ret) {
+	case BZ_OK:
+		break;
+	case BZ_MEM_ERROR:
+		i_fatal_status(FATAL_OUTOFMEM,
+			       "bzlib: Out of memory");
+	case BZ_CONFIG_ERROR:
+		i_fatal("Wrong bzlib library version (broken compilation)");
+	case BZ_PARAM_ERROR:
+		i_fatal("bzlib: Invalid parameters");
+	default:
+		i_fatal("BZ2_bzCompressInit() failed with %d", ret);
+	}
+
+	zstream->zs.next_out = zstream->outbuf;
+	zstream->zs.avail_out = sizeof(zstream->outbuf);
+	return o_stream_create(&zstream->ostream);
+}
+#endif
diff -r 174275bcb1a5 -r 9f0e01905171 src/plugins/zlib/ostream-zlib.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/plugins/zlib/ostream-zlib.c	Sat Feb 06 01:07:44 2010 +0200
@@ -0,0 +1,278 @@
+/* Copyright (c) 2010 Dovecot authors, see the included COPYING file */
+
+#include "lib.h"
+
+#ifdef HAVE_ZLIB
+
+#include "crc32.h"
+#include "ostream-internal.h"
+#include "ostream-zlib.h"
+#include <zlib.h>
+
+#define CHUNK_SIZE (1024*32)
+#define ZLIB_OS_CODE 0x03  /* Unix */
+
+struct zlib_ostream {
+	struct ostream_private ostream;
+	z_stream zs;
+
+	unsigned char gz_header[10];
+	unsigned char outbuf[CHUNK_SIZE];
+
+	struct ostream *output;
+	uint32_t crc, bytes32;
+
+	unsigned int gz:1;
+	unsigned int header_sent:1;
+	unsigned int flushed:1;
+};
+
+static void zstream_copy_error(struct zlib_ostream *zstream)
+{
+	struct ostream *src = zstream->output;
+	struct ostream *dest = &zstream->ostream.ostream;
+
+	dest->stream_errno = src->stream_errno;
+	dest->last_failed_errno = src->last_failed_errno;
+	dest->overflow = src->overflow;
+}
+
+static void o_stream_zlib_close(struct iostream_private *stream)
+{
+	struct zlib_ostream *zstream = (struct zlib_ostream *)stream;
+
+	if (zstream->output == NULL)
+		return;
+
+	o_stream_flush(&zstream->ostream.ostream);
+	o_stream_unref(&zstream->output);
+	(void)deflateEnd(&zstream->zs);
+}
+
+static int o_stream_zlib_send_gz_header(struct zlib_ostream *zstream)
+{
+	ssize_t ret;
+
+	ret = o_stream_send(zstream->output, zstream->gz_header,
+			    sizeof(zstream->gz_header));
+	if ((size_t)ret != sizeof(zstream->gz_header)) {
+		zstream_copy_error(zstream);
+		return -1;
+	}
+	zstream->header_sent = TRUE;
+	return 0;
+}
+
+static int o_stream_zlib_lsb_uint32(struct ostream *output, uint32_t num)
+{
+	unsigned char buf[sizeof(uint32_t)];
+	unsigned int i;
+
+	for (i = 0; i < sizeof(buf); i++) {
+		buf[i] = num & 0xff;
+		num >>= 8;
+	}
+	if (o_stream_send(output, buf, sizeof(buf)) != sizeof(buf))
+		return -1;
+	return 0;
+}
+
+static int o_stream_zlib_send_gz_trailer(struct zlib_ostream *zstream)
+{
+	if (!zstream->gz)
+		return 0;
+
+	if (o_stream_zlib_lsb_uint32(zstream->output, zstream->crc) < 0 ||
+	    o_stream_zlib_lsb_uint32(zstream->output, zstream->bytes32) < 0) {
+		zstream_copy_error(zstream);
+		return -1;
+	}


More information about the dovecot-cvs mailing list