summaryrefslogtreecommitdiffstats
path: root/src/lib-fs/ostream-metawrap.c
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-15 17:36:47 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-15 17:36:47 +0000
commit0441d265f2bb9da249c7abf333f0f771fadb4ab5 (patch)
tree3f3789daa2f6db22da6e55e92bee0062a7d613fe /src/lib-fs/ostream-metawrap.c
parentInitial commit. (diff)
downloaddovecot-0441d265f2bb9da249c7abf333f0f771fadb4ab5.tar.xz
dovecot-0441d265f2bb9da249c7abf333f0f771fadb4ab5.zip
Adding upstream version 1:2.3.21+dfsg1.upstream/1%2.3.21+dfsg1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/lib-fs/ostream-metawrap.c')
-rw-r--r--src/lib-fs/ostream-metawrap.c71
1 files changed, 71 insertions, 0 deletions
diff --git a/src/lib-fs/ostream-metawrap.c b/src/lib-fs/ostream-metawrap.c
new file mode 100644
index 0000000..3359bd3
--- /dev/null
+++ b/src/lib-fs/ostream-metawrap.c
@@ -0,0 +1,71 @@
+/* Copyright (c) 2013-2018 Dovecot authors, see the included COPYING file */
+
+#include "lib.h"
+#include "istream.h"
+#include "ostream-private.h"
+#include "ostream-metawrap.h"
+
+struct metawrap_ostream {
+ struct ostream_private ostream;
+ void (*write_callback)(void *);
+ void *context;
+};
+
+static void o_stream_metawrap_call_callback(struct metawrap_ostream *mstream)
+{
+ void (*write_callback)(void *) = mstream->write_callback;
+
+ if (write_callback != NULL) {
+ mstream->write_callback = NULL;
+ write_callback(mstream->context);
+ /* metadata headers aren't counted as part of the offset */
+ mstream->ostream.ostream.offset = 0;
+ }
+}
+
+static ssize_t
+o_stream_metawrap_sendv(struct ostream_private *stream,
+ const struct const_iovec *iov, unsigned int iov_count)
+{
+ struct metawrap_ostream *mstream = (struct metawrap_ostream *)stream;
+ ssize_t ret;
+
+ o_stream_metawrap_call_callback(mstream);
+ if ((ret = o_stream_sendv(stream->parent, iov, iov_count)) < 0)
+ o_stream_copy_error_from_parent(stream);
+ else
+ stream->ostream.offset += ret;
+ return ret;
+}
+
+static enum ostream_send_istream_result
+o_stream_metawrap_send_istream(struct ostream_private *_outstream,
+ struct istream *instream)
+{
+ struct metawrap_ostream *outstream =
+ (struct metawrap_ostream *)_outstream;
+ uoff_t orig_instream_offset = instream->v_offset;
+ enum ostream_send_istream_result res;
+
+ o_stream_metawrap_call_callback(outstream);
+ if ((res = o_stream_send_istream(_outstream->parent, instream)) == OSTREAM_SEND_ISTREAM_RESULT_ERROR_OUTPUT)
+ o_stream_copy_error_from_parent(_outstream);
+ _outstream->ostream.offset += instream->v_offset - orig_instream_offset;
+ return res;
+}
+
+struct ostream *
+o_stream_create_metawrap(struct ostream *output,
+ void (*write_callback)(void *), void *context)
+{
+ struct metawrap_ostream *mstream;
+
+ mstream = i_new(struct metawrap_ostream, 1);
+ mstream->ostream.sendv = o_stream_metawrap_sendv;
+ mstream->ostream.send_istream = o_stream_metawrap_send_istream;
+ mstream->write_callback = write_callback;
+ mstream->context = context;
+
+ return o_stream_create(&mstream->ostream, output,
+ o_stream_get_fd(output));
+}