return 0;
}
+static void handle_end_of_mail(struct raw_mbox_istream *rstream, size_t pos)
+{
+ rstream->mail_size = rstream->istream.istream.v_offset + pos -
+ rstream->hdr_offset;
+
+ if (rstream->body_offset != (uoff_t)-1 &&
+ rstream->hdr_offset + rstream->mail_size < rstream->body_offset) {
+ /* "headers\n\nFrom ..", the second \n belongs to next
+ message which we didn't know at the time yet. */
+ i_assert(rstream->body_offset ==
+ rstream->hdr_offset + rstream->mail_size + 1);
+ rstream->body_offset =
+ rstream->hdr_offset + rstream->mail_size;
+ }
+}
+
static ssize_t _read(struct _istream *stream)
{
static const char *mbox_from = "\nFrom ";
size_t i, pos, new_pos, from_start_pos;
ssize_t ret = 0;
+ i_assert(stream->istream.v_offset >= rstream->from_offset);
+
if (rstream->eom) {
if (rstream->body_offset == (uoff_t)-1) {
/* missing \n from headers */
do {
ret = i_stream_read(rstream->input);
buf = i_stream_get_data(rstream->input, &pos);
- } while (ret > 0 &&
- stream->istream.v_offset + pos <= rstream->input_peak_offset);
+ } while (ret > 0 && (pos == 1 ||
+ stream->istream.v_offset + pos <=
+ rstream->input_peak_offset));
if (ret < 0) {
if (ret == -2)
rstream->eom = TRUE;
rstream->next_eof = TRUE;
- rstream->mail_size = stream->istream.v_offset + pos -
- rstream->hdr_offset;
+ handle_end_of_mail(rstream, pos);
return ret < 0 ? _read(stream) : ret;
}
/* rewind "\nFrom " */
from_start_pos -= 6;
- rstream->mail_size =
- stream->istream.v_offset +
- from_start_pos -
- rstream->hdr_offset;
+ handle_end_of_mail(rstream,
+ from_start_pos);
break;
}
from_start_pos = 0;
int mbox_sync_rewrite(struct mbox_sync_context *sync_ctx,
uint32_t first_seq, uint32_t last_seq, off_t extra_space);
+int mbox_sync_seek(struct mbox_sync_context *sync_ctx, uoff_t from_offset);
int mbox_move(struct mbox_sync_context *sync_ctx,
uoff_t dest, uoff_t source, uoff_t size);
uint32_t old_prev_msg_uid;
uoff_t offset;
- i_stream_seek(sync_ctx->input, mails[idx].offset);
+ if (mbox_sync_seek(sync_ctx, mails[idx].from_offset) < 0)
+ return -1;
memset(&mail_ctx, 0, sizeof(mail_ctx));
mail_ctx.sync_ctx = sync_ctx;
uint32_t old_prev_msg_uid;
i_assert(start_offset < end_offset);
+
i_stream_seek(sync_ctx->input, mails[idx].offset);
memset(&mail_ctx, 0, sizeof(mail_ctx));
return -1;
}
+ /* just a cleanup - shouldn't be needed anymore */
mails[idx].offset = start_offset;
+ mails[idx].space = 0;
return 0;
}
}
/* now parse it again and give it more space */
- mails[idx].space = extra_per_mail;
mails[idx+1].space = 0; /* from_offset doesn't move.. */
if (mbox_sync_fill_leftover(sync_ctx, mails,
first_seq + idx, idx,
return 1;
}
+int mbox_sync_seek(struct mbox_sync_context *sync_ctx, uoff_t from_offset)
+{
+ if (istream_raw_mbox_seek(sync_ctx->input, from_offset) < 0) {
+ mail_storage_set_critical(sync_ctx->ibox->box.storage,
+ "Unexpectedly lost From-line at offset %"PRIuUOFF_T
+ " from mbox file %s", from_offset,
+ sync_ctx->ibox->path);
+ return -1;
+ }
+ return 0;
+}
+
static int mbox_sync_grow_file(struct mbox_sync_context *sync_ctx,
struct mbox_sync_mail_context *mail_ctx,
uoff_t grow_size)
mail_ctx->mail.body_size =
istream_raw_mbox_get_body_size(sync_ctx->input,
mail_ctx->content_length);
+ i_assert(mail_ctx->mail.body_size < OFF_T_MAX);
/* save the offset permanently with recent flag state */
mail_ctx->mail.from_offset = mail_ctx->from_offset;
if (sync_ctx->need_space_seq != 0) {
if (mbox_sync_handle_missing_space(mail_ctx) < 0)
return -1;
- i_stream_seek(sync_ctx->input, offset);
+ if (mbox_sync_seek(sync_ctx, offset) < 0)
+ return -1;
} else if (sync_ctx->expunged_space > 0) {
if (!expunged) {
/* move the body */
mail_ctx->body_offset,
mail_ctx->mail.body_size) < 0)
return -1;
- i_stream_seek(sync_ctx->input, offset);
+ if (mbox_sync_seek(sync_ctx, offset) < 0)
+ return -1;
}
} else if (sync_ctx->seq >= min_message_count) {
mbox_sync_buffer_delete_old(sync_ctx->syncs, uid+1);
sync_ctx->space_diff -= extra_space;
sync_ctx->space_diff += sync_ctx->expunged_space;
- sync_ctx->expunged_space -= -sync_ctx->space_diff;
+ if (sync_ctx->expunged_space <= -sync_ctx->space_diff)
+ sync_ctx->expunged_space = 0;
+ else
+ sync_ctx->expunged_space -= -sync_ctx->space_diff;
if (mail_ctx->have_eoh && !mail_ctx->updated)
str_append_c(mail_ctx->header, '\n');
{
struct mbox_sync_mail_context mail_ctx;
- if (istream_raw_mbox_seek(sync_ctx->input, 0) < 0) {
- /* doesn't begin with a From-line, which is weird because it
- just did. */
- mail_storage_set_critical(sync_ctx->ibox->box.storage,
- "Unexpectedly lost From-header line from mbox file %s",
- sync_ctx->ibox->path);
+ if (mbox_sync_seek(sync_ctx, 0) < 0)
return -1;
- }
sync_ctx->t = mail_index_transaction_begin(sync_ctx->sync_view, FALSE);
sync_ctx->update_base_uid_last = sync_ctx->next_uid-1;