~ubuntu-branches/ubuntu/wily/dovecot/wily

« back to all changes in this revision

Viewing changes to src/lib/iostream-rawlog.c

  • Committer: Package Import Robot
  • Author(s): Jaldhar H. Vyas
  • Date: 2013-09-09 00:57:32 UTC
  • mfrom: (1.13.11)
  • mto: (4.8.5 experimental) (1.16.1)
  • mto: This revision was merged to the branch mainline in revision 97.
  • Revision ID: package-import@ubuntu.com-20130909005732-dn1eell8srqbhh0e
Tags: upstream-2.2.5
ImportĀ upstreamĀ versionĀ 2.2.5

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* Copyright (c) 2011-2012 Dovecot authors, see the included COPYING file */
 
1
/* Copyright (c) 2011-2013 Dovecot authors, see the included COPYING file */
2
2
 
3
3
#include "lib.h"
4
4
#include "hostpid.h"
5
5
#include "ioloop.h"
 
6
#include "buffer.h"
 
7
#include "str.h"
6
8
#include "write-full.h"
7
9
#include "time-util.h"
8
10
#include "istream.h"
9
11
#include "ostream.h"
 
12
#include "iostream-private.h"
 
13
#include "iostream-rawlog-private.h"
10
14
#include "istream-rawlog.h"
11
15
#include "ostream-rawlog.h"
12
 
#include "iostream-private.h"
13
 
#include "iostream-rawlog-private.h"
14
16
#include "iostream-rawlog.h"
15
17
 
16
18
#include <unistd.h>
17
19
#include <fcntl.h>
18
20
 
19
 
static void
 
21
#define RAWLOG_MAX_LINE_LEN 8192
 
22
 
 
23
static int
20
24
rawlog_write(struct rawlog_iostream *rstream, const void *data, size_t size)
21
25
{
22
26
        if (rstream->rawlog_fd == -1)
23
 
                return;
 
27
                return -1;
24
28
 
25
29
        if (write_full(rstream->rawlog_fd, data, size) < 0) {
26
30
                i_error("rawlog_istream.write(%s) failed: %m",
27
31
                        rstream->rawlog_path);
28
32
                iostream_rawlog_close(rstream);
29
 
        }
30
 
}
31
 
 
32
 
static void rawlog_write_timestamp(struct rawlog_iostream *rstream)
33
 
{
34
 
        char buf[MAX_INT_STRLEN + 6 + 2];
35
 
 
36
 
        i_snprintf(buf, sizeof(buf), "%lu.%06u ",
37
 
                   (unsigned long)ioloop_timeval.tv_sec,
38
 
                   (unsigned int)ioloop_timeval.tv_usec);
39
 
        rawlog_write(rstream, buf, strlen(buf));
 
33
                return -1;
 
34
        }
 
35
        return 0;
 
36
}
 
37
 
 
38
static int
 
39
rawlog_write_timestamp(struct rawlog_iostream *rstream, bool line_ends)
 
40
{
 
41
        unsigned char data[MAX_INT_STRLEN + 6 + 1 + 3];
 
42
        buffer_t buf;
 
43
 
 
44
        buffer_create_from_data(&buf, data, sizeof(data));
 
45
        str_printfa(&buf, "%lu.%06u ",
 
46
                    (unsigned long)ioloop_timeval.tv_sec,
 
47
                    (unsigned int)ioloop_timeval.tv_usec);
 
48
        if ((rstream->flags & IOSTREAM_RAWLOG_FLAG_BUFFERED) != 0) {
 
49
                str_append_c(&buf, rstream->input ? 'I' : 'O');
 
50
                str_append_c(&buf, line_ends ? ':' : '>');
 
51
                str_append_c(&buf, ' ');
 
52
        }
 
53
        return rawlog_write(rstream, buf.data, buf.used);
 
54
}
 
55
 
 
56
void iostream_rawlog_init(struct rawlog_iostream *rstream,
 
57
                          enum iostream_rawlog_flags flags, bool input)
 
58
{
 
59
        rstream->flags = flags;
 
60
        rstream->input = input;
 
61
        if ((rstream->flags & IOSTREAM_RAWLOG_FLAG_BUFFERED) != 0)
 
62
                rstream->buffer = buffer_create_dynamic(default_pool, 1024);
 
63
}
 
