ostream.c revision 3ed2d0f6b5e67e2663d44489d9da3176823789a8
2454dfa32c93c20a8522c6ed42fe057baaac9f9aStephan Bosch/* Copyright (c) 2002-2010 Dovecot authors, see the included COPYING file */
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch#include "lib.h"
ee2633056e67353157bfbce4d9e0d1c3ceaa627aStephan Bosch#include "istream.h"
ee2633056e67353157bfbce4d9e0d1c3ceaa627aStephan Bosch#include "ostream-internal.h"
201c3b9375760bafbc180629b4c6ad71ed554aecStephan Bosch
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Boschvoid o_stream_set_name(struct ostream *stream, const char *name)
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch{
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch i_free(stream->real_stream->iostream.name);
2f64a4c88de91c483fb378bc80d10e1caa6f2305Stephan Bosch stream->real_stream->iostream.name = i_strdup(name);
2f64a4c88de91c483fb378bc80d10e1caa6f2305Stephan Bosch}
2f64a4c88de91c483fb378bc80d10e1caa6f2305Stephan Bosch
2f64a4c88de91c483fb378bc80d10e1caa6f2305Stephan Boschconst char *o_stream_get_name(struct ostream *stream)
2f64a4c88de91c483fb378bc80d10e1caa6f2305Stephan Bosch{
2f64a4c88de91c483fb378bc80d10e1caa6f2305Stephan Bosch return stream->real_stream->iostream.name == NULL ? "" :
2f64a4c88de91c483fb378bc80d10e1caa6f2305Stephan Bosch stream->real_stream->iostream.name;
2f64a4c88de91c483fb378bc80d10e1caa6f2305Stephan Bosch}
2f64a4c88de91c483fb378bc80d10e1caa6f2305Stephan Bosch
2f64a4c88de91c483fb378bc80d10e1caa6f2305Stephan Boschvoid o_stream_destroy(struct ostream **stream)
2f64a4c88de91c483fb378bc80d10e1caa6f2305Stephan Bosch{
2f64a4c88de91c483fb378bc80d10e1caa6f2305Stephan Bosch o_stream_close(*stream);
2f64a4c88de91c483fb378bc80d10e1caa6f2305Stephan Bosch o_stream_unref(stream);
2f64a4c88de91c483fb378bc80d10e1caa6f2305Stephan Bosch}
2f64a4c88de91c483fb378bc80d10e1caa6f2305Stephan Bosch
2f64a4c88de91c483fb378bc80d10e1caa6f2305Stephan Boschvoid o_stream_ref(struct ostream *stream)
2f64a4c88de91c483fb378bc80d10e1caa6f2305Stephan Bosch{
2f64a4c88de91c483fb378bc80d10e1caa6f2305Stephan Bosch io_stream_ref(&stream->real_stream->iostream);
2f64a4c88de91c483fb378bc80d10e1caa6f2305Stephan Bosch}
2f64a4c88de91c483fb378bc80d10e1caa6f2305Stephan Bosch
2f64a4c88de91c483fb378bc80d10e1caa6f2305Stephan Boschvoid o_stream_unref(struct ostream **stream)
2f64a4c88de91c483fb378bc80d10e1caa6f2305Stephan Bosch{
2f64a4c88de91c483fb378bc80d10e1caa6f2305Stephan Bosch io_stream_unref(&(*stream)->real_stream->iostream);
2f64a4c88de91c483fb378bc80d10e1caa6f2305Stephan Bosch *stream = NULL;
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch}
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch
38af46387e565053adf6c47f7f6871676d685de8Stephan Boschvoid o_stream_close(struct ostream *stream)
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch{
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch io_stream_close(&stream->real_stream->iostream);
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch stream->closed = TRUE;
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch}
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch#undef o_stream_set_flush_callback
38af46387e565053adf6c47f7f6871676d685de8Stephan Boschvoid o_stream_set_flush_callback(struct ostream *stream,
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch stream_flush_callback_t *callback,
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch void *context)
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch{
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch struct ostream_private *_stream = stream->real_stream;
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch _stream->callback = callback;
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch _stream->context = context;
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch}
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch
38af46387e565053adf6c47f7f6871676d685de8Stephan Boschvoid o_stream_unset_flush_callback(struct ostream *stream)
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch{
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch struct ostream_private *_stream = stream->real_stream;
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch _stream->callback = NULL;
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch _stream->context = NULL;
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch}
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch
38af46387e565053adf6c47f7f6871676d685de8Stephan Boschvoid o_stream_set_max_buffer_size(struct ostream *stream, size_t max_size)
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch{
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch if (stream->real_stream->iostream.set_max_buffer_size != NULL) {
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch io_stream_set_max_buffer_size(&stream->real_stream->iostream,
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch max_size);
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch } else {
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch stream->real_stream->max_buffer_size = max_size;
2f64a4c88de91c483fb378bc80d10e1caa6f2305Stephan Bosch }
2f64a4c88de91c483fb378bc80d10e1caa6f2305Stephan Bosch}
2f64a4c88de91c483fb378bc80d10e1caa6f2305Stephan Bosch
2f64a4c88de91c483fb378bc80d10e1caa6f2305Stephan Boschvoid o_stream_cork(struct ostream *stream)
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch{
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch struct ostream_private *_stream = stream->real_stream;
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch
2f64a4c88de91c483fb378bc80d10e1caa6f2305Stephan Bosch if (unlikely(stream->closed))
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch return;
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch if (_stream->cork != NULL)
45324f1eafa565dbc65e4dd335de9507dead55e6Timo Sirainen _stream->cork(_stream, TRUE);
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch else
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch _stream->corked = TRUE;
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch}
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Boschvoid o_stream_uncork(struct ostream *stream)
2f64a4c88de91c483fb378bc80d10e1caa6f2305Stephan Bosch{
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch struct ostream_private *_stream = stream->real_stream;
833bed942977673526c72e79bccc09314fc57104Phil Carmody
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch if (unlikely(stream->closed))
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch return;
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch if (_stream->cork != NULL)
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch _stream->cork(_stream, FALSE);
e9228a3918aa0243eff4aae1ff5462bd3198417fTimo Sirainen else {
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch _stream->corked = FALSE;
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch (void)o_stream_flush(stream);
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch }
1e9296de32c9ddda40f33c06556cd568ddadf71fTimo Sirainen}
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Boschint o_stream_flush(struct ostream *stream)
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch{
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch struct ostream_private *_stream = stream->real_stream;
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch int ret = 1;
903f0b38884375179cea63b9d0821e295c38764aTimo Sirainen
903f0b38884375179cea63b9d0821e295c38764aTimo Sirainen if (unlikely(stream->closed))
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch return -1;
1e9296de32c9ddda40f33c06556cd568ddadf71fTimo Sirainen
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch stream->stream_errno = 0;
2f64a4c88de91c483fb378bc80d10e1caa6f2305Stephan Bosch if (_stream->flush != NULL) {
2f64a4c88de91c483fb378bc80d10e1caa6f2305Stephan Bosch if (unlikely((ret = _stream->flush(_stream)) < 0)) {
833bed942977673526c72e79bccc09314fc57104Phil Carmody i_assert(stream->stream_errno != 0);
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch stream->last_failed_errno = stream->stream_errno;
833bed942977673526c72e79bccc09314fc57104Phil Carmody }
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch }
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch return ret;
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch}
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Boschvoid o_stream_set_flush_pending(struct ostream *stream, bool set)
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch{
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch struct ostream_private *_stream = stream->real_stream;
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch if (unlikely(stream->closed))
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch return;
1e9296de32c9ddda40f33c06556cd568ddadf71fTimo Sirainen
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch if (_stream->flush_pending != NULL)
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch _stream->flush_pending(_stream, set);
faa8995f1d300e7a8917407a52bbd1b98e10bf25Timo Sirainen}
faa8995f1d300e7a8917407a52bbd1b98e10bf25Timo Sirainen
faa8995f1d300e7a8917407a52bbd1b98e10bf25Timo Sirainensize_t o_stream_get_buffer_used_size(const struct ostream *stream)
ee2633056e67353157bfbce4d9e0d1c3ceaa627aStephan Bosch{
faa8995f1d300e7a8917407a52bbd1b98e10bf25Timo Sirainen const struct ostream_private *_stream = stream->real_stream;
2f64a4c88de91c483fb378bc80d10e1caa6f2305Stephan Bosch
2f64a4c88de91c483fb378bc80d10e1caa6f2305Stephan Bosch return _stream->get_used_size == NULL ? 0 :
ee2633056e67353157bfbce4d9e0d1c3ceaa627aStephan Bosch _stream->get_used_size(_stream);
ee2633056e67353157bfbce4d9e0d1c3ceaa627aStephan Bosch}
ee2633056e67353157bfbce4d9e0d1c3ceaa627aStephan Bosch
ee2633056e67353157bfbce4d9e0d1c3ceaa627aStephan Boschsize_t o_stream_get_buffer_avail_size(const struct ostream *stream)
23bdbb7b1831785c6ba6df190f6369da882d2b9dTimo Sirainen{
ee2633056e67353157bfbce4d9e0d1c3ceaa627aStephan Bosch size_t used = o_stream_get_buffer_used_size(stream);
ee2633056e67353157bfbce4d9e0d1c3ceaa627aStephan Bosch
14bd2410de3a0261d9c53c6120915027262216bdTimo Sirainen return stream->real_stream->max_buffer_size <= used ? 0 :
14bd2410de3a0261d9c53c6120915027262216bdTimo Sirainen stream->real_stream->max_buffer_size - used;
14bd2410de3a0261d9c53c6120915027262216bdTimo Sirainen}
9f8cef4cbc49797053c343209ea13022fdbc5a63Stephan Bosch
9f8cef4cbc49797053c343209ea13022fdbc5a63Stephan Boschint o_stream_seek(struct ostream *stream, uoff_t offset)
faa8995f1d300e7a8917407a52bbd1b98e10bf25Timo Sirainen{
9f8cef4cbc49797053c343209ea13022fdbc5a63Stephan Bosch struct ostream_private *_stream = stream->real_stream;
faa8995f1d300e7a8917407a52bbd1b98e10bf25Timo Sirainen
faa8995f1d300e7a8917407a52bbd1b98e10bf25Timo Sirainen if (unlikely(stream->closed))
faa8995f1d300e7a8917407a52bbd1b98e10bf25Timo Sirainen return -1;
faa8995f1d300e7a8917407a52bbd1b98e10bf25Timo Sirainen
582b93659812592a27babdb65c6cb4c37042ab00Aki Tuomi stream->stream_errno = 0;
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch if (_stream->seek != NULL) {
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch if (unlikely(_stream->seek(_stream, offset) < 0)) {
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch i_assert(stream->stream_errno != 0);
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch stream->last_failed_errno = stream->stream_errno;
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch }
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch } else {
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch stream->stream_errno = EPIPE;
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch stream->last_failed_errno = EPIPE;
ee2633056e67353157bfbce4d9e0d1c3ceaa627aStephan Bosch return -1;
ee2633056e67353157bfbce4d9e0d1c3ceaa627aStephan Bosch }
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch return 1;
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch}
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Boschssize_t o_stream_send(struct ostream *stream, const void *data, size_t size)
31300f53eadd34fc7bd567b2424565a60c06e2f5Stephan Bosch{
31300f53eadd34fc7bd567b2424565a60c06e2f5Stephan Bosch struct const_iovec iov;
31300f53eadd34fc7bd567b2424565a60c06e2f5Stephan Bosch
2f64a4c88de91c483fb378bc80d10e1caa6f2305Stephan Bosch iov.iov_base = data;
2f64a4c88de91c483fb378bc80d10e1caa6f2305Stephan Bosch iov.iov_len = size;
ee2633056e67353157bfbce4d9e0d1c3ceaa627aStephan Bosch
833bed942977673526c72e79bccc09314fc57104Phil Carmody return o_stream_sendv(stream, &iov, 1);
ee2633056e67353157bfbce4d9e0d1c3ceaa627aStephan Bosch}
ee2633056e67353157bfbce4d9e0d1c3ceaa627aStephan Bosch
ee2633056e67353157bfbce4d9e0d1c3ceaa627aStephan Boschssize_t o_stream_sendv(struct ostream *stream, const struct const_iovec *iov,
ee2633056e67353157bfbce4d9e0d1c3ceaa627aStephan Bosch unsigned int iov_count)
ee2633056e67353157bfbce4d9e0d1c3ceaa627aStephan Bosch{
ee2633056e67353157bfbce4d9e0d1c3ceaa627aStephan Bosch struct ostream_private *_stream = stream->real_stream;
ee2633056e67353157bfbce4d9e0d1c3ceaa627aStephan Bosch unsigned int i;
ee2633056e67353157bfbce4d9e0d1c3ceaa627aStephan Bosch size_t total_size;
ee2633056e67353157bfbce4d9e0d1c3ceaa627aStephan Bosch ssize_t ret;
ee2633056e67353157bfbce4d9e0d1c3ceaa627aStephan Bosch
ee2633056e67353157bfbce4d9e0d1c3ceaa627aStephan Bosch if (unlikely(stream->closed))
ee2633056e67353157bfbce4d9e0d1c3ceaa627aStephan Bosch return -1;
ee2633056e67353157bfbce4d9e0d1c3ceaa627aStephan Bosch
ee2633056e67353157bfbce4d9e0d1c3ceaa627aStephan Bosch stream->stream_errno = 0;
ee2633056e67353157bfbce4d9e0d1c3ceaa627aStephan Bosch for (i = 0, total_size = 0; i < iov_count; i++)
ee2633056e67353157bfbce4d9e0d1c3ceaa627aStephan Bosch total_size += iov[i].iov_len;
ee2633056e67353157bfbce4d9e0d1c3ceaa627aStephan Bosch if (total_size == 0)
ee2633056e67353157bfbce4d9e0d1c3ceaa627aStephan Bosch return 0;
ee2633056e67353157bfbce4d9e0d1c3ceaa627aStephan Bosch
ee2633056e67353157bfbce4d9e0d1c3ceaa627aStephan Bosch ret = _stream->sendv(_stream, iov, iov_count);
ee2633056e67353157bfbce4d9e0d1c3ceaa627aStephan Bosch if (unlikely(ret != (ssize_t)total_size)) {
ee2633056e67353157bfbce4d9e0d1c3ceaa627aStephan Bosch if (ret < 0) {
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch i_assert(stream->stream_errno != 0);
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch stream->last_failed_errno = stream->stream_errno;
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch } else {
ee2633056e67353157bfbce4d9e0d1c3ceaa627aStephan Bosch stream->overflow = TRUE;
ee2633056e67353157bfbce4d9e0d1c3ceaa627aStephan Bosch }
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch }
ee2633056e67353157bfbce4d9e0d1c3ceaa627aStephan Bosch return ret;
ee2633056e67353157bfbce4d9e0d1c3ceaa627aStephan Bosch}
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch
91a482473f200152d6713181c0e36f7a4f03ef6dTimo Sirainenssize_t o_stream_send_str(struct ostream *stream, const char *str)
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch{
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch return o_stream_send(stream, str, strlen(str));
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch}
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Boschoff_t o_stream_send_istream(struct ostream *outstream,
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch struct istream *instream)
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch{
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch struct ostream_private *_outstream = outstream->real_stream;
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch off_t ret;
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch if (unlikely(outstream->closed || instream->closed))
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch return -1;
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch outstream->stream_errno = 0;
85f3bd5926fff0e70b6d259a5c8074bd8cdeb9adTimo Sirainen ret = _outstream->send_istream(_outstream, instream);
85f3bd5926fff0e70b6d259a5c8074bd8cdeb9adTimo Sirainen if (unlikely(ret < 0))
85f3bd5926fff0e70b6d259a5c8074bd8cdeb9adTimo Sirainen errno = outstream->stream_errno;
85f3bd5926fff0e70b6d259a5c8074bd8cdeb9adTimo Sirainen return ret;
85f3bd5926fff0e70b6d259a5c8074bd8cdeb9adTimo Sirainen}
85f3bd5926fff0e70b6d259a5c8074bd8cdeb9adTimo Sirainen
564e117d86ce5b659f9b9570edddc566f9ebb5dfStephan Boschint o_stream_pwrite(struct ostream *stream, const void *data, size_t size,
564e117d86ce5b659f9b9570edddc566f9ebb5dfStephan Bosch uoff_t offset)
564e117d86ce5b659f9b9570edddc566f9ebb5dfStephan Bosch{
564e117d86ce5b659f9b9570edddc566f9ebb5dfStephan Bosch int ret;
564e117d86ce5b659f9b9570edddc566f9ebb5dfStephan Bosch
564e117d86ce5b659f9b9570edddc566f9ebb5dfStephan Bosch if (unlikely(stream->closed))
564e117d86ce5b659f9b9570edddc566f9ebb5dfStephan Bosch return -1;
564e117d86ce5b659f9b9570edddc566f9ebb5dfStephan Bosch
564e117d86ce5b659f9b9570edddc566f9ebb5dfStephan Bosch if (stream->real_stream->write_at == NULL) {
564e117d86ce5b659f9b9570edddc566f9ebb5dfStephan Bosch /* stream doesn't support seeking */
564e117d86ce5b659f9b9570edddc566f9ebb5dfStephan Bosch stream->stream_errno = EPIPE;
564e117d86ce5b659f9b9570edddc566f9ebb5dfStephan Bosch return -1;
564e117d86ce5b659f9b9570edddc566f9ebb5dfStephan Bosch }
564e117d86ce5b659f9b9570edddc566f9ebb5dfStephan Bosch ret = stream->real_stream->write_at(stream->real_stream,
564e117d86ce5b659f9b9570edddc566f9ebb5dfStephan Bosch data, size, offset);
564e117d86ce5b659f9b9570edddc566f9ebb5dfStephan Bosch if (unlikely(ret < 0)) {
93ed69606237a08623f8294c060fa148880058f8Timo Sirainen i_assert(stream->stream_errno != 0);
93ed69606237a08623f8294c060fa148880058f8Timo Sirainen stream->last_failed_errno = stream->stream_errno;
93ed69606237a08623f8294c060fa148880058f8Timo Sirainen }
93ed69606237a08623f8294c060fa148880058f8Timo Sirainen return ret;
93ed69606237a08623f8294c060fa148880058f8Timo Sirainen}
93ed69606237a08623f8294c060fa148880058f8Timo Sirainen
9ec9b6f85c8fbe67bfac523a5e3d33d34f72dddcStephan Boschstatic off_t o_stream_default_send_istream(struct ostream_private *outstream,
9ec9b6f85c8fbe67bfac523a5e3d33d34f72dddcStephan Bosch struct istream *instream)
9ec9b6f85c8fbe67bfac523a5e3d33d34f72dddcStephan Bosch{
9ec9b6f85c8fbe67bfac523a5e3d33d34f72dddcStephan Bosch return io_stream_copy(&outstream->ostream, instream, IO_BLOCK_SIZE);
9ec9b6f85c8fbe67bfac523a5e3d33d34f72dddcStephan Bosch}
9ec9b6f85c8fbe67bfac523a5e3d33d34f72dddcStephan Bosch
9ec9b6f85c8fbe67bfac523a5e3d33d34f72dddcStephan Boschstruct ostream *o_stream_create(struct ostream_private *_stream)
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch{
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch _stream->ostream.real_stream = _stream;
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch if (_stream->send_istream == NULL)
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch _stream->send_istream = o_stream_default_send_istream;
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch io_stream_init(&_stream->iostream);
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch return &_stream->ostream;
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch}
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Boschoff_t io_stream_copy(struct ostream *outstream, struct istream *instream,
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch size_t block_size)
711e8e4c5c5d702dfa062f42a1ede5de14c151c9Stephan Bosch{
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch uoff_t start_offset;
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch struct const_iovec iov;
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch const unsigned char *data;
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch ssize_t ret;
390b600a6f7fdb4ccc65950527ee30129f49a6acStephan Bosch
390b600a6f7fdb4ccc65950527ee30129f49a6acStephan Bosch start_offset = instream->v_offset;
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch for (;;) {
711e8e4c5c5d702dfa062f42a1ede5de14c151c9Stephan Bosch (void)i_stream_read_data(instream, &data, &iov.iov_len,
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch block_size-1);
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch if (iov.iov_len == 0) {
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch /* all sent */
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch break;
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch }
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch iov.iov_base = data;
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch ret = o_stream_sendv(outstream, &iov, 1);
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch if (ret <= 0) {
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch if (ret == 0)
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch break;
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch return -1;
38af46387e565053adf6c47f7f6871676d685de8Stephan Bosch }
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch i_stream_skip(instream, ret);
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch if ((size_t)ret != iov.iov_len)
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch break;
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch }
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch
390b600a6f7fdb4ccc65950527ee30129f49a6acStephan Bosch return (off_t)(instream->v_offset - start_offset);
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch}
3fcb3d2d1f3583025ff62bae95ec706920f398b1Stephan Bosch