istream.c revision 45312f52ff3a3d4c137447be4c7556500c2f8bf2
45312f52ff3a3d4c137447be4c7556500c2f8bf2Timo Sirainen/* Copyright (c) 2002-2009 Dovecot authors, see the included COPYING file */
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;
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainen struct istream_private *_stream = stream->real_stream;
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainen io_stream_close(&stream->real_stream->iostream);
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);
51e1a1c280ccb461a15827f7987d09cb9708b6e3Timo Sirainenvoid i_stream_set_return_partial_line(struct istream *stream, bool set)
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainen struct istream_private *_stream = stream->real_stream;
c09f9f95db314e7482c95e502e1c56ed6c555797Timo Sirainen /* error handling should be easier if we now just
c09f9f95db314e7482c95e502e1c56ed6c555797Timo Sirainen assume the stream is now at EOF */
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);
e3fc1874694a8ddba9552ec23f9952f74f33d1d5Timo Sirainenstatic bool i_stream_can_optimize_seek(struct istream *stream)
e3fc1874694a8ddba9552ec23f9952f74f33d1d5Timo Sirainen /* use the fast route only if the parent stream is at the
e3fc1874694a8ddba9552ec23f9952f74f33d1d5Timo Sirainen expected offset */
e3fc1874694a8ddba9552ec23f9952f74f33d1d5Timo Sirainen expected_offset = stream->real_stream->parent_start_offset +
e3fc1874694a8ddba9552ec23f9952f74f33d1d5Timo Sirainen if (stream->real_stream->parent->v_offset != expected_offset)
e3fc1874694a8ddba9552ec23f9952f74f33d1d5Timo Sirainen return i_stream_can_optimize_seek(stream->real_stream->parent);
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;
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;
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;
8d80659e504ffb34bb0c6a633184fece35751b18Timo Sirainen i_error("i_stream_next_line() called for unmodifiable stream");
5254d77805cd35b9356d072ba325c356c43b0d51Timo Sirainen /* @UNSAFE */
3e25b17126e9536736d5da03697613e4c3af5f76Timo Sirainen for (i = _stream->skip; i < _stream->pos; i++) {
e0c3d5460d1cc0c440cb7723c8c2eef8d0afe9b9Timo Sirainen ret_buf = i_stream_next_line_finish(_stream, i);
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)
fe363b433b8038a69b55169da9dca27892ad7d18Timo Sirainen stream->buffer_size = nearest_power(stream->buffer_size);
7ef5ca6fb59a318c821a852ae48a2edbb671d7ddTimo Sirainen stream->buffer_size > stream->max_buffer_size)
7ef5ca6fb59a318c821a852ae48a2edbb671d7ddTimo Sirainen stream->buffer_size = stream->max_buffer_size;
fe363b433b8038a69b55169da9dca27892ad7d18Timo Sirainen i_realloc(stream->w_buffer, old_size, stream->buffer_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;
7ef5ca6fb59a318c821a852ae48a2edbb671d7ddTimo Sirainenstatic const struct stat *
a94936bafd127680184da114c6a177b37ff656e5Timo Siraineni_stream_default_stat(struct istream_private *stream, bool exact ATTR_UNUSED)
9511a40d933181045343110c8101b75887062aaeTimo Siraineni_stream_create(struct istream_private *_stream, struct istream *parent, int fd)
9511a40d933181045343110c8101b75887062aaeTimo Sirainen _stream->parent_start_offset = parent->v_offset;
9511a40d933181045343110c8101b75887062aaeTimo Sirainen _stream->abs_start_offset = parent->v_offset +
a94936bafd127680184da114c6a177b37ff656e5Timo Sirainen if (_stream->iostream.set_max_buffer_size == NULL) {
07e4875d250e7a7157cd99132aafc773cf3cdf83Timo Sirainen memset(&_stream->statbuf, 0, sizeof(_stream->statbuf));
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen/* gcc istream.c -o teststream liblib.a -Wall -DHAVE_CONFIG_H -DSTREAM_TEST -g */
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainenstatic void check_buffer(const unsigned char *data, size_t size, size_t offset)
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen for (i = 0; i < size; i++)
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen const unsigned char *data;
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen fd1 = open("teststream.1", O_RDWR | O_CREAT | O_TRUNC, 0600);
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen fd2 = open("teststream.2", O_RDWR | O_CREAT | O_TRUNC, 0600);
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen /* write initial data */
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen for (i = 0; i < sizeof(buf); i++)
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen /* test reading */
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen i_assert(i_stream_get_size(input) == sizeof(buf));
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen i_assert(i_stream_read_data(input, &data, &size, 0) > 0);
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen i_assert(i_stream_read_data(input, &data, &size, 0) > 0);
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen i_assert(i_stream_read_data(input, &data, &size, 512) == -2);
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen i_assert(i_stream_read_data(input, &data, &size, 0) > 0);
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen /* test moving data */
2526d52441ef368215ab6bf04fd0356d3b09d235Timo Sirainen output1 = o_stream_create_fd(fd1, 512, FALSE);
2526d52441ef368215ab6bf04fd0356d3b09d235Timo Sirainen output2 = o_stream_create_fd(fd2, 512, FALSE);
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen i_stream_seek(input, 1); size = sizeof(buf)-1;
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen i_assert(o_stream_send_istream(output2, input) == size);
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen i_assert(read(fd2, buf, sizeof(buf)) == size);
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen i_assert(o_stream_send_istream(output1, input) == sizeof(buf));
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen /* test moving with limits */
fe363b433b8038a69b55169da9dca27892ad7d18Timo Sirainen l_input = i_stream_create_limit(input, sizeof(buf)/2, 512);
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen i_assert(o_stream_send_istream(output1, l_input) == 512);
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen i_stream_set_max_buffer_size(input, sizeof(buf));
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen i_assert(i_stream_read_data(input, &data, &size, sizeof(buf)-1) > 0);
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen /* reading within limits */
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen i_assert(i_stream_read_data(l_input, &data, &size, 511) > 0);
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen i_assert(i_stream_read_data(l_input, &data, &size, 512) == -2);
dd62b77c932d1b518f2a3e4bf80e36542becc256Timo Sirainen i_assert(i_stream_read_data(l_input, &data, &size, 0) > 0);