istream.c revision 7af4788b402346c94496095dd819f95ce03fe431
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen/* Copyright (c) 2002-2013 Dovecot authors, see the included COPYING file */
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainenvoid i_stream_set_name(struct istream *stream, const char *name)
c99fe55d4535d839a6ad0735c4719e076a1adb2cTimo Sirainen stream->real_stream->iostream.name = i_strdup(name);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainenconst char *i_stream_get_name(struct istream *stream)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen while (stream->real_stream->iostream.name == NULL) {
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainenstatic void i_stream_close_full(struct istream *stream, bool close_parents)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen io_stream_close(&stream->real_stream->iostream, close_parents);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen io_stream_ref(&stream->real_stream->iostream);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen struct istream_private *_stream = (*stream)->real_stream;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen io_stream_unref(&(*stream)->real_stream->iostream);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainenvoid i_stream_set_destroy_callback(struct istream *stream,
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen struct iostream_private *iostream = &stream->real_stream->iostream;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainenvoid i_stream_unset_destroy_callback(struct istream *stream)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen struct iostream_private *iostream = &stream->real_stream->iostream;
78fa3c578c14ee8a612f86cf73b6181c7f16463fTimo Sirainen struct istream_private *_stream = stream->real_stream;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainenvoid i_stream_set_init_buffer_size(struct istream *stream, size_t size)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainenvoid i_stream_set_max_buffer_size(struct istream *stream, size_t max_size)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen io_stream_set_max_buffer_size(&stream->real_stream->iostream, max_size);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainensize_t i_stream_get_max_buffer_size(struct istream *stream)
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainenvoid i_stream_set_return_partial_line(struct istream *stream, bool set)
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainenstatic void i_stream_update(struct istream_private *stream)
78fa3c578c14ee8a612f86cf73b6181c7f16463fTimo Sirainen stream->parent_expected_offset = stream->parent->v_offset;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen struct istream_private *_stream = stream->real_stream;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen i_stream_seek(_stream->parent, _stream->parent_expected_offset);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen i_assert(old_size <= _stream->pos - _stream->skip);
6d2b3ce2c6ef62334985ece4f0ab8b154e0e9560Timo Sirainen /* error handling should be easier if we now just
6d2b3ce2c6ef62334985ece4f0ab8b154e0e9560Timo Sirainen assume the stream is now at EOF */
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen i_assert(old_size == _stream->pos - _stream->skip);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen i_assert((size_t)ret+old_size == _stream->pos - _stream->skip);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainenssize_t i_stream_read_copy_from_parent(struct istream *istream)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen struct istream_private *stream = istream->real_stream;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen stream->buffer = i_stream_get_data(stream->parent, &pos);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen if ((ret = i_stream_read(stream->parent)) == -2)
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen stream->istream.stream_errno = stream->parent->stream_errno;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen stream->buffer = i_stream_get_data(stream->parent, &pos);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen /* check again, in case the parent stream had been seeked
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen backwards and the previous read() didn't get us far
d39a04db2f4d0599cb9b5f03a9aa10a3c234453cTimo Sirainen ret = pos > stream->pos ? (ssize_t)(pos - stream->pos) :
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainenvoid i_stream_skip(struct istream *stream, uoff_t count)
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen struct istream_private *_stream = stream->real_stream;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen /* within buffer */
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen /* have to seek forward */
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen _stream->seek(_stream, stream->v_offset + count, FALSE);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainenstatic bool i_stream_can_optimize_seek(struct istream_private *stream)
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen /* use the fast route only if the parent stream hasn't been changed */
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen return i_stream_can_optimize_seek(stream->parent->real_stream);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainenvoid i_stream_seek(struct istream *stream, uoff_t v_offset)
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen struct istream_private *_stream = stream->real_stream;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen i_stream_skip(stream, v_offset - stream->v_offset);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainenvoid i_stream_seek_mark(struct istream *stream, uoff_t v_offset)
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen struct istream_private *_stream = stream->real_stream;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen struct istream_private *_stream = stream->real_stream;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainenint i_stream_stat(struct istream *stream, bool exact, const struct stat **st_r)
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen struct istream_private *_stream = stream->real_stream;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainenint i_stream_get_size(struct istream *stream, bool exact, uoff_t *size_r)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen struct istream_private *_stream = stream->real_stream;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen return _stream->get_size(_stream, exact, size_r);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainenbool i_stream_have_bytes_left(const struct istream *stream)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen const struct istream_private *_stream = stream->real_stream;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen return !stream->eof || _stream->skip != _stream->pos;
9240d99920783c56405dda74a1f6c7ff1ebed8e6Timo Sirainen const struct istream_private *_stream = stream->real_stream;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainenuoff_t i_stream_get_absolute_offset(struct istream *stream)
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen return stream->real_stream->abs_start_offset + stream->v_offset;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainenstatic char *i_stream_next_line_finish(struct istream_private *stream, size_t i)
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen /* modify the buffer directly */
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen ret = (char *)stream->w_buffer + stream->skip;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen /* use a temporary string to return it */
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen stream->line_str = str_new(default_pool, 256);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen str_append_n(stream->line_str, stream->buffer + stream->skip,
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainenstatic char *i_stream_last_line(struct istream_private *_stream)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen if (_stream->istream.eof && _stream->skip != _stream->pos &&
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen /* the last line is missing LF and we want to return it. */
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen return i_stream_next_line_finish(_stream, _stream->pos);
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainenchar *i_stream_next_line(struct istream *stream)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen struct istream_private *_stream = stream->real_stream;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen const unsigned char *pos;
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen pos = memchr(_stream->buffer + _stream->skip, '\n',
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainenchar *i_stream_read_next_line(struct istream *stream)
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen return i_stream_last_line(stream->real_stream);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainenbool i_stream_last_line_crlf(struct istream *stream)
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainenconst unsigned char *
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Siraineni_stream_get_data(const struct istream *stream, size_t *size_r)
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen const struct istream_private *_stream = stream->real_stream;
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainensize_t i_stream_get_data_size(const struct istream *stream)
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainen const struct istream_private *_stream = stream->real_stream;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainenunsigned char *i_stream_get_modifiable_data(const struct istream *stream,
d39a04db2f4d0599cb9b5f03a9aa10a3c234453cTimo Sirainen const struct istream_private *_stream = stream->real_stream;
c99fe55d4535d839a6ad0735c4719e076a1adb2cTimo Sirainen if (_stream->skip >= _stream->pos || _stream->w_buffer == NULL) {
8d3278a82b964217d95c340ec6f82037cdc59d19Timo Sirainenint i_stream_read_data(struct istream *stream, const unsigned char **data_r,
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen /* we need more data */
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen } while (ret > 0);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen /* need to read more */
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen /* we read at least some new data */
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainenvoid i_stream_compress(struct istream_private *stream)
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen memmove(stream->w_buffer, stream->w_buffer + stream->skip,
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainenvoid i_stream_grow_buffer(struct istream_private *stream, size_t bytes)
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if (stream->buffer_size <= stream->init_buffer_size)
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen stream->buffer_size = stream->init_buffer_size;
7487ff578435377bbeefffdbfb78ca09ed1292dfTimo Sirainen stream->buffer_size = nearest_power(stream->buffer_size);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if (stream->buffer_size > stream->max_buffer_size)
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen stream->buffer_size = stream->max_buffer_size;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen stream->w_buffer = i_realloc(stream->w_buffer, old_size,
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainenbool i_stream_try_alloc(struct istream_private *stream,
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if (wanted_size > stream->buffer_size - stream->pos) {
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen /* remove the unused bytes from beginning of buffer */
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen stream->buffer_size < stream->max_buffer_size) {
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen /* buffer is full - grow it */
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen i_stream_grow_buffer(stream, I_STREAM_MIN_SIZE);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainenvoid *i_stream_alloc(struct istream_private *stream, size_t size)
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen i_stream_try_alloc(stream, size, &avail_size);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen stream->buffer_size = nearest_power(stream->pos + size);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen stream->w_buffer = i_realloc(stream->w_buffer, old_size,
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen i_stream_try_alloc(stream, size, &avail_size);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainenbool i_stream_add_data(struct istream *_stream, const unsigned char *data,
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen struct istream_private *stream = _stream->real_stream;
return FALSE;
return TRUE;
bool close_parent)
if (available == 0) {
struct istream *