static ssize_t i_stream_mail_read(struct istream_private *stream) { struct mail_istream *mstream = (struct mail_istream *)stream; size_t size; ssize_t ret; i_stream_seek(stream->parent, stream->parent_start_offset + stream->istream.v_offset); ret = i_stream_read_copy_from_parent(&stream->istream); size = i_stream_get_data_size(&stream->istream); if (ret > 0) { mstream->mail->transaction->stats.files_read_bytes += ret; if (!mstream->files_read_increased) { mstream->files_read_increased = TRUE; mstream->mail->transaction->stats.files_read_count++; } if (mstream->expected_size < stream->istream.v_offset + size) { i_stream_mail_set_size_corrupted(mstream, size); return -1; } } else if (ret == -1 && stream->istream.eof) { if (!mstream->input_has_body) { /* trying to read past the header, but this stream doesn't have the body */ return -1; } if (stream->istream.stream_errno != 0) { if (stream->istream.stream_errno == ENOENT) { /* update mail's expunged-flag if needed */ index_mail_refresh_expunged(mstream->mail); } return -1; } if (i_stream_mail_try_get_cached_size(mstream) && mstream->expected_size > stream->istream.v_offset + size) { i_stream_mail_set_size_corrupted(mstream, size); return -1; } } return ret; }
struct istream *i_stream_create_mail(struct mail *mail, struct istream *input, bool input_has_body) { struct mail_istream *mstream; mstream = i_new(struct mail_istream, 1); mstream->mail = mail; mstream->input_has_body = input_has_body; mstream->expected_size = (uoff_t)-1; (void)i_stream_mail_try_get_cached_size(mstream); mstream->istream.max_buffer_size = input->real_stream->max_buffer_size; mstream->istream.stream_size_passthrough = TRUE; mstream->istream.read = i_stream_mail_read; mstream->istream.istream.blocking = input->blocking; mstream->istream.istream.seekable = input->seekable; return i_stream_create(&mstream->istream, input, i_stream_get_fd(input)); }