64
 
 
65
static void
 
66
iostream_rawlog_write_unbuffered(struct rawlog_iostream *rstream,
 
67
                                 const unsigned char *data, size_t size)
 
68
{
 
69
        size_t i, start;
 
70
 
 
71
        if (!rstream->line_continued) {
 
72
                if (rawlog_write_timestamp(rstream, TRUE) < 0)
 
73
                        return;
 
74
        }
 
75
 
 
76
        for (start = 0, i = 1; i < size; i++) {
 
77
                if (data[i-1] == '\n') {
 
78
                        if (rawlog_write(rstream, data + start, i - start) < 0 ||
 
79
                            rawlog_write_timestamp(rstream, TRUE) < 0)
 
80
                                return;
 
81
                        start = i;
 
82
                }
 
83
        }
 
84
        if (start != size) {
 
85
                if (rawlog_write(rstream, data + start, size - start) < 0)
 
86
                        return;
 
87
        }
 
88
        rstream->line_continued = data[size-1] != '\n';
40
89
}
41
90
 
42
91
void iostream_rawlog_write(struct rawlog_iostream *rstream,
43
92
                           const unsigned char *data, size_t size)
44
93
{
45
 
        size_t i, start;
 
94
        const unsigned char *p;
 
95
        size_t pos;
 
96
        bool line_ends;
46
97
 
47
98
        if (size == 0)
48
99
                return;
49
100
 
50
101
        io_loop_time_refresh();
51
 
        if (rstream->write_timestamp)
52
 
                rawlog_write_timestamp(rstream);
53
 
 
54
 
        for (start = 0, i = 1; i < size; i++) {
55
 
                if (data[i-1] == '\n') {
56
 
                        rawlog_write(rstream, data + start, i - start);
57
 
                        rawlog_write_timestamp(rstream);
58
 
                        start = i;
59
 
                }
60
 
        }
61
 
        if (start != size)
62
 
                rawlog_write(rstream, data + start, size - start);
63
 
        rstream->write_timestamp = data[size-1] == '\n';
 
102
        if ((rstream->flags & IOSTREAM_RAWLOG_FLAG_BUFFERED) == 0) {
 
103
                iostream_rawlog_write_unbuffered(rstream, data, size);
 
104
                return;
 
105
        }
 
106
 
 
107
        while (rstream->rawlog_fd != -1 && size > 0) {
 
108
                p = memchr(data, '\n', size);
 
109
                if (p != NULL) {
 
110
                        line_ends = TRUE;
 
111
                        pos = p-data + 1;
 
112
                } else if (rstream->buffer->used + size < RAWLOG_MAX_LINE_LEN) {
 
113
                        buffer_append(rstream->buffer, data, size);
 
114
                        return;
 
115
                } else {
 
116
                        line_ends = FALSE;
 
117
                        pos = size;
 
118
                }
 
119
 
 
120
                if (rawlog_write_timestamp(rstream, line_ends) < 0)
 
121
                        break;
 
122
                if (rstream->buffer->used > 0) {
 
123
                        if (rawlog_write(rstream, rstream->buffer->data,
 
124
                                         rstream->buffer->used) < 0)
 
125
                                break;
 
126
                        buffer_set_used_size(rstream->buffer, 0);
 
127
                }
 
128
                if (rawlog_write(rstream, data, pos) < 0)
 
129
                        break;
 
130
 
 
131
                data += pos;
 
132
                size -= pos;
 
133
        }
64
134
}
65
135
 
