istream.c revision 6eb0192085073a63ea03443860c412bb5312dd7e
02c335c23bf5fa225a467c19f2c063fb0dc7b8c3Timo Sirainen/* Copyright (c) 2002-2016 Dovecot authors, see the included COPYING file */
c2cda8cd0043443566efc5da30f79865508a1947Timo Sirainenstatic bool i_stream_is_buffer_invalid(const struct istream_private *stream);
8cb72c59d5ea4e9e5f638d7ec840bb853f5a188eTimo Sirainenvoid i_stream_set_name(struct istream *stream, const char *name)
8cb72c59d5ea4e9e5f638d7ec840bb853f5a188eTimo Sirainen stream->real_stream->iostream.name = i_strdup(name);
8cb72c59d5ea4e9e5f638d7ec840bb853f5a188eTimo Sirainenconst char *i_stream_get_name(struct istream *stream)
8cb72c59d5ea4e9e5f638d7ec840bb853f5a188eTimo Sirainen while (stream->real_stream->iostream.name == NULL) {
e2ce8d4a6ac5d82a906178148453e7613fab9ba0Timo Sirainenstatic void i_stream_close_full(struct istream *stream, bool close_parents)
e2ce8d4a6ac5d82a906178148453e7613fab9ba0Timo Sirainen io_stream_close(&stream->real_stream->iostream, close_parents);
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainen io_stream_ref(&stream->real_stream->iostream);
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainen struct istream_private *_stream = (*stream)->real_stream;
5a1b498b646b5c5dbd1b3f3861df766f560578c5Timo Sirainen if (!io_stream_unref(&(*stream)->real_stream->iostream)) {
5a1b498b646b5c5dbd1b3f3861df766f560578c5Timo Sirainen i_stream_unref(&(*stream)->real_stream->parent);
5a1b498b646b5c5dbd1b3f3861df766f560578c5Timo Sirainen io_stream_free(&(*stream)->real_stream->iostream);
1a0ece3e873e3864269ed7eaed957dc10c56d25fTimo Sirainenvoid i_stream_add_destroy_callback(struct istream *stream,
eb98a038ca8b0ef33d1d11794803ce09547496faTimo Sirainen io_stream_add_destroy_callback(&stream->real_stream->iostream,
1a0ece3e873e3864269ed7eaed957dc10c56d25fTimo Sirainenvoid i_stream_remove_destroy_callback(struct istream *stream,
eb98a038ca8b0ef33d1d11794803ce09547496faTimo Sirainen io_stream_remove_destroy_callback(&stream->real_stream->iostream,
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainen struct istream_private *_stream = stream->real_stream;
862ec874f9373e3e499e237d3b9f71fdf1413feeTimo Sirainenconst char *i_stream_get_error(struct istream *stream)
46ce4d9273e6df12ef1912bbdb1c8b84b104f394Timo Sirainen /* we'll only return errors for streams that have stream_errno set or
46ce4d9273e6df12ef1912bbdb1c8b84b104f394Timo Sirainen that have reached EOF. we might be returning unintended error
46ce4d9273e6df12ef1912bbdb1c8b84b104f394Timo Sirainen otherwise. */
862ec874f9373e3e499e237d3b9f71fdf1413feeTimo Sirainen for (s = stream; s != NULL; s = s->real_stream->parent) {
5af5137f6dc0c9f358b7813e941e26f7bd735b3aTimo Sirainenconst char *i_stream_get_disconnect_reason(struct istream *stream)
5af5137f6dc0c9f358b7813e941e26f7bd735b3aTimo Sirainen return io_stream_get_disconnect_reason(stream, NULL);
7662010b03ffe5f2a6ecf4b4eb220d1c65efea76Timo Sirainenvoid i_stream_set_init_buffer_size(struct istream *stream, size_t size)
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainenvoid i_stream_set_max_buffer_size(struct istream *stream, size_t max_size)
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainen io_stream_set_max_buffer_size(&stream->real_stream->iostream, max_size);
0a49b316fc729e5d57268ffa63c7122ac73f994cTimo Sirainensize_t i_stream_get_max_buffer_size(struct istream *stream)
51e1a1c280ccb461a15827f7987d09cb9708b6e3Timo Sirainenvoid i_stream_set_return_partial_line(struct istream *stream, bool set)
463f6ea04af934a68facaca0ff089bc306de3f98Timo Sirainenvoid i_stream_set_persistent_buffers(struct istream *stream, bool set)
463f6ea04af934a68facaca0ff089bc306de3f98Timo Sirainen stream->real_stream->nonpersistent_buffers = !set;
4334b9b032298defd4d3906f5357698ff016ead0Timo Sirainenstatic void i_stream_update(struct istream_private *stream)
4334b9b032298defd4d3906f5357698ff016ead0Timo Sirainen stream->parent_expected_offset = stream->parent->v_offset;
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainen struct istream_private *_stream = stream->real_stream;
a2738cdb6d2733fb3e186331d68009421a19ea00Timo Sirainen if (unlikely(stream->closed || stream->stream_errno != 0)) {
4334b9b032298defd4d3906f5357698ff016ead0Timo Sirainen i_stream_seek(_stream->parent, _stream->parent_expected_offset);
7af4788b402346c94496095dd819f95ce03fe431Timo Sirainen i_assert(old_size <= _stream->pos - _stream->skip);
c09f9f95db314e7482c95e502e1c56ed6c555797Timo Sirainen /* error handling should be easier if we now just
c09f9f95db314e7482c95e502e1c56ed6c555797Timo Sirainen assume the stream is now at EOF */
c24ef531ca58abad996482f5c2e8992be9ae8981Timo Sirainen i_assert(old_size == _stream->pos - _stream->skip);
0892446b45c195461bb7be6599f02d97e1e2c9b2Timo Sirainen i_assert((size_t)ret+old_size == _stream->pos - _stream->skip);
fb502495e9306fe51e9d2c0019e622a98e9803abTimo Sirainen /* error handling should be easier if we now just
fb502495e9306fe51e9d2c0019e622a98e9803abTimo Sirainen assume the stream is now at EOF. Note that we could get here
fb502495e9306fe51e9d2c0019e622a98e9803abTimo Sirainen even if read() didn't return -1, although that's a little
fb502495e9306fe51e9d2c0019e622a98e9803abTimo Sirainen bit sloppy istream implementation. */
c2cda8cd0043443566efc5da30f79865508a1947Timo Sirainen /* verify that parents' access_counters are valid. the parent's
c2cda8cd0043443566efc5da30f79865508a1947Timo Sirainen i_stream_read() should guarantee this. */
c2cda8cd0043443566efc5da30f79865508a1947Timo Sirainen i_assert(!i_stream_is_buffer_invalid(_stream));
61e6367a259e2473f33df42fda8ceeb3b8b48416Timo Sirainenssize_t i_stream_read_copy_from_parent(struct istream *istream)
61e6367a259e2473f33df42fda8ceeb3b8b48416Timo Sirainen struct istream_private *stream = istream->real_stream;
61e6367a259e2473f33df42fda8ceeb3b8b48416Timo Sirainen stream->buffer = i_stream_get_data(stream->parent, &pos);
66dc739bb67d678770e1b7a7bc75f4f6f9523d2aTimo Sirainen if ((ret = i_stream_read(stream->parent)) == -2) {
61e6367a259e2473f33df42fda8ceeb3b8b48416Timo Sirainen stream->istream.stream_errno = stream->parent->stream_errno;
61e6367a259e2473f33df42fda8ceeb3b8b48416Timo Sirainen stream->buffer = i_stream_get_data(stream->parent, &pos);
61e6367a259e2473f33df42fda8ceeb3b8b48416Timo Sirainen /* check again, in case the parent stream had been seeked
61e6367a259e2473f33df42fda8ceeb3b8b48416Timo Sirainen backwards and the previous read() didn't get us far
61e6367a259e2473f33df42fda8ceeb3b8b48416Timo Sirainen ret = pos > stream->pos ? (ssize_t)(pos - stream->pos) :
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainenvoid i_stream_skip(struct istream *stream, uoff_t count)
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainen struct istream_private *_stream = stream->real_stream;
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen /* within buffer */
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen /* have to seek forward */
52041ed691a26ca80e4e805765e9f55ec097c8f1Martti Rannanjärvi if (unlikely(stream->closed || stream->stream_errno != 0))
602a0434db30d8e3292d1c161a803d96a879a74fTimo Sirainen _stream->seek(_stream, stream->v_offset + count, FALSE);
4334b9b032298defd4d3906f5357698ff016ead0Timo Sirainenstatic bool i_stream_can_optimize_seek(struct istream_private *stream)
4334b9b032298defd4d3906f5357698ff016ead0Timo Sirainen /* use the fast route only if the parent stream hasn't been changed */
4334b9b032298defd4d3906f5357698ff016ead0Timo Sirainen return i_stream_can_optimize_seek(stream->parent->real_stream);
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainenvoid i_stream_seek(struct istream *stream, uoff_t v_offset)
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainen struct istream_private *_stream = stream->real_stream;
601f5f14c6cde28f0e0c6ca7c5d735315d3d48dfTimo Sirainen i_stream_skip(stream, v_offset - stream->v_offset);
52041ed691a26ca80e4e805765e9f55ec097c8f1Martti Rannanjärvi if (unlikely(stream->closed || stream->stream_errno != 0))
602a0434db30d8e3292d1c161a803d96a879a74fTimo Sirainenvoid i_stream_seek_mark(struct istream *stream, uoff_t v_offset)
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainen struct istream_private *_stream = stream->real_stream;
52041ed691a26ca80e4e805765e9f55ec097c8f1Martti Rannanjärvi if (unlikely(stream->closed || stream->stream_errno != 0))
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainen struct istream_private *_stream = stream->real_stream;
52041ed691a26ca80e4e805765e9f55ec097c8f1Martti Rannanjärvi if (unlikely(stream->closed || stream->stream_errno != 0))
01f4ee4a0243f3fe9af763e1a540cd5cff0d63f5Timo Sirainenint i_stream_stat(struct istream *stream, bool exact, const struct stat **st_r)
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainen struct istream_private *_stream = stream->real_stream;
52041ed691a26ca80e4e805765e9f55ec097c8f1Martti Rannanjärvi if (unlikely(stream->closed || stream->stream_errno != 0))
4b9f99761df5014c659cd87fddaf6854af428cfcTimo Sirainenint i_stream_get_size(struct istream *stream, bool exact, uoff_t *size_r)
4b9f99761df5014c659cd87fddaf6854af428cfcTimo Sirainen struct istream_private *_stream = stream->real_stream;
52041ed691a26ca80e4e805765e9f55ec097c8f1Martti Rannanjärvi if (unlikely(stream->closed || stream->stream_errno != 0))
4b9f99761df5014c659cd87fddaf6854af428cfcTimo Sirainen return _stream->get_size(_stream, exact, size_r);
4106a25399703eb6cbb166dcbd5bb932cb2f7ad2Timo Sirainenbool i_stream_have_bytes_left(struct istream *stream)
4106a25399703eb6cbb166dcbd5bb932cb2f7ad2Timo Sirainen return i_stream_get_data_size(stream) > 0 || !stream->eof;
923115fd382904fa13bb09bf307bf2835b52df60Timo Sirainenuoff_t i_stream_get_absolute_offset(struct istream *stream)
923115fd382904fa13bb09bf307bf2835b52df60Timo Sirainen return stream->real_stream->abs_start_offset + stream->v_offset;
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainenstatic char *i_stream_next_line_finish(struct istream_private *stream, size_t i)
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen /* modify the buffer directly */
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen ret = (char *)stream->w_buffer + stream->skip;
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen /* use a temporary string to return it */
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen stream->line_str = str_new(default_pool, 256);
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen str_append_n(stream->line_str, stream->buffer + stream->skip,
51e1a1c280ccb461a15827f7987d09cb9708b6e3Timo Sirainenstatic char *i_stream_last_line(struct istream_private *_stream)
51e1a1c280ccb461a15827f7987d09cb9708b6e3Timo Sirainen if (_stream->istream.eof && _stream->skip != _stream->pos &&
51e1a1c280ccb461a15827f7987d09cb9708b6e3Timo Sirainen /* the last line is missing LF and we want to return it. */
51e1a1c280ccb461a15827f7987d09cb9708b6e3Timo Sirainen return i_stream_next_line_finish(_stream, _stream->pos);
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainenchar *i_stream_next_line(struct istream *stream)
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainen struct istream_private *_stream = stream->real_stream;
7b42d6cbee8186195d8c5e66078043a0fa1f25c1Timo Sirainen const unsigned char *pos;
7b42d6cbee8186195d8c5e66078043a0fa1f25c1Timo Sirainen pos = memchr(_stream->buffer + _stream->skip, '\n',
89e195dfb5c4b0efd9b9f459771a4467674e5b1fTimo Sirainenchar *i_stream_read_next_line(struct istream *stream)
89c8d5f336e44cca091a1f588d51ba26e5145ad2Timo Sirainen io_stream_set_error(&stream->real_stream->iostream,
89c8d5f336e44cca091a1f588d51ba26e5145ad2Timo Sirainen i_stream_get_data_size(stream), stream->v_offset);
51e1a1c280ccb461a15827f7987d09cb9708b6e3Timo Sirainen return i_stream_last_line(stream->real_stream);
6f08b98ac63c25b747120d0c8f8e319b4e26ab0fTimo Sirainenbool i_stream_last_line_crlf(struct istream *stream)
f5982bb5b0a704e88fa2b44b0b74e365d13103b9Timo Sirainenstatic bool i_stream_is_buffer_invalid(const struct istream_private *stream)
f5982bb5b0a704e88fa2b44b0b74e365d13103b9Timo Sirainen /* the buffer can't point to parent, because it doesn't exist */
f5982bb5b0a704e88fa2b44b0b74e365d13103b9Timo Sirainen /* we can pretty safely assume that the stream is using its
f5982bb5b0a704e88fa2b44b0b74e365d13103b9Timo Sirainen own private buffer, so it can never become invalid. */
f5982bb5b0a704e88fa2b44b0b74e365d13103b9Timo Sirainen stream->parent->real_stream->access_counter) {
f5982bb5b0a704e88fa2b44b0b74e365d13103b9Timo Sirainen /* parent has been modified behind this stream, we can't trust
f5982bb5b0a704e88fa2b44b0b74e365d13103b9Timo Sirainen that our buffer is valid */
f5982bb5b0a704e88fa2b44b0b74e365d13103b9Timo Sirainen return i_stream_is_buffer_invalid(stream->parent->real_stream);
68a4946b12583b88fa802e52ebee45cd96056772Timo Sirainenconst unsigned char *
4106a25399703eb6cbb166dcbd5bb932cb2f7ad2Timo Siraineni_stream_get_data(struct istream *stream, size_t *size_r)
4106a25399703eb6cbb166dcbd5bb932cb2f7ad2Timo Sirainen struct istream_private *_stream = stream->real_stream;
f5982bb5b0a704e88fa2b44b0b74e365d13103b9Timo Sirainen /* This stream may be using parent's buffer directly as
f5982bb5b0a704e88fa2b44b0b74e365d13103b9Timo Sirainen _stream->buffer, but the parent stream has already been
f5982bb5b0a704e88fa2b44b0b74e365d13103b9Timo Sirainen modified indirectly. This means that the buffer might no
f5982bb5b0a704e88fa2b44b0b74e365d13103b9Timo Sirainen longer point to where we assume it points to. So we'll
f5982bb5b0a704e88fa2b44b0b74e365d13103b9Timo Sirainen just return the stream as empty until it's read again.
f5982bb5b0a704e88fa2b44b0b74e365d13103b9Timo Sirainen It's a bit ugly to suddenly drop data from the stream that
f5982bb5b0a704e88fa2b44b0b74e365d13103b9Timo Sirainen was already read, but since this happens only with shared
f5982bb5b0a704e88fa2b44b0b74e365d13103b9Timo Sirainen parent istreams the caller is hopefully aware enough that
f5982bb5b0a704e88fa2b44b0b74e365d13103b9Timo Sirainen something like this might happen. The other solutions would
f5982bb5b0a704e88fa2b44b0b74e365d13103b9Timo Sirainen be to a) try to automatically read the data back (but we
f5982bb5b0a704e88fa2b44b0b74e365d13103b9Timo Sirainen can't handle errors..) or b) always copy data to stream's
f5982bb5b0a704e88fa2b44b0b74e365d13103b9Timo Sirainen own buffer instead of pointing to parent's buffer (but this
f5982bb5b0a704e88fa2b44b0b74e365d13103b9Timo Sirainen causes data copying that is nearly always unnecessary). */
4106a25399703eb6cbb166dcbd5bb932cb2f7ad2Timo Sirainen /* if we had already read until EOF, mark the stream again as
4106a25399703eb6cbb166dcbd5bb932cb2f7ad2Timo Sirainen not being at the end of file. */
4106a25399703eb6cbb166dcbd5bb932cb2f7ad2Timo Sirainensize_t i_stream_get_data_size(struct istream *stream)
4106a25399703eb6cbb166dcbd5bb932cb2f7ad2Timo Sirainenunsigned char *i_stream_get_modifiable_data(struct istream *stream,
4106a25399703eb6cbb166dcbd5bb932cb2f7ad2Timo Sirainen struct istream_private *_stream = stream->real_stream;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen if (_stream->skip >= _stream->pos || _stream->w_buffer == NULL) {
c06f4017027263cf3a08becc551f5126409e2a83Timo Sirainenint i_stream_read_data(struct istream *stream, const unsigned char **data_r,
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen /* we need more data */
abe8754852e70763e92f74caabbcc13d0917714cTimo Sirainen } while (ret > 0);
90b8f131849540fa374aede95edd86d47d35c09dTimo Sirainen /* need to read more */
c09f9f95db314e7482c95e502e1c56ed6c555797Timo Sirainen /* we read at least some new data */
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainenvoid i_stream_compress(struct istream_private *stream)
904f9d5654b9c39edcdf32883e5e88771faf4d69Timo Sirainen memmove(stream->w_buffer, stream->w_buffer + stream->skip,
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainenvoid i_stream_grow_buffer(struct istream_private *stream, size_t bytes)
7662010b03ffe5f2a6ecf4b4eb220d1c65efea76Timo Sirainen if (stream->buffer_size <= stream->init_buffer_size)
7662010b03ffe5f2a6ecf4b4eb220d1c65efea76Timo Sirainen stream->buffer_size = stream->init_buffer_size;
fe363b433b8038a69b55169da9dca27892ad7d18Timo Sirainen stream->buffer_size = nearest_power(stream->buffer_size);
97e62b2b36dda0acb3215667042f5c80cdee8155Timo Sirainen if (stream->buffer_size > stream->max_buffer_size)
7ef5ca6fb59a318c821a852ae48a2edbb671d7ddTimo Sirainen stream->buffer_size = stream->max_buffer_size;
7d5d50dd9a8c2539d7025a69e39d34fca56daeafTimo Sirainen stream->w_buffer = i_realloc(stream->w_buffer, old_size,
dd2df6a67f10792ce31a3666197c0b6885893a3aTimo Sirainenbool i_stream_try_alloc(struct istream_private *stream,
14175321ddb88619015866978c05a27786ca4814Timo Sirainen if (wanted_size > stream->buffer_size - stream->pos) {
14175321ddb88619015866978c05a27786ca4814Timo Sirainen /* remove the unused bytes from beginning of buffer */
07b3a7d8143c083c554e3169c672dacf068eeeb6Timo Sirainen } else if (stream->buffer_size < stream->max_buffer_size) {
14175321ddb88619015866978c05a27786ca4814Timo Sirainen /* buffer is full - grow it */
14175321ddb88619015866978c05a27786ca4814Timo Sirainen i_stream_grow_buffer(stream, I_STREAM_MIN_SIZE);
c7acd38cd4ef76a0f4652f9ca659ea5e64458b52Timo Sirainenvoid *i_stream_alloc(struct istream_private *stream, size_t size)
c7acd38cd4ef76a0f4652f9ca659ea5e64458b52Timo Sirainen i_stream_try_alloc(stream, size, &avail_size);
c7acd38cd4ef76a0f4652f9ca659ea5e64458b52Timo Sirainen stream->buffer_size = nearest_power(stream->pos + size);
c7acd38cd4ef76a0f4652f9ca659ea5e64458b52Timo Sirainen stream->w_buffer = i_realloc(stream->w_buffer, old_size,
c7acd38cd4ef76a0f4652f9ca659ea5e64458b52Timo Sirainen i_stream_try_alloc(stream, size, &avail_size);
282a436a74d8835edb45cc019b1c916013013fd3Timo Sirainenbool i_stream_add_data(struct istream *_stream, const unsigned char *data,
282a436a74d8835edb45cc019b1c916013013fd3Timo Sirainen struct istream_private *stream = _stream->real_stream;
282a436a74d8835edb45cc019b1c916013013fd3Timo Sirainen memcpy(stream->w_buffer + stream->pos, data, size);
4c096615cb86a826fda377b87df22c579bfe5525Timo Sirainenvoid i_stream_set_input_pending(struct istream *stream, bool pending)
4c096615cb86a826fda377b87df22c579bfe5525Timo Sirainenvoid i_stream_switch_ioloop(struct istream *stream)
4c096615cb86a826fda377b87df22c579bfe5525Timo Sirainen if (stream->real_stream->switch_ioloop != NULL)
4c096615cb86a826fda377b87df22c579bfe5525Timo Sirainen stream->real_stream->switch_ioloop(stream->real_stream);
4c096615cb86a826fda377b87df22c579bfe5525Timo Sirainenvoid i_stream_set_io(struct istream *stream, struct io *io)
4c096615cb86a826fda377b87df22c579bfe5525Timo Sirainenvoid i_stream_unset_io(struct istream *stream, struct io *io)
a94936bafd127680184da114c6a177b37ff656e5Timo Siraineni_stream_default_set_max_buffer_size(struct iostream_private *stream,
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainen struct istream_private *_stream = (struct istream_private *)stream;
01e606cda5192c4254c090624a0b2ca92da6da8eTimo Sirainen i_stream_set_max_buffer_size(_stream->parent, max_size);
e2ce8d4a6ac5d82a906178148453e7613fab9ba0Timo Sirainenstatic void i_stream_default_close(struct iostream_private *stream,
e2ce8d4a6ac5d82a906178148453e7613fab9ba0Timo Sirainen struct istream_private *_stream = (struct istream_private *)stream;
01e606cda5192c4254c090624a0b2ca92da6da8eTimo Sirainenstatic void i_stream_default_destroy(struct iostream_private *stream)
01e606cda5192c4254c090624a0b2ca92da6da8eTimo Sirainen struct istream_private *_stream = (struct istream_private *)stream;
032964c7cc6788188b63ae6270fc26cbd4a3ca26Timo Siraineni_stream_default_seek_seekable(struct istream_private *stream,
032964c7cc6788188b63ae6270fc26cbd4a3ca26Timo Sirainenvoid i_stream_default_seek_nonseekable(struct istream_private *stream,
66d84e6f0ae34a3cf5b8fa8e009d6caf025b6a2aTimo Sirainen i_panic("stream %s doesn't support seeking backwards",
b80c329a25b5b07f5e68cd44ef0fef9db6613486Timo Sirainen /* read failed */
73b9c241e7fb6abdccda88e88fbd32e844dbc185Timo Sirainen ", because we have data only up to offset %"
73b9c241e7fb6abdccda88e88fbd32e844dbc185Timo Sirainen stream->istream.v_offset, stream->istream.eof);
12a3540693ab69ec622e04d1b3b66962b8b2a3d9Timo Sirainen if (available <= v_offset - stream->istream.v_offset)
5df8396a7cbad0b38b83a86667fb3d4c223f6f7cTimo Siraineni_stream_default_stat(struct istream_private *stream, bool exact)
d5b3f66491101aba8667369586c95c615cb26ae6Timo Sirainen return stream->istream.stream_errno == 0 ? 0 : -1;
2c0f1cb7a0564d48ec43c7315ea46ea38d2abd19Timo Sirainen if (i_stream_stat(stream->parent, exact, &st) < 0) {
2c0f1cb7a0564d48ec43c7315ea46ea38d2abd19Timo Sirainen stream->istream.stream_errno = stream->parent->stream_errno;
9db5ade1c16c7f67c51004f28c28ea335755d3f0Timo Sirainen if (exact && !stream->stream_size_passthrough) {
9db5ade1c16c7f67c51004f28c28ea335755d3f0Timo Sirainen /* exact size is not known, even if parent returned something */
4b9f99761df5014c659cd87fddaf6854af428cfcTimo Siraineni_stream_default_get_size(struct istream_private *stream,
5f3151744f3ffa73b57391d4a237884b75423f57Timo Sirainenvoid i_stream_init_parent(struct istream_private *_stream,
5f3151744f3ffa73b57391d4a237884b75423f57Timo Sirainen _stream->access_counter = parent->real_stream->access_counter;
5f3151744f3ffa73b57391d4a237884b75423f57Timo Sirainen _stream->parent_start_offset = parent->v_offset;
5f3151744f3ffa73b57391d4a237884b75423f57Timo Sirainen _stream->parent_expected_offset = parent->v_offset;
5f3151744f3ffa73b57391d4a237884b75423f57Timo Sirainen _stream->abs_start_offset = parent->v_offset +
5f3151744f3ffa73b57391d4a237884b75423f57Timo Sirainen /* if parent stream is an istream-error, copy the error */
5f3151744f3ffa73b57391d4a237884b75423f57Timo Sirainen _stream->istream.stream_errno = parent->stream_errno;
9511a40d933181045343110c8101b75887062aaeTimo Siraineni_stream_create(struct istream_private *_stream, struct istream *parent, int fd)
e2ce8d4a6ac5d82a906178148453e7613fab9ba0Timo Sirainen _stream->iostream.close = i_stream_default_close;
01e606cda5192c4254c090624a0b2ca92da6da8eTimo Sirainen _stream->iostream.destroy = i_stream_default_destroy;
4b9f99761df5014c659cd87fddaf6854af428cfcTimo Sirainen _stream->get_size = i_stream_default_get_size;
a94936bafd127680184da114c6a177b37ff656e5Timo Sirainen if (_stream->iostream.set_max_buffer_size == NULL) {
7662010b03ffe5f2a6ecf4b4eb220d1c65efea76Timo Sirainen _stream->init_buffer_size = I_STREAM_MIN_SIZE;
07e4875d250e7a7157cd99132aafc773cf3cdf83Timo Sirainen memset(&_stream->statbuf, 0, sizeof(_stream->statbuf));
0c1835a90dd1dcedaeaedd1cd91672299cbeb5beTimo Sirainenstruct istream *i_stream_create_error(int stream_errno)
0c1835a90dd1dcedaeaedd1cd91672299cbeb5beTimo Sirainen i_stream_set_name(&stream->istream, "(error)");
f4735bf7ec2019fdc730e9ebdb39e5a4ea580405Timo Siraineni_stream_create_error_str(int stream_errno, const char *fmt, ...)