static void i_stream_mail_set_size_corrupted(struct mail_istream *mstream, size_t size) { uoff_t cur_size = mstream->istream.istream.v_offset + size; const char *str, *mail_id; char chr; if (mstream->expected_size < cur_size) { str = "smaller"; chr = '<'; } else { str = "larger"; chr = '>'; } mail_id = i_stream_mail_get_cached_mail_id(mstream); if (mail_id[0] != '\0') mail_id = t_strconcat(", cached ", mail_id, NULL); io_stream_set_error(&mstream->istream.iostream, "Cached message size %s than expected " "(%"PRIuUOFF_T" %c %"PRIuUOFF_T", box=%s, UID=%u%s)", str, mstream->expected_size, chr, cur_size, mailbox_get_vname(mstream->mail->box), mstream->mail->uid, mail_id); mail_set_cache_corrupted_reason(mstream->mail, MAIL_FETCH_PHYSICAL_SIZE, t_strdup_printf("read(%s) failed: %s", i_stream_get_name(&mstream->istream.istream), mstream->istream.iostream.error)); mstream->istream.istream.stream_errno = EINVAL; }
static int fetch_stream_continue(struct imap_fetch_context *ctx) { struct imap_fetch_state *state = &ctx->state; const char *disconnect_reason; uoff_t orig_input_offset = state->cur_input->v_offset; int ret; o_stream_set_max_buffer_size(ctx->client->output, 0); ret = o_stream_send_istream(ctx->client->output, state->cur_input); o_stream_set_max_buffer_size(ctx->client->output, (size_t)-1); if (ctx->state.cur_stats_sizep != NULL) { *ctx->state.cur_stats_sizep += state->cur_input->v_offset - orig_input_offset; } if (state->cur_input->v_offset != state->cur_size) { /* unfinished */ if (state->cur_input->stream_errno != 0) { fetch_read_error(ctx, &disconnect_reason); client_disconnect(ctx->client, disconnect_reason); return -1; } if (!i_stream_have_bytes_left(state->cur_input)) { /* Input stream gave less data than expected */ mail_set_cache_corrupted_reason(state->cur_mail, state->cur_size_field, t_strdup_printf( "read(%s): FETCH %s got too little data: " "%"PRIuUOFF_T" vs %"PRIuUOFF_T, i_stream_get_name(state->cur_input), state->cur_human_name, state->cur_input->v_offset, state->cur_size)); client_disconnect(ctx->client, "FETCH failed"); return -1; } if (ret < 0) { /* client probably disconnected */ return -1; } o_stream_set_flush_pending(ctx->client->output, TRUE); return 0; } return 1; }