ostream.c revision d6193a892452ae87548f5745dada01f82816765d
02c335c23bf5fa225a467c19f2c063fb0dc7b8c3Timo Sirainen/* Copyright (c) 2002-2017 Dovecot authors, see the included COPYING file */
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainenvoid o_stream_set_name(struct ostream *stream, const char *name)
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainen stream->real_stream->iostream.name = i_strdup(name);
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainenconst char *o_stream_get_name(struct ostream *stream)
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainen while (stream->real_stream->iostream.name == NULL) {
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainenconst char *o_stream_get_error(struct ostream *stream)
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainen /* we'll only return errors for streams that have stream_errno set.
e2ce8d4a6ac5d82a906178148453e7613fab9ba0Timo Sirainen we might be returning unintended error otherwise. */
e2ce8d4a6ac5d82a906178148453e7613fab9ba0Timo Sirainen return "<no error>";
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainen for (s = stream; s != NULL; s = s->real_stream->parent) {
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainenstatic void o_stream_close_full(struct ostream *stream, bool close_parents)
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainen /* Ideally o_stream_finish() would be called for all non-failed
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainen ostreams, but strictly requiring it would cause unnecessary
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainen complexity for many callers. Just require that at this point
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainen after flushing there isn't anything in the output buffer or that
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainen we're ignoring all errors. */
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainen i_assert(stream->real_stream->error_handling_disabled);
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainen if (!stream->closed && !stream->real_stream->closing) {
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainen /* first mark the stream as being closed so the
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainen o_stream_copy_error_from_parent() won't recurse us back
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainen here. but don't immediately mark the stream closed, because
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainen we may still want to write something to it. */
46b823ac3bce2c0f9f0fc73911e48d3a77b04fbeTimo Sirainen io_stream_close(&stream->real_stream->iostream, close_parents);
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainen io_stream_ref(&stream->real_stream->iostream);
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainen if (stream->real_stream->last_errors_not_checked &&
d5e839aea288aceaddae28a1578cebda3c9e3b58Timo Sirainen !stream->real_stream->error_handling_disabled &&
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainen stream->real_stream->iostream.refcount == 1) {
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainen i_panic("output stream %s is missing error handling",
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainen if (!io_stream_unref(&stream->real_stream->iostream))
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainen io_stream_free(&stream->real_stream->iostream);
baf346e71ebd7b44fcba4b48f4d39845453b778bTimo Sirainenvoid o_stream_add_destroy_callback(struct ostream *stream,
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainen io_stream_add_destroy_callback(&stream->real_stream->iostream,
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainenvoid o_stream_remove_destroy_callback(struct ostream *stream,
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainen io_stream_remove_destroy_callback(&stream->real_stream->iostream,
baf346e71ebd7b44fcba4b48f4d39845453b778bTimo Sirainenvoid o_stream_set_flush_callback(struct ostream *stream,
baf346e71ebd7b44fcba4b48f4d39845453b778bTimo Sirainen struct ostream_private *_stream = stream->real_stream;
baf346e71ebd7b44fcba4b48f4d39845453b778bTimo Sirainen _stream->set_flush_callback(_stream, callback, context);
baf346e71ebd7b44fcba4b48f4d39845453b778bTimo Sirainenvoid o_stream_unset_flush_callback(struct ostream *stream)
6adf683655750bcb809275cd65dc75fd12214198Timo Sirainen struct ostream_private *_stream = stream->real_stream;
6adf683655750bcb809275cd65dc75fd12214198Timo Sirainen _stream->set_flush_callback(_stream, NULL, NULL);
baf346e71ebd7b44fcba4b48f4d39845453b778bTimo Sirainenvoid o_stream_set_max_buffer_size(struct ostream *stream, size_t max_size)
baf346e71ebd7b44fcba4b48f4d39845453b778bTimo Sirainen io_stream_set_max_buffer_size(&stream->real_stream->iostream, max_size);
baf346e71ebd7b44fcba4b48f4d39845453b778bTimo Sirainensize_t o_stream_get_max_buffer_size(struct ostream *stream)
baf346e71ebd7b44fcba4b48f4d39845453b778bTimo Sirainen struct ostream_private *_stream = stream->real_stream;
baf346e71ebd7b44fcba4b48f4d39845453b778bTimo Sirainen if (unlikely(stream->closed || stream->stream_errno != 0))
baf346e71ebd7b44fcba4b48f4d39845453b778bTimo Sirainen struct ostream_private *_stream = stream->real_stream;
baf346e71ebd7b44fcba4b48f4d39845453b778bTimo Sirainen if (unlikely(stream->closed || stream->stream_errno != 0))
baf346e71ebd7b44fcba4b48f4d39845453b778bTimo Sirainenbool o_stream_is_corked(struct ostream *stream)
6adf683655750bcb809275cd65dc75fd12214198Timo Sirainen struct ostream_private *_stream = stream->real_stream;
baf346e71ebd7b44fcba4b48f4d39845453b778bTimo Sirainen struct ostream_private *_stream = stream->real_stream;
baf346e71ebd7b44fcba4b48f4d39845453b778bTimo Sirainen if (unlikely(stream->closed || stream->stream_errno != 0)) {
fb176cdc122707cda985ab3c09c02ccf3cec0af1Timo Sirainen "Output stream buffer was full (%"PRIuSIZE_T" bytes)",
fb176cdc122707cda985ab3c09c02ccf3cec0af1Timo Sirainen if (unlikely((ret = _stream->flush(_stream)) < 0)) {
d5e839aea288aceaddae28a1578cebda3c9e3b58Timo Sirainenvoid o_stream_set_flush_pending(struct ostream *stream, bool set)
d5e839aea288aceaddae28a1578cebda3c9e3b58Timo Sirainen struct ostream_private *_stream = stream->real_stream;
fb176cdc122707cda985ab3c09c02ccf3cec0af1Timo Sirainen if (unlikely(stream->closed || stream->stream_errno != 0))
153ed0fbca1f5f944b70937dfd71911db172ca97Timo Sirainensize_t o_stream_get_buffer_used_size(const struct ostream *stream)
153ed0fbca1f5f944b70937dfd71911db172ca97Timo Sirainen const struct ostream_private *_stream = stream->real_stream;
2f4f603d4cebab2cc956c72164efb02da83515c5Timo Sirainensize_t o_stream_get_buffer_avail_size(const struct ostream *stream)
2f4f603d4cebab2cc956c72164efb02da83515c5Timo Sirainen size_t used = o_stream_get_buffer_used_size(stream);
2f4f603d4cebab2cc956c72164efb02da83515c5Timo Sirainen return stream->real_stream->max_buffer_size <= used ? 0 :
8a8a3b43987b5ade914f22765e51c9e3de8179d3Timo Sirainenint o_stream_seek(struct ostream *stream, uoff_t offset)
8a8a3b43987b5ade914f22765e51c9e3de8179d3Timo Sirainen struct ostream_private *_stream = stream->real_stream;
8a8a3b43987b5ade914f22765e51c9e3de8179d3Timo Sirainen if (unlikely(stream->closed || stream->stream_errno != 0)) {
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainen if (unlikely(_stream->seek(_stream, offset) < 0)) {
baf346e71ebd7b44fcba4b48f4d39845453b778bTimo Sirainenssize_t o_stream_send(struct ostream *stream, const void *data, size_t size)
2f4f603d4cebab2cc956c72164efb02da83515c5Timo Siraineno_stream_sendv_int(struct ostream *stream, const struct const_iovec *iov,
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainen struct ostream_private *_stream = stream->real_stream;
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainen unsigned int i;
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainen for (i = 0, total_size = 0; i < iov_count; i++)
baf346e71ebd7b44fcba4b48f4d39845453b778bTimo Sirainen ret = _stream->sendv(_stream, iov, iov_count);
baf346e71ebd7b44fcba4b48f4d39845453b778bTimo Sirainenssize_t o_stream_sendv(struct ostream *stream, const struct const_iovec *iov,
baf346e71ebd7b44fcba4b48f4d39845453b778bTimo Sirainen if (unlikely(stream->closed || stream->stream_errno != 0)) {
c096257fbdaf4b9fcf8eb97aae94afdbb4e71ed4Timo Sirainen return o_stream_sendv_int(stream, iov, iov_count, &overflow);
baf346e71ebd7b44fcba4b48f4d39845453b778bTimo Sirainenssize_t o_stream_send_str(struct ostream *stream, const char *str)
e44028b5df7045dd9e7f324175e73e3ff490cb5dTimo Sirainen return o_stream_send(stream, str, strlen(str));
bace943c67e6cd14ce6c994f533d82a3caad5bf1Timo Sirainenvoid o_stream_nsend(struct ostream *stream, const void *data, size_t size)
1a0ece3e873e3864269ed7eaed957dc10c56d25fTimo Sirainenvoid o_stream_nsendv(struct ostream *stream, const struct const_iovec *iov,
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainen if (unlikely(stream->closed || stream->stream_errno != 0 ||
if (overflow)
switch (res) {
return res;
return res;
return res;
i_unreached();
int ret;
return ret;
const unsigned char *data;
else if (ret == 0)
bool close_parent)
if (set) {
int ret;
if (ret < 0)
return ret;
void *context)
static size_t
static ssize_t
return ret;
static enum ostream_send_istream_result
struct ostream *
return output;
struct ostream *
return output;