bcb4e51a409d94ae670de96afb8483a4f7855294Stephan Bosch/* Copyright (c) 2011-2018 Dovecot authors, see the included COPYING file */
be6ad6e46ecb8c7126b421819046e7f4857a2babTimo Sirainen
be6ad6e46ecb8c7126b421819046e7f4857a2babTimo Sirainen#include "lib.h"
be6ad6e46ecb8c7126b421819046e7f4857a2babTimo Sirainen#include "hostpid.h"
be6ad6e46ecb8c7126b421819046e7f4857a2babTimo Sirainen#include "ioloop.h"
f1ed4fa248aaf6841ba638b9d66b2738d9f7aa18Timo Sirainen#include "buffer.h"
f1ed4fa248aaf6841ba638b9d66b2738d9f7aa18Timo Sirainen#include "str.h"
f9b6b5e9c4e18682321959883c888035a56b6be9Timo Sirainen#include "net.h"
be6ad6e46ecb8c7126b421819046e7f4857a2babTimo Sirainen#include "write-full.h"
1f696b6f364516a2d79f946ca88149bafdc9d5adTimo Sirainen#include "time-util.h"
be6ad6e46ecb8c7126b421819046e7f4857a2babTimo Sirainen#include "istream.h"
be6ad6e46ecb8c7126b421819046e7f4857a2babTimo Sirainen#include "ostream.h"
be6ad6e46ecb8c7126b421819046e7f4857a2babTimo Sirainen#include "iostream-private.h"
be6ad6e46ecb8c7126b421819046e7f4857a2babTimo Sirainen#include "iostream-rawlog-private.h"
f1ed4fa248aaf6841ba638b9d66b2738d9f7aa18Timo Sirainen#include "istream-rawlog.h"
f1ed4fa248aaf6841ba638b9d66b2738d9f7aa18Timo Sirainen#include "ostream-rawlog.h"
be6ad6e46ecb8c7126b421819046e7f4857a2babTimo Sirainen#include "iostream-rawlog.h"
be6ad6e46ecb8c7126b421819046e7f4857a2babTimo Sirainen
be6ad6e46ecb8c7126b421819046e7f4857a2babTimo Sirainen#include <unistd.h>
be6ad6e46ecb8c7126b421819046e7f4857a2babTimo Sirainen#include <fcntl.h>
be6ad6e46ecb8c7126b421819046e7f4857a2babTimo Sirainen
f1ed4fa248aaf6841ba638b9d66b2738d9f7aa18Timo Sirainen#define RAWLOG_MAX_LINE_LEN 8192
f1ed4fa248aaf6841ba638b9d66b2738d9f7aa18Timo Sirainen
76d4ff1c1b31a1a09f6cbfe613a8d0efe62cbfd2Timo Sirainenstatic void
f1ed4fa248aaf6841ba638b9d66b2738d9f7aa18Timo Sirainenrawlog_write_timestamp(struct rawlog_iostream *rstream, bool line_ends)
be6ad6e46ecb8c7126b421819046e7f4857a2babTimo Sirainen{
f1ed4fa248aaf6841ba638b9d66b2738d9f7aa18Timo Sirainen unsigned char data[MAX_INT_STRLEN + 6 + 1 + 3];
f1ed4fa248aaf6841ba638b9d66b2738d9f7aa18Timo Sirainen buffer_t buf;
f1ed4fa248aaf6841ba638b9d66b2738d9f7aa18Timo Sirainen
b367011da1a2ba3e9113dfbc601aaa4b6b04317dTimo Sirainen if ((rstream->flags & IOSTREAM_RAWLOG_FLAG_TIMESTAMP) == 0)
76d4ff1c1b31a1a09f6cbfe613a8d0efe62cbfd2Timo Sirainen return;
b367011da1a2ba3e9113dfbc601aaa4b6b04317dTimo Sirainen
3281669db44d09a087a203201248abbc81b3cc1aTimo Sirainen buffer_create_from_data(&buf, data, sizeof(data));
f89eb8f2cda0bd6d40a9f96db1c92517f0593871Martti Rannanjärvi str_printfa(&buf, "%"PRIdTIME_T".%06u ",
f89eb8f2cda0bd6d40a9f96db1c92517f0593871Martti Rannanjärvi ioloop_timeval.tv_sec,
f1ed4fa248aaf6841ba638b9d66b2738d9f7aa18Timo Sirainen (unsigned int)ioloop_timeval.tv_usec);
f1ed4fa248aaf6841ba638b9d66b2738d9f7aa18Timo Sirainen if ((rstream->flags & IOSTREAM_RAWLOG_FLAG_BUFFERED) != 0) {
f1ed4fa248aaf6841ba638b9d66b2738d9f7aa18Timo Sirainen str_append_c(&buf, rstream->input ? 'I' : 'O');
f1ed4fa248aaf6841ba638b9d66b2738d9f7aa18Timo Sirainen str_append_c(&buf, line_ends ? ':' : '>');
f1ed4fa248aaf6841ba638b9d66b2738d9f7aa18Timo Sirainen str_append_c(&buf, ' ');
f1ed4fa248aaf6841ba638b9d66b2738d9f7aa18Timo Sirainen }
76d4ff1c1b31a1a09f6cbfe613a8d0efe62cbfd2Timo Sirainen o_stream_nsend(rstream->rawlog_output, buf.data, buf.used);
f1ed4fa248aaf6841ba638b9d66b2738d9f7aa18Timo Sirainen}
be6ad6e46ecb8c7126b421819046e7f4857a2babTimo Sirainen
f1ed4fa248aaf6841ba638b9d66b2738d9f7aa18Timo Sirainenvoid iostream_rawlog_init(struct rawlog_iostream *rstream,
f1ed4fa248aaf6841ba638b9d66b2738d9f7aa18Timo Sirainen enum iostream_rawlog_flags flags, bool input)
f1ed4fa248aaf6841ba638b9d66b2738d9f7aa18Timo Sirainen{
f1ed4fa248aaf6841ba638b9d66b2738d9f7aa18Timo Sirainen rstream->flags = flags;
f1ed4fa248aaf6841ba638b9d66b2738d9f7aa18Timo Sirainen rstream->input = input;
f1ed4fa248aaf6841ba638b9d66b2738d9f7aa18Timo Sirainen if ((rstream->flags & IOSTREAM_RAWLOG_FLAG_BUFFERED) != 0)
f1ed4fa248aaf6841ba638b9d66b2738d9f7aa18Timo Sirainen rstream->buffer = buffer_create_dynamic(default_pool, 1024);
be6ad6e46ecb8c7126b421819046e7f4857a2babTimo Sirainen}
be6ad6e46ecb8c7126b421819046e7f4857a2babTimo Sirainen
76d4ff1c1b31a1a09f6cbfe613a8d0efe62cbfd2Timo Sirainenstatic void
76d4ff1c1b31a1a09f6cbfe613a8d0efe62cbfd2Timo Siraineniostream_rawlog_write_buffered(struct rawlog_iostream *rstream,
76d4ff1c1b31a1a09f6cbfe613a8d0efe62cbfd2Timo Sirainen const unsigned char *data, size_t size)
76d4ff1c1b31a1a09f6cbfe613a8d0efe62cbfd2Timo Sirainen{
76d4ff1c1b31a1a09f6cbfe613a8d0efe62cbfd2Timo Sirainen const unsigned char *p;
76d4ff1c1b31a1a09f6cbfe613a8d0efe62cbfd2Timo Sirainen size_t pos;
76d4ff1c1b31a1a09f6cbfe613a8d0efe62cbfd2Timo Sirainen bool line_ends;
76d4ff1c1b31a1a09f6cbfe613a8d0efe62cbfd2Timo Sirainen
76d4ff1c1b31a1a09f6cbfe613a8d0efe62cbfd2Timo Sirainen while (size > 0) {
76d4ff1c1b31a1a09f6cbfe613a8d0efe62cbfd2Timo Sirainen p = memchr(data, '\n', size);
76d4ff1c1b31a1a09f6cbfe613a8d0efe62cbfd2Timo Sirainen if (p != NULL) {
76d4ff1c1b31a1a09f6cbfe613a8d0efe62cbfd2Timo Sirainen line_ends = TRUE;
76d4ff1c1b31a1a09f6cbfe613a8d0efe62cbfd2Timo Sirainen pos = p-data + 1;
76d4ff1c1b31a1a09f6cbfe613a8d0efe62cbfd2Timo Sirainen } else if (rstream->buffer->used + size < RAWLOG_MAX_LINE_LEN) {
76d4ff1c1b31a1a09f6cbfe613a8d0efe62cbfd2Timo Sirainen buffer_append(rstream->buffer, data, size);
76d4ff1c1b31a1a09f6cbfe613a8d0efe62cbfd2Timo Sirainen break;
76d4ff1c1b31a1a09f6cbfe613a8d0efe62cbfd2Timo Sirainen } else {
76d4ff1c1b31a1a09f6cbfe613a8d0efe62cbfd2Timo Sirainen line_ends = FALSE;
76d4ff1c1b31a1a09f6cbfe613a8d0efe62cbfd2Timo Sirainen pos = size;
76d4ff1c1b31a1a09f6cbfe613a8d0efe62cbfd2Timo Sirainen }
76d4ff1c1b31a1a09f6cbfe613a8d0efe62cbfd2Timo Sirainen
76d4ff1c1b31a1a09f6cbfe613a8d0efe62cbfd2Timo Sirainen rawlog_write_timestamp(rstream, line_ends);
76d4ff1c1b31a1a09f6cbfe613a8d0efe62cbfd2Timo Sirainen if (rstream->buffer->used > 0) {
76d4ff1c1b31a1a09f6cbfe613a8d0efe62cbfd2Timo Sirainen o_stream_nsend(rstream->rawlog_output,
76d4ff1c1b31a1a09f6cbfe613a8d0efe62cbfd2Timo Sirainen rstream->buffer->data,
76d4ff1c1b31a1a09f6cbfe613a8d0efe62cbfd2Timo Sirainen rstream->buffer->used);
76d4ff1c1b31a1a09f6cbfe613a8d0efe62cbfd2Timo Sirainen buffer_set_used_size(rstream->buffer, 0);
76d4ff1c1b31a1a09f6cbfe613a8d0efe62cbfd2Timo Sirainen }
76d4ff1c1b31a1a09f6cbfe613a8d0efe62cbfd2Timo Sirainen o_stream_nsend(rstream->rawlog_output, data, pos);
76d4ff1c1b31a1a09f6cbfe613a8d0efe62cbfd2Timo Sirainen
76d4ff1c1b31a1a09f6cbfe613a8d0efe62cbfd2Timo Sirainen data += pos;
76d4ff1c1b31a1a09f6cbfe613a8d0efe62cbfd2Timo Sirainen size -= pos;
76d4ff1c1b31a1a09f6cbfe613a8d0efe62cbfd2Timo Sirainen }
76d4ff1c1b31a1a09f6cbfe613a8d0efe62cbfd2Timo Sirainen}
76d4ff1c1b31a1a09f6cbfe613a8d0efe62cbfd2Timo Sirainen
f1ed4fa248aaf6841ba638b9d66b2738d9f7aa18Timo Sirainenstatic void
f1ed4fa248aaf6841ba638b9d66b2738d9f7aa18Timo Siraineniostream_rawlog_write_unbuffered(struct rawlog_iostream *rstream,
f1ed4fa248aaf6841ba638b9d66b2738d9f7aa18Timo Sirainen const unsigned char *data, size_t size)
be6ad6e46ecb8c7126b421819046e7f4857a2babTimo Sirainen{
be6ad6e46ecb8c7126b421819046e7f4857a2babTimo Sirainen size_t i, start;
be6ad6e46ecb8c7126b421819046e7f4857a2babTimo Sirainen
76d4ff1c1b31a1a09f6cbfe613a8d0efe62cbfd2Timo Sirainen if (!rstream->line_continued)
76d4ff1c1b31a1a09f6cbfe613a8d0efe62cbfd2Timo Sirainen rawlog_write_timestamp(rstream, TRUE);
be6ad6e46ecb8c7126b421819046e7f4857a2babTimo Sirainen
be6ad6e46ecb8c7126b421819046e7f4857a2babTimo Sirainen for (start = 0, i = 1; i < size; i++) {
be6ad6e46ecb8c7126b421819046e7f4857a2babTimo Sirainen if (data[i-1] == '\n') {
76d4ff1c1b31a1a09f6cbfe613a8d0efe62cbfd2Timo Sirainen o_stream_nsend(rstream->rawlog_output,
76d4ff1c1b31a1a09f6cbfe613a8d0efe62cbfd2Timo Sirainen data + start, i - start);
76d4ff1c1b31a1a09f6cbfe613a8d0efe62cbfd2Timo Sirainen rawlog_write_timestamp(rstream, TRUE);
be6ad6e46ecb8c7126b421819046e7f4857a2babTimo Sirainen start = i;
be6ad6e46ecb8c7126b421819046e7f4857a2babTimo Sirainen }
be6ad6e46ecb8c7126b421819046e7f4857a2babTimo Sirainen }
4c05697a4f3958c836e23e1eff5b4b7c49ef6617Timo Sirainen if (start != size) {
76d4ff1c1b31a1a09f6cbfe613a8d0efe62cbfd2Timo Sirainen o_stream_nsend(rstream->rawlog_output,
76d4ff1c1b31a1a09f6cbfe613a8d0efe62cbfd2Timo Sirainen data + start, size - start);
4c05697a4f3958c836e23e1eff5b4b7c49ef6617Timo Sirainen }
f1ed4fa248aaf6841ba638b9d66b2738d9f7aa18Timo Sirainen rstream->line_continued = data[size-1] != '\n';
f1ed4fa248aaf6841ba638b9d66b2738d9f7aa18Timo Sirainen}
f1ed4fa248aaf6841ba638b9d66b2738d9f7aa18Timo Sirainen
f1ed4fa248aaf6841ba638b9d66b2738d9f7aa18Timo Sirainenvoid iostream_rawlog_write(struct rawlog_iostream *rstream,
f1ed4fa248aaf6841ba638b9d66b2738d9f7aa18Timo Sirainen const unsigned char *data, size_t size)
f1ed4fa248aaf6841ba638b9d66b2738d9f7aa18Timo Sirainen{
76d4ff1c1b31a1a09f6cbfe613a8d0efe62cbfd2Timo Sirainen if (size == 0 || rstream->rawlog_output == NULL)
fe91058fafc4da453161aecde6f2d48a8fae4a96Timo Sirainen return;
f1ed4fa248aaf6841ba638b9d66b2738d9f7aa18Timo Sirainen
f1ed4fa248aaf6841ba638b9d66b2738d9f7aa18Timo Sirainen io_loop_time_refresh();
f1ed4fa248aaf6841ba638b9d66b2738d9f7aa18Timo Sirainen
76d4ff1c1b31a1a09f6cbfe613a8d0efe62cbfd2Timo Sirainen o_stream_cork(rstream->rawlog_output);
76d4ff1c1b31a1a09f6cbfe613a8d0efe62cbfd2Timo Sirainen if ((rstream->flags & IOSTREAM_RAWLOG_FLAG_BUFFERED) != 0)
76d4ff1c1b31a1a09f6cbfe613a8d0efe62cbfd2Timo Sirainen iostream_rawlog_write_buffered(rstream, data, size);
76d4ff1c1b31a1a09f6cbfe613a8d0efe62cbfd2Timo Sirainen else
76d4ff1c1b31a1a09f6cbfe613a8d0efe62cbfd2Timo Sirainen iostream_rawlog_write_unbuffered(rstream, data, size);
76d4ff1c1b31a1a09f6cbfe613a8d0efe62cbfd2Timo Sirainen o_stream_uncork(rstream->rawlog_output);
f1ed4fa248aaf6841ba638b9d66b2738d9f7aa18Timo Sirainen
d1ba8ecbb936ace90179d2292952546708d68f71Timo Sirainen if (o_stream_flush(rstream->rawlog_output) < 0) {
76d4ff1c1b31a1a09f6cbfe613a8d0efe62cbfd2Timo Sirainen i_error("write(%s) failed: %s",
76d4ff1c1b31a1a09f6cbfe613a8d0efe62cbfd2Timo Sirainen o_stream_get_name(rstream->rawlog_output),
76d4ff1c1b31a1a09f6cbfe613a8d0efe62cbfd2Timo Sirainen o_stream_get_error(rstream->rawlog_output));
76d4ff1c1b31a1a09f6cbfe613a8d0efe62cbfd2Timo Sirainen iostream_rawlog_close(rstream);
640c1f9731a2e0368546bf675110ced42a589a04Timo Sirainen }
be6ad6e46ecb8c7126b421819046e7f4857a2babTimo Sirainen}
be6ad6e46ecb8c7126b421819046e7f4857a2babTimo Sirainen
be6ad6e46ecb8c7126b421819046e7f4857a2babTimo Sirainenvoid iostream_rawlog_close(struct rawlog_iostream *rstream)
be6ad6e46ecb8c7126b421819046e7f4857a2babTimo Sirainen{
204ee6ed414f5e4eeb6f6c10763b55daf56f11acJosef 'Jeff' Sipek o_stream_unref(&rstream->rawlog_output);
6307d76096764e66bddc63d4a3e5a1aa19cc528fJosef 'Jeff' Sipek buffer_free(&rstream->buffer);
be6ad6e46ecb8c7126b421819046e7f4857a2babTimo Sirainen}
be6ad6e46ecb8c7126b421819046e7f4857a2babTimo Sirainen
f9b6b5e9c4e18682321959883c888035a56b6be9Timo Sirainenstatic void
f9b6b5e9c4e18682321959883c888035a56b6be9Timo Siraineniostream_rawlog_create_fd(int fd, const char *path, struct istream **input,
f9b6b5e9c4e18682321959883c888035a56b6be9Timo Sirainen struct ostream **output)
f9b6b5e9c4e18682321959883c888035a56b6be9Timo Sirainen{
f9b6b5e9c4e18682321959883c888035a56b6be9Timo Sirainen struct istream *old_input;
f9b6b5e9c4e18682321959883c888035a56b6be9Timo Sirainen struct ostream *old_output;
f9b6b5e9c4e18682321959883c888035a56b6be9Timo Sirainen
f9b6b5e9c4e18682321959883c888035a56b6be9Timo Sirainen old_input = *input;
f9b6b5e9c4e18682321959883c888035a56b6be9Timo Sirainen old_output = *output;
f9b6b5e9c4e18682321959883c888035a56b6be9Timo Sirainen *input = i_stream_create_rawlog(old_input, path, fd,
f9b6b5e9c4e18682321959883c888035a56b6be9Timo Sirainen IOSTREAM_RAWLOG_FLAG_BUFFERED |
f9b6b5e9c4e18682321959883c888035a56b6be9Timo Sirainen IOSTREAM_RAWLOG_FLAG_TIMESTAMP);
f9b6b5e9c4e18682321959883c888035a56b6be9Timo Sirainen *output = o_stream_create_rawlog(old_output, path, fd,
f9b6b5e9c4e18682321959883c888035a56b6be9Timo Sirainen IOSTREAM_RAWLOG_FLAG_AUTOCLOSE |
f9b6b5e9c4e18682321959883c888035a56b6be9Timo Sirainen IOSTREAM_RAWLOG_FLAG_BUFFERED |
f9b6b5e9c4e18682321959883c888035a56b6be9Timo Sirainen IOSTREAM_RAWLOG_FLAG_TIMESTAMP);
f9b6b5e9c4e18682321959883c888035a56b6be9Timo Sirainen i_stream_unref(&old_input);
f9b6b5e9c4e18682321959883c888035a56b6be9Timo Sirainen o_stream_unref(&old_output);
f9b6b5e9c4e18682321959883c888035a56b6be9Timo Sirainen}
f9b6b5e9c4e18682321959883c888035a56b6be9Timo Sirainen
f9b6b5e9c4e18682321959883c888035a56b6be9Timo Sirainenstatic int
f9b6b5e9c4e18682321959883c888035a56b6be9Timo Siraineniostream_rawlog_try_create_tcp(const char *path,
f9b6b5e9c4e18682321959883c888035a56b6be9Timo Sirainen struct istream **input, struct ostream **output)
f9b6b5e9c4e18682321959883c888035a56b6be9Timo Sirainen{
7c925149e49f7cce41c90d562ff3835b66ddca29Timo Sirainen const char *host;
f9b6b5e9c4e18682321959883c888035a56b6be9Timo Sirainen struct ip_addr *ips;
009217abb57a24a4076092e8e4e165545747839eStephan Bosch unsigned int ips_count;
009217abb57a24a4076092e8e4e165545747839eStephan Bosch in_port_t port;
f9b6b5e9c4e18682321959883c888035a56b6be9Timo Sirainen int ret, fd;
f9b6b5e9c4e18682321959883c888035a56b6be9Timo Sirainen
f9b6b5e9c4e18682321959883c888035a56b6be9Timo Sirainen /* tcp:host:port */
f9b6b5e9c4e18682321959883c888035a56b6be9Timo Sirainen if (strncmp(path, "tcp:", 4) != 0)
f9b6b5e9c4e18682321959883c888035a56b6be9Timo Sirainen return 0;
f9b6b5e9c4e18682321959883c888035a56b6be9Timo Sirainen path += 4;
f9b6b5e9c4e18682321959883c888035a56b6be9Timo Sirainen
f9b6b5e9c4e18682321959883c888035a56b6be9Timo Sirainen if (strchr(path, '/') != NULL)
f9b6b5e9c4e18682321959883c888035a56b6be9Timo Sirainen return 0;
7c925149e49f7cce41c90d562ff3835b66ddca29Timo Sirainen if (net_str2hostport(path, 0, &host, &port) < 0 || port == 0)
f9b6b5e9c4e18682321959883c888035a56b6be9Timo Sirainen return 0;
f9b6b5e9c4e18682321959883c888035a56b6be9Timo Sirainen
f9b6b5e9c4e18682321959883c888035a56b6be9Timo Sirainen ret = net_gethostbyname(host, &ips, &ips_count);
f9b6b5e9c4e18682321959883c888035a56b6be9Timo Sirainen if (ret != 0) {
f9b6b5e9c4e18682321959883c888035a56b6be9Timo Sirainen i_error("net_gethostbyname(%s) failed: %s", host,
f9b6b5e9c4e18682321959883c888035a56b6be9Timo Sirainen net_gethosterror(ret));
f9b6b5e9c4e18682321959883c888035a56b6be9Timo Sirainen return -1;
f9b6b5e9c4e18682321959883c888035a56b6be9Timo Sirainen }
f9b6b5e9c4e18682321959883c888035a56b6be9Timo Sirainen fd = net_connect_ip_blocking(&ips[0], port, NULL);
f9b6b5e9c4e18682321959883c888035a56b6be9Timo Sirainen if (fd == -1) {
f9b6b5e9c4e18682321959883c888035a56b6be9Timo Sirainen i_error("connect(%s:%u) failed: %m", net_ip2addr(&ips[0]), port);
f9b6b5e9c4e18682321959883c888035a56b6be9Timo Sirainen return -1;
f9b6b5e9c4e18682321959883c888035a56b6be9Timo Sirainen }
f9b6b5e9c4e18682321959883c888035a56b6be9Timo Sirainen iostream_rawlog_create_fd(fd, path, input, output);
f9b6b5e9c4e18682321959883c888035a56b6be9Timo Sirainen return 1;
f9b6b5e9c4e18682321959883c888035a56b6be9Timo Sirainen}
f9b6b5e9c4e18682321959883c888035a56b6be9Timo Sirainen
be6ad6e46ecb8c7126b421819046e7f4857a2babTimo Sirainenint iostream_rawlog_create(const char *dir, struct istream **input,
be6ad6e46ecb8c7126b421819046e7f4857a2babTimo Sirainen struct ostream **output)
be6ad6e46ecb8c7126b421819046e7f4857a2babTimo Sirainen{
be6ad6e46ecb8c7126b421819046e7f4857a2babTimo Sirainen static unsigned int counter = 0;
f1ed4fa248aaf6841ba638b9d66b2738d9f7aa18Timo Sirainen const char *timestamp, *prefix;
f8e6e85ab508e80a66f323390f8f4e2edfff2730Timo Sirainen struct stat st;
f9b6b5e9c4e18682321959883c888035a56b6be9Timo Sirainen int ret;
f9b6b5e9c4e18682321959883c888035a56b6be9Timo Sirainen
f9b6b5e9c4e18682321959883c888035a56b6be9Timo Sirainen if ((ret = iostream_rawlog_try_create_tcp(dir, input, output)) != 0)
f9b6b5e9c4e18682321959883c888035a56b6be9Timo Sirainen return ret < 0 ? -1 : 0;
f8e6e85ab508e80a66f323390f8f4e2edfff2730Timo Sirainen if (stat(dir, &st) < 0) {
f8e6e85ab508e80a66f323390f8f4e2edfff2730Timo Sirainen if (errno != ENOENT && errno != EACCES)
f8e6e85ab508e80a66f323390f8f4e2edfff2730Timo Sirainen i_error("rawlog: stat(%s) failed: %m", dir);
f8e6e85ab508e80a66f323390f8f4e2edfff2730Timo Sirainen return -1;
f8e6e85ab508e80a66f323390f8f4e2edfff2730Timo Sirainen }
be6ad6e46ecb8c7126b421819046e7f4857a2babTimo Sirainen
b1f37113a5760bee842c5a7678bb5fa6f5bd8b60Timo Sirainen timestamp = t_strflocaltime("%Y%m%d-%H%M%S", ioloop_time);
be6ad6e46ecb8c7126b421819046e7f4857a2babTimo Sirainen
be6ad6e46ecb8c7126b421819046e7f4857a2babTimo Sirainen counter++;
f1ed4fa248aaf6841ba638b9d66b2738d9f7aa18Timo Sirainen prefix = t_strdup_printf("%s/%s.%s.%u", dir, timestamp, my_pid, counter);
f1ed4fa248aaf6841ba638b9d66b2738d9f7aa18Timo Sirainen return iostream_rawlog_create_prefix(prefix, input, output);
f1ed4fa248aaf6841ba638b9d66b2738d9f7aa18Timo Sirainen}
be6ad6e46ecb8c7126b421819046e7f4857a2babTimo Sirainen
f1ed4fa248aaf6841ba638b9d66b2738d9f7aa18Timo Sirainenint iostream_rawlog_create_prefix(const char *prefix, struct istream **input,
f1ed4fa248aaf6841ba638b9d66b2738d9f7aa18Timo Sirainen struct ostream **output)
f1ed4fa248aaf6841ba638b9d66b2738d9f7aa18Timo Sirainen{
f1ed4fa248aaf6841ba638b9d66b2738d9f7aa18Timo Sirainen const char *in_path, *out_path;
f1ed4fa248aaf6841ba638b9d66b2738d9f7aa18Timo Sirainen struct istream *old_input;
f1ed4fa248aaf6841ba638b9d66b2738d9f7aa18Timo Sirainen struct ostream *old_output;
f1ed4fa248aaf6841ba638b9d66b2738d9f7aa18Timo Sirainen int in_fd, out_fd;
f1ed4fa248aaf6841ba638b9d66b2738d9f7aa18Timo Sirainen
f1ed4fa248aaf6841ba638b9d66b2738d9f7aa18Timo Sirainen in_path = t_strdup_printf("%s.in", prefix);
be6ad6e46ecb8c7126b421819046e7f4857a2babTimo Sirainen in_fd = open(in_path, O_CREAT | O_APPEND | O_WRONLY, 0600);
be6ad6e46ecb8c7126b421819046e7f4857a2babTimo Sirainen if (in_fd == -1) {
be6ad6e46ecb8c7126b421819046e7f4857a2babTimo Sirainen i_error("creat(%s) failed: %m", in_path);
be6ad6e46ecb8c7126b421819046e7f4857a2babTimo Sirainen return -1;
be6ad6e46ecb8c7126b421819046e7f4857a2babTimo Sirainen }
be6ad6e46ecb8c7126b421819046e7f4857a2babTimo Sirainen
f1ed4fa248aaf6841ba638b9d66b2738d9f7aa18Timo Sirainen out_path = t_strdup_printf("%s.out", prefix);
be6ad6e46ecb8c7126b421819046e7f4857a2babTimo Sirainen out_fd = open(out_path, O_CREAT | O_APPEND | O_WRONLY, 0600);
be6ad6e46ecb8c7126b421819046e7f4857a2babTimo Sirainen if (out_fd == -1) {
be6ad6e46ecb8c7126b421819046e7f4857a2babTimo Sirainen i_error("creat(%s) failed: %m", out_path);
4307c886579381dbb1897ea1388ae6978c96f560Timo Sirainen i_close_fd(&in_fd);
46b823ac3bce2c0f9f0fc73911e48d3a77b04fbeTimo Sirainen i_unlink(in_path);
be6ad6e46ecb8c7126b421819046e7f4857a2babTimo Sirainen return -1;
be6ad6e46ecb8c7126b421819046e7f4857a2babTimo Sirainen }
be6ad6e46ecb8c7126b421819046e7f4857a2babTimo Sirainen
be6ad6e46ecb8c7126b421819046e7f4857a2babTimo Sirainen old_input = *input;
be6ad6e46ecb8c7126b421819046e7f4857a2babTimo Sirainen old_output = *output;
b367011da1a2ba3e9113dfbc601aaa4b6b04317dTimo Sirainen
f1ed4fa248aaf6841ba638b9d66b2738d9f7aa18Timo Sirainen *input = i_stream_create_rawlog(old_input, in_path, in_fd,
b367011da1a2ba3e9113dfbc601aaa4b6b04317dTimo Sirainen IOSTREAM_RAWLOG_FLAG_AUTOCLOSE |
b367011da1a2ba3e9113dfbc601aaa4b6b04317dTimo Sirainen IOSTREAM_RAWLOG_FLAG_TIMESTAMP);
f1ed4fa248aaf6841ba638b9d66b2738d9f7aa18Timo Sirainen *output = o_stream_create_rawlog(old_output, out_path, out_fd,
b367011da1a2ba3e9113dfbc601aaa4b6b04317dTimo Sirainen IOSTREAM_RAWLOG_FLAG_AUTOCLOSE |
b367011da1a2ba3e9113dfbc601aaa4b6b04317dTimo Sirainen IOSTREAM_RAWLOG_FLAG_TIMESTAMP);
f1ed4fa248aaf6841ba638b9d66b2738d9f7aa18Timo Sirainen i_stream_unref(&old_input);
f1ed4fa248aaf6841ba638b9d66b2738d9f7aa18Timo Sirainen o_stream_unref(&old_output);
f1ed4fa248aaf6841ba638b9d66b2738d9f7aa18Timo Sirainen return 0;
f1ed4fa248aaf6841ba638b9d66b2738d9f7aa18Timo Sirainen}
f1ed4fa248aaf6841ba638b9d66b2738d9f7aa18Timo Sirainen
f1ed4fa248aaf6841ba638b9d66b2738d9f7aa18Timo Sirainenint iostream_rawlog_create_path(const char *path, struct istream **input,
f1ed4fa248aaf6841ba638b9d66b2738d9f7aa18Timo Sirainen struct ostream **output)
f1ed4fa248aaf6841ba638b9d66b2738d9f7aa18Timo Sirainen{
f9b6b5e9c4e18682321959883c888035a56b6be9Timo Sirainen int ret, fd;
f1ed4fa248aaf6841ba638b9d66b2738d9f7aa18Timo Sirainen
f9b6b5e9c4e18682321959883c888035a56b6be9Timo Sirainen if ((ret = iostream_rawlog_try_create_tcp(path, input, output)) != 0)
f9b6b5e9c4e18682321959883c888035a56b6be9Timo Sirainen return ret < 0 ? -1 : 0;
f1ed4fa248aaf6841ba638b9d66b2738d9f7aa18Timo Sirainen fd = open(path, O_CREAT | O_APPEND | O_WRONLY, 0600);
f1ed4fa248aaf6841ba638b9d66b2738d9f7aa18Timo Sirainen if (fd == -1) {
f1ed4fa248aaf6841ba638b9d66b2738d9f7aa18Timo Sirainen i_error("creat(%s) failed: %m", path);
f1ed4fa248aaf6841ba638b9d66b2738d9f7aa18Timo Sirainen return -1;
f1ed4fa248aaf6841ba638b9d66b2738d9f7aa18Timo Sirainen }
f9b6b5e9c4e18682321959883c888035a56b6be9Timo Sirainen iostream_rawlog_create_fd(fd, path, input, output);
be6ad6e46ecb8c7126b421819046e7f4857a2babTimo Sirainen return 0;
be6ad6e46ecb8c7126b421819046e7f4857a2babTimo Sirainen}
76d4ff1c1b31a1a09f6cbfe613a8d0efe62cbfd2Timo Sirainen
76d4ff1c1b31a1a09f6cbfe613a8d0efe62cbfd2Timo Sirainenvoid iostream_rawlog_create_from_stream(struct ostream *rawlog_output,
76d4ff1c1b31a1a09f6cbfe613a8d0efe62cbfd2Timo Sirainen struct istream **input,
76d4ff1c1b31a1a09f6cbfe613a8d0efe62cbfd2Timo Sirainen struct ostream **output)
76d4ff1c1b31a1a09f6cbfe613a8d0efe62cbfd2Timo Sirainen{
76d4ff1c1b31a1a09f6cbfe613a8d0efe62cbfd2Timo Sirainen const enum iostream_rawlog_flags rawlog_flags =
76d4ff1c1b31a1a09f6cbfe613a8d0efe62cbfd2Timo Sirainen IOSTREAM_RAWLOG_FLAG_BUFFERED |
76d4ff1c1b31a1a09f6cbfe613a8d0efe62cbfd2Timo Sirainen IOSTREAM_RAWLOG_FLAG_TIMESTAMP;
76d4ff1c1b31a1a09f6cbfe613a8d0efe62cbfd2Timo Sirainen struct istream *old_input;
76d4ff1c1b31a1a09f6cbfe613a8d0efe62cbfd2Timo Sirainen struct ostream *old_output;
76d4ff1c1b31a1a09f6cbfe613a8d0efe62cbfd2Timo Sirainen
fc64b2b538099893e2c2dde103b5c5af1d05d6daTimo Sirainen if (input != NULL) {
fc64b2b538099893e2c2dde103b5c5af1d05d6daTimo Sirainen old_input = *input;
fc64b2b538099893e2c2dde103b5c5af1d05d6daTimo Sirainen *input = i_stream_create_rawlog_from_stream(old_input,
fc64b2b538099893e2c2dde103b5c5af1d05d6daTimo Sirainen rawlog_output, rawlog_flags);
fc64b2b538099893e2c2dde103b5c5af1d05d6daTimo Sirainen i_stream_unref(&old_input);
fc64b2b538099893e2c2dde103b5c5af1d05d6daTimo Sirainen }
fc64b2b538099893e2c2dde103b5c5af1d05d6daTimo Sirainen if (output != NULL) {
fc64b2b538099893e2c2dde103b5c5af1d05d6daTimo Sirainen old_output = *output;
fc64b2b538099893e2c2dde103b5c5af1d05d6daTimo Sirainen *output = o_stream_create_rawlog_from_stream(old_output,
fc64b2b538099893e2c2dde103b5c5af1d05d6daTimo Sirainen rawlog_output, rawlog_flags);
fc64b2b538099893e2c2dde103b5c5af1d05d6daTimo Sirainen o_stream_unref(&old_output);
fc64b2b538099893e2c2dde103b5c5af1d05d6daTimo Sirainen }
75157863d633300d814fe630590ccb5310b9fdc2Timo Sirainen if (input != NULL && output != NULL)
75157863d633300d814fe630590ccb5310b9fdc2Timo Sirainen o_stream_ref(rawlog_output);
76d4ff1c1b31a1a09f6cbfe613a8d0efe62cbfd2Timo Sirainen}