istream.c revision a10ed8c47534b4c6b6bf2711ccfe577e720a47b4
5f5870385cff47efd2f58e7892f251cf13761528Timo Sirainen/* Copyright (c) 2002-2012 Dovecot authors, see the included COPYING file */
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) {
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainen io_stream_ref(&stream->real_stream->iostream);
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainen struct istream_private *_stream = (*stream)->real_stream;
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainen io_stream_unref(&(*stream)->real_stream->iostream);
5ac0b0bf32898c63da086ae169674ecac151a31eTimo Sirainenvoid i_stream_set_destroy_callback(struct istream *stream,
5ac0b0bf32898c63da086ae169674ecac151a31eTimo Sirainen struct iostream_private *iostream = &stream->real_stream->iostream;
c28f6aa0b70af4811c9ace9114fe827c2f503455Timo Sirainenvoid i_stream_unset_destroy_callback(struct istream *stream)
c28f6aa0b70af4811c9ace9114fe827c2f503455Timo Sirainen struct iostream_private *iostream = &stream->real_stream->iostream;
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainen struct istream_private *_stream = stream->real_stream;
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainen io_stream_close(&stream->real_stream->iostream);
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)
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;
4334b9b032298defd4d3906f5357698ff016ead0Timo Sirainen i_stream_seek(_stream->parent, _stream->parent_expected_offset);
c09f9f95db314e7482c95e502e1c56ed6c555797Timo Sirainen /* error handling should be easier if we now just
c09f9f95db314e7482c95e502e1c56ed6c555797Timo Sirainen assume the stream is now at EOF */
0892446b45c195461bb7be6599f02d97e1e2c9b2Timo Sirainen i_assert((size_t)ret+old_size == _stream->pos - _stream->skip);
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);
61e6367a259e2473f33df42fda8ceeb3b8b48416Timo 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 */
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);
602a0434db30d8e3292d1c161a803d96a879a74fTimo Sirainenvoid i_stream_seek_mark(struct istream *stream, uoff_t v_offset)
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainen struct istream_private *_stream = stream->real_stream;
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainen struct istream_private *_stream = stream->real_stream;
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainenconst struct stat *i_stream_stat(struct istream *stream, bool exact)
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainen struct istream_private *_stream = stream->real_stream;
4b9f99761df5014c659cd87fddaf6854af428cfcTimo Sirainenint i_stream_get_size(struct istream *stream, bool exact, uoff_t *size_r)
4b9f99761df5014c659cd87fddaf6854af428cfcTimo Sirainen struct istream_private *_stream = stream->real_stream;
4b9f99761df5014c659cd87fddaf6854af428cfcTimo Sirainen return _stream->get_size(_stream, exact, size_r);
68a4946b12583b88fa802e52ebee45cd96056772Timo Sirainenbool i_stream_have_bytes_left(const struct istream *stream)
68a4946b12583b88fa802e52ebee45cd96056772Timo Sirainen const struct istream_private *_stream = stream->real_stream;
7e1f68ad71d3485f1882142837b01f7a98ca8467Timo Sirainen return !stream->eof || _stream->skip != _stream->pos;
a3c197999dfe2b0c8ea38cb77cfa5e95026005c0Timo Sirainen const struct istream_private *_stream = stream->real_stream;
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)
51e1a1c280ccb461a15827f7987d09cb9708b6e3Timo Sirainen return i_stream_last_line(stream->real_stream);
68a4946b12583b88fa802e52ebee45cd96056772Timo Sirainenconst unsigned char *
68a4946b12583b88fa802e52ebee45cd96056772Timo Siraineni_stream_get_data(const struct istream *stream, size_t *size_r)
68a4946b12583b88fa802e52ebee45cd96056772Timo Sirainen const struct istream_private *_stream = stream->real_stream;
68a4946b12583b88fa802e52ebee45cd96056772Timo Sirainenunsigned char *i_stream_get_modifiable_data(const struct istream *stream,
68a4946b12583b88fa802e52ebee45cd96056772Timo Sirainen const 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,
14175321ddb88619015866978c05a27786ca4814Timo Sirainenbool i_stream_get_buffer_space(struct istream_private *stream,
14175321ddb88619015866978c05a27786ca4814Timo Sirainen if (wanted_size > stream->buffer_size - stream->pos) {
14175321ddb88619015866978c05a27786ca4814Timo Sirainen /* remove the unused bytes from beginning of buffer */
14175321ddb88619015866978c05a27786ca4814Timo Sirainen 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);
282a436a74d8835edb45cc019b1c916013013fd3Timo Sirainenbool i_stream_add_data(struct istream *_stream, const unsigned char *data,
282a436a74d8835edb45cc019b1c916013013fd3Timo Sirainen struct istream_private *stream = _stream->real_stream;
282a436a74d8835edb45cc019b1c916013013fd3Timo Sirainen (void)i_stream_get_buffer_space(stream, size, &size2);
282a436a74d8835edb45cc019b1c916013013fd3Timo Sirainen memcpy(stream->w_buffer + stream->pos, data, size);
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);
01e606cda5192c4254c090624a0b2ca92da6da8eTimo Sirainenstatic void i_stream_default_destroy(struct iostream_private *stream)
01e606cda5192c4254c090624a0b2ca92da6da8eTimo Sirainen struct istream_private *_stream = (struct istream_private *)stream;
d9ab8a13b51c9d8f4e13e1bf785eeadce6702b3bTimo Sirainenvoid i_stream_default_seek(struct istream_private *stream,
12a3540693ab69ec622e04d1b3b66962b8b2a3d9Timo Sirainen i_panic("stream doesn't support seeking backwards");
12a3540693ab69ec622e04d1b3b66962b8b2a3d9Timo Sirainen if (available <= v_offset - stream->istream.v_offset)
7ef5ca6fb59a318c821a852ae48a2edbb671d7ddTimo Sirainenstatic const struct stat *
a94936bafd127680184da114c6a177b37ff656e5Timo Siraineni_stream_default_stat(struct istream_private *stream, bool exact ATTR_UNUSED)
4b9f99761df5014c659cd87fddaf6854af428cfcTimo Siraineni_stream_default_get_size(struct istream_private *stream,
9511a40d933181045343110c8101b75887062aaeTimo Siraineni_stream_create(struct istream_private *_stream, struct istream *parent, int fd)
4334b9b032298defd4d3906f5357698ff016ead0Timo Sirainen _stream->access_counter = parent->real_stream->access_counter;
9511a40d933181045343110c8101b75887062aaeTimo Sirainen _stream->parent_start_offset = parent->v_offset;
4334b9b032298defd4d3906f5357698ff016ead0Timo Sirainen _stream->parent_expected_offset = parent->v_offset;
9511a40d933181045343110c8101b75887062aaeTimo Sirainen _stream->abs_start_offset = parent->v_offset +
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));