]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
Added rawlog i/ostreams.
authorTimo Sirainen <tss@iki.fi>
Wed, 21 Sep 2011 12:57:57 +0000 (15:57 +0300)
committerTimo Sirainen <tss@iki.fi>
Wed, 21 Sep 2011 12:57:57 +0000 (15:57 +0300)
src/lib/Makefile.am
src/lib/iostream-rawlog-private.h [new file with mode: 0644]
src/lib/iostream-rawlog.c [new file with mode: 0644]
src/lib/iostream-rawlog.h [new file with mode: 0644]
src/lib/istream-rawlog.c [new file with mode: 0644]
src/lib/istream-rawlog.h [new file with mode: 0644]
src/lib/ostream-rawlog.c [new file with mode: 0644]
src/lib/ostream-rawlog.h [new file with mode: 0644]

index 921f46f639eac743769b63e21075d2675ec7bbcb..a69ffaec6bc0c7fed7160ba4cd032a3b4f96a88e 100644 (file)
@@ -48,6 +48,7 @@ liblib_la_SOURCES = \
        imem.c \
        ipwd.c \
        iostream.c \
+       iostream-rawlog.c \
        istream.c \
        istream-base64-encoder.c \
        istream-concat.c \
@@ -56,6 +57,7 @@ liblib_la_SOURCES = \
        istream-file.c \
        istream-limit.c \
        istream-mmap.c \
+       istream-rawlog.c \
        istream-seekable.c \
        istream-tee.c \
        ioloop.c \
@@ -88,6 +90,7 @@ liblib_la_SOURCES = \
        ostream.c \
        ostream-file.c \
        ostream-buffer.c \
+       ostream-rawlog.c \
        primes.c \
        printf-format-fix.c \
        process-title.c \
@@ -162,11 +165,14 @@ headers = \
        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 \
@@ -189,6 +195,7 @@ headers = \
        nfs-workarounds.h \
        ostream.h \
        ostream-private.h \
+       ostream-rawlog.h \
        primes.h \
        printf-format-fix.h \
        process-title.h \
diff --git a/src/lib/iostream-rawlog-private.h b/src/lib/iostream-rawlog-private.h
new file mode 100644 (file)
index 0000000..684e6e6
--- /dev/null
@@ -0,0 +1,18 @@
+#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
diff --git a/src/lib/iostream-rawlog.c b/src/lib/iostream-rawlog.c
new file mode 100644 (file)
index 0000000..0831ea2
--- /dev/null
@@ -0,0 +1,118 @@
+/* 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;
+}
diff --git a/src/lib/iostream-rawlog.h b/src/lib/iostream-rawlog.h
new file mode 100644 (file)
index 0000000..70a5a46
--- /dev/null
@@ -0,0 +1,7 @@
+#ifndef IOSTREAM_RAWLOG_H
+#define IOSTREAM_RAWLOG_H
+
+int iostream_rawlog_create(const char *dir, struct istream **input,
+                          struct ostream **output);
+
+#endif
diff --git a/src/lib/istream-rawlog.c b/src/lib/istream-rawlog.c
new file mode 100644 (file)
index 0000000..064d050
--- /dev/null
@@ -0,0 +1,104 @@
+/* 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));
+}
diff --git a/src/lib/istream-rawlog.h b/src/lib/istream-rawlog.h
new file mode 100644 (file)
index 0000000..f2af639
--- /dev/null
@@ -0,0 +1,8 @@
+#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
diff --git a/src/lib/ostream-rawlog.c b/src/lib/ostream-rawlog.c
new file mode 100644 (file)
index 0000000..0124550
--- /dev/null
@@ -0,0 +1,62 @@
+/* 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);
+}
diff --git a/src/lib/ostream-rawlog.h b/src/lib/ostream-rawlog.h
new file mode 100644 (file)
index 0000000..682725f
--- /dev/null
@@ -0,0 +1,8 @@
+#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