bcb4e51a409d94ae670de96afb8483a4f7855294Stephan Bosch/* Copyright (c) 2002-2018 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);
f4169072aebf5607b272f954fb405c838e1aa4d6Josef 'Jeff' Sipek if (!io_stream_unref(&_stream->iostream)) {
82ea464c113f43aaa2b2e23de334cf3081c332beTimo Sirainen i_stream_snapshot_free(&_stream->prev_snapshot);
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)
71aed7ba87b5fd5e96e97a22d89ac025b883d60aTimo Sirainen if (max_size < stream->real_stream->max_buffer_size)
71aed7ba87b5fd5e96e97a22d89ac025b883d60aTimo Sirainen max_size = stream->real_stream->max_buffer_size;
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;
0b6924ad1943fe5c6917fc49f675d8f316b0d939Timo Sirainenvoid i_stream_set_blocking(struct istream *stream, bool blocking)
0b6924ad1943fe5c6917fc49f675d8f316b0d939Timo Sirainen fd_set_nonblock(stream->real_stream->fd, !blocking);
4334b9b032298defd4d3906f5357698ff016ead0Timo Sirainenstatic void i_stream_update(struct istream_private *stream)
4334b9b032298defd4d3906f5357698ff016ead0Timo Sirainen stream->parent_expected_offset = stream->parent->v_offset;
82ea464c113f43aaa2b2e23de334cf3081c332beTimo Sirainenstatic bool snapshot_has_memarea(struct istream_snapshot *snapshot,
82ea464c113f43aaa2b2e23de334cf3081c332beTimo Sirainen return snapshot_has_memarea(snapshot->prev_snapshot, memarea);
82ea464c113f43aaa2b2e23de334cf3081c332beTimo Siraineni_stream_default_snapshot(struct istream_private *stream,
82ea464c113f43aaa2b2e23de334cf3081c332beTimo Sirainen if (snapshot_has_memarea(prev_snapshot, stream->memarea))
82ea464c113f43aaa2b2e23de334cf3081c332beTimo Sirainen /* This stream has a memarea. Reference it, so we can later on
82ea464c113f43aaa2b2e23de334cf3081c332beTimo Sirainen rollback if needed. */
ba55ec8fdf79301bfce9838d773250cef9486178Timo Sirainen /* Assume that memarea would be used normally, but
ba55ec8fdf79301bfce9838d773250cef9486178Timo Sirainen now it's NULL because the buffer is empty and
ba55ec8fdf79301bfce9838d773250cef9486178Timo Sirainen empty buffers are freed. */
82ea464c113f43aaa2b2e23de334cf3081c332beTimo Sirainen i_panic("%s is missing istream.snapshot() implementation",
82ea464c113f43aaa2b2e23de334cf3081c332beTimo Sirainen return _parent_stream->snapshot(_parent_stream, prev_snapshot);
82ea464c113f43aaa2b2e23de334cf3081c332beTimo Sirainenvoid i_stream_snapshot_free(struct istream_snapshot **_snapshot)
82ea464c113f43aaa2b2e23de334cf3081c332beTimo Sirainen struct istream_snapshot *snapshot = *_snapshot;
82ea464c113f43aaa2b2e23de334cf3081c332beTimo Sirainen i_stream_snapshot_free(&snapshot->prev_snapshot);
89a89730a1dd98edb5c16a5b65f693389eb81124Timo Siraineni_stream_noop_snapshot(struct istream_private *stream ATTR_UNUSED,
e0fab14602b73ff590b2a9c5d9e67e2dfb5d1f9eTimo Sirainen struct istream_private *_stream = stream->real_stream;
66967e15d8ed35f30493dd9694a0aabe1a266f9dTimo Sirainen const unsigned char *prev_data = _stream->buffer;
66967e15d8ed35f30493dd9694a0aabe1a266f9dTimo Sirainen size_t prev_skip = _stream->skip, prev_pos = _stream->pos;
66967e15d8ed35f30493dd9694a0aabe1a266f9dTimo Sirainen bool invalid = i_stream_is_buffer_invalid(_stream);
66967e15d8ed35f30493dd9694a0aabe1a266f9dTimo Sirainen memcpy(prev_buf, prev_data + prev_skip, prev_pos - prev_skip);
66967e15d8ed35f30493dd9694a0aabe1a266f9dTimo Sirainen memcpy(prev_buf+2, prev_data + prev_pos - 2, 2);
e0fab14602b73ff590b2a9c5d9e67e2dfb5d1f9eTimo Sirainen _stream->snapshot(_stream, _stream->prev_snapshot);
e0fab14602b73ff590b2a9c5d9e67e2dfb5d1f9eTimo Sirainen i_stream_snapshot_free(&_stream->prev_snapshot);
66967e15d8ed35f30493dd9694a0aabe1a266f9dTimo Sirainen i_assert((_stream->pos - _stream->skip) == (prev_pos - prev_skip));
66967e15d8ed35f30493dd9694a0aabe1a266f9dTimo Sirainen i_assert(memcmp(prev_buf, prev_data + prev_skip, prev_pos - prev_skip) == 0);
66967e15d8ed35f30493dd9694a0aabe1a266f9dTimo Sirainen i_assert(memcmp(prev_buf, prev_data + prev_skip, 2) == 0);
66967e15d8ed35f30493dd9694a0aabe1a266f9dTimo Sirainen i_assert(memcmp(prev_buf+2, prev_data + prev_pos - 2, 2) == 0);
e0fab14602b73ff590b2a9c5d9e67e2dfb5d1f9eTimo Sirainenssize_t i_stream_read_memarea(struct istream *stream)
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));
e0fab14602b73ff590b2a9c5d9e67e2dfb5d1f9eTimo Sirainenint i_stream_read_more_memarea(struct istream *stream,
a215abacb2d2d1e1bcd475756aab809038ae4277Timo Sirainenvoid i_stream_get_last_read_time(struct istream *stream, struct timeval *tv_r)
a215abacb2d2d1e1bcd475756aab809038ae4277Timo Sirainen *tv_r = stream->real_stream->last_read_timeval;
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);
bcd286622779a93f809b11993db0550f8c7cc9b5Timo Sirainen if ((ret = i_stream_read_memarea(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) :
785ee8becdb11e41abaaf64c28eb3923215d1f27Timo Sirainenvoid i_stream_free_buffer(struct istream_private *stream)
785ee8becdb11e41abaaf64c28eb3923215d1f27Timo Sirainen /* don't know how to free it */
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);
a85c629c5d75a5fd9489ba14d5d4f54f3cddd591Aki Tuomi 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))
a85c629c5d75a5fd9489ba14d5d4f54f3cddd591Aki Tuomi if ((ret = _stream->get_size(_stream, exact, size_r)) < 0)
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)
d28179fd78550a58be44dcb1e3e830ab7d33172dTimo Sirainen abs_offset += stream->real_stream->start_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 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)
6d404348751c19ac37cfb42375abdd3c5f298e30Timo Sirainen memmove(stream->w_buffer, stream->w_buffer + stream->skip,
5ca745ae8e9903ef5265360e4c882e9314595020Timo Siraineni_stream_w_buffer_realloc(struct istream_private *stream, size_t old_size)
5ca745ae8e9903ef5265360e4c882e9314595020Timo Sirainen /* Nobody else is referencing the memarea.
5ca745ae8e9903ef5265360e4c882e9314595020Timo Sirainen We can just reallocate it. */
5ca745ae8e9903ef5265360e4c882e9314595020Timo Sirainen memarea_free_without_callback(&stream->memarea);
5ca745ae8e9903ef5265360e4c882e9314595020Timo Sirainen new_buffer = i_realloc(stream->w_buffer, old_size,
5aa1aa87a24ff39d566a3ad90d0f8d054118cfe7Timo Sirainen memcpy(new_buffer, stream->w_buffer, old_size);
5ca745ae8e9903ef5265360e4c882e9314595020Timo Sirainen stream->memarea = memarea_init(stream->w_buffer, stream->buffer_size,
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);
0928812e725cd3a4debab2a93d0c9b0436a4de9fTimo Sirainen max_size = i_stream_get_max_buffer_size(&stream->istream);
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 */
5ca745ae8e9903ef5265360e4c882e9314595020Timo Sirainen /* The memarea is still referenced. We can't
5ca745ae8e9903ef5265360e4c882e9314595020Timo Sirainen overwrite data until extra references are
5ca745ae8e9903ef5265360e4c882e9314595020Timo Sirainen i_stream_w_buffer_realloc(stream, stream->buffer_size);
0928812e725cd3a4debab2a93d0c9b0436a4de9fTimo Sirainen } else if (stream->buffer_size < i_stream_get_max_buffer_size(&stream->istream)) {
14175321ddb88619015866978c05a27786ca4814Timo Sirainen /* buffer is full - grow it */
14175321ddb88619015866978c05a27786ca4814Timo Sirainen i_stream_grow_buffer(stream, I_STREAM_MIN_SIZE);
51d379cbc50242a13462d0fded50e013eb00cc07Timo Siraineni_stream_try_alloc_avoid_compress(struct istream_private *stream,
51d379cbc50242a13462d0fded50e013eb00cc07Timo Sirainen /* try first with skip=0, so no compression is done */
51d379cbc50242a13462d0fded50e013eb00cc07Timo Sirainen bool ret = i_stream_try_alloc(stream, wanted_size, size_r);
51d379cbc50242a13462d0fded50e013eb00cc07Timo Sirainen /* it's full. try with compression. */
51d379cbc50242a13462d0fded50e013eb00cc07Timo Sirainen return i_stream_try_alloc(stream, wanted_size, size_r);
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 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);
5a9bbcb13b2dd2cf9a825c7ed09fe7ee143b1275Timo Sirainenstruct istream *i_stream_get_root_io(struct istream *stream)
5a9bbcb13b2dd2cf9a825c7ed09fe7ee143b1275Timo Sirainenvoid i_stream_set_input_pending(struct istream *stream, bool pending)
038c2831447440bf0bef89b43dd0968afc298abcStephan Boschvoid i_stream_switch_ioloop_to(struct istream *stream, struct ioloop *ioloop)
038c2831447440bf0bef89b43dd0968afc298abcStephan Bosch io_stream_switch_ioloop_to(&stream->real_stream->iostream, ioloop);
038c2831447440bf0bef89b43dd0968afc298abcStephan Bosch if (stream->real_stream->switch_ioloop_to != NULL) {
038c2831447440bf0bef89b43dd0968afc298abcStephan Boschvoid i_stream_switch_ioloop(struct istream *stream)
038c2831447440bf0bef89b43dd0968afc298abcStephan Bosch i_stream_switch_ioloop_to(stream, current_ioloop);
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 %"
f0339f522dc9c8e2e8a29ef9a3f937c431c6bd1bTimo Sirainen stream->istream.v_offset, stream->istream.eof ? 1 : 0);
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 /* if parent stream is an istream-error, copy the error */
5f3151744f3ffa73b57391d4a237884b75423f57Timo Sirainen _stream->istream.stream_errno = parent->stream_errno;
2974dca6be5120e49279f06c8aa952e5fac56048Timo Siraineni_stream_create(struct istream_private *_stream, struct istream *parent, int fd,
89a89730a1dd98edb5c16a5b65f693389eb81124Timo Sirainen bool noop_snapshot = (flags & ISTREAM_CREATE_FLAG_NOOP_SNAPSHOT) != 0;
89a89730a1dd98edb5c16a5b65f693389eb81124Timo Sirainen else if (_stream->memarea == NULL && !noop_snapshot) {
82ea464c113f43aaa2b2e23de334cf3081c332beTimo Sirainen /* The stream has no parent and no memarea yet. We'll assume
82ea464c113f43aaa2b2e23de334cf3081c332beTimo Sirainen that it wants to be using memareas for the reads. */
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;
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, ...)