66
136
void iostream_rawlog_close(struct rawlog_iostream *rstream)
67
137
{
68
 
        if (rstream->autoclose_fd && rstream->rawlog_fd != -1) {
 
138
        if ((rstream->flags & IOSTREAM_RAWLOG_FLAG_AUTOCLOSE) != 0 &&
 
139
            rstream->rawlog_fd != -1) {
69
140
                if (close(rstream->rawlog_fd) < 0) {
70
141
                        i_error("rawlog_istream.close(%s) failed: %m",
71
142
                                rstream->rawlog_path);
73
144
        }
74
145
        rstream->rawlog_fd = -1;
75
146
        i_free_and_null(rstream->rawlog_path);
 
147
        if (rstream->buffer != NULL)
 
148
                buffer_free(&rstream->buffer);
76
149
}
77
150
 
78
151
int iostream_rawlog_create(const char *dir, struct istream **input,
79
152
                           struct ostream **output)
80
153
{
81
154
        static unsigned int counter = 0;
82
 
        const char *timestamp, *in_path, *out_path;
83
 
        struct istream *old_input;
84
 
        struct ostream *old_output;
85
 
        int in_fd, out_fd;
 
155
        const char *timestamp, *prefix;
86
156
 
87
157
        timestamp = t_strflocaltime("%Y%m%d-%H%M%S", ioloop_time);
88
158
 
89
159
        counter++;
90
 
        in_path = t_strdup_printf("%s/%s.%s.%u.in",
91
 
                                  dir, timestamp, my_pid, counter);
92
 
        out_path = t_strdup_printf("%s/%s.%s.%u.out",
93
 
                                   dir, timestamp, my_pid, counter);
94
 
 
 
160
        prefix = t_strdup_printf("%s/%s.%s.%u", dir, timestamp, my_pid, counter);
 
161
        return iostream_rawlog_create_prefix(prefix, input, output);
 
162
}
 
163
 
 
164
int iostream_rawlog_create_prefix(const char *prefix, struct istream **input,
 
165
                                  struct ostream **output)
 
166
{
 
167
        const char *in_path, *out_path;
 
168
        struct istream *old_input;
 
169
        struct ostream *old_output;
 
170
        int in_fd, out_fd;
 
171
 
 
172
        in_path = t_strdup_printf("%s.in", prefix);
95
173
        in_fd = open(in_path, O_CREAT | O_APPEND | O_WRONLY, 0600);
96
174
        if (in_fd == -1) {
97
175
                i_error("creat(%s) failed: %m", in_path);
98
176
                return -1;
99
177
        }
100
178
 
 
179
        out_path = t_strdup_printf("%s.out", prefix);
101
180
        out_fd = open(out_path, O_CREAT | O_APPEND | O_WRONLY, 0600);
102
181
        if (out_fd == -1) {
103
182
                i_error("creat(%s) failed: %m", out_path);
104
 
                (void)close(in_fd);
 
183
                i_close_fd(&in_fd);
105
184
                (void)unlink(in_path);
106
185
                return -1;
107
186
        }
108
187
 
109
188
        old_input = *input;
110
189
        old_output = *output;
111
 
        *input = i_stream_create_rawlog(old_input, in_path, in_fd, TRUE);
112
 
        *output = o_stream_create_rawlog(old_output, out_path, out_fd, TRUE);
 
190
        *input = i_stream_create_rawlog(old_input, in_path, in_fd,
 
191
                                        IOSTREAM_RAWLOG_FLAG_AUTOCLOSE);
 
192
        *output = o_stream_create_rawlog(old_output, out_path, out_fd,
 
193
                                         IOSTREAM_RAWLOG_FLAG_AUTOCLOSE);
 
194
        i_stream_unref(&old_input);
 
195
        o_stream_unref(&old_output);
 
196
        return 0;
 
197
}
 
198
 
 
199
int iostream_rawlog_create_path(const char *path, struct istream **input,
 
200
                                struct ostream **output)
 
201
{
 
202
        struct istream *old_input;
 
203
        struct ostream *old_output;
 
204
        int fd;
 
205
 
 
206
        fd = open(path, O_CREAT | O_APPEND | O_WRONLY, 0600);
 
207
        if (fd == -1) {
 
208
                i_error("creat(%s) failed: %m", path);
 
209
                return -1;
 
210
        }
 
211
 
 
212
        old_input = *input;
 
213
        old_output = *output;
 
214
        *input = i_stream_create_rawlog(old_input, path, fd,
 
215
                                        IOSTREAM_RAWLOG_FLAG_BUFFERED);
 
216
        *output = o_stream_create_rawlog(old_output, path, fd,
 
217
                                         IOSTREAM_RAWLOG_FLAG_AUTOCLOSE |
 
218
                                         IOSTREAM_RAWLOG_FLAG_BUFFERED);
113
219
        i_stream_unref(&old_input);
114
220
        o_stream_unref(&old_output);
115
221
        return 0;