istream.c revision 5aa1aa87a24ff39d566a3ad90d0f8d054118cfe7
89a126810703c666309310d0f3189e9834d70b5bTimo Sirainen/* Copyright (c) 2002-2017 Dovecot authors, see the included COPYING file */
94e1adead9faddec88a623485b9999a87b1684faTimo Sirainenstatic bool i_stream_is_buffer_invalid(const struct istream_private *stream);
503e5ef896c7b4a51cf73efb0d132860a8c747e6Timo Sirainenvoid i_stream_set_name(struct istream *stream, const char *name)
3ccfcf0856958cb9208a9fc51c3bdf13c58ad52aTimo Sirainen stream->real_stream->iostream.name = i_strdup(name);
3ccfcf0856958cb9208a9fc51c3bdf13c58ad52aTimo Sirainenconst char *i_stream_get_name(struct istream *stream)
3ccfcf0856958cb9208a9fc51c3bdf13c58ad52aTimo Sirainen while (stream->real_stream->iostream.name == NULL) {
cb951d3282610a9a0960230865bc5f3e3347b203Timo Sirainenstatic void i_stream_close_full(struct istream *stream, bool close_parents)
3fe44a0df5a0bdd80c495f79cbf0e384441d6fccTimo Sirainen io_stream_close(&stream->real_stream->iostream, close_parents);
fc84f8af4794f4bb6caf6e5ec3fb1f8cebd0462aTimo Sirainen io_stream_ref(&stream->real_stream->iostream);
8a1c866a4c429f26c8746525f82024bc387f1407Timo Sirainen i_stream_snapshot_free(&_stream->prev_snapshot);
82995cc154a929f37aa486a72a6485e9f8d34a30Timo Sirainen if (!io_stream_unref(&(*stream)->real_stream->iostream)) {
82995cc154a929f37aa486a72a6485e9f8d34a30Timo Sirainen i_stream_unref(&(*stream)->real_stream->parent);
3ccfcf0856958cb9208a9fc51c3bdf13c58ad52aTimo Sirainen io_stream_free(&(*stream)->real_stream->iostream);
82995cc154a929f37aa486a72a6485e9f8d34a30Timo Sirainenvoid i_stream_add_destroy_callback(struct istream *stream,
fd1f0e9ef52b3e157cfd1a01c464c2ac7458ab17Timo Sirainen io_stream_add_destroy_callback(&stream->real_stream->iostream,
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainenvoid i_stream_remove_destroy_callback(struct istream *stream,
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen io_stream_remove_destroy_callback(&stream->real_stream->iostream,
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen struct istream_private *_stream = stream->real_stream;
3ccfcf0856958cb9208a9fc51c3bdf13c58ad52aTimo Sirainenconst char *i_stream_get_error(struct istream *stream)
3ccfcf0856958cb9208a9fc51c3bdf13c58ad52aTimo Sirainen /* we'll only return errors for streams that have stream_errno set or
3ccfcf0856958cb9208a9fc51c3bdf13c58ad52aTimo Sirainen that have reached EOF. we might be returning unintended error
82995cc154a929f37aa486a72a6485e9f8d34a30Timo Sirainen otherwise. */
3ccfcf0856958cb9208a9fc51c3bdf13c58ad52aTimo Sirainen for (s = stream; s != NULL; s = s->real_stream->parent) {
3ccfcf0856958cb9208a9fc51c3bdf13c58ad52aTimo Sirainenconst char *i_stream_get_disconnect_reason(struct istream *stream)
3ccfcf0856958cb9208a9fc51c3bdf13c58ad52aTimo Sirainen return io_stream_get_disconnect_reason(stream, NULL);
3ccfcf0856958cb9208a9fc51c3bdf13c58ad52aTimo Sirainenvoid i_stream_set_init_buffer_size(struct istream *stream, size_t size)
26a8b7deb3a5b6f26f9c4d71538e1248f680e4beTimo Sirainenvoid i_stream_set_max_buffer_size(struct istream *stream, size_t max_size)
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen io_stream_set_max_buffer_size(&stream->real_stream->iostream, max_size);
3ccfcf0856958cb9208a9fc51c3bdf13c58ad52aTimo Sirainensize_t i_stream_get_max_buffer_size(struct istream *stream)
3ccfcf0856958cb9208a9fc51c3bdf13c58ad52aTimo Sirainen if (max_size < stream->real_stream->max_buffer_size)
82995cc154a929f37aa486a72a6485e9f8d34a30Timo Sirainen max_size = stream->real_stream->max_buffer_size;
3ccfcf0856958cb9208a9fc51c3bdf13c58ad52aTimo Sirainenvoid i_stream_set_return_partial_line(struct istream *stream, bool set)
8a1c866a4c429f26c8746525f82024bc387f1407Timo Sirainenvoid i_stream_set_persistent_buffers(struct istream *stream, bool set)
82995cc154a929f37aa486a72a6485e9f8d34a30Timo Sirainen stream->real_stream->nonpersistent_buffers = !set;
82995cc154a929f37aa486a72a6485e9f8d34a30Timo Sirainenvoid i_stream_set_blocking(struct istream *stream, bool blocking)
3ccfcf0856958cb9208a9fc51c3bdf13c58ad52aTimo Sirainen fd_set_nonblock(stream->real_stream->fd, !blocking);
3ccfcf0856958cb9208a9fc51c3bdf13c58ad52aTimo Sirainenstatic void i_stream_update(struct istream_private *stream)
3ccfcf0856958cb9208a9fc51c3bdf13c58ad52aTimo Sirainen stream->parent_expected_offset = stream->parent->v_offset;
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainenstatic bool snapshot_has_memarea(struct istream_snapshot *snapshot,
a449ed9df03e9f7e93d1ec278754416ac3ad9073Timo Sirainen return snapshot_has_memarea(snapshot->prev_snapshot, memarea);
a449ed9df03e9f7e93d1ec278754416ac3ad9073Timo Siraineni_stream_default_snapshot(struct istream_private *stream,
a449ed9df03e9f7e93d1ec278754416ac3ad9073Timo Sirainen if (snapshot_has_memarea(prev_snapshot, stream->memarea))
a449ed9df03e9f7e93d1ec278754416ac3ad9073Timo Sirainen /* This stream has a memarea. Reference it, so we can later on
a449ed9df03e9f7e93d1ec278754416ac3ad9073Timo Sirainen rollback if needed. */
94e1adead9faddec88a623485b9999a87b1684faTimo Sirainen i_panic("%s is missing istream.snapshot() implementation",
94e1adead9faddec88a623485b9999a87b1684faTimo Sirainen return _parent_stream->snapshot(_parent_stream, prev_snapshot);
94e1adead9faddec88a623485b9999a87b1684faTimo Sirainenvoid i_stream_snapshot_free(struct istream_snapshot **_snapshot)
94e1adead9faddec88a623485b9999a87b1684faTimo Sirainen struct istream_snapshot *snapshot = *_snapshot;
94e1adead9faddec88a623485b9999a87b1684faTimo Sirainen i_stream_snapshot_free(&snapshot->prev_snapshot);
94e1adead9faddec88a623485b9999a87b1684faTimo Siraineni_stream_noop_snapshot(struct istream_private *stream ATTR_UNUSED,
94e1adead9faddec88a623485b9999a87b1684faTimo Sirainen struct istream_private *_stream = stream->real_stream;
94e1adead9faddec88a623485b9999a87b1684faTimo Sirainen const unsigned char *prev_data = _stream->buffer;
94e1adead9faddec88a623485b9999a87b1684faTimo Sirainen size_t prev_skip = _stream->skip, prev_pos = _stream->pos;
94e1adead9faddec88a623485b9999a87b1684faTimo Sirainen bool invalid = i_stream_is_buffer_invalid(_stream);
94e1adead9faddec88a623485b9999a87b1684faTimo Sirainen memcpy(prev_buf, prev_data + prev_skip, prev_pos - prev_skip);
a449ed9df03e9f7e93d1ec278754416ac3ad9073Timo Sirainen memcpy(prev_buf+2, prev_data + prev_pos - 2, 2);
a449ed9df03e9f7e93d1ec278754416ac3ad9073Timo Sirainen _stream->snapshot(_stream, _stream->prev_snapshot);
94e1adead9faddec88a623485b9999a87b1684faTimo Sirainen i_stream_snapshot_free(&_stream->prev_snapshot);
94e1adead9faddec88a623485b9999a87b1684faTimo Sirainen i_assert((_stream->pos - _stream->skip) == (prev_pos - prev_skip));
94e1adead9faddec88a623485b9999a87b1684faTimo Sirainen i_assert(memcmp(prev_buf, prev_data + prev_skip, prev_pos - prev_skip) == 0);
94e1adead9faddec88a623485b9999a87b1684faTimo Sirainen i_assert(memcmp(prev_buf, prev_data + prev_skip, 2) == 0);
3ccfcf0856958cb9208a9fc51c3bdf13c58ad52aTimo Sirainen i_assert(memcmp(prev_buf+2, prev_data + prev_pos - 2, 2) == 0);
f3bf2314198da2877ce640360581a61d60c90991Timo Sirainenssize_t i_stream_read_memarea(struct istream *stream)
f3bf2314198da2877ce640360581a61d60c90991Timo Sirainen struct istream_private *_stream = stream->real_stream;
3ccfcf0856958cb9208a9fc51c3bdf13c58ad52aTimo Sirainen if (unlikely(stream->closed || stream->stream_errno != 0)) {
3ccfcf0856958cb9208a9fc51c3bdf13c58ad52aTimo Sirainen i_stream_seek(_stream->parent, _stream->parent_expected_offset);
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen i_assert(old_size <= _stream->pos - _stream->skip);
3ccfcf0856958cb9208a9fc51c3bdf13c58ad52aTimo Sirainen /* error handling should be easier if we now just
fc84f8af4794f4bb6caf6e5ec3fb1f8cebd0462aTimo Sirainen assume the stream is now at EOF */
fc84f8af4794f4bb6caf6e5ec3fb1f8cebd0462aTimo Sirainen i_assert(old_size == _stream->pos - _stream->skip);
3ccfcf0856958cb9208a9fc51c3bdf13c58ad52aTimo Sirainen i_assert((size_t)ret+old_size == _stream->pos - _stream->skip);
3ccfcf0856958cb9208a9fc51c3bdf13c58ad52aTimo Sirainen /* error handling should be easier if we now just
3ccfcf0856958cb9208a9fc51c3bdf13c58ad52aTimo Sirainen assume the stream is now at EOF. Note that we could get here
3ccfcf0856958cb9208a9fc51c3bdf13c58ad52aTimo Sirainen even if read() didn't return -1, although that's a little
3ccfcf0856958cb9208a9fc51c3bdf13c58ad52aTimo Sirainen bit sloppy istream implementation. */
3ccfcf0856958cb9208a9fc51c3bdf13c58ad52aTimo Sirainen /* verify that parents' access_counters are valid. the parent's
3ccfcf0856958cb9208a9fc51c3bdf13c58ad52aTimo Sirainen i_stream_read() should guarantee this. */
3ccfcf0856958cb9208a9fc51c3bdf13c58ad52aTimo Sirainen i_assert(!i_stream_is_buffer_invalid(_stream));
3ccfcf0856958cb9208a9fc51c3bdf13c58ad52aTimo Sirainenint i_stream_read_more_memarea(struct istream *stream,
3ccfcf0856958cb9208a9fc51c3bdf13c58ad52aTimo Sirainenssize_t i_stream_read_copy_from_parent(struct istream *istream)
3ccfcf0856958cb9208a9fc51c3bdf13c58ad52aTimo Sirainen struct istream_private *stream = istream->real_stream;
de5c7c99783cd86f3bdbc057345cbee923b51a20Timo Sirainen stream->buffer = i_stream_get_data(stream->parent, &pos);
de5c7c99783cd86f3bdbc057345cbee923b51a20Timo Sirainen if ((ret = i_stream_read_memarea(stream->parent)) == -2) {
de5c7c99783cd86f3bdbc057345cbee923b51a20Timo Sirainen stream->istream.stream_errno = stream->parent->stream_errno;
3ccfcf0856958cb9208a9fc51c3bdf13c58ad52aTimo Sirainen stream->buffer = i_stream_get_data(stream->parent, &pos);
82995cc154a929f37aa486a72a6485e9f8d34a30Timo Sirainen /* check again, in case the parent stream had been seeked
3ccfcf0856958cb9208a9fc51c3bdf13c58ad52aTimo Sirainen backwards and the previous read() didn't get us far
3ccfcf0856958cb9208a9fc51c3bdf13c58ad52aTimo Sirainen ret = pos > stream->pos ? (ssize_t)(pos - stream->pos) :
3ccfcf0856958cb9208a9fc51c3bdf13c58ad52aTimo Sirainenvoid i_stream_free_buffer(struct istream_private *stream)
3ccfcf0856958cb9208a9fc51c3bdf13c58ad52aTimo Sirainen /* don't know how to free it */
3ccfcf0856958cb9208a9fc51c3bdf13c58ad52aTimo Sirainenvoid i_stream_skip(struct istream *stream, uoff_t count)
3ccfcf0856958cb9208a9fc51c3bdf13c58ad52aTimo Sirainen struct istream_private *_stream = stream->real_stream;
503e5ef896c7b4a51cf73efb0d132860a8c747e6Timo Sirainen /* within buffer */
503e5ef896c7b4a51cf73efb0d132860a8c747e6Timo Sirainen /* have to seek forward */
503e5ef896c7b4a51cf73efb0d132860a8c747e6Timo Sirainen if (unlikely(stream->closed || stream->stream_errno != 0))
503e5ef896c7b4a51cf73efb0d132860a8c747e6Timo Sirainen _stream->seek(_stream, stream->v_offset + count, FALSE);
503e5ef896c7b4a51cf73efb0d132860a8c747e6Timo Sirainenstatic bool i_stream_can_optimize_seek(struct istream_private *stream)
503e5ef896c7b4a51cf73efb0d132860a8c747e6Timo Sirainen /* use the fast route only if the parent stream hasn't been changed */
503e5ef896c7b4a51cf73efb0d132860a8c747e6Timo Sirainen return i_stream_can_optimize_seek(stream->parent->real_stream);
503e5ef896c7b4a51cf73efb0d132860a8c747e6Timo Sirainenvoid i_stream_seek(struct istream *stream, uoff_t v_offset)
3ccfcf0856958cb9208a9fc51c3bdf13c58ad52aTimo Sirainen struct istream_private *_stream = stream->real_stream;
82995cc154a929f37aa486a72a6485e9f8d34a30Timo Sirainen i_stream_skip(stream, v_offset - stream->v_offset);
3ccfcf0856958cb9208a9fc51c3bdf13c58ad52aTimo Sirainen if (unlikely(stream->closed || stream->stream_errno != 0)) {
3ccfcf0856958cb9208a9fc51c3bdf13c58ad52aTimo Sirainenvoid i_stream_seek_mark(struct istream *stream, uoff_t v_offset)
3ccfcf0856958cb9208a9fc51c3bdf13c58ad52aTimo Sirainen struct istream_private *_stream = stream->real_stream;
3ccfcf0856958cb9208a9fc51c3bdf13c58ad52aTimo Sirainen if (unlikely(stream->closed || stream->stream_errno != 0))
3ccfcf0856958cb9208a9fc51c3bdf13c58ad52aTimo Sirainen struct istream_private *_stream = stream->real_stream;
3ccfcf0856958cb9208a9fc51c3bdf13c58ad52aTimo Sirainen if (unlikely(stream->closed || stream->stream_errno != 0))
bd7b1a9000b12349e2a99bb43b3ce8b96a18e92bTimo Sirainenint i_stream_stat(struct istream *stream, bool exact, const struct stat **st_r)
bd7b1a9000b12349e2a99bb43b3ce8b96a18e92bTimo Sirainen struct istream_private *_stream = stream->real_stream;
bd7b1a9000b12349e2a99bb43b3ce8b96a18e92bTimo Sirainen if (unlikely(stream->closed || stream->stream_errno != 0))
3ccfcf0856958cb9208a9fc51c3bdf13c58ad52aTimo Sirainenint i_stream_get_size(struct istream *stream, bool exact, uoff_t *size_r)
82995cc154a929f37aa486a72a6485e9f8d34a30Timo Sirainen struct istream_private *_stream = stream->real_stream;
4981827cb5e32cf767b7b0e3070137e6b36f42afTimo Sirainen if (unlikely(stream->closed || stream->stream_errno != 0))
3ccfcf0856958cb9208a9fc51c3bdf13c58ad52aTimo Sirainen if ((ret = _stream->get_size(_stream, exact, size_r)) < 0)
3fe44a0df5a0bdd80c495f79cbf0e384441d6fccTimo Sirainenbool i_stream_have_bytes_left(struct istream *stream)
f6f94063c4c3080280b87ab47ac2bb756ba002f9Timo Sirainen return i_stream_get_data_size(stream) > 0 || !stream->eof;
e392fcb39a06609af20a9e79017683f194de3ddeTimo Sirainenuoff_t i_stream_get_absolute_offset(struct istream *stream)
3ccfcf0856958cb9208a9fc51c3bdf13c58ad52aTimo Sirainen abs_offset += stream->real_stream->start_offset;
3ccfcf0856958cb9208a9fc51c3bdf13c58ad52aTimo Sirainenstatic char *i_stream_next_line_finish(struct istream_private *stream, size_t i)
3ccfcf0856958cb9208a9fc51c3bdf13c58ad52aTimo Sirainen /* modify the buffer directly */
3ccfcf0856958cb9208a9fc51c3bdf13c58ad52aTimo Sirainen ret = (char *)stream->w_buffer + stream->skip;
ff7056842f14fd3b30a2d327dfab165b9d15dd30Timo Sirainen /* use a temporary string to return it */
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainen stream->line_str = str_new(default_pool, 256);
3ccfcf0856958cb9208a9fc51c3bdf13c58ad52aTimo Sirainen str_append_n(stream->line_str, stream->buffer + stream->skip,
1795e934ebcd58175d3b5bbdd811b13c7889efa3Timo Sirainenstatic char *i_stream_last_line(struct istream_private *_stream)
b2e181e33889f0a4a3ba9dc23d676cbfe1bf7782Timo Sirainen if (_stream->istream.eof && _stream->skip != _stream->pos &&
b2e181e33889f0a4a3ba9dc23d676cbfe1bf7782Timo Sirainen /* the last line is missing LF and we want to return it. */
b2e181e33889f0a4a3ba9dc23d676cbfe1bf7782Timo Sirainen return i_stream_next_line_finish(_stream, _stream->pos);
b2e181e33889f0a4a3ba9dc23d676cbfe1bf7782Timo Sirainenchar *i_stream_next_line(struct istream *stream)
b2e181e33889f0a4a3ba9dc23d676cbfe1bf7782Timo Sirainen struct istream_private *_stream = stream->real_stream;
b2e181e33889f0a4a3ba9dc23d676cbfe1bf7782Timo Sirainen const unsigned char *pos;
b2e181e33889f0a4a3ba9dc23d676cbfe1bf7782Timo Sirainen pos = memchr(_stream->buffer + _stream->skip, '\n',
b2e181e33889f0a4a3ba9dc23d676cbfe1bf7782Timo Sirainenchar *i_stream_read_next_line(struct istream *stream)
b2e181e33889f0a4a3ba9dc23d676cbfe1bf7782Timo Sirainen io_stream_set_error(&stream->real_stream->iostream,
b2e181e33889f0a4a3ba9dc23d676cbfe1bf7782Timo Sirainen i_stream_get_data_size(stream), stream->v_offset);
503e5ef896c7b4a51cf73efb0d132860a8c747e6Timo Sirainen return i_stream_last_line(stream->real_stream);
503e5ef896c7b4a51cf73efb0d132860a8c747e6Timo Sirainenbool i_stream_last_line_crlf(struct istream *stream)
503e5ef896c7b4a51cf73efb0d132860a8c747e6Timo Sirainenstatic bool i_stream_is_buffer_invalid(const struct istream_private *stream)
503e5ef896c7b4a51cf73efb0d132860a8c747e6Timo Sirainen /* the buffer can't point to parent, because it doesn't exist */
503e5ef896c7b4a51cf73efb0d132860a8c747e6Timo Sirainen /* we can pretty safely assume that the stream is using its
503e5ef896c7b4a51cf73efb0d132860a8c747e6Timo Sirainen own private buffer, so it can never become invalid. */
503e5ef896c7b4a51cf73efb0d132860a8c747e6Timo Sirainen stream->parent->real_stream->access_counter) {
503e5ef896c7b4a51cf73efb0d132860a8c747e6Timo Sirainen /* parent has been modified behind this stream, we can't trust
503e5ef896c7b4a51cf73efb0d132860a8c747e6Timo Sirainen that our buffer is valid */
503e5ef896c7b4a51cf73efb0d132860a8c747e6Timo Sirainen return i_stream_is_buffer_invalid(stream->parent->real_stream);
503e5ef896c7b4a51cf73efb0d132860a8c747e6Timo Sirainenconst unsigned char *
503e5ef896c7b4a51cf73efb0d132860a8c747e6Timo Siraineni_stream_get_data(struct istream *stream, size_t *size_r)
503e5ef896c7b4a51cf73efb0d132860a8c747e6Timo Sirainen struct istream_private *_stream = stream->real_stream;
503e5ef896c7b4a51cf73efb0d132860a8c747e6Timo Sirainen /* This stream may be using parent's buffer directly as
503e5ef896c7b4a51cf73efb0d132860a8c747e6Timo Sirainen _stream->buffer, but the parent stream has already been
503e5ef896c7b4a51cf73efb0d132860a8c747e6Timo Sirainen modified indirectly. This means that the buffer might no
503e5ef896c7b4a51cf73efb0d132860a8c747e6Timo Sirainen longer point to where we assume it points to. So we'll
503e5ef896c7b4a51cf73efb0d132860a8c747e6Timo Sirainen just return the stream as empty until it's read again.
503e5ef896c7b4a51cf73efb0d132860a8c747e6Timo Sirainen It's a bit ugly to suddenly drop data from the stream that
503e5ef896c7b4a51cf73efb0d132860a8c747e6Timo Sirainen was already read, but since this happens only with shared
503e5ef896c7b4a51cf73efb0d132860a8c747e6Timo Sirainen parent istreams the caller is hopefully aware enough that
503e5ef896c7b4a51cf73efb0d132860a8c747e6Timo Sirainen something like this might happen. The other solutions would
503e5ef896c7b4a51cf73efb0d132860a8c747e6Timo Sirainen be to a) try to automatically read the data back (but we
503e5ef896c7b4a51cf73efb0d132860a8c747e6Timo Sirainen can't handle errors..) or b) always copy data to stream's
503e5ef896c7b4a51cf73efb0d132860a8c747e6Timo Sirainen own buffer instead of pointing to parent's buffer (but this
503e5ef896c7b4a51cf73efb0d132860a8c747e6Timo Sirainen causes data copying that is nearly always unnecessary). */
503e5ef896c7b4a51cf73efb0d132860a8c747e6Timo Sirainen /* if we had already read until EOF, mark the stream again as
503e5ef896c7b4a51cf73efb0d132860a8c747e6Timo Sirainen not being at the end of file. */
503e5ef896c7b4a51cf73efb0d132860a8c747e6Timo Sirainensize_t i_stream_get_data_size(struct istream *stream)
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainenunsigned char *i_stream_get_modifiable_data(struct istream *stream,
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen struct istream_private *_stream = stream->real_stream;
f6f94063c4c3080280b87ab47ac2bb756ba002f9Timo Sirainen if (_stream->skip >= _stream->pos || _stream->w_buffer == NULL) {
b2e181e33889f0a4a3ba9dc23d676cbfe1bf7782Timo Sirainenint i_stream_read_data(struct istream *stream, const unsigned char **data_r,
3fe44a0df5a0bdd80c495f79cbf0e384441d6fccTimo Sirainen /* we need more data */
6800c6607013d4fdef5a4f764bae407301c6cce8Timo Sirainen } while (ret > 0);
3ccfcf0856958cb9208a9fc51c3bdf13c58ad52aTimo Sirainen /* need to read more */
3ccfcf0856958cb9208a9fc51c3bdf13c58ad52aTimo Sirainen /* we read at least some new data */
6800c6607013d4fdef5a4f764bae407301c6cce8Timo Sirainenvoid i_stream_compress(struct istream_private *stream)
6800c6607013d4fdef5a4f764bae407301c6cce8Timo Sirainen memmove(stream->w_buffer, stream->w_buffer + stream->skip,
bd7b1a9000b12349e2a99bb43b3ce8b96a18e92bTimo Siraineni_stream_w_buffer_realloc(struct istream_private *stream, size_t old_size)
bd7b1a9000b12349e2a99bb43b3ce8b96a18e92bTimo Sirainen /* Nobody else is referencing the memarea.
bd7b1a9000b12349e2a99bb43b3ce8b96a18e92bTimo Sirainen We can just reallocate it. */
3ccfcf0856958cb9208a9fc51c3bdf13c58ad52aTimo Sirainen memarea_free_without_callback(&stream->memarea);
6800c6607013d4fdef5a4f764bae407301c6cce8Timo Sirainen new_buffer = i_realloc(stream->w_buffer, old_size,
return *size_r > 0;
return ret;
return FALSE;
return TRUE;
if (!pending)
bool close_parent)
if (close_parent)
if (available == 0) {
struct istream *
struct istream *
return input;