mbox-sync.c revision 709aa305126c32b49657e53d04826087b6838c16
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch/* Copyright (C) 2004 Timo Sirainen */
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch Modifying mbox can be slow, so we try to do it all at once minimizing the
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch required disk I/O. We may need to:
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch - Update message flags in Status, X-Status and X-Keywords headers
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch - Write missing X-UID and X-IMAPbase headers
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch - Write missing or broken Content-Length header if there's space
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch - Expunge specified messages
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch Here's how we do it:
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch - Start reading the mails from the beginning
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch - X-Keywords, X-UID and X-IMAPbase headers may contain padding at the end
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch of them, remember how much each message has and offset to beginning of the
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch - If header needs to be rewritten and there's enough space, do it
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch - If we didn't have enough space, remember how much was missing
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch - Continue reading and counting the padding in each message. If available
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch padding is enough to rewrite all the previous messages needing it, do it
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch - When we encounter expunged message, treat all of it as padding and
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch rewrite previous messages if needed (and there's enough space).
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch Afterwards keep moving messages backwards to fill the expunged space.
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch Moving is done by rewriting each message's headers, with possibly adding
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch missing Content-Length header and padding. Message bodies are moved
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch without modifications.
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch - If we encounter end of file, grow the file and rewrite needed messages
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch - Rewriting is done by moving message body forward, rewriting message's
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch header and doing the same for previous message, until all of them are
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Boschint mbox_sync_seek(struct mbox_sync_context *sync_ctx, uoff_t from_offset)
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch if (istream_raw_mbox_seek(sync_ctx->input, from_offset) < 0) {
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch mail_storage_set_critical(sync_ctx->ibox->box.storage,
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch "Unexpectedly lost From-line at offset %"PRIuUOFF_T
d01c7c7dfbcbb350ac9e23c3434ef85a7de6b7dfStephan Boschstatic void mbox_sync_buffer_delete_old(buffer_t *syncs_buf, uint32_t uid)
0b5bdb5ba6c8cb928b6d2dcc4636148bfa1a7ec7Stephan Bosch sync = buffer_get_modifyable_data(syncs_buf, &size);
79fa0267d03997f5b9d86a38949119f46c11a35fStephan Bosch /* keep it */
for (i = 0; i < size; i++) {
return TRUE;
return FALSE;
int ret;
if (uid == 0) {
sizeof(*sync_rec));
if (ret < 0) {
if (ret == 0) {
if (!*sync_expunge_r)
for (i = 0; i < size; i++) {
int ret = 0;
if (ret < 0) {
return ret;
unsigned char hdr_md5_sum[],
const void *data;
int ret;
if (ret < 0) {
&data) < 0) {
int nocheck)
const void *data;
if (!nocheck) {
&data) < 0) {
INDEX_KEYWORDS_BYTE_COUNT) == 0) {
MAIL_INDEX_MAIL_FLAG_DIRTY) != 0;
INDEX_KEYWORDS_BYTE_COUNT) != 0) {
const unsigned char *data;
if (from_line_size == 0)
int ret;
if (ret < 0)
if (ret > 0) {
move_diff = 0;
if (seq == 0) {
seq++;
if (ret < 0)
if (ret == 0) {
old_offset) < 0) {
uid = 0;
if (seq1 == 0) {
file_size) < 0) {
messages_count : 0);
&expunged) < 0)
if (size == 0)
if (ret <= 0)
return ret;
uid = 0;
if (uid != 0) {
if (ret < 0)
if (ret == 0) {
uid = 0;
&rec) < 0)
&expunged) < 0)
if (!expunged) {
if (!expunged) {
rec) < 0)
if (!expunged) {
if (!partial)
trailer_size = 0;
trailer_size) < 0)
min_msg_count = 0;
if (ret <= 0) {
if (ret < 0)
if (ret <= 0) {
unsigned int lock_id = 0;
if (!changed)
lock_id = 0;
if (changed) {
if (ret <= 0) {
if (ret < 0)
if (lock_id != 0)
return ret;
if (lock_id != 0)
if (lock_id == 0) {
goto __again;
if (ret < 0)
if (ret < 0)
if (ret < 0)
&seq,
&offset) < 0) {
index_sync_ctx) < 0) {
unsigned int read_lock_id = 0;
return ret;
struct mailbox_sync_context *
int ret = 0;