if (errno != ENOENT)
e_error(event, "stat(%s) failed: %m", file->cur_path);
/* the file was unlinked between opening and locking it. */
- } else if (st.st_size != rec->offset + rec->size &&
+ } else if (rec->size != 0 &&
+ st.st_size != rec->offset + rec->size &&
/* check if there's any garbage at the end of file.
note that there may be valid messages added by another
session before we locked it (but after we refreshed
break;
}
+ /* Don't append to the index if the record indicates this is the
+ last mail with special size=0. */
+ if (rec->size == 0)
+ continue;
+
/* first lookup: this should be enough usually, but we can't
be sure until after locking. also if messages were recently
moved, this message might not be the last one in the file. */
rec.file_id = mfile->file_id;
rec.offset = appends[i].offset;
- rec.size = appends[i].size;
+ /* A mail that exceeds 4GB is the final mail in the record and
+ thusly is registered with size=0. */
+ rec.size = (appends[i].size > UINT32_MAX) ? 0 : appends[i].size;
mail_index_append(ctx->trans, 0, &seq);
mail_index_update_ext(ctx->trans, seq, ctx->map->map_ext_id,
i_assert(j < appends_count);
rec.file_id = mfile->file_id;
rec.offset = appends[j].offset;
- rec.size = appends[j].size;
+ /* A mail that exceeds 4GB is the final mail in the record and
+ thusly is registered with size=0. */
+ rec.size = (appends[j].size > UINT32_MAX) ? 0 : appends[j].size;
j++;
if (!mail_index_lookup_seq(ctx->atomic->sync_view,
struct mdbox_map_mail_index_record {
uint32_t file_id;
uint32_t offset;
- uint32_t size; /* including pre/post metadata */
+ /* Size is used to find the next mail in the same mdbox file.
+ Special case is size=0, which indicates it's the last mail in the
+ record and can be arbitrarily sized (i.e. larger than 4GB).
+ Includes pre/post metadata. */
+ uint32_t size;
};
struct mdbox_map_file_msg {