/src/dovecot/src/lib-fs/ostream-metawrap.c
Line | Count | Source |
1 | | /* Copyright (c) 2013-2018 Dovecot authors, see the included COPYING file */ |
2 | | |
3 | | #include "lib.h" |
4 | | #include "istream.h" |
5 | | #include "ostream-private.h" |
6 | | #include "ostream-metawrap.h" |
7 | | |
8 | | struct metawrap_ostream { |
9 | | struct ostream_private ostream; |
10 | | void (*write_callback)(void *); |
11 | | void *context; |
12 | | }; |
13 | | |
14 | | static void o_stream_metawrap_call_callback(struct metawrap_ostream *mstream) |
15 | 0 | { |
16 | 0 | void (*write_callback)(void *) = mstream->write_callback; |
17 | |
|
18 | 0 | if (write_callback != NULL) { |
19 | 0 | mstream->write_callback = NULL; |
20 | 0 | write_callback(mstream->context); |
21 | | /* metadata headers aren't counted as part of the offset */ |
22 | 0 | mstream->ostream.ostream.offset = 0; |
23 | 0 | } |
24 | 0 | } |
25 | | |
26 | | static ssize_t |
27 | | o_stream_metawrap_sendv(struct ostream_private *stream, |
28 | | const struct const_iovec *iov, unsigned int iov_count) |
29 | 0 | { |
30 | 0 | struct metawrap_ostream *mstream = (struct metawrap_ostream *)stream; |
31 | 0 | ssize_t ret; |
32 | |
|
33 | 0 | o_stream_metawrap_call_callback(mstream); |
34 | 0 | if ((ret = o_stream_sendv(stream->parent, iov, iov_count)) < 0) |
35 | 0 | o_stream_copy_error_from_parent(stream); |
36 | 0 | else |
37 | 0 | stream->ostream.offset += ret; |
38 | 0 | return ret; |
39 | 0 | } |
40 | | |
41 | | static enum ostream_send_istream_result |
42 | | o_stream_metawrap_send_istream(struct ostream_private *_outstream, |
43 | | struct istream *instream) |
44 | 0 | { |
45 | 0 | struct metawrap_ostream *outstream = |
46 | 0 | (struct metawrap_ostream *)_outstream; |
47 | 0 | uoff_t orig_instream_offset = instream->v_offset; |
48 | 0 | enum ostream_send_istream_result res; |
49 | |
|
50 | 0 | o_stream_metawrap_call_callback(outstream); |
51 | 0 | if ((res = o_stream_send_istream(_outstream->parent, instream)) == OSTREAM_SEND_ISTREAM_RESULT_ERROR_OUTPUT) |
52 | 0 | o_stream_copy_error_from_parent(_outstream); |
53 | 0 | _outstream->ostream.offset += instream->v_offset - orig_instream_offset; |
54 | 0 | return res; |
55 | 0 | } |
56 | | |
57 | | struct ostream * |
58 | | o_stream_create_metawrap(struct ostream *output, |
59 | | void (*write_callback)(void *), void *context) |
60 | 0 | { |
61 | 0 | struct metawrap_ostream *mstream; |
62 | |
|
63 | 0 | mstream = i_new(struct metawrap_ostream, 1); |
64 | 0 | mstream->ostream.sendv = o_stream_metawrap_sendv; |
65 | 0 | mstream->ostream.send_istream = o_stream_metawrap_send_istream; |
66 | 0 | mstream->write_callback = write_callback; |
67 | 0 | mstream->context = context; |
68 | |
|
69 | 0 | return o_stream_create(&mstream->ostream, output, |
70 | 0 | o_stream_get_fd(output)); |
71 | 0 | } |