ostream.c revision 8cdb3234fe3c77e477c7a0e6934678f58fc54d4d
45312f52ff3a3d4c137447be4c7556500c2f8bf2Timo Sirainen/* Copyright (c) 2002-2009 Dovecot authors, see the included COPYING file */
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen#include "lib.h"
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen#include "istream.h"
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen#include "ostream-internal.h"
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
cd56a23e21f1df3f79648cf07e2f4385e2fadebbTimo Sirainenvoid o_stream_destroy(struct ostream **stream)
cd56a23e21f1df3f79648cf07e2f4385e2fadebbTimo Sirainen{
cd56a23e21f1df3f79648cf07e2f4385e2fadebbTimo Sirainen o_stream_close(*stream);
cd56a23e21f1df3f79648cf07e2f4385e2fadebbTimo Sirainen o_stream_unref(stream);
cd56a23e21f1df3f79648cf07e2f4385e2fadebbTimo Sirainen}
cd56a23e21f1df3f79648cf07e2f4385e2fadebbTimo Sirainen
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainenvoid o_stream_ref(struct ostream *stream)
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen{
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainen io_stream_ref(&stream->real_stream->iostream);
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen}
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainenvoid o_stream_unref(struct ostream **stream)
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen{
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainen io_stream_unref(&(*stream)->real_stream->iostream);
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen *stream = NULL;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen}
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainenvoid o_stream_close(struct ostream *stream)
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen{
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainen io_stream_close(&stream->real_stream->iostream);
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen stream->closed = TRUE;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen}
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
59151b71059df1190acd75d8717ed04a7920c862Timo Sirainen#undef o_stream_set_flush_callback
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainenvoid o_stream_set_flush_callback(struct ostream *stream,
211ed7806d8715ec2280ffbf5d10f0d6e4f1beb2Timo Sirainen stream_flush_callback_t *callback,
211ed7806d8715ec2280ffbf5d10f0d6e4f1beb2Timo Sirainen void *context)
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen{
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainen struct ostream_private *_stream = stream->real_stream;
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen _stream->callback = callback;
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen _stream->context = context;
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen}
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen
59151b71059df1190acd75d8717ed04a7920c862Timo Sirainenvoid o_stream_unset_flush_callback(struct ostream *stream)
59151b71059df1190acd75d8717ed04a7920c862Timo Sirainen{
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainen struct ostream_private *_stream = stream->real_stream;
59151b71059df1190acd75d8717ed04a7920c862Timo Sirainen
59151b71059df1190acd75d8717ed04a7920c862Timo Sirainen _stream->callback = NULL;
59151b71059df1190acd75d8717ed04a7920c862Timo Sirainen _stream->context = NULL;
59151b71059df1190acd75d8717ed04a7920c862Timo Sirainen}
59151b71059df1190acd75d8717ed04a7920c862Timo Sirainen
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainenvoid o_stream_set_max_buffer_size(struct ostream *stream, size_t max_size)
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen{
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainen io_stream_set_max_buffer_size(&stream->real_stream->iostream, max_size);
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen}
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainenvoid o_stream_cork(struct ostream *stream)
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen{
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainen struct ostream_private *_stream = stream->real_stream;
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen
c9bf63e9094761767a63ac6b189bcf60bcffdc44Timo Sirainen if (unlikely(stream->closed))
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen return;
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen _stream->cork(_stream, TRUE);
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen}
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainenvoid o_stream_uncork(struct ostream *stream)
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen{
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainen struct ostream_private *_stream = stream->real_stream;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
c9bf63e9094761767a63ac6b189bcf60bcffdc44Timo Sirainen if (unlikely(stream->closed))
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen return;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen _stream->cork(_stream, FALSE);
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen}
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainenint o_stream_flush(struct ostream *stream)
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen{
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainen struct ostream_private *_stream = stream->real_stream;
6cc0546c058f3e6253c6f99727b28dd602712974Timo Sirainen int ret;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
c9bf63e9094761767a63ac6b189bcf60bcffdc44Timo Sirainen if (unlikely(stream->closed))
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen return -1;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
53cd46dd843c22f21f7e6efcc52a3e0f76cd1e52Timo Sirainen stream->stream_errno = 0;
6cc0546c058f3e6253c6f99727b28dd602712974Timo Sirainen if (unlikely((ret = _stream->flush(_stream)) < 0)) {
6cc0546c058f3e6253c6f99727b28dd602712974Timo Sirainen i_assert(stream->stream_errno != 0);
6cc0546c058f3e6253c6f99727b28dd602712974Timo Sirainen stream->last_failed_errno = stream->stream_errno;
6cc0546c058f3e6253c6f99727b28dd602712974Timo Sirainen }
6cc0546c058f3e6253c6f99727b28dd602712974Timo Sirainen return ret;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen}
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainenvoid o_stream_set_flush_pending(struct ostream *stream, bool set)
5238111c460098d9cc8cc22527026138a278b9a4Timo Sirainen{
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainen struct ostream_private *_stream = stream->real_stream;
5238111c460098d9cc8cc22527026138a278b9a4Timo Sirainen
c9bf63e9094761767a63ac6b189bcf60bcffdc44Timo Sirainen if (unlikely(stream->closed))
c9bf63e9094761767a63ac6b189bcf60bcffdc44Timo Sirainen return;
c9bf63e9094761767a63ac6b189bcf60bcffdc44Timo Sirainen
c9bf63e9094761767a63ac6b189bcf60bcffdc44Timo Sirainen _stream->flush_pending(_stream, set);
5238111c460098d9cc8cc22527026138a278b9a4Timo Sirainen}
5238111c460098d9cc8cc22527026138a278b9a4Timo Sirainen
68a4946b12583b88fa802e52ebee45cd96056772Timo Sirainensize_t o_stream_get_buffer_used_size(const struct ostream *stream)
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen{
68a4946b12583b88fa802e52ebee45cd96056772Timo Sirainen const struct ostream_private *_stream = stream->real_stream;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen return _stream->get_used_size(_stream);
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen}
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainenint o_stream_seek(struct ostream *stream, uoff_t offset)
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen{
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainen struct ostream_private *_stream = stream->real_stream;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
c9bf63e9094761767a63ac6b189bcf60bcffdc44Timo Sirainen if (unlikely(stream->closed))
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen return -1;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
53cd46dd843c22f21f7e6efcc52a3e0f76cd1e52Timo Sirainen stream->stream_errno = 0;
6cc0546c058f3e6253c6f99727b28dd602712974Timo Sirainen if (unlikely(_stream->seek(_stream, offset) < 0)) {
6cc0546c058f3e6253c6f99727b28dd602712974Timo Sirainen i_assert(stream->stream_errno != 0);
6cc0546c058f3e6253c6f99727b28dd602712974Timo Sirainen stream->last_failed_errno = stream->stream_errno;
6cc0546c058f3e6253c6f99727b28dd602712974Timo Sirainen }
6cc0546c058f3e6253c6f99727b28dd602712974Timo Sirainen return 1;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen}
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
b92e979748a22925b0770d3004eaab043ed69574Timo Sirainenssize_t o_stream_send(struct ostream *stream, const void *data, size_t size)
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen{
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen struct const_iovec iov;
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen iov.iov_base = data;
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen iov.iov_len = size;
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen return o_stream_sendv(stream, &iov, 1);
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen}
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainenssize_t o_stream_sendv(struct ostream *stream, const struct const_iovec *iov,
0ce5f96804e81cb0f857e7df32c0272f1eed9377Timo Sirainen unsigned int iov_count)
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen{
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainen struct ostream_private *_stream = stream->real_stream;
0ce5f96804e81cb0f857e7df32c0272f1eed9377Timo Sirainen unsigned int i;
0ce5f96804e81cb0f857e7df32c0272f1eed9377Timo Sirainen size_t total_size;
0ce5f96804e81cb0f857e7df32c0272f1eed9377Timo Sirainen ssize_t ret;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
c9bf63e9094761767a63ac6b189bcf60bcffdc44Timo Sirainen if (unlikely(stream->closed))
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen return -1;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
53cd46dd843c22f21f7e6efcc52a3e0f76cd1e52Timo Sirainen stream->stream_errno = 0;
0ce5f96804e81cb0f857e7df32c0272f1eed9377Timo Sirainen for (i = 0, total_size = 0; i < iov_count; i++)
0ce5f96804e81cb0f857e7df32c0272f1eed9377Timo Sirainen total_size += iov[i].iov_len;
0dbcf4026ff8471b4d6d2e14f7e52321396bf087Timo Sirainen if (total_size == 0)
0dbcf4026ff8471b4d6d2e14f7e52321396bf087Timo Sirainen return 0;
0ce5f96804e81cb0f857e7df32c0272f1eed9377Timo Sirainen
0ce5f96804e81cb0f857e7df32c0272f1eed9377Timo Sirainen ret = _stream->sendv(_stream, iov, iov_count);
6cc0546c058f3e6253c6f99727b28dd602712974Timo Sirainen if (unlikely(ret != (ssize_t)total_size)) {
6cc0546c058f3e6253c6f99727b28dd602712974Timo Sirainen if (ret < 0) {
6cc0546c058f3e6253c6f99727b28dd602712974Timo Sirainen i_assert(stream->stream_errno != 0);
6cc0546c058f3e6253c6f99727b28dd602712974Timo Sirainen stream->last_failed_errno = stream->stream_errno;
6cc0546c058f3e6253c6f99727b28dd602712974Timo Sirainen } else {
6cc0546c058f3e6253c6f99727b28dd602712974Timo Sirainen stream->overflow = TRUE;
6cc0546c058f3e6253c6f99727b28dd602712974Timo Sirainen }
6cc0546c058f3e6253c6f99727b28dd602712974Timo Sirainen }
0ce5f96804e81cb0f857e7df32c0272f1eed9377Timo Sirainen return ret;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen}
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
b92e979748a22925b0770d3004eaab043ed69574Timo Sirainenssize_t o_stream_send_str(struct ostream *stream, const char *str)
555ebb032f9b8f0cdb66f27ce7374734833e7cacTimo Sirainen{
555ebb032f9b8f0cdb66f27ce7374734833e7cacTimo Sirainen return o_stream_send(stream, str, strlen(str));
555ebb032f9b8f0cdb66f27ce7374734833e7cacTimo Sirainen}
555ebb032f9b8f0cdb66f27ce7374734833e7cacTimo Sirainen
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainenoff_t o_stream_send_istream(struct ostream *outstream,
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainen struct istream *instream)
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen{
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainen struct ostream_private *_outstream = outstream->real_stream;
989cafb9d84d8c98d6441fc1ab45b4c37762a98aTimo Sirainen off_t ret;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
c9bf63e9094761767a63ac6b189bcf60bcffdc44Timo Sirainen if (unlikely(outstream->closed || instream->closed))
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen return -1;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
53cd46dd843c22f21f7e6efcc52a3e0f76cd1e52Timo Sirainen outstream->stream_errno = 0;
989cafb9d84d8c98d6441fc1ab45b4c37762a98aTimo Sirainen ret = _outstream->send_istream(_outstream, instream);
c9bf63e9094761767a63ac6b189bcf60bcffdc44Timo Sirainen if (unlikely(ret < 0))
989cafb9d84d8c98d6441fc1ab45b4c37762a98aTimo Sirainen errno = outstream->stream_errno;
989cafb9d84d8c98d6441fc1ab45b4c37762a98aTimo Sirainen return ret;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen}
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
8cdb3234fe3c77e477c7a0e6934678f58fc54d4dTimo Sirainenint o_stream_pwrite(struct ostream *stream, const void *data, size_t size,
8cdb3234fe3c77e477c7a0e6934678f58fc54d4dTimo Sirainen uoff_t offset)
8cdb3234fe3c77e477c7a0e6934678f58fc54d4dTimo Sirainen{
8cdb3234fe3c77e477c7a0e6934678f58fc54d4dTimo Sirainen int ret;
8cdb3234fe3c77e477c7a0e6934678f58fc54d4dTimo Sirainen
8cdb3234fe3c77e477c7a0e6934678f58fc54d4dTimo Sirainen if (unlikely(stream->closed))
8cdb3234fe3c77e477c7a0e6934678f58fc54d4dTimo Sirainen return -1;
8cdb3234fe3c77e477c7a0e6934678f58fc54d4dTimo Sirainen
8cdb3234fe3c77e477c7a0e6934678f58fc54d4dTimo Sirainen ret = stream->real_stream->write_at(stream->real_stream,
8cdb3234fe3c77e477c7a0e6934678f58fc54d4dTimo Sirainen data, size, offset);
8cdb3234fe3c77e477c7a0e6934678f58fc54d4dTimo Sirainen if (unlikely(ret < 0)) {
8cdb3234fe3c77e477c7a0e6934678f58fc54d4dTimo Sirainen i_assert(stream->stream_errno != 0);
8cdb3234fe3c77e477c7a0e6934678f58fc54d4dTimo Sirainen stream->last_failed_errno = stream->stream_errno;
8cdb3234fe3c77e477c7a0e6934678f58fc54d4dTimo Sirainen }
8cdb3234fe3c77e477c7a0e6934678f58fc54d4dTimo Sirainen return ret;
8cdb3234fe3c77e477c7a0e6934678f58fc54d4dTimo Sirainen}
8cdb3234fe3c77e477c7a0e6934678f58fc54d4dTimo Sirainen
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainenstruct ostream *o_stream_create(struct ostream_private *_stream)
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen{
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen _stream->ostream.real_stream = _stream;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainen io_stream_init(&_stream->iostream);
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen return &_stream->ostream;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen}