aboutsummaryrefslogtreecommitdiffstats
path: root/smtpd/compress_gzip.c
diff options
context:
space:
mode:
Diffstat (limited to 'smtpd/compress_gzip.c')
-rw-r--r--smtpd/compress_gzip.c186
1 files changed, 186 insertions, 0 deletions
diff --git a/smtpd/compress_gzip.c b/smtpd/compress_gzip.c
new file mode 100644
index 00000000..dd60aeec
--- /dev/null
+++ b/smtpd/compress_gzip.c
@@ -0,0 +1,186 @@
+/* $OpenBSD: compress_gzip.c,v 1.10 2015/12/28 22:08:30 jung Exp $ */
+
+/*
+ * Copyright (c) 2012 Gilles Chehade <gilles@poolp.org>
+ * Copyright (c) 2012 Charles Longeau <chl@openbsd.org>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "includes.h"
+
+#include <sys/types.h>
+#include <sys/queue.h>
+#include <sys/tree.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+
+#include <ctype.h>
+#include <err.h>
+#include <fcntl.h>
+#include <imsg.h>
+#include <pwd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <limits.h>
+
+#include <zlib.h>
+
+#include "smtpd.h"
+#include "log.h"
+
+
+#define GZIP_BUFFER_SIZE 16384
+
+
+static size_t compress_gzip_chunk(void *, size_t, void *, size_t);
+static size_t uncompress_gzip_chunk(void *, size_t, void *, size_t);
+static int compress_gzip_file(FILE *, FILE *);
+static int uncompress_gzip_file(FILE *, FILE *);
+
+
+struct compress_backend compress_gzip = {
+ compress_gzip_chunk,
+ uncompress_gzip_chunk,
+
+ compress_gzip_file,
+ uncompress_gzip_file,
+};
+
+static size_t
+compress_gzip_chunk(void *ib, size_t ibsz, void *ob, size_t obsz)
+{
+ z_stream *strm;
+ size_t ret = 0;
+
+ if ((strm = calloc(1, sizeof *strm)) == NULL)
+ return 0;
+
+ strm->zalloc = Z_NULL;
+ strm->zfree = Z_NULL;
+ strm->opaque = Z_NULL;
+ if (deflateInit2(strm, Z_DEFAULT_COMPRESSION, Z_DEFLATED,
+ (15+16), 8, Z_DEFAULT_STRATEGY) != Z_OK)
+ goto end;
+
+ strm->avail_in = ibsz;
+ strm->next_in = (unsigned char *)ib;
+ strm->avail_out = obsz;
+ strm->next_out = (unsigned char *)ob;
+ if (deflate(strm, Z_FINISH) != Z_STREAM_END)
+ goto end;
+
+ ret = strm->total_out;
+
+end:
+ deflateEnd(strm);
+ free(strm);
+ return ret;
+}
+
+
+static size_t
+uncompress_gzip_chunk(void *ib, size_t ibsz, void *ob, size_t obsz)
+{
+ z_stream *strm;
+ size_t ret = 0;
+
+ if ((strm = calloc(1, sizeof *strm)) == NULL)
+ return 0;
+
+ strm->zalloc = Z_NULL;
+ strm->zfree = Z_NULL;
+ strm->opaque = Z_NULL;
+ strm->avail_in = 0;
+ strm->next_in = Z_NULL;
+
+ if (inflateInit2(strm, (15+16)) != Z_OK)
+ goto end;
+
+ strm->avail_in = ibsz;
+ strm->next_in = (unsigned char *)ib;
+ strm->avail_out = obsz;
+ strm->next_out = (unsigned char *)ob;
+
+ if (inflate(strm, Z_FINISH) != Z_STREAM_END)
+ goto end;
+
+ ret = strm->total_out;
+
+end:
+ deflateEnd(strm);
+ free(strm);
+ return ret;
+}
+
+
+static int
+compress_gzip_file(FILE *in, FILE *out)
+{
+ gzFile gzf;
+ char ibuf[GZIP_BUFFER_SIZE];
+ int r, w;
+ int ret = 0;
+
+ if (in == NULL || out == NULL)
+ return (0);
+
+ gzf = gzdopen(fileno(out), "wb");
+ if (gzf == NULL)
+ return (0);
+
+ while ((r = fread(ibuf, 1, GZIP_BUFFER_SIZE, in)) != 0) {
+ if ((w = gzwrite(gzf, ibuf, r)) != r)
+ goto end;
+ }
+ if (!feof(in))
+ goto end;
+
+ ret = 1;
+
+end:
+ gzclose(gzf);
+ return (ret);
+}
+
+
+static int
+uncompress_gzip_file(FILE *in, FILE *out)
+{
+ gzFile gzf;
+ char obuf[GZIP_BUFFER_SIZE];
+ int r, w;
+ int ret = 0;
+
+ if (in == NULL || out == NULL)
+ return (0);
+
+ gzf = gzdopen(fileno(in), "r");
+ if (gzf == NULL)
+ return (0);
+
+ while ((r = gzread(gzf, obuf, sizeof(obuf))) > 0) {
+ if ((w = fwrite(obuf, r, 1, out)) != 1)
+ goto end;
+ }
+ if (!gzeof(gzf))
+ goto end;
+
+ ret = 1;
+
+end:
+ gzclose(gzf);
+ return (ret);
+}