imem.c \
ipwd.c \
iostream.c \
+ iostream-rawlog.c \
istream.c \
istream-base64-encoder.c \
istream-concat.c \
istream-file.c \
istream-limit.c \
istream-mmap.c \
+ istream-rawlog.c \
istream-seekable.c \
istream-tee.c \
ioloop.c \
ostream.c \
ostream-file.c \
ostream-buffer.c \
+ ostream-rawlog.c \
primes.c \
printf-format-fix.c \
process-title.c \
imem.h \
ipwd.h \
iostream-private.h \
+ iostream-rawlog.h \
+ iostream-rawlog-private.h \
istream.h \
istream-base64-encoder.h \
istream-concat.h \
istream-crlf.h \
istream-private.h \
+ istream-rawlog.h \
istream-seekable.h \
istream-tee.h \
ioloop.h \
nfs-workarounds.h \
ostream.h \
ostream-private.h \
+ ostream-rawlog.h \
primes.h \
printf-format-fix.h \
process-title.h \
--- /dev/null
+#ifndef IOSTREAM_RAWLOG_PRIVATE_H
+#define IOSTREAM_RAWLOG_PRIVATE_H
+
+struct rawlog_iostream {
+ struct iostream_private *iostream;
+
+ char *rawlog_path;
+ int rawlog_fd;
+
+ bool autoclose_fd;
+ bool write_timestamp;
+};
+
+void iostream_rawlog_write(struct rawlog_iostream *rstream,
+ const unsigned char *data, size_t size);
+void iostream_rawlog_close(struct rawlog_iostream *rstream);
+
+#endif
--- /dev/null
+/* Copyright (c) 2011 Dovecot authors, see the included COPYING file */
+
+#include "lib.h"
+#include "hostpid.h"
+#include "ioloop.h"
+#include "write-full.h"
+#include "istream.h"
+#include "ostream.h"
+#include "istream-rawlog.h"
+#include "ostream-rawlog.h"
+#include "iostream-private.h"
+#include "iostream-rawlog-private.h"
+#include "iostream-rawlog.h"
+
+#include <unistd.h>
+#include <fcntl.h>
+
+static void
+rawlog_write(struct rawlog_iostream *rstream, const void *data, size_t size)
+{
+ if (rstream->rawlog_fd == -1)
+ return;
+
+ if (write_full(rstream->rawlog_fd, data, size) < 0) {
+ i_error("rawlog_istream.write(%s) failed: %m",
+ rstream->rawlog_path);
+ iostream_rawlog_close(rstream);
+ }
+}
+
+static void rawlog_write_timestamp(struct rawlog_iostream *rstream)
+{
+ char buf[MAX_INT_STRLEN + 6 + 2];
+
+ i_snprintf(buf, sizeof(buf), "%lu.%06u ",
+ (unsigned long)ioloop_timeval.tv_sec,
+ (unsigned int)ioloop_timeval.tv_usec);
+ rawlog_write(rstream, buf, strlen(buf));
+}
+
+void iostream_rawlog_write(struct rawlog_iostream *rstream,
+ const unsigned char *data, size_t size)
+{
+ size_t i, start;
+
+ i_assert(size > 0);
+
+ io_loop_time_refresh();
+ if (rstream->write_timestamp)
+ rawlog_write_timestamp(rstream);
+
+ for (start = 0, i = 1; i < size; i++) {
+ if (data[i-1] == '\n') {
+ rawlog_write(rstream, data + start, i - start);
+ rawlog_write_timestamp(rstream);
+ start = i;
+ }
+ }
+ if (start != size)
+ rawlog_write(rstream, data + start, size - start);
+ rstream->write_timestamp = data[size-1] == '\n';
+}
+
+void iostream_rawlog_close(struct rawlog_iostream *rstream)
+{
+ if (rstream->autoclose_fd && rstream->rawlog_fd != -1) {
+ if (close(rstream->rawlog_fd) < 0) {
+ i_error("rawlog_istream.close(%s) failed: %m",
+ rstream->rawlog_path);
+ }
+ }
+ rstream->rawlog_fd = -1;
+ i_free_and_null(rstream->rawlog_path);
+}
+
+int iostream_rawlog_create(const char *dir, struct istream **input,
+ struct ostream **output)
+{
+ static unsigned int counter = 0;
+ const char *in_path, *out_path;
+ struct istream *old_input;
+ struct ostream *old_output;
+ struct tm *tm;
+ char timestamp[50];
+ int in_fd, out_fd;
+
+ tm = localtime(&ioloop_time);
+ if (strftime(timestamp, sizeof(timestamp), "%Y%m%d-%H%M%S", tm) <= 0)
+ i_fatal("strftime() failed");
+
+ counter++;
+ in_path = t_strdup_printf("%s/%s.%s.%u.in",
+ dir, timestamp, my_pid, counter);
+ out_path = t_strdup_printf("%s/%s.%s.%u.out",
+ dir, timestamp, my_pid, counter);
+
+ in_fd = open(in_path, O_CREAT | O_APPEND | O_WRONLY, 0600);
+ if (in_fd == -1) {
+ i_error("creat(%s) failed: %m", in_path);
+ return -1;
+ }
+
+ out_fd = open(out_path, O_CREAT | O_APPEND | O_WRONLY, 0600);
+ if (out_fd == -1) {
+ i_error("creat(%s) failed: %m", out_path);
+ (void)close(in_fd);
+ (void)unlink(in_path);
+ return -1;
+ }
+
+ old_input = *input;
+ old_output = *output;
+ *input = i_stream_create_rawlog(old_input, in_path, in_fd, TRUE);
+ *output = o_stream_create_rawlog(old_output, out_path, out_fd, TRUE);
+ i_stream_unref(&old_input);
+ o_stream_unref(&old_output);
+ return 0;
+}
--- /dev/null
+#ifndef IOSTREAM_RAWLOG_H
+#define IOSTREAM_RAWLOG_H
+
+int iostream_rawlog_create(const char *dir, struct istream **input,
+ struct ostream **output);
+
+#endif
--- /dev/null
+/* Copyright (c) 2011 Dovecot authors, see the included COPYING file */
+
+#include "lib.h"
+#include "iostream-rawlog-private.h"
+#include "istream-private.h"
+#include "istream-rawlog.h"
+
+struct rawlog_istream {
+ struct istream_private istream;
+ struct rawlog_iostream riostream;
+};
+
+static void i_stream_rawlog_close(struct iostream_private *stream)
+{
+ struct rawlog_istream *rstream = (struct rawlog_istream *)stream;
+
+ iostream_rawlog_close(&rstream->riostream);
+}
+
+static void i_stream_rawlog_destroy(struct iostream_private *stream)
+{
+ struct rawlog_istream *rstream = (struct rawlog_istream *)stream;
+ uoff_t v_offset;
+
+ v_offset = rstream->istream.parent_start_offset +
+ rstream->istream.istream.v_offset;
+ if (rstream->istream.parent->seekable ||
+ v_offset > rstream->istream.parent->v_offset) {
+ /* get to same position in parent stream */
+ i_stream_seek(rstream->istream.parent, v_offset);
+ }
+ i_stream_unref(&rstream->istream.parent);
+}
+
+static ssize_t i_stream_rawlog_read(struct istream_private *stream)
+{
+ struct rawlog_istream *rstream = (struct rawlog_istream *)stream;
+ ssize_t ret;
+ size_t pos;
+
+ i_stream_seek(stream->parent, rstream->istream.parent_start_offset +
+ stream->istream.v_offset);
+
+ stream->pos -= stream->skip;
+ stream->skip = 0;
+
+ stream->buffer = i_stream_get_data(stream->parent, &pos);
+ if (pos > stream->pos)
+ ret = 0;
+ else do {
+ if ((ret = i_stream_read(stream->parent)) == -2)
+ return -2;
+
+ stream->istream.stream_errno = stream->parent->stream_errno;
+ stream->istream.eof = stream->parent->eof;
+ stream->buffer = i_stream_get_data(stream->parent, &pos);
+ } while (pos <= stream->pos && ret > 0);
+
+ if (pos <= stream->pos)
+ ret = ret == 0 ? 0 : -1;
+ else {
+ ret = (ssize_t)(pos - stream->pos);
+ iostream_rawlog_write(&rstream->riostream,
+ stream->buffer + stream->pos, ret);
+ }
+ stream->pos = pos;
+ i_assert(ret != -1 || stream->istream.eof ||
+ stream->istream.stream_errno != 0);
+ return ret;
+}
+
+static const struct stat *
+i_stream_rawlog_stat(struct istream_private *stream, bool exact)
+{
+ return i_stream_stat(stream->parent, exact);
+}
+
+struct istream *
+i_stream_create_rawlog(struct istream *input, const char *rawlog_path,
+ int rawlog_fd, bool autoclose_fd)
+{
+ struct rawlog_istream *rstream;
+
+ i_assert(rawlog_path != NULL);
+ i_assert(rawlog_fd != -1);
+
+ rstream = i_new(struct rawlog_istream, 1);
+ rstream->istream.max_buffer_size = input->real_stream->max_buffer_size;
+ rstream->riostream.rawlog_path = i_strdup(rawlog_path);
+ rstream->riostream.rawlog_fd = rawlog_fd;
+ rstream->riostream.autoclose_fd = autoclose_fd;
+ rstream->riostream.write_timestamp = TRUE;
+
+ rstream->istream.read = i_stream_rawlog_read;
+ rstream->istream.stat = i_stream_rawlog_stat;
+ rstream->istream.iostream.close = i_stream_rawlog_close;
+ rstream->istream.iostream.destroy = i_stream_rawlog_destroy;
+
+ rstream->istream.istream.readable_fd = input->readable_fd;
+ rstream->istream.istream.blocking = input->blocking;
+ rstream->istream.istream.seekable = input->seekable;
+ return i_stream_create(&rstream->istream, input,
+ i_stream_get_fd(input));
+}
--- /dev/null
+#ifndef ISTREAM_RAWLOG_H
+#define ISTREAM_RAWLOG_H
+
+struct istream *
+i_stream_create_rawlog(struct istream *input, const char *rawlog_path,
+ int rawlog_fd, bool autoclose_fd);
+
+#endif
--- /dev/null
+/* Copyright (c) 2011 Dovecot authors, see the included COPYING file */
+
+#include "lib.h"
+#include "iostream-rawlog-private.h"
+#include "ostream-private.h"
+#include "ostream-rawlog.h"
+
+struct rawlog_ostream {
+ struct ostream_private ostream;
+ struct rawlog_iostream riostream;
+};
+
+static void o_stream_rawlog_close(struct iostream_private *stream)
+{
+ struct rawlog_ostream *rstream = (struct rawlog_ostream *)stream;
+
+ o_stream_flush(rstream->ostream.parent);
+ iostream_rawlog_close(&rstream->riostream);
+}
+
+static ssize_t
+o_stream_rawlog_sendv(struct ostream_private *stream,
+ const struct const_iovec *iov, unsigned int iov_count)
+{
+ struct rawlog_ostream *rstream = (struct rawlog_ostream *)stream;
+ unsigned int i;
+ ssize_t ret;
+
+ for (i = 0; i < iov_count; i++) {
+ iostream_rawlog_write(&rstream->riostream,
+ iov[i].iov_base, iov[i].iov_len);
+ }
+
+ if ((ret = o_stream_sendv(stream->parent, iov, iov_count)) < 0) {
+ o_stream_copy_error_from_parent(stream);
+ return -1;
+ }
+
+ stream->ostream.offset += ret;
+ return ret;
+}
+
+struct ostream *
+o_stream_create_rawlog(struct ostream *output, const char *rawlog_path,
+ int rawlog_fd, bool autoclose_fd)
+{
+ struct rawlog_ostream *rstream;
+
+ i_assert(rawlog_path != NULL);
+ i_assert(rawlog_fd != -1);
+
+ rstream = i_new(struct rawlog_ostream, 1);
+ rstream->ostream.sendv = o_stream_rawlog_sendv;
+ rstream->ostream.iostream.close = o_stream_rawlog_close;
+
+ rstream->riostream.rawlog_path = i_strdup(rawlog_path);
+ rstream->riostream.rawlog_fd = rawlog_fd;
+ rstream->riostream.autoclose_fd = autoclose_fd;
+ rstream->riostream.write_timestamp = TRUE;
+
+ return o_stream_create(&rstream->ostream, output);
+}
--- /dev/null
+#ifndef OSTREAM_RAWLOG_H
+#define OSTREAM_RAWLOG_H
+
+struct ostream *
+o_stream_create_rawlog(struct ostream *output, const char *rawlog_path,
+ int rawlog_fd, bool autoclose_fd);
+
+#endif