istream.c revision fa39c427573ada77265b833db687ca7e854794a1
2454dfa32c93c20a8522c6ed42fe057baaac9f9aStephan Bosch/* Copyright (c) 2002-2017 Dovecot authors, see the included COPYING file */
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainenstatic bool i_stream_is_buffer_invalid(const struct istream_private *stream);
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainenvoid i_stream_set_name(struct istream *stream, const char *name)
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen stream->real_stream->iostream.name = i_strdup(name);
0db42260be85e797aa9909a29b20296996f52e75Timo Sirainenconst char *i_stream_get_name(struct istream *stream)
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen while (stream->real_stream->iostream.name == NULL) {
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainenstatic void i_stream_close_full(struct istream *stream, bool close_parents)
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen io_stream_close(&stream->real_stream->iostream, close_parents);
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen io_stream_ref(&stream->real_stream->iostream);
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen i_stream_snapshot_free(&_stream->prev_snapshot);
7a88e726e7300fb0273cb4e55b43c27fbd90bdbdTimo Sirainen if (!io_stream_unref(&(*stream)->real_stream->iostream)) {
16cb5d65265dd0b216542803fd80c4b999ae118eTimo Sirainen i_stream_unref(&(*stream)->real_stream->parent);
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen io_stream_free(&(*stream)->real_stream->iostream);
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainenvoid i_stream_add_destroy_callback(struct istream *stream,
16cb5d65265dd0b216542803fd80c4b999ae118eTimo Sirainen io_stream_add_destroy_callback(&stream->real_stream->iostream,
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainenvoid i_stream_remove_destroy_callback(struct istream *stream,
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen io_stream_remove_destroy_callback(&stream->real_stream->iostream,
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen struct istream_private *_stream = stream->real_stream;
56aa97d74071f3a2987140c2ff1cfd5a59cb35aaTimo Sirainenconst char *i_stream_get_error(struct istream *stream)
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen /* we'll only return errors for streams that have stream_errno set or
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen that have reached EOF. we might be returning unintended error
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen otherwise. */
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen for (s = stream; s != NULL; s = s->real_stream->parent) {
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainenconst char *i_stream_get_disconnect_reason(struct istream *stream)
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen return io_stream_get_disconnect_reason(stream, NULL);
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainenvoid i_stream_set_init_buffer_size(struct istream *stream, size_t size)
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainenvoid i_stream_set_max_buffer_size(struct istream *stream, size_t max_size)
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen io_stream_set_max_buffer_size(&stream->real_stream->iostream, max_size);
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainensize_t i_stream_get_max_buffer_size(struct istream *stream)
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen if (max_size < stream->real_stream->max_buffer_size)
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen max_size = stream->real_stream->max_buffer_size;
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainenvoid i_stream_set_return_partial_line(struct istream *stream, bool set)
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainenvoid i_stream_set_persistent_buffers(struct istream *stream, bool set)
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen stream->real_stream->nonpersistent_buffers = !set;
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainenvoid i_stream_set_blocking(struct istream *stream, bool blocking)
9a1f68e5ab08eabd352d533315cba1c69006e2c1Timo Sirainen fd_set_nonblock(stream->real_stream->fd, !blocking);
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainenstatic void i_stream_update(struct istream_private *stream)
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen stream->parent_expected_offset = stream->parent->v_offset;
95d62f8d6d281cc488dc4f488d4388701e559012Josef 'Jeff' Sipekstatic bool snapshot_has_memarea(struct istream_snapshot *snapshot,
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen return snapshot_has_memarea(snapshot->prev_snapshot, memarea);
01435c38e7d671d5a892c4b802cfb204881cd454Timo Siraineni_stream_default_snapshot(struct istream_private *stream,
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen if (snapshot_has_memarea(prev_snapshot, stream->memarea))
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen /* This stream has a memarea. Reference it, so we can later on
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen rollback if needed. */
5d4a0dac041964a04405bc6b94de51315ca917afTimo Sirainen i_panic("%s is missing istream.snapshot() implementation",
050acc3755ccc5bcf261a6de3250164a54a0b6f3Timo Sirainen return _parent_stream->snapshot(_parent_stream, prev_snapshot);
050acc3755ccc5bcf261a6de3250164a54a0b6f3Timo Sirainenvoid i_stream_snapshot_free(struct istream_snapshot **_snapshot)
050acc3755ccc5bcf261a6de3250164a54a0b6f3Timo Sirainen struct istream_snapshot *snapshot = *_snapshot;
050acc3755ccc5bcf261a6de3250164a54a0b6f3Timo Sirainen i_stream_snapshot_free(&snapshot->prev_snapshot);
cf35bb040d505e2fc333470850c65029992778a4Timo Siraineni_stream_noop_snapshot(struct istream_private *stream ATTR_UNUSED,
cf35bb040d505e2fc333470850c65029992778a4Timo Sirainen struct istream_private *_stream = stream->real_stream;
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen const unsigned char *prev_data = _stream->buffer;
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen size_t prev_skip = _stream->skip, prev_pos = _stream->pos;
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen bool invalid = i_stream_is_buffer_invalid(_stream);
2e708f348f20caa47210cf46cf7654f167fa47bbTimo Sirainen memcpy(prev_buf, prev_data + prev_skip, prev_pos - prev_skip);
2e708f348f20caa47210cf46cf7654f167fa47bbTimo Sirainen memcpy(prev_buf+2, prev_data + prev_pos - 2, 2);
2e708f348f20caa47210cf46cf7654f167fa47bbTimo Sirainen _stream->snapshot(_stream, _stream->prev_snapshot);
2e708f348f20caa47210cf46cf7654f167fa47bbTimo Sirainen i_stream_snapshot_free(&_stream->prev_snapshot);
2e708f348f20caa47210cf46cf7654f167fa47bbTimo Sirainen i_assert((_stream->pos - _stream->skip) == (prev_pos - prev_skip));
2e708f348f20caa47210cf46cf7654f167fa47bbTimo Sirainen i_assert(memcmp(prev_buf, prev_data + prev_skip, prev_pos - prev_skip) == 0);
2e708f348f20caa47210cf46cf7654f167fa47bbTimo Sirainen i_assert(memcmp(prev_buf, prev_data + prev_skip, 2) == 0);
2e708f348f20caa47210cf46cf7654f167fa47bbTimo Sirainen i_assert(memcmp(prev_buf+2, prev_data + prev_pos - 2, 2) == 0);
2e708f348f20caa47210cf46cf7654f167fa47bbTimo Sirainenssize_t i_stream_read_memarea(struct istream *stream)
2e708f348f20caa47210cf46cf7654f167fa47bbTimo Sirainen struct istream_private *_stream = stream->real_stream;
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen if (unlikely(stream->closed || stream->stream_errno != 0)) {
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen i_stream_seek(_stream->parent, _stream->parent_expected_offset);
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen i_assert(old_size <= _stream->pos - _stream->skip);
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen /* error handling should be easier if we now just
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen assume the stream is now at EOF */
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen i_assert(old_size == _stream->pos - _stream->skip);
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen i_assert((size_t)ret+old_size == _stream->pos - _stream->skip);
cf35bb040d505e2fc333470850c65029992778a4Timo Sirainen /* error handling should be easier if we now just
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen assume the stream is now at EOF. Note that we could get here
62041dfb7d6ac6e9c633a557075999cdfcff7bd5Timo Sirainen even if read() didn't return -1, although that's a little
62041dfb7d6ac6e9c633a557075999cdfcff7bd5Timo Sirainen bit sloppy istream implementation. */
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen /* verify that parents' access_counters are valid. the parent's
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen i_stream_read() should guarantee this. */
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen i_assert(!i_stream_is_buffer_invalid(_stream));
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainenint i_stream_read_more_memarea(struct istream *stream,
2e708f348f20caa47210cf46cf7654f167fa47bbTimo Sirainenssize_t i_stream_read_copy_from_parent(struct istream *istream)
01435c38e7d671d5a892c4b802cfb204881cd454Timo Sirainen struct istream_private *stream = istream->real_stream;
ret = 0;
return ret;
return TRUE;
return FALSE;
int ret;
return ret;
return abs_offset;
char *ret;
end = i;
return ret;
return NULL;
const unsigned char *pos;
return NULL;
char *line;
return NULL;
return NULL;
return line;
return FALSE;
return FALSE;
return TRUE;
*size_r = 0;
return uchar_empty_ptr;
*size_r = 0;
return uchar_empty_ptr;
return size;
*size_r = 0;
return NULL;
if (ret > 0)
} while (ret > 0);
if (ret == 0) {
if (read_more) {
void *new_buffer;
return *size_r > 0;
return ret;
return FALSE;
return TRUE;
if (!pending)
bool close_parent)
if (available == 0) {
struct istream *
struct istream *
return input;