ostream.c revision 6adf683655750bcb809275cd65dc75fd12214198
5f5870385cff47efd2f58e7892f251cf13761528Timo Sirainen/* Copyright (c) 2002-2016 Dovecot authors, see the included COPYING file */
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen#include "lib.h"
47e0598840ecffa364ebed523e06939e22738f06Timo Sirainen#include "istream.h"
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen#include "ostream-private.h"
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainenvoid o_stream_set_name(struct ostream *stream, const char *name)
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen{
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen i_free(stream->real_stream->iostream.name);
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen stream->real_stream->iostream.name = i_strdup(name);
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen}
95a1a5195d56f3cf5d1e529aad668f87ad3b979bTimo Sirainen
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainenconst char *o_stream_get_name(struct ostream *stream)
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen{
1d738cce754bc64bbc66d3355ebdaf3f6eac55f1Timo Sirainen while (stream->real_stream->iostream.name == NULL) {
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen stream = stream->real_stream->parent;
bdd7a96c363346f7c38f389791be1487ca08775bTimo Sirainen if (stream == NULL)
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen return "";
63e2edd14ae7b1dc4a08e2e659501dbf519462f9Timo Sirainen }
63e2edd14ae7b1dc4a08e2e659501dbf519462f9Timo Sirainen return stream->real_stream->iostream.name;
63e2edd14ae7b1dc4a08e2e659501dbf519462f9Timo Sirainen}
029cfcdce65b284d5230adf1c920a5f526b03b5cTimo Sirainen
029cfcdce65b284d5230adf1c920a5f526b03b5cTimo Sirainenint o_stream_get_fd(struct ostream *stream)
029cfcdce65b284d5230adf1c920a5f526b03b5cTimo Sirainen{
029cfcdce65b284d5230adf1c920a5f526b03b5cTimo Sirainen return stream->real_stream->fd;
029cfcdce65b284d5230adf1c920a5f526b03b5cTimo Sirainen}
029cfcdce65b284d5230adf1c920a5f526b03b5cTimo Sirainen
029cfcdce65b284d5230adf1c920a5f526b03b5cTimo Sirainenconst char *o_stream_get_error(struct ostream *stream)
029cfcdce65b284d5230adf1c920a5f526b03b5cTimo Sirainen{
90c23747727c85f80e4e8eed7968f0edbeac7ac5Timo Sirainen struct ostream *s;
90c23747727c85f80e4e8eed7968f0edbeac7ac5Timo Sirainen
90c23747727c85f80e4e8eed7968f0edbeac7ac5Timo Sirainen /* we'll only return errors for streams that have stream_errno set.
90c23747727c85f80e4e8eed7968f0edbeac7ac5Timo Sirainen we might be returning unintended error otherwise. */
90c23747727c85f80e4e8eed7968f0edbeac7ac5Timo Sirainen if (stream->stream_errno == 0)
90c23747727c85f80e4e8eed7968f0edbeac7ac5Timo Sirainen return "<no error>";
90c23747727c85f80e4e8eed7968f0edbeac7ac5Timo Sirainen
90c23747727c85f80e4e8eed7968f0edbeac7ac5Timo Sirainen for (s = stream; s != NULL; s = s->real_stream->parent) {
90c23747727c85f80e4e8eed7968f0edbeac7ac5Timo Sirainen if (s->stream_errno == 0)
90c23747727c85f80e4e8eed7968f0edbeac7ac5Timo Sirainen break;
90c23747727c85f80e4e8eed7968f0edbeac7ac5Timo Sirainen if (s->real_stream->iostream.error != NULL)
90c23747727c85f80e4e8eed7968f0edbeac7ac5Timo Sirainen return s->real_stream->iostream.error;
90c23747727c85f80e4e8eed7968f0edbeac7ac5Timo Sirainen }
90c23747727c85f80e4e8eed7968f0edbeac7ac5Timo Sirainen return strerror(stream->stream_errno);
90c23747727c85f80e4e8eed7968f0edbeac7ac5Timo Sirainen}
90c23747727c85f80e4e8eed7968f0edbeac7ac5Timo Sirainen
90c23747727c85f80e4e8eed7968f0edbeac7ac5Timo Sirainenstatic void o_stream_close_full(struct ostream *stream, bool close_parents)
90c23747727c85f80e4e8eed7968f0edbeac7ac5Timo Sirainen{
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen if (!stream->closed && !stream->real_stream->closing) {
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen /* first mark the stream as being closed so the
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen o_stream_copy_error_from_parent() won't recurse us back
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen here. but don't immediately mark the stream closed, because
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen we may still want to write something to it. */
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen stream->real_stream->closing = TRUE;
2d49f150b4bce6f2f59a84e268e4777901c3e42cTimo Sirainen io_stream_close(&stream->real_stream->iostream, close_parents);
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen stream->closed = TRUE;
90c23747727c85f80e4e8eed7968f0edbeac7ac5Timo Sirainen }
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen if (stream->stream_errno == 0)
19e8adccba16ff419f5675b1575358c2956dce83Timo Sirainen stream->stream_errno = EPIPE;
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen}
b397665e90fa0fc7c6a9156fdd6cf28b571e8e39Timo Sirainen
b397665e90fa0fc7c6a9156fdd6cf28b571e8e39Timo Sirainenvoid o_stream_destroy(struct ostream **stream)
b397665e90fa0fc7c6a9156fdd6cf28b571e8e39Timo Sirainen{
b397665e90fa0fc7c6a9156fdd6cf28b571e8e39Timo Sirainen o_stream_close_full(*stream, FALSE);
19e8adccba16ff419f5675b1575358c2956dce83Timo Sirainen o_stream_unref(stream);
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen}
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainenvoid o_stream_ref(struct ostream *stream)
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen{
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen io_stream_ref(&stream->real_stream->iostream);
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen}
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainenvoid o_stream_unref(struct ostream **_stream)
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen{
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen struct ostream *stream = *_stream;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen if (stream->real_stream->last_errors_not_checked &&
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen !stream->real_stream->error_handling_disabled &&
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen stream->real_stream->iostream.refcount == 1) {
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen i_panic("output stream %s is missing error handling",
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen o_stream_get_name(stream));
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen }
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen if (!io_stream_unref(&stream->real_stream->iostream))
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen io_stream_free(&stream->real_stream->iostream);
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen *_stream = NULL;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen}
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen#undef o_stream_add_destroy_callback
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainenvoid o_stream_add_destroy_callback(struct ostream *stream,
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen ostream_callback_t *callback, void *context)
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen{
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen io_stream_add_destroy_callback(&stream->real_stream->iostream,
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen callback, context);
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen}
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainenvoid o_stream_remove_destroy_callback(struct ostream *stream,
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen void (*callback)())
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen{
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen io_stream_remove_destroy_callback(&stream->real_stream->iostream,
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen callback);
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen}
0f66f12eb4cdbf47670975044c88d8f388bf92dfTimo Sirainen
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainenvoid o_stream_close(struct ostream *stream)
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen{
029cfcdce65b284d5230adf1c920a5f526b03b5cTimo Sirainen o_stream_close_full(stream, TRUE);
029cfcdce65b284d5230adf1c920a5f526b03b5cTimo Sirainen}
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen#undef o_stream_set_flush_callback
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainenvoid o_stream_set_flush_callback(struct ostream *stream,
029cfcdce65b284d5230adf1c920a5f526b03b5cTimo Sirainen stream_flush_callback_t *callback,
029cfcdce65b284d5230adf1c920a5f526b03b5cTimo Sirainen void *context)
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen{
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen struct ostream_private *_stream = stream->real_stream;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen _stream->set_flush_callback(_stream, callback, context);
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen}
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainenvoid o_stream_unset_flush_callback(struct ostream *stream)
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen{
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen struct ostream_private *_stream = stream->real_stream;
85144b5f0bc763de14c7d87291a90ef74ac241a2Timo Sirainen
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen _stream->set_flush_callback(_stream, NULL, NULL);
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen}
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen
95a1a5195d56f3cf5d1e529aad668f87ad3b979bTimo Sirainenvoid o_stream_set_max_buffer_size(struct ostream *stream, size_t max_size)
85144b5f0bc763de14c7d87291a90ef74ac241a2Timo Sirainen{
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen io_stream_set_max_buffer_size(&stream->real_stream->iostream, max_size);
85144b5f0bc763de14c7d87291a90ef74ac241a2Timo Sirainen}
85144b5f0bc763de14c7d87291a90ef74ac241a2Timo Sirainen
85144b5f0bc763de14c7d87291a90ef74ac241a2Timo Sirainensize_t o_stream_get_max_buffer_size(struct ostream *stream)
85144b5f0bc763de14c7d87291a90ef74ac241a2Timo Sirainen{
85144b5f0bc763de14c7d87291a90ef74ac241a2Timo Sirainen return stream->real_stream->max_buffer_size;
85144b5f0bc763de14c7d87291a90ef74ac241a2Timo Sirainen}
85144b5f0bc763de14c7d87291a90ef74ac241a2Timo Sirainen
85144b5f0bc763de14c7d87291a90ef74ac241a2Timo Sirainenvoid o_stream_cork(struct ostream *stream)
85144b5f0bc763de14c7d87291a90ef74ac241a2Timo Sirainen{
85144b5f0bc763de14c7d87291a90ef74ac241a2Timo Sirainen struct ostream_private *_stream = stream->real_stream;
85144b5f0bc763de14c7d87291a90ef74ac241a2Timo Sirainen
85144b5f0bc763de14c7d87291a90ef74ac241a2Timo Sirainen if (unlikely(stream->closed || stream->stream_errno != 0))
85144b5f0bc763de14c7d87291a90ef74ac241a2Timo Sirainen return;
85144b5f0bc763de14c7d87291a90ef74ac241a2Timo Sirainen
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen _stream->cork(_stream, TRUE);
95a1a5195d56f3cf5d1e529aad668f87ad3b979bTimo Sirainen}
85144b5f0bc763de14c7d87291a90ef74ac241a2Timo Sirainen
85144b5f0bc763de14c7d87291a90ef74ac241a2Timo Sirainenvoid o_stream_uncork(struct ostream *stream)
85144b5f0bc763de14c7d87291a90ef74ac241a2Timo Sirainen{
85144b5f0bc763de14c7d87291a90ef74ac241a2Timo Sirainen struct ostream_private *_stream = stream->real_stream;
0bf3eac1110a902e7ec7e695c64e8e46c114e623Timo Sirainen
0bf3eac1110a902e7ec7e695c64e8e46c114e623Timo Sirainen if (unlikely(stream->closed || stream->stream_errno != 0))
85144b5f0bc763de14c7d87291a90ef74ac241a2Timo Sirainen return;
85144b5f0bc763de14c7d87291a90ef74ac241a2Timo Sirainen
85144b5f0bc763de14c7d87291a90ef74ac241a2Timo Sirainen _stream->cork(_stream, FALSE);
85144b5f0bc763de14c7d87291a90ef74ac241a2Timo Sirainen}
85144b5f0bc763de14c7d87291a90ef74ac241a2Timo Sirainen
85144b5f0bc763de14c7d87291a90ef74ac241a2Timo Sirainenbool o_stream_is_corked(struct ostream *stream)
85144b5f0bc763de14c7d87291a90ef74ac241a2Timo Sirainen{
85144b5f0bc763de14c7d87291a90ef74ac241a2Timo Sirainen struct ostream_private *_stream = stream->real_stream;
85144b5f0bc763de14c7d87291a90ef74ac241a2Timo Sirainen
85144b5f0bc763de14c7d87291a90ef74ac241a2Timo Sirainen return _stream->corked;
85144b5f0bc763de14c7d87291a90ef74ac241a2Timo Sirainen}
85144b5f0bc763de14c7d87291a90ef74ac241a2Timo Sirainen
85144b5f0bc763de14c7d87291a90ef74ac241a2Timo Sirainenint o_stream_flush(struct ostream *stream)
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen{
f153a2cec0319f549388d28f8cfd4d50229d1132Timo Sirainen struct ostream_private *_stream = stream->real_stream;
f153a2cec0319f549388d28f8cfd4d50229d1132Timo Sirainen int ret = 1;
f153a2cec0319f549388d28f8cfd4d50229d1132Timo Sirainen
f153a2cec0319f549388d28f8cfd4d50229d1132Timo Sirainen if (unlikely(stream->closed || stream->stream_errno != 0)) {
f153a2cec0319f549388d28f8cfd4d50229d1132Timo Sirainen errno = stream->stream_errno;
dffa503fd4ce31334346e539496084c80a2d8d37Timo Sirainen return -1;
dffa503fd4ce31334346e539496084c80a2d8d37Timo Sirainen }
85144b5f0bc763de14c7d87291a90ef74ac241a2Timo Sirainen
85144b5f0bc763de14c7d87291a90ef74ac241a2Timo Sirainen if (unlikely((ret = _stream->flush(_stream)) < 0)) {
85144b5f0bc763de14c7d87291a90ef74ac241a2Timo Sirainen i_assert(stream->stream_errno != 0);
85144b5f0bc763de14c7d87291a90ef74ac241a2Timo Sirainen errno = stream->stream_errno;
85144b5f0bc763de14c7d87291a90ef74ac241a2Timo Sirainen }
85144b5f0bc763de14c7d87291a90ef74ac241a2Timo Sirainen return ret;
85144b5f0bc763de14c7d87291a90ef74ac241a2Timo Sirainen}
85144b5f0bc763de14c7d87291a90ef74ac241a2Timo Sirainen
85144b5f0bc763de14c7d87291a90ef74ac241a2Timo Sirainenvoid o_stream_set_flush_pending(struct ostream *stream, bool set)
85144b5f0bc763de14c7d87291a90ef74ac241a2Timo Sirainen{
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen struct ostream_private *_stream = stream->real_stream;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen
85144b5f0bc763de14c7d87291a90ef74ac241a2Timo Sirainen if (unlikely(stream->closed || stream->stream_errno != 0))
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen return;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen _stream->flush_pending(_stream, set);
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen}
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainensize_t o_stream_get_buffer_used_size(const struct ostream *stream)
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen{
63e2edd14ae7b1dc4a08e2e659501dbf519462f9Timo Sirainen const struct ostream_private *_stream = stream->real_stream;
63e2edd14ae7b1dc4a08e2e659501dbf519462f9Timo Sirainen
63e2edd14ae7b1dc4a08e2e659501dbf519462f9Timo Sirainen return _stream->get_used_size(_stream);
63e2edd14ae7b1dc4a08e2e659501dbf519462f9Timo Sirainen}
63e2edd14ae7b1dc4a08e2e659501dbf519462f9Timo Sirainen
63e2edd14ae7b1dc4a08e2e659501dbf519462f9Timo Sirainensize_t o_stream_get_buffer_avail_size(const struct ostream *stream)
63e2edd14ae7b1dc4a08e2e659501dbf519462f9Timo Sirainen{
63e2edd14ae7b1dc4a08e2e659501dbf519462f9Timo Sirainen size_t used = o_stream_get_buffer_used_size(stream);
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen return stream->real_stream->max_buffer_size <= used ? 0 :
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen stream->real_stream->max_buffer_size - used;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen}
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainenint o_stream_seek(struct ostream *stream, uoff_t offset)
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen{
b5b3b4c9159f506cdfdce7399faaeeffdf73faf7Timo Sirainen struct ostream_private *_stream = stream->real_stream;
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen if (unlikely(stream->closed || stream->stream_errno != 0)) {
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen errno = stream->stream_errno;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen return -1;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen }
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen if (unlikely(_stream->seek(_stream, offset) < 0)) {
40ad2c4902e9d83557f2e8a4bff3d98fea2c8aa1Timo Sirainen i_assert(stream->stream_errno != 0);
aef92409cf369afdd2ecd81a4f80083cd4082f46Timo Sirainen errno = stream->stream_errno;
aef92409cf369afdd2ecd81a4f80083cd4082f46Timo Sirainen return -1;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen }
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen return 1;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen}
2d49f150b4bce6f2f59a84e268e4777901c3e42cTimo Sirainen
14c474d9f4591c397ed0b5206af6537c7b52c924Timo Sirainenssize_t o_stream_send(struct ostream *stream, const void *data, size_t size)
14c474d9f4591c397ed0b5206af6537c7b52c924Timo Sirainen{
2d49f150b4bce6f2f59a84e268e4777901c3e42cTimo Sirainen struct const_iovec iov;
2d49f150b4bce6f2f59a84e268e4777901c3e42cTimo Sirainen
2d49f150b4bce6f2f59a84e268e4777901c3e42cTimo Sirainen memset(&iov, 0, sizeof(iov));
2d49f150b4bce6f2f59a84e268e4777901c3e42cTimo Sirainen iov.iov_base = data;
2d49f150b4bce6f2f59a84e268e4777901c3e42cTimo Sirainen iov.iov_len = size;
2d49f150b4bce6f2f59a84e268e4777901c3e42cTimo Sirainen
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen return o_stream_sendv(stream, &iov, 1);
8d131435ba4648c8821160ec38d508c97177c715Timo Sirainen}
8d131435ba4648c8821160ec38d508c97177c715Timo Sirainen
8d131435ba4648c8821160ec38d508c97177c715Timo Sirainenstatic ssize_t
8d131435ba4648c8821160ec38d508c97177c715Timo Siraineno_stream_sendv_int(struct ostream *stream, const struct const_iovec *iov,
b6612c334604eeb27e1ca2bd804ac66dcbc2eaadTimo Sirainen unsigned int iov_count, bool *overflow_r)
95a1a5195d56f3cf5d1e529aad668f87ad3b979bTimo Sirainen{
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen struct ostream_private *_stream = stream->real_stream;
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen unsigned int i;
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen size_t total_size;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen ssize_t ret;
e64d7b6f388fecd0c83a4f2acb54e30d5ac98c6cTimo Sirainen
b5b3b4c9159f506cdfdce7399faaeeffdf73faf7Timo Sirainen *overflow_r = FALSE;
b5b3b4c9159f506cdfdce7399faaeeffdf73faf7Timo Sirainen
b5b3b4c9159f506cdfdce7399faaeeffdf73faf7Timo Sirainen for (i = 0, total_size = 0; i < iov_count; i++)
b5b3b4c9159f506cdfdce7399faaeeffdf73faf7Timo Sirainen total_size += iov[i].iov_len;
b5b3b4c9159f506cdfdce7399faaeeffdf73faf7Timo Sirainen if (total_size == 0)
b5b3b4c9159f506cdfdce7399faaeeffdf73faf7Timo Sirainen return 0;
b5b3b4c9159f506cdfdce7399faaeeffdf73faf7Timo Sirainen
b5b3b4c9159f506cdfdce7399faaeeffdf73faf7Timo Sirainen ret = _stream->sendv(_stream, iov, iov_count);
e64d7b6f388fecd0c83a4f2acb54e30d5ac98c6cTimo Sirainen if (unlikely(ret != (ssize_t)total_size)) {
e64d7b6f388fecd0c83a4f2acb54e30d5ac98c6cTimo Sirainen if (ret < 0) {
e64d7b6f388fecd0c83a4f2acb54e30d5ac98c6cTimo Sirainen i_assert(stream->stream_errno != 0);
e64d7b6f388fecd0c83a4f2acb54e30d5ac98c6cTimo Sirainen errno = stream->stream_errno;
e64d7b6f388fecd0c83a4f2acb54e30d5ac98c6cTimo Sirainen } else {
e64d7b6f388fecd0c83a4f2acb54e30d5ac98c6cTimo Sirainen i_assert(!stream->blocking);
e64d7b6f388fecd0c83a4f2acb54e30d5ac98c6cTimo Sirainen stream->overflow = TRUE;
e64d7b6f388fecd0c83a4f2acb54e30d5ac98c6cTimo Sirainen *overflow_r = TRUE;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen }
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen }
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen return ret;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen}
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainenssize_t o_stream_sendv(struct ostream *stream, const struct const_iovec *iov,
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen unsigned int iov_count)
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen{
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen bool overflow;
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen if (unlikely(stream->closed || stream->stream_errno != 0)) {
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen errno = stream->stream_errno;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen return -1;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen }
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen return o_stream_sendv_int(stream, iov, iov_count, &overflow);
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen}
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainenssize_t o_stream_send_str(struct ostream *stream, const char *str)
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen{
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen return o_stream_send(stream, str, strlen(str));
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen}
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainenvoid o_stream_nsend(struct ostream *stream, const void *data, size_t size)
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen{
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen struct const_iovec iov;
bdd7a96c363346f7c38f389791be1487ca08775bTimo Sirainen
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen memset(&iov, 0, sizeof(iov));
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen iov.iov_base = data;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen iov.iov_len = size;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen o_stream_nsendv(stream, &iov, 1);
bdd7a96c363346f7c38f389791be1487ca08775bTimo Sirainen}
bdd7a96c363346f7c38f389791be1487ca08775bTimo Sirainen
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainenvoid o_stream_nsendv(struct ostream *stream, const struct const_iovec *iov,
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen unsigned int iov_count)
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen{
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen bool overflow;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen
d9fda7e3a0fa5551547ac3e3054b837fc77f4bfbTimo Sirainen if (unlikely(stream->closed || stream->stream_errno != 0 ||
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen stream->real_stream->noverflow))
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen return;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen (void)o_stream_sendv_int(stream, iov, iov_count, &overflow);
029cfcdce65b284d5230adf1c920a5f526b03b5cTimo Sirainen if (overflow)
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen stream->real_stream->noverflow = TRUE;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen stream->real_stream->last_errors_not_checked = TRUE;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen}
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen
bdd7a96c363346f7c38f389791be1487ca08775bTimo Sirainenvoid o_stream_nsend_str(struct ostream *stream, const char *str)
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen{
bdd7a96c363346f7c38f389791be1487ca08775bTimo Sirainen o_stream_nsend(stream, str, strlen(str));
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen}
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainenvoid o_stream_nflush(struct ostream *stream)
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen{
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen if (unlikely(stream->closed || stream->stream_errno != 0))
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen return;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen (void)o_stream_flush(stream);
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen stream->real_stream->last_errors_not_checked = TRUE;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen}
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainenint o_stream_nfinish(struct ostream *stream)
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen{
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen o_stream_nflush(stream);
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen o_stream_ignore_last_errors(stream);
029cfcdce65b284d5230adf1c920a5f526b03b5cTimo Sirainen if (stream->stream_errno == 0 && stream->real_stream->noverflow) {
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen io_stream_set_error(&stream->real_stream->iostream,
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen "Output stream buffer was full (%"PRIuSIZE_T" bytes)",
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen o_stream_get_max_buffer_size(stream));
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen stream->stream_errno = ENOBUFS;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen }
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen return stream->stream_errno != 0 ? -1 : 0;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen}
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainenvoid o_stream_ignore_last_errors(struct ostream *stream)
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen{
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen while (stream != NULL) {
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen stream->real_stream->last_errors_not_checked = FALSE;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen stream = stream->real_stream->parent;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen }
036626b19f14bef582f96e556913ae91b1d67881Timo Sirainen}
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainenvoid o_stream_set_no_error_handling(struct ostream *stream, bool set)
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen{
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen stream->real_stream->error_handling_disabled = set;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen}
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainenint o_stream_send_istream(struct ostream *outstream, struct istream *instream)
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen{
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen struct ostream_private *_outstream = outstream->real_stream;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen uoff_t old_outstream_offset = outstream->offset;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen uoff_t old_instream_offset = instream->v_offset;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen int ret;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen if (unlikely(outstream->closed || instream->closed ||
036626b19f14bef582f96e556913ae91b1d67881Timo Sirainen outstream->stream_errno != 0)) {
036626b19f14bef582f96e556913ae91b1d67881Timo Sirainen errno = outstream->stream_errno;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen return -1;
036626b19f14bef582f96e556913ae91b1d67881Timo Sirainen }
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen ret = _outstream->send_istream(_outstream, instream);
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen if (instream->stream_errno != 0) {
d9fda7e3a0fa5551547ac3e3054b837fc77f4bfbTimo Sirainen errno = instream->stream_errno;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen return -1;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen } else if (outstream->stream_errno != 0) {
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen errno = outstream->stream_errno;
029cfcdce65b284d5230adf1c920a5f526b03b5cTimo Sirainen return -1;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen }
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen if (ret == 0) {
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen /* partial send */
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen i_assert(!outstream->blocking || !instream->blocking);
bdd7a96c363346f7c38f389791be1487ca08775bTimo Sirainen } else {
bdd7a96c363346f7c38f389791be1487ca08775bTimo Sirainen /* fully sent everything */
bdd7a96c363346f7c38f389791be1487ca08775bTimo Sirainen i_assert(!i_stream_have_bytes_left(instream));
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen }
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen i_assert((outstream->offset - old_outstream_offset) ==
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen (instream->v_offset - old_instream_offset));
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen return ret;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen}
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen
d9fda7e3a0fa5551547ac3e3054b837fc77f4bfbTimo Sirainenint o_stream_pwrite(struct ostream *stream, const void *data, size_t size,
d9fda7e3a0fa5551547ac3e3054b837fc77f4bfbTimo Sirainen uoff_t offset)
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen{
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen int ret;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen if (unlikely(stream->closed || stream->stream_errno != 0)) {
07e80e04c8876b6bf3f95266f48b41e1a681e445Timo Sirainen errno = stream->stream_errno;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen return -1;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen }
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen ret = stream->real_stream->write_at(stream->real_stream,
d9fda7e3a0fa5551547ac3e3054b837fc77f4bfbTimo Sirainen data, size, offset);
d9fda7e3a0fa5551547ac3e3054b837fc77f4bfbTimo Sirainen if (unlikely(ret < 0)) {
d9fda7e3a0fa5551547ac3e3054b837fc77f4bfbTimo Sirainen i_assert(stream->stream_errno != 0);
d9fda7e3a0fa5551547ac3e3054b837fc77f4bfbTimo Sirainen errno = stream->stream_errno;
d9fda7e3a0fa5551547ac3e3054b837fc77f4bfbTimo Sirainen }
d9fda7e3a0fa5551547ac3e3054b837fc77f4bfbTimo Sirainen return ret;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen}
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainenint io_stream_copy(struct ostream *outstream, struct istream *instream)
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen{
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen struct const_iovec iov;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen const unsigned char *data;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen ssize_t ret;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen
aef92409cf369afdd2ecd81a4f80083cd4082f46Timo Sirainen while (i_stream_read_more(instream, &data, &iov.iov_len) > 0) {
aef92409cf369afdd2ecd81a4f80083cd4082f46Timo Sirainen iov.iov_base = data;
aef92409cf369afdd2ecd81a4f80083cd4082f46Timo Sirainen if ((ret = o_stream_sendv(outstream, &iov, 1)) <= 0)
9061a2a9a7f8da780a5b50af3603f828167c6b13Timo Sirainen return ret;
9061a2a9a7f8da780a5b50af3603f828167c6b13Timo Sirainen i_stream_skip(instream, ret);
9061a2a9a7f8da780a5b50af3603f828167c6b13Timo Sirainen }
9061a2a9a7f8da780a5b50af3603f828167c6b13Timo Sirainen
9061a2a9a7f8da780a5b50af3603f828167c6b13Timo Sirainen if (instream->stream_errno != 0)
aef92409cf369afdd2ecd81a4f80083cd4082f46Timo Sirainen return -1;
aef92409cf369afdd2ecd81a4f80083cd4082f46Timo Sirainen return i_stream_have_bytes_left(instream) ? 0 : 1;
9061a2a9a7f8da780a5b50af3603f828167c6b13Timo Sirainen}
63e2edd14ae7b1dc4a08e2e659501dbf519462f9Timo Sirainen
63e2edd14ae7b1dc4a08e2e659501dbf519462f9Timo Sirainenvoid o_stream_switch_ioloop(struct ostream *stream)
63e2edd14ae7b1dc4a08e2e659501dbf519462f9Timo Sirainen{
9061a2a9a7f8da780a5b50af3603f828167c6b13Timo Sirainen struct ostream_private *_stream = stream->real_stream;
9061a2a9a7f8da780a5b50af3603f828167c6b13Timo Sirainen
9061a2a9a7f8da780a5b50af3603f828167c6b13Timo Sirainen _stream->switch_ioloop(_stream);
9061a2a9a7f8da780a5b50af3603f828167c6b13Timo Sirainen}
9061a2a9a7f8da780a5b50af3603f828167c6b13Timo Sirainen
9061a2a9a7f8da780a5b50af3603f828167c6b13Timo Sirainenstatic void o_stream_default_close(struct iostream_private *stream,
9061a2a9a7f8da780a5b50af3603f828167c6b13Timo Sirainen bool close_parent)
9061a2a9a7f8da780a5b50af3603f828167c6b13Timo Sirainen{
9061a2a9a7f8da780a5b50af3603f828167c6b13Timo Sirainen struct ostream_private *_stream = (struct ostream_private *)stream;
aef92409cf369afdd2ecd81a4f80083cd4082f46Timo Sirainen
9061a2a9a7f8da780a5b50af3603f828167c6b13Timo Sirainen (void)o_stream_flush(&_stream->ostream);
9061a2a9a7f8da780a5b50af3603f828167c6b13Timo Sirainen if (close_parent && _stream->parent != NULL)
aef92409cf369afdd2ecd81a4f80083cd4082f46Timo Sirainen o_stream_close(_stream->parent);
aef92409cf369afdd2ecd81a4f80083cd4082f46Timo Sirainen}
9061a2a9a7f8da780a5b50af3603f828167c6b13Timo Sirainen
9061a2a9a7f8da780a5b50af3603f828167c6b13Timo Sirainenstatic void o_stream_default_destroy(struct iostream_private *stream)
aef92409cf369afdd2ecd81a4f80083cd4082f46Timo Sirainen{
aef92409cf369afdd2ecd81a4f80083cd4082f46Timo Sirainen struct ostream_private *_stream = (struct ostream_private *)stream;
9061a2a9a7f8da780a5b50af3603f828167c6b13Timo Sirainen
9061a2a9a7f8da780a5b50af3603f828167c6b13Timo Sirainen if (_stream->parent != NULL)
9061a2a9a7f8da780a5b50af3603f828167c6b13Timo Sirainen o_stream_unref(&_stream->parent);
9061a2a9a7f8da780a5b50af3603f828167c6b13Timo Sirainen}
9061a2a9a7f8da780a5b50af3603f828167c6b13Timo Sirainen
9061a2a9a7f8da780a5b50af3603f828167c6b13Timo Sirainenstatic void
9061a2a9a7f8da780a5b50af3603f828167c6b13Timo Siraineno_stream_default_set_max_buffer_size(struct iostream_private *stream,
9061a2a9a7f8da780a5b50af3603f828167c6b13Timo Sirainen size_t max_size)
9061a2a9a7f8da780a5b50af3603f828167c6b13Timo Sirainen{
aef92409cf369afdd2ecd81a4f80083cd4082f46Timo Sirainen struct ostream_private *_stream = (struct ostream_private *)stream;
aef92409cf369afdd2ecd81a4f80083cd4082f46Timo Sirainen
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen if (_stream->parent != NULL)
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen o_stream_set_max_buffer_size(_stream->parent, max_size);
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen _stream->max_buffer_size = max_size;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen}
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainenstatic void o_stream_default_cork(struct ostream_private *_stream, bool set)
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen{
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen _stream->corked = set;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen if (set) {
2d49f150b4bce6f2f59a84e268e4777901c3e42cTimo Sirainen if (_stream->parent != NULL)
2d49f150b4bce6f2f59a84e268e4777901c3e42cTimo Sirainen o_stream_cork(_stream->parent);
2d49f150b4bce6f2f59a84e268e4777901c3e42cTimo Sirainen } else {
aef92409cf369afdd2ecd81a4f80083cd4082f46Timo Sirainen (void)o_stream_flush(&_stream->ostream);
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen if (_stream->parent != NULL)
029cfcdce65b284d5230adf1c920a5f526b03b5cTimo Sirainen o_stream_uncork(_stream->parent);
029cfcdce65b284d5230adf1c920a5f526b03b5cTimo Sirainen }
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen}
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen
aef92409cf369afdd2ecd81a4f80083cd4082f46Timo Sirainenvoid o_stream_copy_error_from_parent(struct ostream_private *_stream)
aef92409cf369afdd2ecd81a4f80083cd4082f46Timo Sirainen{
aef92409cf369afdd2ecd81a4f80083cd4082f46Timo Sirainen struct ostream *src = _stream->parent;
aef92409cf369afdd2ecd81a4f80083cd4082f46Timo Sirainen struct ostream *dest = &_stream->ostream;
aef92409cf369afdd2ecd81a4f80083cd4082f46Timo Sirainen
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen dest->stream_errno = src->stream_errno;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen dest->overflow = src->overflow;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen if (src->closed)
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen o_stream_close(dest);
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen}
aef92409cf369afdd2ecd81a4f80083cd4082f46Timo Sirainen
aef92409cf369afdd2ecd81a4f80083cd4082f46Timo Sirainenint o_stream_flush_parent_if_needed(struct ostream_private *_stream)
aef92409cf369afdd2ecd81a4f80083cd4082f46Timo Sirainen{
aef92409cf369afdd2ecd81a4f80083cd4082f46Timo Sirainen if (o_stream_get_buffer_used_size(_stream->parent) >= IO_BLOCK_SIZE) {
40ad2c4902e9d83557f2e8a4bff3d98fea2c8aa1Timo Sirainen /* we already have quite a lot of data in parent stream.
aef92409cf369afdd2ecd81a4f80083cd4082f46Timo Sirainen unless we can flush it, don't add any more to it or we
aef92409cf369afdd2ecd81a4f80083cd4082f46Timo Sirainen could keep wasting memory by just increasing the buffer
aef92409cf369afdd2ecd81a4f80083cd4082f46Timo Sirainen size all the time. */
aef92409cf369afdd2ecd81a4f80083cd4082f46Timo Sirainen if (o_stream_flush(_stream->parent) < 0) {
aef92409cf369afdd2ecd81a4f80083cd4082f46Timo Sirainen o_stream_copy_error_from_parent(_stream);
aef92409cf369afdd2ecd81a4f80083cd4082f46Timo Sirainen return -1;
aef92409cf369afdd2ecd81a4f80083cd4082f46Timo Sirainen }
aef92409cf369afdd2ecd81a4f80083cd4082f46Timo Sirainen if (o_stream_get_buffer_used_size(_stream->parent) >= IO_BLOCK_SIZE)
aef92409cf369afdd2ecd81a4f80083cd4082f46Timo Sirainen return 0;
aef92409cf369afdd2ecd81a4f80083cd4082f46Timo Sirainen }
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen return 1;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen}
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainenstatic int o_stream_default_flush(struct ostream_private *_stream)
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen{
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen int ret;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen if (_stream->parent == NULL)
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen return 1;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen if ((ret = o_stream_flush(_stream->parent)) < 0)
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen o_stream_copy_error_from_parent(_stream);
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen return ret;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen}
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen
2d49f150b4bce6f2f59a84e268e4777901c3e42cTimo Sirainenstatic void
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Siraineno_stream_default_set_flush_callback(struct ostream_private *_stream,
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen stream_flush_callback_t *callback,
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen void *context)
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen{
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen if (_stream->parent != NULL)
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen o_stream_set_flush_callback(_stream->parent, callback, context);
94aa90d2d17a7aebcda5a4193a62e80ddbb169b7Timo Sirainen
94aa90d2d17a7aebcda5a4193a62e80ddbb169b7Timo Sirainen _stream->callback = callback;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen _stream->context = context;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen}
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen
2d49f150b4bce6f2f59a84e268e4777901c3e42cTimo Sirainenstatic void
2d49f150b4bce6f2f59a84e268e4777901c3e42cTimo Siraineno_stream_default_set_flush_pending(struct ostream_private *_stream, bool set)
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen{
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen if (_stream->parent != NULL)
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen o_stream_set_flush_pending(_stream->parent, set);
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen}
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainenstatic size_t
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Siraineno_stream_default_get_used_size(const struct ostream_private *_stream)
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen{
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen if (_stream->parent == NULL)
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen return 0;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen else
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen return o_stream_get_buffer_used_size(_stream->parent);
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen}
8f0e6d627f3646e559ac5224c306839669d1a5e0Timo Sirainen
2e99f3f3bb35715ce5e0a75a2f2a9bac3ab4224bTimo Sirainenstatic int
2e99f3f3bb35715ce5e0a75a2f2a9bac3ab4224bTimo Siraineno_stream_default_seek(struct ostream_private *_stream,
90c23747727c85f80e4e8eed7968f0edbeac7ac5Timo Sirainen uoff_t offset ATTR_UNUSED)
90c23747727c85f80e4e8eed7968f0edbeac7ac5Timo Sirainen{
90c23747727c85f80e4e8eed7968f0edbeac7ac5Timo Sirainen _stream->ostream.stream_errno = ESPIPE;
90c23747727c85f80e4e8eed7968f0edbeac7ac5Timo Sirainen return -1;
90c23747727c85f80e4e8eed7968f0edbeac7ac5Timo Sirainen}
90c23747727c85f80e4e8eed7968f0edbeac7ac5Timo Sirainen
90c23747727c85f80e4e8eed7968f0edbeac7ac5Timo Sirainenstatic ssize_t
90c23747727c85f80e4e8eed7968f0edbeac7ac5Timo Siraineno_stream_default_sendv(struct ostream_private *stream,
90c23747727c85f80e4e8eed7968f0edbeac7ac5Timo Sirainen const struct const_iovec *iov, unsigned int iov_count)
90c23747727c85f80e4e8eed7968f0edbeac7ac5Timo Sirainen{
8f0e6d627f3646e559ac5224c306839669d1a5e0Timo Sirainen ssize_t ret;
8f0e6d627f3646e559ac5224c306839669d1a5e0Timo Sirainen
8f0e6d627f3646e559ac5224c306839669d1a5e0Timo Sirainen if ((ret = o_stream_sendv(stream->parent, iov, iov_count)) < 0) {
8f0e6d627f3646e559ac5224c306839669d1a5e0Timo Sirainen o_stream_copy_error_from_parent(stream);
8f0e6d627f3646e559ac5224c306839669d1a5e0Timo Sirainen return -1;
8f0e6d627f3646e559ac5224c306839669d1a5e0Timo Sirainen }
8f0e6d627f3646e559ac5224c306839669d1a5e0Timo Sirainen stream->ostream.offset += ret;
90c23747727c85f80e4e8eed7968f0edbeac7ac5Timo Sirainen return ret;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen}
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainenstatic int
95a1a5195d56f3cf5d1e529aad668f87ad3b979bTimo Siraineno_stream_default_write_at(struct ostream_private *_stream,
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen const void *data ATTR_UNUSED,
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen size_t size ATTR_UNUSED, uoff_t offset ATTR_UNUSED)
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen{
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen _stream->ostream.stream_errno = ESPIPE;
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen return -1;
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen}
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainenstatic int o_stream_default_send_istream(struct ostream_private *outstream,
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen struct istream *instream)
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen{
85da8c055280cd45553b6b335e9fb226d6e2801eTimo Sirainen return io_stream_copy(&outstream->ostream, instream);
029cfcdce65b284d5230adf1c920a5f526b03b5cTimo Sirainen}
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainenstatic void o_stream_default_switch_ioloop(struct ostream_private *_stream)
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen{
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen if (_stream->parent != NULL)
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen o_stream_switch_ioloop(_stream->parent);
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen}
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainenstruct ostream *
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Siraineno_stream_create(struct ostream_private *_stream, struct ostream *parent, int fd)
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen{
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen _stream->fd = fd;
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen _stream->ostream.real_stream = _stream;
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen if (parent != NULL) {
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen _stream->ostream.blocking = parent->blocking;
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen _stream->parent = parent;
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen o_stream_ref(parent);
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen _stream->callback = parent->real_stream->callback;
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen _stream->context = parent->real_stream->context;
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen _stream->max_buffer_size = parent->real_stream->max_buffer_size;
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen _stream->error_handling_disabled =
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen parent->real_stream->error_handling_disabled;
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen }
47e0598840ecffa364ebed523e06939e22738f06Timo Sirainen
47e0598840ecffa364ebed523e06939e22738f06Timo Sirainen if (_stream->iostream.close == NULL)
47e0598840ecffa364ebed523e06939e22738f06Timo Sirainen _stream->iostream.close = o_stream_default_close;
47e0598840ecffa364ebed523e06939e22738f06Timo Sirainen if (_stream->iostream.destroy == NULL)
47e0598840ecffa364ebed523e06939e22738f06Timo Sirainen _stream->iostream.destroy = o_stream_default_destroy;
47e0598840ecffa364ebed523e06939e22738f06Timo Sirainen if (_stream->iostream.set_max_buffer_size == NULL) {
47e0598840ecffa364ebed523e06939e22738f06Timo Sirainen _stream->iostream.set_max_buffer_size =
47e0598840ecffa364ebed523e06939e22738f06Timo Sirainen o_stream_default_set_max_buffer_size;
47e0598840ecffa364ebed523e06939e22738f06Timo Sirainen }
47e0598840ecffa364ebed523e06939e22738f06Timo Sirainen
47e0598840ecffa364ebed523e06939e22738f06Timo Sirainen if (_stream->cork == NULL)
47e0598840ecffa364ebed523e06939e22738f06Timo Sirainen _stream->cork = o_stream_default_cork;
47e0598840ecffa364ebed523e06939e22738f06Timo Sirainen if (_stream->flush == NULL)
47e0598840ecffa364ebed523e06939e22738f06Timo Sirainen _stream->flush = o_stream_default_flush;
47e0598840ecffa364ebed523e06939e22738f06Timo Sirainen if (_stream->set_flush_callback == NULL) {
47e0598840ecffa364ebed523e06939e22738f06Timo Sirainen _stream->set_flush_callback =
47e0598840ecffa364ebed523e06939e22738f06Timo Sirainen o_stream_default_set_flush_callback;
47e0598840ecffa364ebed523e06939e22738f06Timo Sirainen }
47e0598840ecffa364ebed523e06939e22738f06Timo Sirainen if (_stream->flush_pending == NULL)
47e0598840ecffa364ebed523e06939e22738f06Timo Sirainen _stream->flush_pending = o_stream_default_set_flush_pending;
47e0598840ecffa364ebed523e06939e22738f06Timo Sirainen if (_stream->get_used_size == NULL)
47e0598840ecffa364ebed523e06939e22738f06Timo Sirainen _stream->get_used_size = o_stream_default_get_used_size;
47e0598840ecffa364ebed523e06939e22738f06Timo Sirainen if (_stream->seek == NULL)
47e0598840ecffa364ebed523e06939e22738f06Timo Sirainen _stream->seek = o_stream_default_seek;
47e0598840ecffa364ebed523e06939e22738f06Timo Sirainen if (_stream->sendv == NULL)
47e0598840ecffa364ebed523e06939e22738f06Timo Sirainen _stream->sendv = o_stream_default_sendv;
47e0598840ecffa364ebed523e06939e22738f06Timo Sirainen if (_stream->write_at == NULL)
47e0598840ecffa364ebed523e06939e22738f06Timo Sirainen _stream->write_at = o_stream_default_write_at;
47e0598840ecffa364ebed523e06939e22738f06Timo Sirainen if (_stream->send_istream == NULL)
47e0598840ecffa364ebed523e06939e22738f06Timo Sirainen _stream->send_istream = o_stream_default_send_istream;
47e0598840ecffa364ebed523e06939e22738f06Timo Sirainen if (_stream->switch_ioloop == NULL)
47e0598840ecffa364ebed523e06939e22738f06Timo Sirainen _stream->switch_ioloop = o_stream_default_switch_ioloop;
47e0598840ecffa364ebed523e06939e22738f06Timo Sirainen
47e0598840ecffa364ebed523e06939e22738f06Timo Sirainen io_stream_init(&_stream->iostream);
47e0598840ecffa364ebed523e06939e22738f06Timo Sirainen return &_stream->ostream;
47e0598840ecffa364ebed523e06939e22738f06Timo Sirainen}
47e0598840ecffa364ebed523e06939e22738f06Timo Sirainen
47e0598840ecffa364ebed523e06939e22738f06Timo Sirainenstruct ostream *o_stream_create_error(int stream_errno)
47e0598840ecffa364ebed523e06939e22738f06Timo Sirainen{
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen struct ostream_private *stream;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen struct ostream *output;
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen stream = i_new(struct ostream_private, 1);
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen stream->ostream.blocking = TRUE;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen stream->ostream.closed = TRUE;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen stream->ostream.stream_errno = stream_errno;
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen
47e0598840ecffa364ebed523e06939e22738f06Timo Sirainen output = o_stream_create(stream, NULL, -1);
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen o_stream_set_no_error_handling(output, TRUE);
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen o_stream_set_name(output, "(error)");
4bc96ba6f1d67a90a75fa131bcd2cd508ea5a05aTimo Sirainen return output;
b780aa272b742a43579cdb523cc79cc8d4521306Timo Sirainen}
04b8a90af181cc4c7959266855e8ed50a22ed413Timo Sirainen
04b8a90af181cc4c7959266855e8ed50a22ed413Timo Sirainenstruct ostream *
04b8a90af181cc4c7959266855e8ed50a22ed413Timo Siraineno_stream_create_error_str(int stream_errno, const char *fmt, ...)
04b8a90af181cc4c7959266855e8ed50a22ed413Timo Sirainen{
04b8a90af181cc4c7959266855e8ed50a22ed413Timo Sirainen struct ostream *output;
51b979b6414b940f04677a7e2d064be119345954Timo Sirainen va_list args;
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen va_start(args, fmt);
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen output = o_stream_create_error(stream_errno);
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen io_stream_set_verror(&output->real_stream->iostream, fmt, args);
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen va_end(args);
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen return output;
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen}
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainenstruct ostream *o_stream_create_passthrough(struct ostream *output)
029cfcdce65b284d5230adf1c920a5f526b03b5cTimo Sirainen{
029cfcdce65b284d5230adf1c920a5f526b03b5cTimo Sirainen struct ostream_private *stream;
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen stream = i_new(struct ostream_private, 1);
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen return o_stream_create(stream, output, o_stream_get_fd(output));
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen}
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen