struct header_filter_istream *mstream =
(struct header_filter_istream *)stream;
ssize_t ret;
- size_t pos;
if (!mstream->header_read ||
stream->istream.v_offset < mstream->header_size.virtual_size) {
stream->istream.v_offset -
mstream->header_size.virtual_size +
mstream->header_size.physical_size);
-
- stream->pos -= stream->skip;
- stream->skip = 0;
-
- stream->buffer = i_stream_get_data(stream->parent, &pos);
- if (pos <= stream->pos) {
- if ((ret = i_stream_read(stream->parent)) == -2) {
- i_assert(stream->skip != stream->pos);
- return -2;
- }
- stream->istream.stream_errno = stream->parent->stream_errno;
- stream->istream.eof = stream->parent->eof;
- stream->buffer = i_stream_get_data(stream->parent, &pos);
- } else {
- ret = 0;
- }
-
- ret = pos > stream->pos ? (ssize_t)(pos - stream->pos) :
- (ret == 0 ? 0 : -1);
- stream->pos = pos;
- return ret;
+ return i_stream_read_copy_from_parent(&stream->istream);
}
static void parse_header(struct header_filter_istream *mstream)
{
struct mail_stats_istream *mstream =
(struct mail_stats_istream *)stream;
- size_t pos;
ssize_t ret;
if (stream->parent->v_offset !=
stream->istream.v_offset);
}
- stream->buffer = i_stream_get_data(stream->parent, &pos);
- if (pos <= stream->pos) {
- if ((ret = i_stream_read(stream->parent)) == -2)
- return -2;
-
- if (ret > 0) {
- mstream->mail->stats_files_read_bytes+= ret;
- if (!mstream->files_read_increased) {
- mstream->files_read_increased = TRUE;
- mstream->mail->stats_files_read_count++;
- }
+ ret = i_stream_read_copy_from_parent(&stream->istream);
+ if (ret > 0) {
+ mstream->mail->stats_files_read_bytes += ret;
+ if (!mstream->files_read_increased) {
+ mstream->files_read_increased = TRUE;
+ mstream->mail->stats_files_read_count++;
}
-
- stream->istream.stream_errno = stream->parent->stream_errno;
- stream->istream.eof = stream->parent->eof;
- stream->buffer = i_stream_get_data(stream->parent, &pos);
- } else {
- ret = 0;
}
-
- stream->pos -= stream->skip;
- stream->skip = 0;
-
- ret = pos > stream->pos ? (ssize_t)(pos - stream->pos) :
- (ret == 0 ? 0 : -1);
- stream->pos = pos;
- i_assert(ret != -1 || stream->istream.eof ||
- stream->istream.stream_errno != 0);
return ret;
}
void i_stream_grow_buffer(struct istream_private *stream, size_t bytes);
bool i_stream_get_buffer_space(struct istream_private *stream,
size_t wanted_size, size_t *size_r);
+ssize_t i_stream_read_copy_from_parent(struct istream *istream);
#endif
stream->istream.v_offset);
}
+ stream->pos -= stream->skip;
+ stream->skip = 0;
+
stream->buffer = i_stream_get_data(stream->parent, &pos);
- if (pos <= stream->pos) {
+ if (pos > stream->pos)
+ ret = 0;
+ else do {
if ((ret = i_stream_read(stream->parent)) == -2)
return -2;
stream->istream.stream_errno = stream->parent->stream_errno;
stream->istream.eof = stream->parent->eof;
stream->buffer = i_stream_get_data(stream->parent, &pos);
- } else {
- ret = 0;
- }
-
- stream->pos -= stream->skip;
- stream->skip = 0;
+ } while (pos <= stream->pos && ret > 0);
if (lstream->v_size != (uoff_t)-1) {
left = lstream->v_size - stream->istream.v_offset;
return ret;
}
+ssize_t i_stream_read_copy_from_parent(struct istream *istream)
+{
+ struct istream_private *stream = istream->real_stream;
+ size_t pos;
+ ssize_t ret;
+
+ stream->pos -= stream->skip;
+ stream->skip = 0;
+
+ stream->buffer = i_stream_get_data(stream->parent, &pos);
+ if (pos > stream->pos)
+ ret = 0;
+ else do {
+ if ((ret = i_stream_read(stream->parent)) == -2)
+ return -2;
+
+ stream->istream.stream_errno = stream->parent->stream_errno;
+ stream->istream.eof = stream->parent->eof;
+ stream->buffer = i_stream_get_data(stream->parent, &pos);
+ /* check again, in case the parent stream had been seeked
+ backwards and the previous read() didn't get us far
+ enough. */
+ } while (pos <= stream->pos && ret > 0);
+
+ ret = pos > stream->pos ? (ssize_t)(pos - stream->pos) :
+ (ret == 0 ? 0 : -1);
+ stream->pos = pos;
+ i_assert(ret != -1 || stream->istream.eof ||
+ stream->istream.stream_errno != 0);
+ return ret;
+}
+
void i_stream_skip(struct istream *stream, uoff_t count)
{
struct istream_private *_stream = stream->real_stream;