mbox-sync.c revision 8e1f0e57b7e90d9f454ebeac7a283485ced3780c
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen/* Copyright (C) 2004 Timo Sirainen */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen/*
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen Modifying mbox can be slow, so we try to do it all at once minimizing the
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen required disk I/O. We may need to:
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen - Update message flags in Status, X-Status and X-Keywords headers
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen - Write missing X-UID and X-IMAPbase headers
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen - Write missing or broken Content-Length header if there's space
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen - Expunge specified messages
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen Here's how we do it:
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
f16c114c20bbd7d292d93415d1e56c8dd6abd3e7Timo Sirainen - Start reading the mails from the beginning
f16c114c20bbd7d292d93415d1e56c8dd6abd3e7Timo Sirainen - X-Keywords, X-UID and X-IMAPbase headers may contain padding at the end
f16c114c20bbd7d292d93415d1e56c8dd6abd3e7Timo Sirainen of them, remember how much each message has and offset to beginning of the
f16c114c20bbd7d292d93415d1e56c8dd6abd3e7Timo Sirainen padding
f16c114c20bbd7d292d93415d1e56c8dd6abd3e7Timo Sirainen - If header needs to be rewritten and there's enough space, do it
f16c114c20bbd7d292d93415d1e56c8dd6abd3e7Timo Sirainen - If we didn't have enough space, remember how much was missing
f16c114c20bbd7d292d93415d1e56c8dd6abd3e7Timo Sirainen - Continue reading and counting the padding in each message. If available
f16c114c20bbd7d292d93415d1e56c8dd6abd3e7Timo Sirainen padding is enough to rewrite all the previous messages needing it, do it
f16c114c20bbd7d292d93415d1e56c8dd6abd3e7Timo Sirainen - When we encounter expunged message, treat all of it as padding and
f16c114c20bbd7d292d93415d1e56c8dd6abd3e7Timo Sirainen rewrite previous messages if needed (and there's enough space).
f16c114c20bbd7d292d93415d1e56c8dd6abd3e7Timo Sirainen Afterwards keep moving messages backwards to fill the expunged space.
f16c114c20bbd7d292d93415d1e56c8dd6abd3e7Timo Sirainen Moving is done by rewriting each message's headers, with possibly adding
f16c114c20bbd7d292d93415d1e56c8dd6abd3e7Timo Sirainen missing Content-Length header and padding. Message bodies are moved
f16c114c20bbd7d292d93415d1e56c8dd6abd3e7Timo Sirainen without modifications.
f16c114c20bbd7d292d93415d1e56c8dd6abd3e7Timo Sirainen - If we encounter end of file, grow the file and rewrite needed messages
f16c114c20bbd7d292d93415d1e56c8dd6abd3e7Timo Sirainen - Rewriting is done by moving message body forward, rewriting message's
f16c114c20bbd7d292d93415d1e56c8dd6abd3e7Timo Sirainen header and doing the same for previous message, until all of them are
f16c114c20bbd7d292d93415d1e56c8dd6abd3e7Timo Sirainen rewritten.
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen*/
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "lib.h"
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen#include "ioloop.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "buffer.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "istream.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "file-set-size.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "str.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "write-full.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "istream-raw-mbox.h"
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen#include "mbox-storage.h"
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen#include "mbox-file.h"
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen#include "mbox-lock.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "mbox-sync-private.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen#include <stddef.h>
7a6b45405fb1544ac476e6eb1402a70cc1ddcdcfTimo Sirainen#include <stdlib.h>
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen#include <sys/stat.h>
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen#define MBOX_SYNC_SECS 1
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen
02b79f9c2636da1829eee5b92753602bba8b67edTimo Sirainenint mbox_sync_seek(struct mbox_sync_context *sync_ctx, uoff_t from_offset)
02b79f9c2636da1829eee5b92753602bba8b67edTimo Sirainen{
02b79f9c2636da1829eee5b92753602bba8b67edTimo Sirainen if (istream_raw_mbox_seek(sync_ctx->input, from_offset) < 0) {
02b79f9c2636da1829eee5b92753602bba8b67edTimo Sirainen mail_storage_set_critical(sync_ctx->ibox->box.storage,
02b79f9c2636da1829eee5b92753602bba8b67edTimo Sirainen "Unexpectedly lost From-line at offset %"PRIuUOFF_T
02b79f9c2636da1829eee5b92753602bba8b67edTimo Sirainen " from mbox file %s", from_offset,
02b79f9c2636da1829eee5b92753602bba8b67edTimo Sirainen sync_ctx->ibox->path);
02b79f9c2636da1829eee5b92753602bba8b67edTimo Sirainen return -1;
02b79f9c2636da1829eee5b92753602bba8b67edTimo Sirainen }
02b79f9c2636da1829eee5b92753602bba8b67edTimo Sirainen return 0;
02b79f9c2636da1829eee5b92753602bba8b67edTimo Sirainen}
02b79f9c2636da1829eee5b92753602bba8b67edTimo Sirainen
659fe5d24825b160cae512538088020d97a60239Timo Sirainenstatic void mbox_sync_buffer_delete_old(buffer_t *syncs_buf, uint32_t uid)
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen{
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen struct mail_index_sync_rec *sync;
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen size_t size, src, dest;
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen sync = buffer_get_modifyable_data(syncs_buf, &size);
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen size /= sizeof(*sync);
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen for (src = dest = 0; src < size; src++) {
445f9e31c6c3aa6c0a72be8565da8f6e594d24fbTimo Sirainen if (uid <= sync[src].uid2) {
445f9e31c6c3aa6c0a72be8565da8f6e594d24fbTimo Sirainen /* keep it */
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen if (src != dest)
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen sync[dest] = sync[src];
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen dest++;
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen }
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen }
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen buffer_set_used_size(syncs_buf, dest * sizeof(*sync));
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen}
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainenstatic int
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainenmbox_sync_read_next_mail(struct mbox_sync_context *sync_ctx,
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen struct mbox_sync_mail_context *mail_ctx)
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen{
9e59a1f3f095b3099478562cf3f3970a24736970Timo Sirainen /* get EOF */
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen (void)istream_raw_mbox_get_header_offset(sync_ctx->input);
178511b57faa7c3f8203dd8b7e4059d00cbfc23aTimo Sirainen if (istream_raw_mbox_is_eof(sync_ctx->input))
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen return 0;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen memset(mail_ctx, 0, sizeof(*mail_ctx));
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen mail_ctx->sync_ctx = sync_ctx;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen mail_ctx->seq = ++sync_ctx->seq;
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen mail_ctx->header = sync_ctx->header;
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen
4d25408732be27e91f0430f71e87242760c2517cTimo Sirainen mail_ctx->mail.from_offset =
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen istream_raw_mbox_get_start_offset(sync_ctx->input);
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen mail_ctx->mail.offset =
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen istream_raw_mbox_get_header_offset(sync_ctx->input);
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen
9e59a1f3f095b3099478562cf3f3970a24736970Timo Sirainen if (mail_ctx->seq == 1)
9e59a1f3f095b3099478562cf3f3970a24736970Timo Sirainen sync_ctx->seen_first_mail = TRUE;
96c253a039f102fa78a313ee05200ab3970112dcTimo Sirainen
e5c08648676d1989f6e70b95e5990c26b3e8b96bTimo Sirainen mbox_sync_parse_next_mail(sync_ctx->input, mail_ctx);
4d25408732be27e91f0430f71e87242760c2517cTimo Sirainen i_assert(sync_ctx->input->v_offset != mail_ctx->mail.from_offset ||
c3412ddeb9abc13f99d3caf50faf76cd99f7e9d2Timo Sirainen sync_ctx->input->eof);
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen mail_ctx->mail.body_size =
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen istream_raw_mbox_get_body_size(sync_ctx->input,
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen mail_ctx->content_length);
02b79f9c2636da1829eee5b92753602bba8b67edTimo Sirainen i_assert(mail_ctx->mail.body_size < OFF_T_MAX);
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen
b9ac6179d3aee0d1641a4ee1d78da28628929c61Timo Sirainen if ((mail_ctx->mail.flags & MBOX_NONRECENT) == 0 && !mail_ctx->pseudo) {
9a06cabdfdf4d5e2f19a07e506c3c7d08a7e7038Timo Sirainen if (!sync_ctx->ibox->keep_recent) {
9a06cabdfdf4d5e2f19a07e506c3c7d08a7e7038Timo Sirainen /* need to add 'O' flag to Status-header */
9a06cabdfdf4d5e2f19a07e506c3c7d08a7e7038Timo Sirainen mail_ctx->need_rewrite = TRUE;
9a06cabdfdf4d5e2f19a07e506c3c7d08a7e7038Timo Sirainen }
e8a35266a5ceacdfafeeffd6bddae77931ff97ebTimo Sirainen mail_ctx->recent = TRUE;
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen }
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen return 1;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen}
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
b3febb0933fdce10394d25093e23ce0a5aadddd3Timo Sirainenstatic int mbox_sync_buf_have_expunges(buffer_t *syncs_buf)
b3febb0933fdce10394d25093e23ce0a5aadddd3Timo Sirainen{
b3febb0933fdce10394d25093e23ce0a5aadddd3Timo Sirainen const struct mail_index_sync_rec *sync;
b3febb0933fdce10394d25093e23ce0a5aadddd3Timo Sirainen size_t size, i;
b3febb0933fdce10394d25093e23ce0a5aadddd3Timo Sirainen
b3febb0933fdce10394d25093e23ce0a5aadddd3Timo Sirainen sync = buffer_get_data(syncs_buf, &size);
b3febb0933fdce10394d25093e23ce0a5aadddd3Timo Sirainen size /= sizeof(*sync);
b3febb0933fdce10394d25093e23ce0a5aadddd3Timo Sirainen
b3febb0933fdce10394d25093e23ce0a5aadddd3Timo Sirainen for (i = 0; i < size; i++) {
b3febb0933fdce10394d25093e23ce0a5aadddd3Timo Sirainen if (sync[i].type == MAIL_INDEX_SYNC_TYPE_EXPUNGE)
b3febb0933fdce10394d25093e23ce0a5aadddd3Timo Sirainen return TRUE;
b3febb0933fdce10394d25093e23ce0a5aadddd3Timo Sirainen }
b3febb0933fdce10394d25093e23ce0a5aadddd3Timo Sirainen return FALSE;
b3febb0933fdce10394d25093e23ce0a5aadddd3Timo Sirainen}
b3febb0933fdce10394d25093e23ce0a5aadddd3Timo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainenstatic int mbox_sync_read_index_syncs(struct mbox_sync_context *sync_ctx,
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen uint32_t uid, int *sync_expunge_r)
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen{
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen struct mail_index_sync_rec *sync_rec = &sync_ctx->sync_rec;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen int ret;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen *sync_expunge_r = FALSE;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
7a6b45405fb1544ac476e6eb1402a70cc1ddcdcfTimo Sirainen if (sync_ctx->index_sync_ctx == NULL)
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen return 0;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
6843896c40bee4f9b6680ca7ced598c446e9f999Timo Sirainen if (uid == 0) {
6843896c40bee4f9b6680ca7ced598c446e9f999Timo Sirainen /* nothing for this or the future ones */
6843896c40bee4f9b6680ca7ced598c446e9f999Timo Sirainen uid = (uint32_t)-1;
6843896c40bee4f9b6680ca7ced598c446e9f999Timo Sirainen }
6843896c40bee4f9b6680ca7ced598c446e9f999Timo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen mbox_sync_buffer_delete_old(sync_ctx->syncs, uid);
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen while (uid >= sync_rec->uid1) {
755fe6da51ab7f54aa1d86913cb344bffef60e79Timo Sirainen if (uid <= sync_rec->uid2 &&
7a6b45405fb1544ac476e6eb1402a70cc1ddcdcfTimo Sirainen sync_rec->type != MAIL_INDEX_SYNC_TYPE_APPEND &&
7a6b45405fb1544ac476e6eb1402a70cc1ddcdcfTimo Sirainen (sync_rec->type != MAIL_INDEX_SYNC_TYPE_EXPUNGE ||
7a6b45405fb1544ac476e6eb1402a70cc1ddcdcfTimo Sirainen !sync_ctx->ibox->mbox_readonly)) {
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen buffer_append(sync_ctx->syncs, sync_rec,
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen sizeof(*sync_rec));
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen if (sync_rec->type == MAIL_INDEX_SYNC_TYPE_EXPUNGE)
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen *sync_expunge_r = TRUE;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen }
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen ret = mail_index_sync_next(sync_ctx->index_sync_ctx, sync_rec);
36e2fa21c22452470c1509cc63de20f7415c7b5eTimo Sirainen if (ret < 0) {
36e2fa21c22452470c1509cc63de20f7415c7b5eTimo Sirainen mail_storage_set_index_error(sync_ctx->ibox);
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen return -1;
36e2fa21c22452470c1509cc63de20f7415c7b5eTimo Sirainen }
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen if (ret == 0) {
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen memset(sync_rec, 0, sizeof(*sync_rec));
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen break;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen }
345212e8f61ebf14ff4f80df26df9e655eb5121eTimo Sirainen
345212e8f61ebf14ff4f80df26df9e655eb5121eTimo Sirainen if (sync_rec->type == MAIL_INDEX_SYNC_TYPE_APPEND) {
345212e8f61ebf14ff4f80df26df9e655eb5121eTimo Sirainen if (sync_rec->uid2 >= sync_ctx->next_uid) {
345212e8f61ebf14ff4f80df26df9e655eb5121eTimo Sirainen sync_ctx->next_uid = sync_rec->uid2 + 1;
345212e8f61ebf14ff4f80df26df9e655eb5121eTimo Sirainen sync_ctx->update_base_uid_last = sync_rec->uid2;
345212e8f61ebf14ff4f80df26df9e655eb5121eTimo Sirainen }
345212e8f61ebf14ff4f80df26df9e655eb5121eTimo Sirainen memset(sync_rec, 0, sizeof(*sync_rec));
345212e8f61ebf14ff4f80df26df9e655eb5121eTimo Sirainen }
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen }
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
b3febb0933fdce10394d25093e23ce0a5aadddd3Timo Sirainen if (!*sync_expunge_r)
b3febb0933fdce10394d25093e23ce0a5aadddd3Timo Sirainen *sync_expunge_r = mbox_sync_buf_have_expunges(sync_ctx->syncs);
b3febb0933fdce10394d25093e23ce0a5aadddd3Timo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen return 0;
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen}
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainenstatic void mbox_sync_apply_index_syncs(buffer_t *syncs_buf, uint8_t *flags)
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen{
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen const struct mail_index_sync_rec *sync;
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen size_t size, i;
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen sync = buffer_get_data(syncs_buf, &size);
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen size /= sizeof(*sync);
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen
db7c9201c88e3d9bee10485194ee5b0c67249916Timo Sirainen for (i = 0; i < size; i++) {
db7c9201c88e3d9bee10485194ee5b0c67249916Timo Sirainen if (sync[i].type != MAIL_INDEX_SYNC_TYPE_FLAGS)
db7c9201c88e3d9bee10485194ee5b0c67249916Timo Sirainen continue;
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen mail_index_sync_flags_apply(&sync[i], flags);
db7c9201c88e3d9bee10485194ee5b0c67249916Timo Sirainen }
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen}
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainenstatic int
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainenmbox_sync_read_index_rec(struct mbox_sync_context *sync_ctx,
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen uint32_t uid, const struct mail_index_record **rec_r)
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen{
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen const struct mail_index_record *rec = NULL;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen uint32_t messages_count;
6843896c40bee4f9b6680ca7ced598c446e9f999Timo Sirainen int ret = 0;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
df4018ae2f0a95be602f724ca70df7e0e3bd6a7dTimo Sirainen messages_count =
df4018ae2f0a95be602f724ca70df7e0e3bd6a7dTimo Sirainen mail_index_view_get_messages_count(sync_ctx->sync_view);
a393d9d6dabdc46cf724f8cb004a652b4036d53dTimo Sirainen while (sync_ctx->idx_seq <= messages_count) {
6843896c40bee4f9b6680ca7ced598c446e9f999Timo Sirainen ret = mail_index_lookup(sync_ctx->sync_view,
a393d9d6dabdc46cf724f8cb004a652b4036d53dTimo Sirainen sync_ctx->idx_seq, &rec);
6843896c40bee4f9b6680ca7ced598c446e9f999Timo Sirainen if (ret < 0) {
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen mail_storage_set_index_error(sync_ctx->ibox);
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen return -1;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen }
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen if (uid <= rec->uid)
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen break;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen /* externally expunged message, remove from index */
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen mail_index_expunge(sync_ctx->t, sync_ctx->idx_seq);
a393d9d6dabdc46cf724f8cb004a652b4036d53dTimo Sirainen sync_ctx->idx_seq++;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen rec = NULL;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen }
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
9a06cabdfdf4d5e2f19a07e506c3c7d08a7e7038Timo Sirainen if (ret == 0 && uid < sync_ctx->hdr->next_uid) {
9a06cabdfdf4d5e2f19a07e506c3c7d08a7e7038Timo Sirainen /* this UID was already in index and it was expunged */
9a06cabdfdf4d5e2f19a07e506c3c7d08a7e7038Timo Sirainen mail_storage_set_critical(sync_ctx->ibox->box.storage,
9a06cabdfdf4d5e2f19a07e506c3c7d08a7e7038Timo Sirainen "mbox sync: Expunged message reappeared in mailbox %s "
9a06cabdfdf4d5e2f19a07e506c3c7d08a7e7038Timo Sirainen "(UID %u < %u)", sync_ctx->ibox->path, uid,
9a06cabdfdf4d5e2f19a07e506c3c7d08a7e7038Timo Sirainen sync_ctx->hdr->next_uid);
2ae575a66f2a302f047f6de062a70b75f8bebc7bTimo Sirainen ret = 0; rec = NULL;
9a06cabdfdf4d5e2f19a07e506c3c7d08a7e7038Timo Sirainen } else if (rec != NULL && rec->uid != uid) {
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen /* new UID in the middle of the mailbox - shouldn't happen */
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen mail_storage_set_critical(sync_ctx->ibox->box.storage,
7f773564b94e6054a40d3785cb63c29f1e4d4deeTimo Sirainen "mbox sync: UID inserted in the middle of mailbox %s "
7f773564b94e6054a40d3785cb63c29f1e4d4deeTimo Sirainen "(%u > %u)", sync_ctx->ibox->path, rec->uid, uid);
484efa22e65c509f787dbbc892351146c726c257Timo Sirainen ret = 0; rec = NULL;
9a06cabdfdf4d5e2f19a07e506c3c7d08a7e7038Timo Sirainen } else {
9a06cabdfdf4d5e2f19a07e506c3c7d08a7e7038Timo Sirainen ret = 1;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen }
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen *rec_r = rec;
6843896c40bee4f9b6680ca7ced598c446e9f999Timo Sirainen return ret;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen}
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
7f3be7d885c75cdd77f536929a45bc9764595960Timo Sirainenstatic int mbox_sync_find_index_md5(struct mbox_sync_context *sync_ctx,
7f3be7d885c75cdd77f536929a45bc9764595960Timo Sirainen unsigned char hdr_md5_sum[],
7f3be7d885c75cdd77f536929a45bc9764595960Timo Sirainen const struct mail_index_record **rec_r)
7f3be7d885c75cdd77f536929a45bc9764595960Timo Sirainen{
7f3be7d885c75cdd77f536929a45bc9764595960Timo Sirainen const struct mail_index_record *rec = NULL;
7f3be7d885c75cdd77f536929a45bc9764595960Timo Sirainen uint32_t messages_count;
7f3be7d885c75cdd77f536929a45bc9764595960Timo Sirainen const void *data;
7f3be7d885c75cdd77f536929a45bc9764595960Timo Sirainen int ret;
7f3be7d885c75cdd77f536929a45bc9764595960Timo Sirainen
df4018ae2f0a95be602f724ca70df7e0e3bd6a7dTimo Sirainen messages_count =
df4018ae2f0a95be602f724ca70df7e0e3bd6a7dTimo Sirainen mail_index_view_get_messages_count(sync_ctx->sync_view);
7f3be7d885c75cdd77f536929a45bc9764595960Timo Sirainen while (sync_ctx->idx_seq <= messages_count) {
7f3be7d885c75cdd77f536929a45bc9764595960Timo Sirainen ret = mail_index_lookup(sync_ctx->sync_view,
7f3be7d885c75cdd77f536929a45bc9764595960Timo Sirainen sync_ctx->idx_seq, &rec);
7f3be7d885c75cdd77f536929a45bc9764595960Timo Sirainen if (ret < 0) {
7f3be7d885c75cdd77f536929a45bc9764595960Timo Sirainen mail_storage_set_index_error(sync_ctx->ibox);
7f3be7d885c75cdd77f536929a45bc9764595960Timo Sirainen return -1;
7f3be7d885c75cdd77f536929a45bc9764595960Timo Sirainen }
7f3be7d885c75cdd77f536929a45bc9764595960Timo Sirainen
7797aa2479e99aeb71057b7a2584b2cb72e4d3f8Timo Sirainen if (mail_index_lookup_ext(sync_ctx->sync_view,
7797aa2479e99aeb71057b7a2584b2cb72e4d3f8Timo Sirainen sync_ctx->idx_seq,
7797aa2479e99aeb71057b7a2584b2cb72e4d3f8Timo Sirainen sync_ctx->ibox->md5hdr_ext_idx,
7797aa2479e99aeb71057b7a2584b2cb72e4d3f8Timo Sirainen &data) < 0) {
7f3be7d885c75cdd77f536929a45bc9764595960Timo Sirainen mail_storage_set_index_error(sync_ctx->ibox);
7f3be7d885c75cdd77f536929a45bc9764595960Timo Sirainen return -1;
7f3be7d885c75cdd77f536929a45bc9764595960Timo Sirainen }
7f3be7d885c75cdd77f536929a45bc9764595960Timo Sirainen
f0f9c8e94abac18f8acd91b9e724c4c32863723aTimo Sirainen if (data != NULL && memcmp(data, hdr_md5_sum, 16) == 0)
7f3be7d885c75cdd77f536929a45bc9764595960Timo Sirainen break;
7f3be7d885c75cdd77f536929a45bc9764595960Timo Sirainen
7f3be7d885c75cdd77f536929a45bc9764595960Timo Sirainen /* externally expunged message, remove from index */
7f3be7d885c75cdd77f536929a45bc9764595960Timo Sirainen mail_index_expunge(sync_ctx->t, sync_ctx->idx_seq);
7f3be7d885c75cdd77f536929a45bc9764595960Timo Sirainen sync_ctx->idx_seq++;
7f3be7d885c75cdd77f536929a45bc9764595960Timo Sirainen rec = NULL;
7f3be7d885c75cdd77f536929a45bc9764595960Timo Sirainen }
7f3be7d885c75cdd77f536929a45bc9764595960Timo Sirainen
7f3be7d885c75cdd77f536929a45bc9764595960Timo Sirainen *rec_r = rec;
7f3be7d885c75cdd77f536929a45bc9764595960Timo Sirainen return 0;
7f3be7d885c75cdd77f536929a45bc9764595960Timo Sirainen}
7f3be7d885c75cdd77f536929a45bc9764595960Timo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainenstatic int
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainenmbox_sync_update_from_offset(struct mbox_sync_context *sync_ctx,
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen struct mbox_sync_mail *mail,
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen int nocheck)
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen{
4d25408732be27e91f0430f71e87242760c2517cTimo Sirainen const void *data;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen uint64_t offset;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen if (!nocheck) {
4d25408732be27e91f0430f71e87242760c2517cTimo Sirainen /* see if from_offset needs updating */
7797aa2479e99aeb71057b7a2584b2cb72e4d3f8Timo Sirainen if (mail_index_lookup_ext(sync_ctx->sync_view,
7797aa2479e99aeb71057b7a2584b2cb72e4d3f8Timo Sirainen sync_ctx->idx_seq,
7797aa2479e99aeb71057b7a2584b2cb72e4d3f8Timo Sirainen sync_ctx->ibox->mbox_ext_idx,
7797aa2479e99aeb71057b7a2584b2cb72e4d3f8Timo Sirainen &data) < 0) {
4d25408732be27e91f0430f71e87242760c2517cTimo Sirainen mail_storage_set_index_error(sync_ctx->ibox);
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen return -1;
4d25408732be27e91f0430f71e87242760c2517cTimo Sirainen }
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
4d25408732be27e91f0430f71e87242760c2517cTimo Sirainen if (data != NULL &&
4d25408732be27e91f0430f71e87242760c2517cTimo Sirainen *((const uint64_t *)data) == mail->from_offset)
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen return 0;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen }
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
8af07808ba203f8709e2ff9eaf2291e1c4a4d53dTimo Sirainen offset = mail->from_offset;
7797aa2479e99aeb71057b7a2584b2cb72e4d3f8Timo Sirainen mail_index_update_ext(sync_ctx->t, sync_ctx->idx_seq,
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen sync_ctx->ibox->mbox_ext_idx, &offset, NULL);
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen return 0;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen}
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainenstatic int mbox_sync_update_index(struct mbox_sync_context *sync_ctx,
33d63688ed8b26dc333e3c2edbfb2fe6e412604dTimo Sirainen struct mbox_sync_mail_context *mail_ctx,
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen const struct mail_index_record *rec)
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen{
33d63688ed8b26dc333e3c2edbfb2fe6e412604dTimo Sirainen struct mbox_sync_mail *mail = &mail_ctx->mail;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen uint8_t idx_flags, mbox_flags;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen if (rec == NULL) {
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen /* new message */
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen mail_index_append(sync_ctx->t, mail->uid, &sync_ctx->idx_seq);
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen mbox_flags = mail->flags & (MAIL_FLAGS_MASK^MAIL_RECENT);
7a6b45405fb1544ac476e6eb1402a70cc1ddcdcfTimo Sirainen if (mail_ctx->dirty)
7a6b45405fb1544ac476e6eb1402a70cc1ddcdcfTimo Sirainen mbox_flags |= MAIL_INDEX_MAIL_FLAG_DIRTY;
b9ac6179d3aee0d1641a4ee1d78da28628929c61Timo Sirainen if (sync_ctx->ibox->keep_recent &&
b9ac6179d3aee0d1641a4ee1d78da28628929c61Timo Sirainen (mail->flags & MBOX_NONRECENT) == 0)
b9ac6179d3aee0d1641a4ee1d78da28628929c61Timo Sirainen mbox_flags |= MAIL_RECENT;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen mail_index_update_flags(sync_ctx->t, sync_ctx->idx_seq,
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen MODIFY_REPLACE, mbox_flags);
7f3be7d885c75cdd77f536929a45bc9764595960Timo Sirainen
6e71799ee07bfd2289beae77c9bb5d7f1d30dccaTimo Sirainen if (sync_ctx->ibox->mbox_save_md5 != 0) {
7797aa2479e99aeb71057b7a2584b2cb72e4d3f8Timo Sirainen mail_index_update_ext(sync_ctx->t, sync_ctx->idx_seq,
7797aa2479e99aeb71057b7a2584b2cb72e4d3f8Timo Sirainen sync_ctx->ibox->md5hdr_ext_idx,
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen mail_ctx->hdr_md5_sum, NULL);
7f3be7d885c75cdd77f536929a45bc9764595960Timo Sirainen }
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen } else {
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen /* see if flags changed */
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen idx_flags = rec->flags;
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen mbox_sync_apply_index_syncs(sync_ctx->syncs, &idx_flags);
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
7a6b45405fb1544ac476e6eb1402a70cc1ddcdcfTimo Sirainen if ((idx_flags & MAIL_INDEX_MAIL_FLAG_DIRTY) != 0) {
77af8c68c416179e717fc2d551f72ec50b499c13Timo Sirainen /* flags are dirty, ignore whatever was in the file.
77af8c68c416179e717fc2d551f72ec50b499c13Timo Sirainen but remove recent flag if needed. */
7a6b45405fb1544ac476e6eb1402a70cc1ddcdcfTimo Sirainen mbox_flags = idx_flags;
77af8c68c416179e717fc2d551f72ec50b499c13Timo Sirainen if (!sync_ctx->ibox->keep_recent)
77af8c68c416179e717fc2d551f72ec50b499c13Timo Sirainen mbox_flags &= ~MAIL_RECENT;
7a6b45405fb1544ac476e6eb1402a70cc1ddcdcfTimo Sirainen } else {
7a6b45405fb1544ac476e6eb1402a70cc1ddcdcfTimo Sirainen mbox_flags = (rec->flags & ~MAIL_FLAGS_MASK) |
7a6b45405fb1544ac476e6eb1402a70cc1ddcdcfTimo Sirainen (mail->flags & MAIL_FLAGS_MASK);
7a6b45405fb1544ac476e6eb1402a70cc1ddcdcfTimo Sirainen mbox_flags ^= MAIL_RECENT;
7a6b45405fb1544ac476e6eb1402a70cc1ddcdcfTimo Sirainen }
7a6b45405fb1544ac476e6eb1402a70cc1ddcdcfTimo Sirainen
7a6b45405fb1544ac476e6eb1402a70cc1ddcdcfTimo Sirainen if (mail_ctx->dirty)
7a6b45405fb1544ac476e6eb1402a70cc1ddcdcfTimo Sirainen mbox_flags |= MAIL_INDEX_MAIL_FLAG_DIRTY;
e5ee67f18b03015c88b579c8c1f17ebe6ce19b76Timo Sirainen else if (!sync_ctx->delay_writes)
7a6b45405fb1544ac476e6eb1402a70cc1ddcdcfTimo Sirainen mbox_flags &= ~MAIL_INDEX_MAIL_FLAG_DIRTY;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
7a6b45405fb1544ac476e6eb1402a70cc1ddcdcfTimo Sirainen if ((idx_flags & ~MAIL_INDEX_MAIL_FLAG_DIRTY) ==
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen (mbox_flags & ~MAIL_INDEX_MAIL_FLAG_DIRTY)) {
7a6b45405fb1544ac476e6eb1402a70cc1ddcdcfTimo Sirainen if (idx_flags != mbox_flags) {
7a6b45405fb1544ac476e6eb1402a70cc1ddcdcfTimo Sirainen /* dirty flag state changed */
7a6b45405fb1544ac476e6eb1402a70cc1ddcdcfTimo Sirainen int dirty = (mbox_flags &
7a6b45405fb1544ac476e6eb1402a70cc1ddcdcfTimo Sirainen MAIL_INDEX_MAIL_FLAG_DIRTY) != 0;
7a6b45405fb1544ac476e6eb1402a70cc1ddcdcfTimo Sirainen mail_index_update_flags(sync_ctx->t,
7a6b45405fb1544ac476e6eb1402a70cc1ddcdcfTimo Sirainen sync_ctx->idx_seq,
7a6b45405fb1544ac476e6eb1402a70cc1ddcdcfTimo Sirainen dirty ? MODIFY_ADD : MODIFY_REMOVE,
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen MAIL_INDEX_MAIL_FLAG_DIRTY);
7a6b45405fb1544ac476e6eb1402a70cc1ddcdcfTimo Sirainen }
7a6b45405fb1544ac476e6eb1402a70cc1ddcdcfTimo Sirainen } else if ((idx_flags & ~MAIL_RECENT) !=
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen (mbox_flags & ~MAIL_RECENT)) {
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen mail_index_update_flags(sync_ctx->t, sync_ctx->idx_seq,
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen MODIFY_REPLACE, mbox_flags);
88553367d677170a4b703b9d52aac9eabf91c656Timo Sirainen } else if (((idx_flags ^ mbox_flags) & MAIL_RECENT) != 0) {
88553367d677170a4b703b9d52aac9eabf91c656Timo Sirainen /* drop recent flag */
88553367d677170a4b703b9d52aac9eabf91c656Timo Sirainen mail_index_update_flags(sync_ctx->t, sync_ctx->idx_seq,
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen MODIFY_REMOVE, MAIL_RECENT);
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen }
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen // FIXME: keywords
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen }
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
3023fb352cbc2052b156f6d325c2629531a1b5b4Timo Sirainen if (mail_ctx->recent &&
3023fb352cbc2052b156f6d325c2629531a1b5b4Timo Sirainen (rec == NULL || (rec->flags & MAIL_INDEX_MAIL_FLAG_DIRTY) == 0 ||
3023fb352cbc2052b156f6d325c2629531a1b5b4Timo Sirainen (rec->flags & MAIL_RECENT) != 0))
e8a35266a5ceacdfafeeffd6bddae77931ff97ebTimo Sirainen index_mailbox_set_recent(sync_ctx->ibox, sync_ctx->idx_seq);
e8a35266a5ceacdfafeeffd6bddae77931ff97ebTimo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen /* update from_offsets, but not if we're going to rewrite this message.
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen rewriting would just move it anyway. */
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen if (sync_ctx->need_space_seq == 0) {
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen int nocheck = rec == NULL || sync_ctx->expunged_space > 0;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen if (mbox_sync_update_from_offset(sync_ctx, mail, nocheck) < 0)
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen return -1;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen }
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen return 0;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen}
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainenstatic int mbox_read_from_line(struct mbox_sync_mail_context *ctx)
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen{
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen struct istream *input = ctx->sync_ctx->file_input;
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen const unsigned char *data;
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen size_t size, from_line_size;
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen buffer_set_used_size(ctx->sync_ctx->from_line, 0);
4d25408732be27e91f0430f71e87242760c2517cTimo Sirainen from_line_size = ctx->hdr_offset - ctx->mail.from_offset;
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen
4d25408732be27e91f0430f71e87242760c2517cTimo Sirainen i_stream_seek(input, ctx->mail.from_offset);
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen for (;;) {
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen data = i_stream_get_data(input, &size);
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen if (size >= from_line_size)
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen size = from_line_size;
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen buffer_append(ctx->sync_ctx->from_line, data, size);
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen i_stream_skip(input, size);
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen from_line_size -= size;
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen if (from_line_size == 0)
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen break;
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen if (i_stream_read(input) < 0)
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen return -1;
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen }
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen return 0;
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen}
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainenstatic int
064bfeee2f9156683b191cc0f3f7b242720942f7Timo Sirainenmbox_write_from_line(struct mbox_sync_mail_context *ctx)
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen{
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen string_t *str = ctx->sync_ctx->from_line;
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen if (pwrite_full(ctx->sync_ctx->fd, str_data(str), str_len(str),
064bfeee2f9156683b191cc0f3f7b242720942f7Timo Sirainen ctx->mail.from_offset) < 0) {
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen mbox_set_syscall_error(ctx->sync_ctx->ibox, "pwrite_full()");
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen return -1;
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen }
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen istream_raw_mbox_flush(ctx->sync_ctx->input);
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen return 0;
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen}
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen
8907d617ce7c4f390c0f42f6f694db2fecdd5775Timo Sirainenstatic void update_from_offsets(struct mbox_sync_context *sync_ctx)
01cbf4ac5d44137ab434791be7f838d98d0fcf3bTimo Sirainen{
01cbf4ac5d44137ab434791be7f838d98d0fcf3bTimo Sirainen const struct mbox_sync_mail *mails;
7797aa2479e99aeb71057b7a2584b2cb72e4d3f8Timo Sirainen uint32_t idx, ext_idx;
ab3c1eab9ca13916358a9e8b12df8212fefb7dbfTimo Sirainen uint64_t offset;
99be58a447b69d62cbd9e764000a06226b9c9c89Timo Sirainen size_t size;
01cbf4ac5d44137ab434791be7f838d98d0fcf3bTimo Sirainen
7797aa2479e99aeb71057b7a2584b2cb72e4d3f8Timo Sirainen ext_idx = sync_ctx->ibox->mbox_ext_idx;
3021a062b16ff0138408be6107d6bcd0ced280b9Timo Sirainen
e5c08648676d1989f6e70b95e5990c26b3e8b96bTimo Sirainen mails = buffer_get_modifyable_data(sync_ctx->mails, &size);
e5c08648676d1989f6e70b95e5990c26b3e8b96bTimo Sirainen size /= sizeof(*mails);
01cbf4ac5d44137ab434791be7f838d98d0fcf3bTimo Sirainen
3021a062b16ff0138408be6107d6bcd0ced280b9Timo Sirainen for (idx = 0; idx < size; idx++) {
7a6b45405fb1544ac476e6eb1402a70cc1ddcdcfTimo Sirainen if (mails[idx].idx_seq == 0 ||
7a6b45405fb1544ac476e6eb1402a70cc1ddcdcfTimo Sirainen (mails[idx].flags & MBOX_EXPUNGED) != 0)
e5c08648676d1989f6e70b95e5990c26b3e8b96bTimo Sirainen continue;
e5c08648676d1989f6e70b95e5990c26b3e8b96bTimo Sirainen
ff640b54224881abbc21141f217c881d6ba5cd28Timo Sirainen offset = mails[idx].from_offset;
7797aa2479e99aeb71057b7a2584b2cb72e4d3f8Timo Sirainen mail_index_update_ext(sync_ctx->t, mails[idx].idx_seq,
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen ext_idx, &offset, NULL);
01cbf4ac5d44137ab434791be7f838d98d0fcf3bTimo Sirainen }
01cbf4ac5d44137ab434791be7f838d98d0fcf3bTimo Sirainen}
01cbf4ac5d44137ab434791be7f838d98d0fcf3bTimo Sirainen
8907d617ce7c4f390c0f42f6f694db2fecdd5775Timo Sirainenstatic void mbox_sync_handle_expunge(struct mbox_sync_mail_context *mail_ctx)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
7a6b45405fb1544ac476e6eb1402a70cc1ddcdcfTimo Sirainen mail_ctx->mail.flags = MBOX_EXPUNGED;
4d25408732be27e91f0430f71e87242760c2517cTimo Sirainen mail_ctx->mail.offset = mail_ctx->mail.from_offset;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen mail_ctx->mail.space =
4d25408732be27e91f0430f71e87242760c2517cTimo Sirainen mail_ctx->body_offset - mail_ctx->mail.from_offset +
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen mail_ctx->mail.body_size;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen mail_ctx->mail.body_size = 0;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
1276e0340fe29495b6694dc7508f070cf6fca1cfTimo Sirainen if (mail_ctx->sync_ctx->seq == 1) {
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen /* expunging first message, fix space to contain next
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen message's \n header too since it will be removed. */
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen mail_ctx->mail.space++;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen }
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen mail_ctx->sync_ctx->expunged_space += mail_ctx->mail.space;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen}
b2ecd50bb98c44816cb07c17aa17fae2b425f941Timo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainenstatic int mbox_sync_handle_header(struct mbox_sync_mail_context *mail_ctx)
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen{
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen struct mbox_sync_context *sync_ctx = mail_ctx->sync_ctx;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen off_t move_diff;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen int ret;
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen if (sync_ctx->expunged_space > 0 && sync_ctx->need_space_seq == 0) {
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen /* move the header backwards to fill expunged space */
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen move_diff = -sync_ctx->expunged_space;
b2ecd50bb98c44816cb07c17aa17fae2b425f941Timo Sirainen
7fd72a47d7ddfbd38c8697e228b6951f495dfb61Timo Sirainen if (sync_ctx->dest_first_mail) {
7fd72a47d7ddfbd38c8697e228b6951f495dfb61Timo Sirainen /* we're moving this mail to beginning of file.
7fd72a47d7ddfbd38c8697e228b6951f495dfb61Timo Sirainen skip the initial \n (it's already counted in
7fd72a47d7ddfbd38c8697e228b6951f495dfb61Timo Sirainen expunged_space) */
7fd72a47d7ddfbd38c8697e228b6951f495dfb61Timo Sirainen mail_ctx->mail.from_offset++;
7fd72a47d7ddfbd38c8697e228b6951f495dfb61Timo Sirainen }
7fd72a47d7ddfbd38c8697e228b6951f495dfb61Timo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen /* read the From-line before rewriting overwrites it */
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen if (mbox_read_from_line(mail_ctx) < 0)
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen return -1;
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen mbox_sync_update_header(mail_ctx, sync_ctx->syncs);
6a1e4eb2c6a267bec1e8704ce9137bebb7792702Timo Sirainen ret = mbox_sync_try_rewrite(mail_ctx, move_diff);
60d3fa9883237e896a8704275b6116fa46f7ffdaTimo Sirainen if (ret < 0)
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen return -1;
659fe5d24825b160cae512538088020d97a60239Timo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen if (ret > 0) {
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen /* rewrite successful, write From-line to
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen new location */
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen mail_ctx->mail.from_offset += move_diff;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen mail_ctx->mail.offset += move_diff;
064bfeee2f9156683b191cc0f3f7b242720942f7Timo Sirainen if (mbox_write_from_line(mail_ctx) < 0)
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen return -1;
7fd72a47d7ddfbd38c8697e228b6951f495dfb61Timo Sirainen } else {
7fd72a47d7ddfbd38c8697e228b6951f495dfb61Timo Sirainen if (sync_ctx->dest_first_mail) {
7fd72a47d7ddfbd38c8697e228b6951f495dfb61Timo Sirainen /* didn't have enough space, move the offset
7fd72a47d7ddfbd38c8697e228b6951f495dfb61Timo Sirainen back so seeking into it doesn't fail */
7fd72a47d7ddfbd38c8697e228b6951f495dfb61Timo Sirainen mail_ctx->mail.from_offset--;
7fd72a47d7ddfbd38c8697e228b6951f495dfb61Timo Sirainen }
b2ecd50bb98c44816cb07c17aa17fae2b425f941Timo Sirainen }
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen } else if (mail_ctx->need_rewrite ||
345212e8f61ebf14ff4f80df26df9e655eb5121eTimo Sirainen buffer_get_used_size(sync_ctx->syncs) != 0 ||
345212e8f61ebf14ff4f80df26df9e655eb5121eTimo Sirainen (mail_ctx->seq == 1 &&
345212e8f61ebf14ff4f80df26df9e655eb5121eTimo Sirainen sync_ctx->update_base_uid_last != 0)) {
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen mbox_sync_update_header(mail_ctx, sync_ctx->syncs);
7a6b45405fb1544ac476e6eb1402a70cc1ddcdcfTimo Sirainen if (sync_ctx->delay_writes) {
7a6b45405fb1544ac476e6eb1402a70cc1ddcdcfTimo Sirainen /* mark it dirty and do it later */
7a6b45405fb1544ac476e6eb1402a70cc1ddcdcfTimo Sirainen mail_ctx->dirty = TRUE;
7a6b45405fb1544ac476e6eb1402a70cc1ddcdcfTimo Sirainen return 0;
7a6b45405fb1544ac476e6eb1402a70cc1ddcdcfTimo Sirainen }
7a6b45405fb1544ac476e6eb1402a70cc1ddcdcfTimo Sirainen
6a1e4eb2c6a267bec1e8704ce9137bebb7792702Timo Sirainen if ((ret = mbox_sync_try_rewrite(mail_ctx, 0)) < 0)
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen return -1;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen } else {
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen /* nothing to do */
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen return 0;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen }
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen if (ret == 0 && sync_ctx->need_space_seq == 0) {
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen /* first mail with no space to write it */
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen sync_ctx->need_space_seq = sync_ctx->seq;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen sync_ctx->space_diff = 0;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen if (sync_ctx->expunged_space > 0) {
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen /* create dummy message to describe the expunged data */
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen struct mbox_sync_mail mail;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen memset(&mail, 0, sizeof(mail));
907723f35f4d3dfc774ca42d00a8a7b8ef90dd5dTimo Sirainen mail.flags = MBOX_EXPUNGED;
36816b5af1472ae76a1909ae3cf29fd614b2ebfcTimo Sirainen mail.offset = mail.from_offset =
829c036d4ddfbd9ea49bd8a7c54e3057177d346eTimo Sirainen (sync_ctx->dest_first_mail ? 1 : 0) +
36816b5af1472ae76a1909ae3cf29fd614b2ebfcTimo Sirainen mail_ctx->mail.from_offset -
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen sync_ctx->expunged_space;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen mail.space = sync_ctx->expunged_space;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
dc8552739fa29f011ab71ec383ec6d580a5a9661Timo Sirainen sync_ctx->space_diff = sync_ctx->expunged_space;
dc8552739fa29f011ab71ec383ec6d580a5a9661Timo Sirainen sync_ctx->expunged_space = 0;
8d5991f5c4a8840bf1ea754093dbec505564ab78Timo Sirainen i_assert(sync_ctx->space_diff < -mail_ctx->mail.space);
dc8552739fa29f011ab71ec383ec6d580a5a9661Timo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen sync_ctx->need_space_seq--;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen buffer_append(sync_ctx->mails, &mail, sizeof(mail));
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen }
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen }
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen return 0;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen}
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainenstatic int
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainenmbox_sync_handle_missing_space(struct mbox_sync_mail_context *mail_ctx)
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen{
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen struct mbox_sync_context *sync_ctx = mail_ctx->sync_ctx;
4214b59ac7f3899f8d887d055ef519f5a622d249Timo Sirainen uoff_t end_offset, move_diff, extra_space, needed_space;
7a6b45405fb1544ac476e6eb1402a70cc1ddcdcfTimo Sirainen uint32_t last_seq;
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen
2cb565cd978aafd5714792b5161889986d49e431Timo Sirainen i_assert(mail_ctx->mail.uid == 0 || mail_ctx->mail.space > 0 ||
2cb565cd978aafd5714792b5161889986d49e431Timo Sirainen mail_ctx->mail.offset == mail_ctx->hdr_offset);
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen buffer_append(sync_ctx->mails, &mail_ctx->mail, sizeof(mail_ctx->mail));
b2ecd50bb98c44816cb07c17aa17fae2b425f941Timo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen sync_ctx->space_diff += mail_ctx->mail.space;
dc8552739fa29f011ab71ec383ec6d580a5a9661Timo Sirainen if (sync_ctx->space_diff < 0) {
dc8552739fa29f011ab71ec383ec6d580a5a9661Timo Sirainen if (sync_ctx->expunged_space > 0) {
dc8552739fa29f011ab71ec383ec6d580a5a9661Timo Sirainen i_assert(sync_ctx->expunged_space ==
dc8552739fa29f011ab71ec383ec6d580a5a9661Timo Sirainen mail_ctx->mail.space);
dc8552739fa29f011ab71ec383ec6d580a5a9661Timo Sirainen sync_ctx->expunged_space = 0;
dc8552739fa29f011ab71ec383ec6d580a5a9661Timo Sirainen }
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen return 0;
dc8552739fa29f011ab71ec383ec6d580a5a9661Timo Sirainen }
b2ecd50bb98c44816cb07c17aa17fae2b425f941Timo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen /* we have enough space now */
6a1e4eb2c6a267bec1e8704ce9137bebb7792702Timo Sirainen if (mail_ctx->mail.uid == 0) {
4214b59ac7f3899f8d887d055ef519f5a622d249Timo Sirainen /* this message was expunged. fill more or less of the space.
4214b59ac7f3899f8d887d055ef519f5a622d249Timo Sirainen space_diff now consists of a negative "bytes needed" sum,
4214b59ac7f3899f8d887d055ef519f5a622d249Timo Sirainen plus the expunged space of this message. so it contains how
4214b59ac7f3899f8d887d055ef519f5a622d249Timo Sirainen many bytes of _extra_ space we have. */
8d5991f5c4a8840bf1ea754093dbec505564ab78Timo Sirainen i_assert(mail_ctx->mail.space >= sync_ctx->space_diff);
6a1e4eb2c6a267bec1e8704ce9137bebb7792702Timo Sirainen extra_space = MBOX_HEADER_PADDING *
6a1e4eb2c6a267bec1e8704ce9137bebb7792702Timo Sirainen (sync_ctx->seq - sync_ctx->need_space_seq + 1);
4214b59ac7f3899f8d887d055ef519f5a622d249Timo Sirainen needed_space = mail_ctx->mail.space - sync_ctx->space_diff;
4214b59ac7f3899f8d887d055ef519f5a622d249Timo Sirainen if ((uoff_t)sync_ctx->space_diff > needed_space + extra_space) {
6a1e4eb2c6a267bec1e8704ce9137bebb7792702Timo Sirainen /* don't waste too much on padding */
930dcf1576f99057ad572420d9c75f3212e46a2eTimo Sirainen move_diff = needed_space + extra_space;
930dcf1576f99057ad572420d9c75f3212e46a2eTimo Sirainen sync_ctx->expunged_space =
930dcf1576f99057ad572420d9c75f3212e46a2eTimo Sirainen mail_ctx->mail.space - move_diff;
6a1e4eb2c6a267bec1e8704ce9137bebb7792702Timo Sirainen } else {
930dcf1576f99057ad572420d9c75f3212e46a2eTimo Sirainen move_diff = mail_ctx->mail.space;
c9a03c8a03a782488981f81bd7c6b5e01ff55f06Timo Sirainen extra_space = sync_ctx->space_diff;
829c036d4ddfbd9ea49bd8a7c54e3057177d346eTimo Sirainen sync_ctx->expunged_space = 0;
6a1e4eb2c6a267bec1e8704ce9137bebb7792702Timo Sirainen }
7a6b45405fb1544ac476e6eb1402a70cc1ddcdcfTimo Sirainen last_seq = sync_ctx->seq - 1;
7a6b45405fb1544ac476e6eb1402a70cc1ddcdcfTimo Sirainen buffer_set_used_size(sync_ctx->mails, sync_ctx->mails->used -
7a6b45405fb1544ac476e6eb1402a70cc1ddcdcfTimo Sirainen sizeof(mail_ctx->mail));
6a1e4eb2c6a267bec1e8704ce9137bebb7792702Timo Sirainen end_offset = mail_ctx->mail.from_offset;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen } else {
6a1e4eb2c6a267bec1e8704ce9137bebb7792702Timo Sirainen /* this message gave enough space from headers. rewriting stops
6a1e4eb2c6a267bec1e8704ce9137bebb7792702Timo Sirainen at the end of this message's headers. */
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen sync_ctx->expunged_space = 0;
7a6b45405fb1544ac476e6eb1402a70cc1ddcdcfTimo Sirainen last_seq = sync_ctx->seq;
6a1e4eb2c6a267bec1e8704ce9137bebb7792702Timo Sirainen end_offset = mail_ctx->body_offset;
6a1e4eb2c6a267bec1e8704ce9137bebb7792702Timo Sirainen
6a1e4eb2c6a267bec1e8704ce9137bebb7792702Timo Sirainen move_diff = 0;
6a1e4eb2c6a267bec1e8704ce9137bebb7792702Timo Sirainen extra_space = sync_ctx->space_diff;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen }
b2ecd50bb98c44816cb07c17aa17fae2b425f941Timo Sirainen
6a1e4eb2c6a267bec1e8704ce9137bebb7792702Timo Sirainen if (mbox_sync_rewrite(sync_ctx, end_offset, move_diff, extra_space,
7a6b45405fb1544ac476e6eb1402a70cc1ddcdcfTimo Sirainen sync_ctx->need_space_seq, last_seq) < 0)
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen return -1;
b2ecd50bb98c44816cb07c17aa17fae2b425f941Timo Sirainen
8907d617ce7c4f390c0f42f6f694db2fecdd5775Timo Sirainen update_from_offsets(sync_ctx);
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen /* mail_ctx may contain wrong data after rewrite, so make sure we
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen don't try to access it */
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen memset(mail_ctx, 0, sizeof(*mail_ctx));
01cbf4ac5d44137ab434791be7f838d98d0fcf3bTimo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen sync_ctx->need_space_seq = 0;
6a1e4eb2c6a267bec1e8704ce9137bebb7792702Timo Sirainen sync_ctx->space_diff = 0;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen buffer_set_used_size(sync_ctx->mails, 0);
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen return 0;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen}
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainenstatic int
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainenmbox_sync_seek_to_seq(struct mbox_sync_context *sync_ctx, uint32_t seq)
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen{
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen struct index_mailbox *ibox = sync_ctx->ibox;
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen uoff_t old_offset;
319944c0f35b311c998854e96d6463a084fd90aeTimo Sirainen uint32_t uid;
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen int ret, deleted;
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen if (seq == 0) {
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen if (istream_raw_mbox_seek(ibox->mbox_stream, 0) < 0) {
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen mail_storage_set_error(ibox->box.storage,
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen "Mailbox isn't a valid mbox file");
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen return -1;
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen }
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen seq++;
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen } else {
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen old_offset = istream_raw_mbox_get_start_offset(sync_ctx->input);
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen ret = mbox_file_seek(ibox, sync_ctx->sync_view, seq, &deleted);
6a87059fc7d4e919aa55d0b208ff20708e13e2d7Timo Sirainen if (ret < 0)
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen return -1;
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen if (ret == 0) {
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen if (istream_raw_mbox_seek(ibox->mbox_stream,
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen old_offset) < 0) {
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen mail_storage_set_critical(ibox->box.storage,
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen "Error seeking back to original "
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen "offset %s in mbox file %s",
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen dec2str(old_offset), ibox->path);
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen return -1;
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen }
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen return 0;
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen }
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen }
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen
319944c0f35b311c998854e96d6463a084fd90aeTimo Sirainen if (seq <= 1)
319944c0f35b311c998854e96d6463a084fd90aeTimo Sirainen uid = 0;
319944c0f35b311c998854e96d6463a084fd90aeTimo Sirainen else if (mail_index_lookup_uid(sync_ctx->sync_view, seq-1, &uid) < 0) {
319944c0f35b311c998854e96d6463a084fd90aeTimo Sirainen mail_storage_set_index_error(ibox);
319944c0f35b311c998854e96d6463a084fd90aeTimo Sirainen return -1;
319944c0f35b311c998854e96d6463a084fd90aeTimo Sirainen }
319944c0f35b311c998854e96d6463a084fd90aeTimo Sirainen
319944c0f35b311c998854e96d6463a084fd90aeTimo Sirainen sync_ctx->prev_msg_uid = uid;
319944c0f35b311c998854e96d6463a084fd90aeTimo Sirainen
a393d9d6dabdc46cf724f8cb004a652b4036d53dTimo Sirainen /* set to -1, since it's always increased later */
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen sync_ctx->seq = seq-1;
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen if (sync_ctx->seq == 0 &&
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen istream_raw_mbox_get_start_offset(sync_ctx->input) != 0) {
cece2b9cd692c06025cc0a7a0ff54d996a8c90efTimo Sirainen /* this mbox has pseudo mail which contains the X-IMAP header */
cece2b9cd692c06025cc0a7a0ff54d996a8c90efTimo Sirainen sync_ctx->seq++;
cece2b9cd692c06025cc0a7a0ff54d996a8c90efTimo Sirainen }
cece2b9cd692c06025cc0a7a0ff54d996a8c90efTimo Sirainen
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen sync_ctx->idx_seq = seq;
f0569d9fbb25c8437760be69f194595a841ad711Timo Sirainen sync_ctx->dest_first_mail = sync_ctx->seq == 0;
db7c9201c88e3d9bee10485194ee5b0c67249916Timo Sirainen (void)istream_raw_mbox_get_body_offset(sync_ctx->input);
755fe6da51ab7f54aa1d86913cb344bffef60e79Timo Sirainen return 1;
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen}
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainenstatic int
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainenmbox_sync_seek_to_uid(struct mbox_sync_context *sync_ctx, uint32_t uid)
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen{
a10e5606a9e93f49cf13b3a35c8dc3f5d6ab5909Timo Sirainen struct mail_index_view *sync_view = sync_ctx->sync_view;
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen uint32_t seq1, seq2;
0a6f8311541ae59381171620b77f82be58be562eTimo Sirainen uoff_t file_size;
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen
a10e5606a9e93f49cf13b3a35c8dc3f5d6ab5909Timo Sirainen if (mail_index_lookup_uid_range(sync_view, uid, (uint32_t)-1,
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen &seq1, &seq2) < 0) {
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen mail_storage_set_index_error(sync_ctx->ibox);
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen return -1;
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen }
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen
0a6f8311541ae59381171620b77f82be58be562eTimo Sirainen if (seq1 == 0) {
0a6f8311541ae59381171620b77f82be58be562eTimo Sirainen /* doesn't exist anymore, seek to end of file */
0a6f8311541ae59381171620b77f82be58be562eTimo Sirainen file_size = i_stream_get_size(sync_ctx->ibox->mbox_file_stream);
0a6f8311541ae59381171620b77f82be58be562eTimo Sirainen if (istream_raw_mbox_seek(sync_ctx->ibox->mbox_stream,
0a6f8311541ae59381171620b77f82be58be562eTimo Sirainen file_size) < 0) {
0a6f8311541ae59381171620b77f82be58be562eTimo Sirainen mail_storage_set_critical(sync_ctx->ibox->box.storage,
0a6f8311541ae59381171620b77f82be58be562eTimo Sirainen "Error seeking to end of mbox file %s",
0a6f8311541ae59381171620b77f82be58be562eTimo Sirainen sync_ctx->ibox->path);
0a6f8311541ae59381171620b77f82be58be562eTimo Sirainen return -1;
0a6f8311541ae59381171620b77f82be58be562eTimo Sirainen }
a10e5606a9e93f49cf13b3a35c8dc3f5d6ab5909Timo Sirainen sync_ctx->idx_seq =
df4018ae2f0a95be602f724ca70df7e0e3bd6a7dTimo Sirainen mail_index_view_get_messages_count(sync_view) + 1;
0a6f8311541ae59381171620b77f82be58be562eTimo Sirainen return 1;
0a6f8311541ae59381171620b77f82be58be562eTimo Sirainen }
0a6f8311541ae59381171620b77f82be58be562eTimo Sirainen
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen return mbox_sync_seek_to_seq(sync_ctx, seq1);
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen}
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainenstatic int mbox_sync_loop(struct mbox_sync_context *sync_ctx,
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen struct mbox_sync_mail_context *mail_ctx,
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen uint32_t min_message_count, int partial)
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen{
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen const struct mail_index_record *rec;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen uint32_t uid, messages_count;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen uoff_t offset;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen int ret, expunged;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
df4018ae2f0a95be602f724ca70df7e0e3bd6a7dTimo Sirainen messages_count =
df4018ae2f0a95be602f724ca70df7e0e3bd6a7dTimo Sirainen mail_index_view_get_messages_count(sync_ctx->sync_view);
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen
470475238f0472ae2b7a4cca59786ab76eed083cTimo Sirainen if (!mail_index_sync_have_more(sync_ctx->index_sync_ctx) ||
974ed9e53724507b99fe02e715e4b6153d2be92bTimo Sirainen (!partial && min_message_count != 0)) {
3343a61404603b21c246783a7963b77833095f31Timo Sirainen ret = mbox_sync_seek_to_seq(sync_ctx, partial ?
3343a61404603b21c246783a7963b77833095f31Timo Sirainen messages_count : 0);
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen } else {
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen /* we sync only what we need to. jump to first record that
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen needs updating */
f1b7a02a05fbca580934c7312aae63ea9542aa79Timo Sirainen const struct mail_index_sync_rec *sync_rec;
f0569d9fbb25c8437760be69f194595a841ad711Timo Sirainen size_t size;
f1b7a02a05fbca580934c7312aae63ea9542aa79Timo Sirainen
f0569d9fbb25c8437760be69f194595a841ad711Timo Sirainen if (buffer_get_used_size(sync_ctx->syncs) == 0 &&
f0569d9fbb25c8437760be69f194595a841ad711Timo Sirainen sync_ctx->sync_rec.uid1 == 0) {
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen if (mbox_sync_read_index_syncs(sync_ctx, 1,
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen &expunged) < 0)
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen return -1;
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen
f0569d9fbb25c8437760be69f194595a841ad711Timo Sirainen if (buffer_get_used_size(sync_ctx->syncs) == 0 &&
f0569d9fbb25c8437760be69f194595a841ad711Timo Sirainen sync_ctx->sync_rec.uid1 == 0) {
f1b7a02a05fbca580934c7312aae63ea9542aa79Timo Sirainen /* nothing to do */
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen return 1;
f1b7a02a05fbca580934c7312aae63ea9542aa79Timo Sirainen }
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen }
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen
f0569d9fbb25c8437760be69f194595a841ad711Timo Sirainen sync_rec = buffer_get_data(sync_ctx->syncs, &size);
f0569d9fbb25c8437760be69f194595a841ad711Timo Sirainen if (size == 0)
f0569d9fbb25c8437760be69f194595a841ad711Timo Sirainen sync_rec = &sync_ctx->sync_rec;
755fe6da51ab7f54aa1d86913cb344bffef60e79Timo Sirainen
755fe6da51ab7f54aa1d86913cb344bffef60e79Timo Sirainen ret = mbox_sync_seek_to_uid(sync_ctx, sync_rec->uid1);
755fe6da51ab7f54aa1d86913cb344bffef60e79Timo Sirainen }
755fe6da51ab7f54aa1d86913cb344bffef60e79Timo Sirainen
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen if (ret <= 0)
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen return ret;
71a74e26cf070a205d31cf6c6fae003f90027b63Timo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen while ((ret = mbox_sync_read_next_mail(sync_ctx, mail_ctx)) > 0) {
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen uid = mail_ctx->mail.uid;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
319944c0f35b311c998854e96d6463a084fd90aeTimo Sirainen if (mail_ctx->seq == 1 && sync_ctx->base_uid_validity != 0 &&
319944c0f35b311c998854e96d6463a084fd90aeTimo Sirainen sync_ctx->hdr->uid_validity != 0 &&
319944c0f35b311c998854e96d6463a084fd90aeTimo Sirainen sync_ctx->base_uid_validity !=
319944c0f35b311c998854e96d6463a084fd90aeTimo Sirainen sync_ctx->hdr->uid_validity) {
319944c0f35b311c998854e96d6463a084fd90aeTimo Sirainen mail_storage_set_critical(sync_ctx->ibox->box.storage,
319944c0f35b311c998854e96d6463a084fd90aeTimo Sirainen "UIDVALIDITY changed (%u -> %u) "
319944c0f35b311c998854e96d6463a084fd90aeTimo Sirainen "in mbox file %s",
319944c0f35b311c998854e96d6463a084fd90aeTimo Sirainen sync_ctx->hdr->uid_validity,
319944c0f35b311c998854e96d6463a084fd90aeTimo Sirainen sync_ctx->base_uid_validity,
319944c0f35b311c998854e96d6463a084fd90aeTimo Sirainen sync_ctx->ibox->path);
319944c0f35b311c998854e96d6463a084fd90aeTimo Sirainen mail_index_mark_corrupted(sync_ctx->ibox->index);
319944c0f35b311c998854e96d6463a084fd90aeTimo Sirainen return -1;
319944c0f35b311c998854e96d6463a084fd90aeTimo Sirainen }
319944c0f35b311c998854e96d6463a084fd90aeTimo Sirainen
319944c0f35b311c998854e96d6463a084fd90aeTimo Sirainen if (mail_ctx->uid_broken && partial) {
319944c0f35b311c998854e96d6463a084fd90aeTimo Sirainen /* UID ordering problems, resync everything to make
319944c0f35b311c998854e96d6463a084fd90aeTimo Sirainen sure we get everything right */
319944c0f35b311c998854e96d6463a084fd90aeTimo Sirainen return 0;
319944c0f35b311c998854e96d6463a084fd90aeTimo Sirainen }
319944c0f35b311c998854e96d6463a084fd90aeTimo Sirainen
907723f35f4d3dfc774ca42d00a8a7b8ef90dd5dTimo Sirainen if (mail_ctx->pseudo)
907723f35f4d3dfc774ca42d00a8a7b8ef90dd5dTimo Sirainen uid = 0;
907723f35f4d3dfc774ca42d00a8a7b8ef90dd5dTimo Sirainen
2ae575a66f2a302f047f6de062a70b75f8bebc7bTimo Sirainen rec = NULL; ret = 1;
7a6b45405fb1544ac476e6eb1402a70cc1ddcdcfTimo Sirainen if (uid != 0) {
6843896c40bee4f9b6680ca7ced598c446e9f999Timo Sirainen ret = mbox_sync_read_index_rec(sync_ctx, uid, &rec);
6843896c40bee4f9b6680ca7ced598c446e9f999Timo Sirainen if (ret < 0)
6843896c40bee4f9b6680ca7ced598c446e9f999Timo Sirainen return -1;
6843896c40bee4f9b6680ca7ced598c446e9f999Timo Sirainen }
7f3be7d885c75cdd77f536929a45bc9764595960Timo Sirainen
2ae575a66f2a302f047f6de062a70b75f8bebc7bTimo Sirainen if (ret == 0) {
2ae575a66f2a302f047f6de062a70b75f8bebc7bTimo Sirainen /* UID found but it's broken */
2ae575a66f2a302f047f6de062a70b75f8bebc7bTimo Sirainen uid = 0;
2ae575a66f2a302f047f6de062a70b75f8bebc7bTimo Sirainen } else if (uid == 0 && !mail_ctx->pseudo &&
2ae575a66f2a302f047f6de062a70b75f8bebc7bTimo Sirainen (sync_ctx->delay_writes ||
2ae575a66f2a302f047f6de062a70b75f8bebc7bTimo Sirainen sync_ctx->idx_seq <= messages_count)) {
7a6b45405fb1544ac476e6eb1402a70cc1ddcdcfTimo Sirainen /* If we can't use/store X-UID header, use MD5 sum.
7a6b45405fb1544ac476e6eb1402a70cc1ddcdcfTimo Sirainen Also check for existing MD5 sums when we're actually
7a6b45405fb1544ac476e6eb1402a70cc1ddcdcfTimo Sirainen able to write X-UIDs. */
6e71799ee07bfd2289beae77c9bb5d7f1d30dccaTimo Sirainen sync_ctx->ibox->mbox_save_md5 = TRUE;
7f3be7d885c75cdd77f536929a45bc9764595960Timo Sirainen
7f3be7d885c75cdd77f536929a45bc9764595960Timo Sirainen if (mbox_sync_find_index_md5(sync_ctx,
7f3be7d885c75cdd77f536929a45bc9764595960Timo Sirainen mail_ctx->hdr_md5_sum,
7f3be7d885c75cdd77f536929a45bc9764595960Timo Sirainen &rec) < 0)
7f3be7d885c75cdd77f536929a45bc9764595960Timo Sirainen return -1;
7f3be7d885c75cdd77f536929a45bc9764595960Timo Sirainen
7f3be7d885c75cdd77f536929a45bc9764595960Timo Sirainen if (rec != NULL)
7a6b45405fb1544ac476e6eb1402a70cc1ddcdcfTimo Sirainen uid = mail_ctx->mail.uid = rec->uid;
7a6b45405fb1544ac476e6eb1402a70cc1ddcdcfTimo Sirainen }
7a6b45405fb1544ac476e6eb1402a70cc1ddcdcfTimo Sirainen
7a6b45405fb1544ac476e6eb1402a70cc1ddcdcfTimo Sirainen if (!mail_ctx->pseudo) {
7a6b45405fb1544ac476e6eb1402a70cc1ddcdcfTimo Sirainen /* get all sync records related to this message */
7a6b45405fb1544ac476e6eb1402a70cc1ddcdcfTimo Sirainen if (mbox_sync_read_index_syncs(sync_ctx, uid,
7a6b45405fb1544ac476e6eb1402a70cc1ddcdcfTimo Sirainen &expunged) < 0)
7a6b45405fb1544ac476e6eb1402a70cc1ddcdcfTimo Sirainen return -1;
7a6b45405fb1544ac476e6eb1402a70cc1ddcdcfTimo Sirainen } else {
7a6b45405fb1544ac476e6eb1402a70cc1ddcdcfTimo Sirainen expunged = FALSE;
7f3be7d885c75cdd77f536929a45bc9764595960Timo Sirainen }
7f3be7d885c75cdd77f536929a45bc9764595960Timo Sirainen
907723f35f4d3dfc774ca42d00a8a7b8ef90dd5dTimo Sirainen if (uid == 0 && !mail_ctx->pseudo) {
71a74e26cf070a205d31cf6c6fae003f90027b63Timo Sirainen /* missing/broken X-UID. all the rest of the mails
71a74e26cf070a205d31cf6c6fae003f90027b63Timo Sirainen need new UIDs. */
a393d9d6dabdc46cf724f8cb004a652b4036d53dTimo Sirainen while (sync_ctx->idx_seq <= messages_count) {
71a74e26cf070a205d31cf6c6fae003f90027b63Timo Sirainen mail_index_expunge(sync_ctx->t,
71a74e26cf070a205d31cf6c6fae003f90027b63Timo Sirainen sync_ctx->idx_seq++);
71a74e26cf070a205d31cf6c6fae003f90027b63Timo Sirainen }
6843896c40bee4f9b6680ca7ced598c446e9f999Timo Sirainen mail_ctx->need_rewrite = TRUE;
6843896c40bee4f9b6680ca7ced598c446e9f999Timo Sirainen mail_ctx->mail.uid = sync_ctx->next_uid++;
6843896c40bee4f9b6680ca7ced598c446e9f999Timo Sirainen sync_ctx->prev_msg_uid = mail_ctx->mail.uid;
6843896c40bee4f9b6680ca7ced598c446e9f999Timo Sirainen }
6843896c40bee4f9b6680ca7ced598c446e9f999Timo Sirainen
d0e5f8252516c4d4df2fbcdae4d37f9e5f931199Timo Sirainen mail_ctx->mail.idx_seq = sync_ctx->idx_seq;
d0e5f8252516c4d4df2fbcdae4d37f9e5f931199Timo Sirainen
f0569d9fbb25c8437760be69f194595a841ad711Timo Sirainen if (!expunged) {
8907d617ce7c4f390c0f42f6f694db2fecdd5775Timo Sirainen if (mbox_sync_handle_header(mail_ctx) < 0)
8907d617ce7c4f390c0f42f6f694db2fecdd5775Timo Sirainen return -1;
f0569d9fbb25c8437760be69f194595a841ad711Timo Sirainen sync_ctx->dest_first_mail = FALSE;
f0569d9fbb25c8437760be69f194595a841ad711Timo Sirainen } else {
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen mail_ctx->mail.uid = 0;
8907d617ce7c4f390c0f42f6f694db2fecdd5775Timo Sirainen mbox_sync_handle_expunge(mail_ctx);
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen }
b2ecd50bb98c44816cb07c17aa17fae2b425f941Timo Sirainen
907723f35f4d3dfc774ca42d00a8a7b8ef90dd5dTimo Sirainen if (!mail_ctx->pseudo) {
907723f35f4d3dfc774ca42d00a8a7b8ef90dd5dTimo Sirainen if (!expunged) {
907723f35f4d3dfc774ca42d00a8a7b8ef90dd5dTimo Sirainen if (mbox_sync_update_index(sync_ctx, mail_ctx,
907723f35f4d3dfc774ca42d00a8a7b8ef90dd5dTimo Sirainen rec) < 0)
907723f35f4d3dfc774ca42d00a8a7b8ef90dd5dTimo Sirainen return -1;
907723f35f4d3dfc774ca42d00a8a7b8ef90dd5dTimo Sirainen }
907723f35f4d3dfc774ca42d00a8a7b8ef90dd5dTimo Sirainen sync_ctx->idx_seq++;
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen }
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen istream_raw_mbox_next(sync_ctx->input,
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen mail_ctx->mail.body_size);
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen offset = istream_raw_mbox_get_start_offset(sync_ctx->input);
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen if (sync_ctx->need_space_seq != 0) {
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen if (mbox_sync_handle_missing_space(mail_ctx) < 0)
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen return -1;
02b79f9c2636da1829eee5b92753602bba8b67edTimo Sirainen if (mbox_sync_seek(sync_ctx, offset) < 0)
02b79f9c2636da1829eee5b92753602bba8b67edTimo Sirainen return -1;
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen } else if (sync_ctx->expunged_space > 0) {
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen if (!expunged) {
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen /* move the body */
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen if (mbox_move(sync_ctx,
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen mail_ctx->body_offset -
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen sync_ctx->expunged_space,
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen mail_ctx->body_offset,
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen mail_ctx->mail.body_size) < 0)
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen return -1;
02b79f9c2636da1829eee5b92753602bba8b67edTimo Sirainen if (mbox_sync_seek(sync_ctx, offset) < 0)
02b79f9c2636da1829eee5b92753602bba8b67edTimo Sirainen return -1;
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen }
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen } else if (sync_ctx->seq >= min_message_count) {
b0349bc8041abfca33feba16a5fd72ef2238289dTimo Sirainen /* +1 because we want to delete sync records
b0349bc8041abfca33feba16a5fd72ef2238289dTimo Sirainen from the current UID as well */
b0349bc8041abfca33feba16a5fd72ef2238289dTimo Sirainen mbox_sync_buffer_delete_old(sync_ctx->syncs, uid+1);
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen if (buffer_get_used_size(sync_ctx->syncs) == 0) {
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen /* if there's no sync records left,
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen we can stop */
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen if (sync_ctx->sync_rec.uid1 == 0)
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen break;
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen /* we can skip forward to next record which
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen needs updating. if it failes because the
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen offset is dirty, just ignore and continue
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen from where we are now. */
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen uid = sync_ctx->sync_rec.uid1;
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen if (mbox_sync_seek_to_uid(sync_ctx, uid) < 0)
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen return -1;
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
178511b57faa7c3f8203dd8b7e4059d00cbfc23aTimo Sirainen if (istream_raw_mbox_is_eof(sync_ctx->input)) {
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen /* rest of the messages in index don't exist -> expunge them */
a393d9d6dabdc46cf724f8cb004a652b4036d53dTimo Sirainen while (sync_ctx->idx_seq <= messages_count)
a393d9d6dabdc46cf724f8cb004a652b4036d53dTimo Sirainen mail_index_expunge(sync_ctx->t, sync_ctx->idx_seq++);
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen }
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen if (!partial)
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen sync_ctx->ibox->mbox_sync_dirty = FALSE;
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen return 1;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen}
3cfff0ca01961d885bdbd6ef08d761880116af07Timo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainenstatic int mbox_sync_handle_eof_updates(struct mbox_sync_context *sync_ctx,
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen struct mbox_sync_mail_context *mail_ctx)
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen{
f5b919e9b07dfd9d2401b998ef8759e5f0312719Timo Sirainen uoff_t file_size, offset, padding, trailer_size;
33ae95df45c9b5ec51332a6b39eb5322038686b9Timo Sirainen
178511b57faa7c3f8203dd8b7e4059d00cbfc23aTimo Sirainen if (!istream_raw_mbox_is_eof(sync_ctx->input)) {
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen i_assert(sync_ctx->need_space_seq == 0);
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen i_assert(sync_ctx->expunged_space == 0);
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen return 0;
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen }
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen
5edfc0f1c3c55e906d8316d9cdeaa3b0c7000c19Timo Sirainen file_size = i_stream_get_size(sync_ctx->file_input);
5edfc0f1c3c55e906d8316d9cdeaa3b0c7000c19Timo Sirainen i_assert(file_size >= sync_ctx->file_input->v_offset);
5edfc0f1c3c55e906d8316d9cdeaa3b0c7000c19Timo Sirainen trailer_size = file_size - sync_ctx->file_input->v_offset;
8e1f0e57b7e90d9f454ebeac7a283485ced3780cTimo Sirainen i_assert(trailer_size <= 1);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen if (sync_ctx->need_space_seq != 0) {
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen i_assert(sync_ctx->space_diff < 0);
f16c114c20bbd7d292d93415d1e56c8dd6abd3e7Timo Sirainen padding = MBOX_HEADER_PADDING *
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen (sync_ctx->seq - sync_ctx->need_space_seq + 1);
f16c114c20bbd7d292d93415d1e56c8dd6abd3e7Timo Sirainen sync_ctx->space_diff -= padding;
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen
f5b919e9b07dfd9d2401b998ef8759e5f0312719Timo Sirainen i_assert(sync_ctx->expunged_space <= -sync_ctx->space_diff);
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen sync_ctx->space_diff += sync_ctx->expunged_space;
f5b919e9b07dfd9d2401b998ef8759e5f0312719Timo Sirainen sync_ctx->expunged_space = 0;
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen if (mail_ctx->have_eoh && !mail_ctx->updated)
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen str_append_c(mail_ctx->header, '\n');
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen
6a1e4eb2c6a267bec1e8704ce9137bebb7792702Timo Sirainen i_assert(sync_ctx->space_diff < 0);
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen
6a1e4eb2c6a267bec1e8704ce9137bebb7792702Timo Sirainen if (file_set_size(sync_ctx->fd,
f5b919e9b07dfd9d2401b998ef8759e5f0312719Timo Sirainen file_size + -sync_ctx->space_diff) < 0) {
6a1e4eb2c6a267bec1e8704ce9137bebb7792702Timo Sirainen mbox_set_syscall_error(sync_ctx->ibox,
6a1e4eb2c6a267bec1e8704ce9137bebb7792702Timo Sirainen "file_set_size()");
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen return -1;
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen }
6a1e4eb2c6a267bec1e8704ce9137bebb7792702Timo Sirainen istream_raw_mbox_flush(sync_ctx->input);
6a1e4eb2c6a267bec1e8704ce9137bebb7792702Timo Sirainen
f5b919e9b07dfd9d2401b998ef8759e5f0312719Timo Sirainen if (mbox_sync_rewrite(sync_ctx, file_size,
6a1e4eb2c6a267bec1e8704ce9137bebb7792702Timo Sirainen -sync_ctx->space_diff, padding,
6a1e4eb2c6a267bec1e8704ce9137bebb7792702Timo Sirainen sync_ctx->need_space_seq,
6a1e4eb2c6a267bec1e8704ce9137bebb7792702Timo Sirainen sync_ctx->seq) < 0)
6a1e4eb2c6a267bec1e8704ce9137bebb7792702Timo Sirainen return -1;
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen
8907d617ce7c4f390c0f42f6f694db2fecdd5775Timo Sirainen update_from_offsets(sync_ctx);
99be58a447b69d62cbd9e764000a06226b9c9c89Timo Sirainen
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen sync_ctx->need_space_seq = 0;
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen buffer_set_used_size(sync_ctx->mails, 0);
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen }
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen if (sync_ctx->expunged_space > 0) {
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen /* copy trailer, then truncate the file */
5edfc0f1c3c55e906d8316d9cdeaa3b0c7000c19Timo Sirainen file_size = i_stream_get_size(sync_ctx->file_input);
b397a802ec245a9169dab6b62efa4f7f877c07f6Timo Sirainen if (file_size == (uoff_t)sync_ctx->expunged_space) {
b397a802ec245a9169dab6b62efa4f7f877c07f6Timo Sirainen /* everything deleted, the trailer_size still contains
b397a802ec245a9169dab6b62efa4f7f877c07f6Timo Sirainen the \n trailer though */
b397a802ec245a9169dab6b62efa4f7f877c07f6Timo Sirainen trailer_size = 0;
b397a802ec245a9169dab6b62efa4f7f877c07f6Timo Sirainen }
b397a802ec245a9169dab6b62efa4f7f877c07f6Timo Sirainen
5edfc0f1c3c55e906d8316d9cdeaa3b0c7000c19Timo Sirainen i_assert(file_size >= sync_ctx->expunged_space + trailer_size);
5edfc0f1c3c55e906d8316d9cdeaa3b0c7000c19Timo Sirainen offset = file_size - sync_ctx->expunged_space - trailer_size;
eb276c05bf6b0a383c772d61e31cf09a8dbd36c7Timo Sirainen i_assert(offset == 0 || offset > 31);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen if (mbox_move(sync_ctx, offset,
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen offset + sync_ctx->expunged_space,
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen trailer_size) < 0)
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen return -1;
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen if (ftruncate(sync_ctx->fd, offset + trailer_size) < 0) {
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen mbox_set_syscall_error(sync_ctx->ibox, "ftruncate()");
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen return -1;
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen }
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
db7c9201c88e3d9bee10485194ee5b0c67249916Timo Sirainen sync_ctx->expunged_space = 0;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen istream_raw_mbox_flush(sync_ctx->input);
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen }
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen return 0;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen}
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
af6d4a24cb6d18e50d172540cf49b1448a6f9872Timo Sirainenstatic int mbox_sync_update_index_header(struct mbox_sync_context *sync_ctx)
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen{
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen struct stat st;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen if (fstat(sync_ctx->fd, &st) < 0) {
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen mbox_set_syscall_error(sync_ctx->ibox, "fstat()");
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen return -1;
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
292a66475ffe1037c2535063614f8beb71d266bfTimo Sirainen if ((sync_ctx->base_uid_validity != 0 &&
292a66475ffe1037c2535063614f8beb71d266bfTimo Sirainen sync_ctx->base_uid_validity != sync_ctx->hdr->uid_validity) ||
4e2c7d21a3f2b8b432fce7f9ee7114ba1c6b1177Timo Sirainen sync_ctx->hdr->uid_validity == 0) {
9e59a1f3f095b3099478562cf3f3970a24736970Timo Sirainen if (sync_ctx->base_uid_validity == 0) {
7a6b45405fb1544ac476e6eb1402a70cc1ddcdcfTimo Sirainen /* we didn't rewrite X-IMAPbase header because
4e2c7d21a3f2b8b432fce7f9ee7114ba1c6b1177Timo Sirainen a) mbox is read-only, b) we're lazy-writing,
4e2c7d21a3f2b8b432fce7f9ee7114ba1c6b1177Timo Sirainen c) it's empty */
4e2c7d21a3f2b8b432fce7f9ee7114ba1c6b1177Timo Sirainen i_assert(sync_ctx->delay_writes ||
4e2c7d21a3f2b8b432fce7f9ee7114ba1c6b1177Timo Sirainen sync_ctx->hdr->uid_validity == 0);
292a66475ffe1037c2535063614f8beb71d266bfTimo Sirainen sync_ctx->base_uid_validity = time(NULL);
292a66475ffe1037c2535063614f8beb71d266bfTimo Sirainen }
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen mail_index_update_header(sync_ctx->t,
fcfd317f7eb1f0216764c75c5fab3555020552d4Timo Sirainen offsetof(struct mail_index_header, uid_validity),
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen &sync_ctx->base_uid_validity,
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen sizeof(sync_ctx->base_uid_validity));
fcfd317f7eb1f0216764c75c5fab3555020552d4Timo Sirainen }
9e59a1f3f095b3099478562cf3f3970a24736970Timo Sirainen
178511b57faa7c3f8203dd8b7e4059d00cbfc23aTimo Sirainen if (istream_raw_mbox_is_eof(sync_ctx->input) &&
b3febb0933fdce10394d25093e23ce0a5aadddd3Timo Sirainen sync_ctx->next_uid != sync_ctx->hdr->next_uid) {
b3febb0933fdce10394d25093e23ce0a5aadddd3Timo Sirainen i_assert(sync_ctx->next_uid != 0);
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen mail_index_update_header(sync_ctx->t,
fcfd317f7eb1f0216764c75c5fab3555020552d4Timo Sirainen offsetof(struct mail_index_header, next_uid),
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen &sync_ctx->next_uid, sizeof(sync_ctx->next_uid));
fcfd317f7eb1f0216764c75c5fab3555020552d4Timo Sirainen }
fcfd317f7eb1f0216764c75c5fab3555020552d4Timo Sirainen
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen if ((uint32_t)st.st_mtime != sync_ctx->hdr->sync_stamp &&
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen !sync_ctx->ibox->mbox_sync_dirty) {
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen uint32_t sync_stamp = st.st_mtime;
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen mail_index_update_header(sync_ctx->t,
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen offsetof(struct mail_index_header, sync_stamp),
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen &sync_stamp, sizeof(sync_stamp));
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen }
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen if ((uint64_t)st.st_size != sync_ctx->hdr->sync_size &&
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen !sync_ctx->ibox->mbox_sync_dirty) {
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen uint64_t sync_size = st.st_size;
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen mail_index_update_header(sync_ctx->t,
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen offsetof(struct mail_index_header, sync_size),
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen &sync_size, sizeof(sync_size));
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen }
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen sync_ctx->ibox->mbox_dirty_stamp = st.st_mtime;
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen sync_ctx->ibox->mbox_dirty_size = st.st_size;
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen return 0;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen}
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainenstatic void mbox_sync_restart(struct mbox_sync_context *sync_ctx)
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen{
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen sync_ctx->base_uid_validity = 0;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen sync_ctx->base_uid_last = 0;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
c263e92d73889da530b308c9ab28b4b74031550eTimo Sirainen buffer_set_used_size(sync_ctx->mails, 0);
c263e92d73889da530b308c9ab28b4b74031550eTimo Sirainen buffer_set_used_size(sync_ctx->syncs, 0);
c263e92d73889da530b308c9ab28b4b74031550eTimo Sirainen memset(&sync_ctx->sync_rec, 0, sizeof(sync_ctx->sync_rec));
c263e92d73889da530b308c9ab28b4b74031550eTimo Sirainen
f0569d9fbb25c8437760be69f194595a841ad711Timo Sirainen sync_ctx->prev_msg_uid = 0;
c263e92d73889da530b308c9ab28b4b74031550eTimo Sirainen sync_ctx->next_uid = sync_ctx->hdr->next_uid;
a393d9d6dabdc46cf724f8cb004a652b4036d53dTimo Sirainen sync_ctx->seq = 0;
c263e92d73889da530b308c9ab28b4b74031550eTimo Sirainen sync_ctx->idx_seq = 1;
c263e92d73889da530b308c9ab28b4b74031550eTimo Sirainen sync_ctx->need_space_seq = 0;
c263e92d73889da530b308c9ab28b4b74031550eTimo Sirainen sync_ctx->expunged_space = 0;
c263e92d73889da530b308c9ab28b4b74031550eTimo Sirainen sync_ctx->space_diff = 0;
325f4573edfa5b751832ac01023f3e81be992bf0Timo Sirainen
9e59a1f3f095b3099478562cf3f3970a24736970Timo Sirainen sync_ctx->dest_first_mail = TRUE;
9e59a1f3f095b3099478562cf3f3970a24736970Timo Sirainen sync_ctx->seen_first_mail = FALSE;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen}
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainenstatic int mbox_sync_do(struct mbox_sync_context *sync_ctx,
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen enum mbox_sync_flags flags)
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen{
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen struct mbox_sync_mail_context mail_ctx;
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen struct stat st;
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen uint32_t min_msg_count;
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen int ret, partial;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen partial = FALSE;
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen if ((flags & MBOX_SYNC_HEADER) != 0)
345212e8f61ebf14ff4f80df26df9e655eb5121eTimo Sirainen min_msg_count = 1;
345212e8f61ebf14ff4f80df26df9e655eb5121eTimo Sirainen else {
345212e8f61ebf14ff4f80df26df9e655eb5121eTimo Sirainen if (fstat(sync_ctx->fd, &st) < 0) {
345212e8f61ebf14ff4f80df26df9e655eb5121eTimo Sirainen mbox_set_syscall_error(sync_ctx->ibox, "stat()");
345212e8f61ebf14ff4f80df26df9e655eb5121eTimo Sirainen return -1;
345212e8f61ebf14ff4f80df26df9e655eb5121eTimo Sirainen }
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen if ((uint32_t)st.st_mtime == sync_ctx->hdr->sync_stamp &&
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen (uint64_t)st.st_size == sync_ctx->hdr->sync_size) {
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen /* file is fully synced */
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen sync_ctx->ibox->mbox_sync_dirty = FALSE;
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen min_msg_count = 0;
4761938897eb785e19aa7081a589ac3a528f4eb8Timo Sirainen } else if ((flags & MBOX_SYNC_UNDIRTY) != 0 ||
4761938897eb785e19aa7081a589ac3a528f4eb8Timo Sirainen (uint64_t)st.st_size == sync_ctx->hdr->sync_size) {
4761938897eb785e19aa7081a589ac3a528f4eb8Timo Sirainen /* we want to do full syncing. always do this if
4761938897eb785e19aa7081a589ac3a528f4eb8Timo Sirainen file size hasn't changed but timestamp has. it most
4761938897eb785e19aa7081a589ac3a528f4eb8Timo Sirainen likely means that someone had modified some header
4761938897eb785e19aa7081a589ac3a528f4eb8Timo Sirainen and we probably want to know about it */
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen min_msg_count = (uint32_t)-1;
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen sync_ctx->ibox->mbox_sync_dirty = TRUE;
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen } else {
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen /* see if we can delay syncing the whole file.
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen normally we only notice expunges and appends
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen in partial syncing. */
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen partial = TRUE;
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen min_msg_count = (uint32_t)-1;
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen sync_ctx->ibox->mbox_sync_dirty = TRUE;
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen }
345212e8f61ebf14ff4f80df26df9e655eb5121eTimo Sirainen }
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen mbox_sync_restart(sync_ctx);
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen ret = mbox_sync_loop(sync_ctx, &mail_ctx, min_msg_count, partial);
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen if (ret <= 0) {
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen if (ret < 0)
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen return -1;
b3febb0933fdce10394d25093e23ce0a5aadddd3Timo Sirainen
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen /* partial syncing didn't work, do it again */
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen mbox_sync_restart(sync_ctx);
319944c0f35b311c998854e96d6463a084fd90aeTimo Sirainen
319944c0f35b311c998854e96d6463a084fd90aeTimo Sirainen mail_index_transaction_rollback(sync_ctx->t);
319944c0f35b311c998854e96d6463a084fd90aeTimo Sirainen sync_ctx->t = mail_index_transaction_begin(sync_ctx->sync_view,
7c95b03620a03a43dd72d39608cea5fc77393ad6Timo Sirainen FALSE, TRUE);
319944c0f35b311c998854e96d6463a084fd90aeTimo Sirainen
319944c0f35b311c998854e96d6463a084fd90aeTimo Sirainen ret = mbox_sync_loop(sync_ctx, &mail_ctx, (uint32_t)-1, FALSE);
319944c0f35b311c998854e96d6463a084fd90aeTimo Sirainen if (ret <= 0) {
319944c0f35b311c998854e96d6463a084fd90aeTimo Sirainen i_assert(ret != 0);
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen return -1;
319944c0f35b311c998854e96d6463a084fd90aeTimo Sirainen }
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen if (mbox_sync_handle_eof_updates(sync_ctx, &mail_ctx) < 0)
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen return -1;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
db7c9201c88e3d9bee10485194ee5b0c67249916Timo Sirainen /* only syncs left should be just appends (and their updates)
db7c9201c88e3d9bee10485194ee5b0c67249916Timo Sirainen which weren't synced yet for some reason (crash). we'll just
db7c9201c88e3d9bee10485194ee5b0c67249916Timo Sirainen ignore them, as we've overwritten them above. */
db7c9201c88e3d9bee10485194ee5b0c67249916Timo Sirainen buffer_set_used_size(sync_ctx->syncs, 0);
db7c9201c88e3d9bee10485194ee5b0c67249916Timo Sirainen memset(&sync_ctx->sync_rec, 0, sizeof(sync_ctx->sync_rec));
db7c9201c88e3d9bee10485194ee5b0c67249916Timo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen if (mbox_sync_update_index_header(sync_ctx) < 0)
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen return -1;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen return 0;
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen}
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainenint mbox_sync_has_changed(struct index_mailbox *ibox, int leave_dirty)
0b17b95357d5d73d941f1eb4ca9fc543bc510e42Timo Sirainen{
0b17b95357d5d73d941f1eb4ca9fc543bc510e42Timo Sirainen const struct mail_index_header *hdr;
0b17b95357d5d73d941f1eb4ca9fc543bc510e42Timo Sirainen struct stat st;
0b17b95357d5d73d941f1eb4ca9fc543bc510e42Timo Sirainen
b20fb5b1df9d604a7541f5118fc5b4b466d211efTimo Sirainen hdr = mail_index_get_header(ibox->view);
0b17b95357d5d73d941f1eb4ca9fc543bc510e42Timo Sirainen
0b17b95357d5d73d941f1eb4ca9fc543bc510e42Timo Sirainen if (stat(ibox->path, &st) < 0) {
0b17b95357d5d73d941f1eb4ca9fc543bc510e42Timo Sirainen mbox_set_syscall_error(ibox, "stat()");
0b17b95357d5d73d941f1eb4ca9fc543bc510e42Timo Sirainen return -1;
0b17b95357d5d73d941f1eb4ca9fc543bc510e42Timo Sirainen }
0b17b95357d5d73d941f1eb4ca9fc543bc510e42Timo Sirainen
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen if ((uint32_t)st.st_mtime == hdr->sync_stamp &&
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen (uint64_t)st.st_size == hdr->sync_size) {
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen /* fully synced */
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen ibox->mbox_sync_dirty = FALSE;
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen return 0;
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen }
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen if (!ibox->mbox_sync_dirty || !leave_dirty)
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen return 1;
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen return st.st_mtime != ibox->mbox_dirty_stamp ||
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen st.st_size != ibox->mbox_dirty_size;
0b17b95357d5d73d941f1eb4ca9fc543bc510e42Timo Sirainen}
0b17b95357d5d73d941f1eb4ca9fc543bc510e42Timo Sirainen
b3febb0933fdce10394d25093e23ce0a5aadddd3Timo Sirainenstatic int mbox_sync_update_imap_base(struct mbox_sync_context *sync_ctx)
b3febb0933fdce10394d25093e23ce0a5aadddd3Timo Sirainen{
b3febb0933fdce10394d25093e23ce0a5aadddd3Timo Sirainen struct mbox_sync_mail_context mail_ctx;
b3febb0933fdce10394d25093e23ce0a5aadddd3Timo Sirainen
7c95b03620a03a43dd72d39608cea5fc77393ad6Timo Sirainen sync_ctx->t = mail_index_transaction_begin(sync_ctx->sync_view,
7c95b03620a03a43dd72d39608cea5fc77393ad6Timo Sirainen FALSE, TRUE);
b3febb0933fdce10394d25093e23ce0a5aadddd3Timo Sirainen sync_ctx->update_base_uid_last = sync_ctx->next_uid-1;
b3febb0933fdce10394d25093e23ce0a5aadddd3Timo Sirainen
b3febb0933fdce10394d25093e23ce0a5aadddd3Timo Sirainen mbox_sync_restart(sync_ctx);
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen if (mbox_sync_loop(sync_ctx, &mail_ctx, 1, 0) < 0)
b3febb0933fdce10394d25093e23ce0a5aadddd3Timo Sirainen return -1;
b3febb0933fdce10394d25093e23ce0a5aadddd3Timo Sirainen
b3febb0933fdce10394d25093e23ce0a5aadddd3Timo Sirainen if (mbox_sync_handle_eof_updates(sync_ctx, &mail_ctx) < 0)
b3febb0933fdce10394d25093e23ce0a5aadddd3Timo Sirainen return -1;
b3febb0933fdce10394d25093e23ce0a5aadddd3Timo Sirainen
b3febb0933fdce10394d25093e23ce0a5aadddd3Timo Sirainen if (mbox_sync_update_index_header(sync_ctx) < 0)
b3febb0933fdce10394d25093e23ce0a5aadddd3Timo Sirainen return -1;
b3febb0933fdce10394d25093e23ce0a5aadddd3Timo Sirainen
b3febb0933fdce10394d25093e23ce0a5aadddd3Timo Sirainen return 0;
b3febb0933fdce10394d25093e23ce0a5aadddd3Timo Sirainen}
b3febb0933fdce10394d25093e23ce0a5aadddd3Timo Sirainen
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainenint mbox_sync(struct index_mailbox *ibox, enum mbox_sync_flags flags)
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen{
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen struct mail_index_sync_ctx *index_sync_ctx;
0b17b95357d5d73d941f1eb4ca9fc543bc510e42Timo Sirainen struct mail_index_view *sync_view;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen struct mbox_sync_context sync_ctx;
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen uint32_t seq;
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen uoff_t offset;
63a61b7a739ae0f3f520215137d9c50f94d0f34fTimo Sirainen unsigned int lock_id = 0;
d9de52132072d80b8c268094b879c0ef5a108db3Timo Sirainen int ret, changed;
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen
6597506f9317f3be644e708c9153dacaeeece84cTimo Sirainen ibox->sync_last_check = ioloop_time;
6597506f9317f3be644e708c9153dacaeeece84cTimo Sirainen
d252f81a2ff1bdd5439f9d2b3df715b70a4bcd3dTimo Sirainen if (!ibox->mbox_do_dirty_syncs)
d252f81a2ff1bdd5439f9d2b3df715b70a4bcd3dTimo Sirainen flags |= MBOX_SYNC_UNDIRTY;
d252f81a2ff1bdd5439f9d2b3df715b70a4bcd3dTimo Sirainen
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen if ((flags & MBOX_SYNC_LOCK_READING) != 0) {
63a61b7a739ae0f3f520215137d9c50f94d0f34fTimo Sirainen if (mbox_lock(ibox, F_RDLCK, &lock_id) <= 0)
63a61b7a739ae0f3f520215137d9c50f94d0f34fTimo Sirainen return -1;
63a61b7a739ae0f3f520215137d9c50f94d0f34fTimo Sirainen }
63a61b7a739ae0f3f520215137d9c50f94d0f34fTimo Sirainen
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen if ((flags & MBOX_SYNC_HEADER) != 0)
d9de52132072d80b8c268094b879c0ef5a108db3Timo Sirainen changed = 1;
345212e8f61ebf14ff4f80df26df9e655eb5121eTimo Sirainen else {
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen int leave_dirty = (flags & MBOX_SYNC_UNDIRTY) == 0;
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen if ((changed = mbox_sync_has_changed(ibox, leave_dirty)) < 0) {
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen if ((flags & MBOX_SYNC_LOCK_READING) != 0)
345212e8f61ebf14ff4f80df26df9e655eb5121eTimo Sirainen (void)mbox_unlock(ibox, lock_id);
345212e8f61ebf14ff4f80df26df9e655eb5121eTimo Sirainen return -1;
345212e8f61ebf14ff4f80df26df9e655eb5121eTimo Sirainen }
63a61b7a739ae0f3f520215137d9c50f94d0f34fTimo Sirainen }
345212e8f61ebf14ff4f80df26df9e655eb5121eTimo Sirainen
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen if ((flags & MBOX_SYNC_LOCK_READING) != 0) {
d9de52132072d80b8c268094b879c0ef5a108db3Timo Sirainen /* we just want to lock it for reading. if mbox hasn't been
d9de52132072d80b8c268094b879c0ef5a108db3Timo Sirainen modified don't do any syncing. */
d9de52132072d80b8c268094b879c0ef5a108db3Timo Sirainen if (!changed)
d9de52132072d80b8c268094b879c0ef5a108db3Timo Sirainen return 0;
d9de52132072d80b8c268094b879c0ef5a108db3Timo Sirainen
d9de52132072d80b8c268094b879c0ef5a108db3Timo Sirainen /* have to sync to make sure offsets have stayed the same */
d9de52132072d80b8c268094b879c0ef5a108db3Timo Sirainen (void)mbox_unlock(ibox, lock_id);
d9de52132072d80b8c268094b879c0ef5a108db3Timo Sirainen lock_id = 0;
d9de52132072d80b8c268094b879c0ef5a108db3Timo Sirainen }
d9de52132072d80b8c268094b879c0ef5a108db3Timo Sirainen
f2b79667fc7a8f7c2c72cad18bd71d49730e36f6Timo Sirainen /* reopen input stream to make sure it has nothing buffered */
f2b79667fc7a8f7c2c72cad18bd71d49730e36f6Timo Sirainen mbox_file_close_stream(ibox);
f2b79667fc7a8f7c2c72cad18bd71d49730e36f6Timo Sirainen
d9de52132072d80b8c268094b879c0ef5a108db3Timo Sirainen__again:
d9de52132072d80b8c268094b879c0ef5a108db3Timo Sirainen if (changed) {
d9de52132072d80b8c268094b879c0ef5a108db3Timo Sirainen /* we're most likely modifying the mbox while syncing, just
d9de52132072d80b8c268094b879c0ef5a108db3Timo Sirainen lock it for writing immediately. the mbox must be locked
d9de52132072d80b8c268094b879c0ef5a108db3Timo Sirainen before index syncing is started to avoid deadlocks, so we
d9de52132072d80b8c268094b879c0ef5a108db3Timo Sirainen don't have much choice either (well, easy ones anyway). */
f755bf320bfa321de210b85d6455eb6d7092bb4aTimo Sirainen int lock_type = ibox->mbox_readonly ? F_RDLCK : F_WRLCK;
f755bf320bfa321de210b85d6455eb6d7092bb4aTimo Sirainen if (mbox_lock(ibox, lock_type, &lock_id) <= 0)
d9de52132072d80b8c268094b879c0ef5a108db3Timo Sirainen return -1;
d9de52132072d80b8c268094b879c0ef5a108db3Timo Sirainen }
d9de52132072d80b8c268094b879c0ef5a108db3Timo Sirainen
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen if ((flags & MBOX_SYNC_LAST_COMMIT) != 0) {
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen seq = ibox->commit_log_file_seq;
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen offset = ibox->commit_log_file_offset;
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen } else {
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen seq = (uint32_t)-1;
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen offset = (uoff_t)-1;
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen }
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen ret = mail_index_sync_begin(ibox->index, &index_sync_ctx, &sync_view,
757726d9acbd04cf0d0d4be8ce14e11525476a0bTimo Sirainen seq, offset, !ibox->keep_recent,
757726d9acbd04cf0d0d4be8ce14e11525476a0bTimo Sirainen (flags & MBOX_SYNC_REWRITE) != 0);
0b17b95357d5d73d941f1eb4ca9fc543bc510e42Timo Sirainen if (ret <= 0) {
0b17b95357d5d73d941f1eb4ca9fc543bc510e42Timo Sirainen if (ret < 0)
0b17b95357d5d73d941f1eb4ca9fc543bc510e42Timo Sirainen mail_storage_set_index_error(ibox);
d9de52132072d80b8c268094b879c0ef5a108db3Timo Sirainen if (lock_id != 0)
d9de52132072d80b8c268094b879c0ef5a108db3Timo Sirainen (void)mbox_unlock(ibox, lock_id);
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen return ret;
0b17b95357d5d73d941f1eb4ca9fc543bc510e42Timo Sirainen }
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen
88553367d677170a4b703b9d52aac9eabf91c656Timo Sirainen if (!changed && !mail_index_sync_have_more(index_sync_ctx)) {
d9de52132072d80b8c268094b879c0ef5a108db3Timo Sirainen /* nothing to do */
d9de52132072d80b8c268094b879c0ef5a108db3Timo Sirainen if (lock_id != 0)
d9de52132072d80b8c268094b879c0ef5a108db3Timo Sirainen (void)mbox_unlock(ibox, lock_id);
4d10cf8c7879ccd377e7fb136913b2a258ba8d93Timo Sirainen
4d10cf8c7879ccd377e7fb136913b2a258ba8d93Timo Sirainen /* index may need to do internal syncing though, so commit
4d10cf8c7879ccd377e7fb136913b2a258ba8d93Timo Sirainen instead of rollbacking. */
4d10cf8c7879ccd377e7fb136913b2a258ba8d93Timo Sirainen if (mail_index_sync_commit(index_sync_ctx) < 0) {
4d10cf8c7879ccd377e7fb136913b2a258ba8d93Timo Sirainen mail_storage_set_index_error(ibox);
4d10cf8c7879ccd377e7fb136913b2a258ba8d93Timo Sirainen return -1;
4d10cf8c7879ccd377e7fb136913b2a258ba8d93Timo Sirainen }
88553367d677170a4b703b9d52aac9eabf91c656Timo Sirainen return 0;
88553367d677170a4b703b9d52aac9eabf91c656Timo Sirainen }
88553367d677170a4b703b9d52aac9eabf91c656Timo Sirainen
d9de52132072d80b8c268094b879c0ef5a108db3Timo Sirainen if (lock_id == 0) {
d9de52132072d80b8c268094b879c0ef5a108db3Timo Sirainen /* ok, we have something to do but no locks. we'll have to
d9de52132072d80b8c268094b879c0ef5a108db3Timo Sirainen restart syncing to avoid deadlocking. */
d9de52132072d80b8c268094b879c0ef5a108db3Timo Sirainen mail_index_sync_rollback(index_sync_ctx);
d9de52132072d80b8c268094b879c0ef5a108db3Timo Sirainen changed = 1;
d9de52132072d80b8c268094b879c0ef5a108db3Timo Sirainen goto __again;
d9de52132072d80b8c268094b879c0ef5a108db3Timo Sirainen }
d9de52132072d80b8c268094b879c0ef5a108db3Timo Sirainen
d9de52132072d80b8c268094b879c0ef5a108db3Timo Sirainen if (mbox_file_open_stream(ibox) < 0) {
d9de52132072d80b8c268094b879c0ef5a108db3Timo Sirainen mail_index_sync_rollback(index_sync_ctx);
d9de52132072d80b8c268094b879c0ef5a108db3Timo Sirainen (void)mbox_unlock(ibox, lock_id);
d9de52132072d80b8c268094b879c0ef5a108db3Timo Sirainen return -1;
d9de52132072d80b8c268094b879c0ef5a108db3Timo Sirainen }
d9de52132072d80b8c268094b879c0ef5a108db3Timo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen memset(&sync_ctx, 0, sizeof(sync_ctx));
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen sync_ctx.ibox = ibox;
de4288b7369945a31c4001add9445fd0195a358dTimo Sirainen
b20fb5b1df9d604a7541f5118fc5b4b466d211efTimo Sirainen sync_ctx.hdr = mail_index_get_header(sync_view);
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen sync_ctx.from_line = str_new(default_pool, 256);
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen sync_ctx.header = str_new(default_pool, 4096);
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen sync_ctx.index_sync_ctx = index_sync_ctx;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen sync_ctx.sync_view = sync_view;
7c95b03620a03a43dd72d39608cea5fc77393ad6Timo Sirainen sync_ctx.t = mail_index_transaction_begin(sync_view, FALSE, TRUE);
33ae95df45c9b5ec51332a6b39eb5322038686b9Timo Sirainen
4b058f90f9e8a2c6b2eed275de4eb8cc5195a71dTimo Sirainen sync_ctx.mails = buffer_create_dynamic(default_pool, 4096);
4b058f90f9e8a2c6b2eed275de4eb8cc5195a71dTimo Sirainen sync_ctx.syncs = buffer_create_dynamic(default_pool, 256);
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
d9de52132072d80b8c268094b879c0ef5a108db3Timo Sirainen sync_ctx.file_input = sync_ctx.ibox->mbox_file_stream;
d9de52132072d80b8c268094b879c0ef5a108db3Timo Sirainen sync_ctx.input = sync_ctx.ibox->mbox_stream;
d9de52132072d80b8c268094b879c0ef5a108db3Timo Sirainen sync_ctx.fd = sync_ctx.ibox->mbox_fd;
7a6b45405fb1544ac476e6eb1402a70cc1ddcdcfTimo Sirainen sync_ctx.flags = flags;
7a6b45405fb1544ac476e6eb1402a70cc1ddcdcfTimo Sirainen sync_ctx.delay_writes = sync_ctx.ibox->mbox_readonly ||
e5ee67f18b03015c88b579c8c1f17ebe6ce19b76Timo Sirainen sync_ctx.ibox->readonly ||
e5ee67f18b03015c88b579c8c1f17ebe6ce19b76Timo Sirainen ((flags & MBOX_SYNC_REWRITE) == 0 &&
7a6b45405fb1544ac476e6eb1402a70cc1ddcdcfTimo Sirainen getenv("MBOX_LAZY_WRITES") != NULL);
7a6b45405fb1544ac476e6eb1402a70cc1ddcdcfTimo Sirainen
de4288b7369945a31c4001add9445fd0195a358dTimo Sirainen ret = mbox_sync_do(&sync_ctx, flags);
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen if (ret < 0)
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen mail_index_transaction_rollback(sync_ctx.t);
36e2fa21c22452470c1509cc63de20f7415c7b5eTimo Sirainen else if (mail_index_transaction_commit(sync_ctx.t, &seq, &offset) < 0) {
36e2fa21c22452470c1509cc63de20f7415c7b5eTimo Sirainen mail_storage_set_index_error(ibox);
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen ret = -1;
36e2fa21c22452470c1509cc63de20f7415c7b5eTimo Sirainen } else {
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen ibox->commit_log_file_seq = 0;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen ibox->commit_log_file_offset = 0;
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen }
b3febb0933fdce10394d25093e23ce0a5aadddd3Timo Sirainen sync_ctx.t = NULL;
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen
79c9f3069bde51f799a64ca5923d68c9a5bc2ad2Timo Sirainen if (ret < 0)
79c9f3069bde51f799a64ca5923d68c9a5bc2ad2Timo Sirainen mail_index_sync_rollback(index_sync_ctx);
79c9f3069bde51f799a64ca5923d68c9a5bc2ad2Timo Sirainen else if (mail_index_sync_commit(index_sync_ctx) < 0) {
36e2fa21c22452470c1509cc63de20f7415c7b5eTimo Sirainen mail_storage_set_index_error(ibox);
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen ret = -1;
36e2fa21c22452470c1509cc63de20f7415c7b5eTimo Sirainen }
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
345212e8f61ebf14ff4f80df26df9e655eb5121eTimo Sirainen if (sync_ctx.seen_first_mail &&
345212e8f61ebf14ff4f80df26df9e655eb5121eTimo Sirainen sync_ctx.base_uid_last != sync_ctx.next_uid-1 &&
7a6b45405fb1544ac476e6eb1402a70cc1ddcdcfTimo Sirainen ret == 0 && !sync_ctx.delay_writes) {
b3febb0933fdce10394d25093e23ce0a5aadddd3Timo Sirainen /* rewrite X-IMAPbase header. do it after mail_index_sync_end()
b3febb0933fdce10394d25093e23ce0a5aadddd3Timo Sirainen so previous transactions have been committed. */
b3febb0933fdce10394d25093e23ce0a5aadddd3Timo Sirainen /* FIXME: ugly .. */
b3febb0933fdce10394d25093e23ce0a5aadddd3Timo Sirainen ret = mail_index_sync_begin(ibox->index,
b3febb0933fdce10394d25093e23ce0a5aadddd3Timo Sirainen &sync_ctx.index_sync_ctx,
b3febb0933fdce10394d25093e23ce0a5aadddd3Timo Sirainen &sync_ctx.sync_view,
757726d9acbd04cf0d0d4be8ce14e11525476a0bTimo Sirainen (uint32_t)-1, (uoff_t)-1,
757726d9acbd04cf0d0d4be8ce14e11525476a0bTimo Sirainen FALSE, FALSE);
b3febb0933fdce10394d25093e23ce0a5aadddd3Timo Sirainen if (ret < 0)
b3febb0933fdce10394d25093e23ce0a5aadddd3Timo Sirainen mail_storage_set_index_error(ibox);
b3febb0933fdce10394d25093e23ce0a5aadddd3Timo Sirainen else {
b20fb5b1df9d604a7541f5118fc5b4b466d211efTimo Sirainen sync_ctx.hdr =
b20fb5b1df9d604a7541f5118fc5b4b466d211efTimo Sirainen mail_index_get_header(sync_ctx.sync_view);
b3febb0933fdce10394d25093e23ce0a5aadddd3Timo Sirainen if ((ret = mbox_sync_update_imap_base(&sync_ctx)) < 0)
b3febb0933fdce10394d25093e23ce0a5aadddd3Timo Sirainen mail_index_transaction_rollback(sync_ctx.t);
b3febb0933fdce10394d25093e23ce0a5aadddd3Timo Sirainen else if (mail_index_transaction_commit(sync_ctx.t,
b3febb0933fdce10394d25093e23ce0a5aadddd3Timo Sirainen &seq,
36e2fa21c22452470c1509cc63de20f7415c7b5eTimo Sirainen &offset) < 0) {
36e2fa21c22452470c1509cc63de20f7415c7b5eTimo Sirainen mail_storage_set_index_error(ibox);
b3febb0933fdce10394d25093e23ce0a5aadddd3Timo Sirainen ret = -1;
36e2fa21c22452470c1509cc63de20f7415c7b5eTimo Sirainen }
b3febb0933fdce10394d25093e23ce0a5aadddd3Timo Sirainen
d9de52132072d80b8c268094b879c0ef5a108db3Timo Sirainen if (mail_index_sync_commit(sync_ctx.
d9de52132072d80b8c268094b879c0ef5a108db3Timo Sirainen index_sync_ctx) < 0) {
36e2fa21c22452470c1509cc63de20f7415c7b5eTimo Sirainen mail_storage_set_index_error(ibox);
b3febb0933fdce10394d25093e23ce0a5aadddd3Timo Sirainen ret = -1;
36e2fa21c22452470c1509cc63de20f7415c7b5eTimo Sirainen }
b3febb0933fdce10394d25093e23ce0a5aadddd3Timo Sirainen }
b3febb0933fdce10394d25093e23ce0a5aadddd3Timo Sirainen }
b3febb0933fdce10394d25093e23ce0a5aadddd3Timo Sirainen
709aa305126c32b49657e53d04826087b6838c16Timo Sirainen if (ret == 0 && ibox->mbox_lock_type == F_WRLCK &&
709aa305126c32b49657e53d04826087b6838c16Timo Sirainen !ibox->mbox_writeonly) {
8573a63139eab50fee1e497276f126f0d04d5637Timo Sirainen if (fsync(ibox->mbox_fd) < 0) {
8573a63139eab50fee1e497276f126f0d04d5637Timo Sirainen mbox_set_syscall_error(ibox, "fsync()");
8573a63139eab50fee1e497276f126f0d04d5637Timo Sirainen ret = -1;
8573a63139eab50fee1e497276f126f0d04d5637Timo Sirainen }
8573a63139eab50fee1e497276f126f0d04d5637Timo Sirainen }
8573a63139eab50fee1e497276f126f0d04d5637Timo Sirainen
d9de52132072d80b8c268094b879c0ef5a108db3Timo Sirainen if (lock_id != 0 && ibox->mbox_lock_type != F_RDLCK) {
2c7ab05ef98c46eb70c8ba6ea85e49749aafb2a3Timo Sirainen /* drop to read lock */
d9de52132072d80b8c268094b879c0ef5a108db3Timo Sirainen unsigned int read_lock_id = 0;
2c7ab05ef98c46eb70c8ba6ea85e49749aafb2a3Timo Sirainen
d9de52132072d80b8c268094b879c0ef5a108db3Timo Sirainen if (mbox_lock(ibox, F_RDLCK, &read_lock_id) <= 0)
2c7ab05ef98c46eb70c8ba6ea85e49749aafb2a3Timo Sirainen ret = -1;
2c7ab05ef98c46eb70c8ba6ea85e49749aafb2a3Timo Sirainen else {
d9de52132072d80b8c268094b879c0ef5a108db3Timo Sirainen if (mbox_unlock(ibox, lock_id) < 0)
2c7ab05ef98c46eb70c8ba6ea85e49749aafb2a3Timo Sirainen ret = -1;
d9de52132072d80b8c268094b879c0ef5a108db3Timo Sirainen lock_id = read_lock_id;
2c7ab05ef98c46eb70c8ba6ea85e49749aafb2a3Timo Sirainen }
2c7ab05ef98c46eb70c8ba6ea85e49749aafb2a3Timo Sirainen }
2c7ab05ef98c46eb70c8ba6ea85e49749aafb2a3Timo Sirainen
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen if (lock_id != 0 && (flags & MBOX_SYNC_LOCK_READING) == 0) {
2c7ab05ef98c46eb70c8ba6ea85e49749aafb2a3Timo Sirainen /* FIXME: keep the lock MBOX_SYNC_SECS+1 to make sure we
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen notice changes made by others .. and this has to be done
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen even if lock_reading is set.. except if
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen mbox_sync_dirty = TRUE */
d9de52132072d80b8c268094b879c0ef5a108db3Timo Sirainen if (mbox_unlock(ibox, lock_id) < 0)
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen ret = -1;
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen }
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen str_free(sync_ctx.header);
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen str_free(sync_ctx.from_line);
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen buffer_free(sync_ctx.mails);
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen buffer_free(sync_ctx.syncs);
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen return ret;
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
d756ebcfa96bd7cff02097c8f26df9df368b81b1Timo Sirainenstruct mailbox_sync_context *
d756ebcfa96bd7cff02097c8f26df9df368b81b1Timo Sirainenmbox_storage_sync_init(struct mailbox *box, enum mailbox_sync_flags flags)
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen{
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen struct index_mailbox *ibox = (struct index_mailbox *)box;
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen enum mbox_sync_flags mbox_sync_flags = 0;
d756ebcfa96bd7cff02097c8f26df9df368b81b1Timo Sirainen int ret = 0;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen if ((flags & MAILBOX_SYNC_FLAG_FAST) == 0 ||
95ed89440faab05cbb4f2473f2f4af19e848bde8Timo Sirainen ibox->sync_last_check + MAILBOX_FULL_SYNC_INTERVAL <= ioloop_time) {
29e945d8550f297707f3a5f627a938401046c0ccTimo Sirainen if ((flags & MAILBOX_SYNC_FLAG_FULL_READ) != 0 &&
29e945d8550f297707f3a5f627a938401046c0ccTimo Sirainen !ibox->mbox_very_dirty_syncs)
95ed89440faab05cbb4f2473f2f4af19e848bde8Timo Sirainen mbox_sync_flags |= MBOX_SYNC_UNDIRTY;
e5ee67f18b03015c88b579c8c1f17ebe6ce19b76Timo Sirainen if ((flags & MAILBOX_SYNC_FLAG_FULL_WRITE) != 0)
e5ee67f18b03015c88b579c8c1f17ebe6ce19b76Timo Sirainen mbox_sync_flags |= MBOX_SYNC_REWRITE;
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen ret = mbox_sync(ibox, mbox_sync_flags);
95ed89440faab05cbb4f2473f2f4af19e848bde8Timo Sirainen }
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen
d756ebcfa96bd7cff02097c8f26df9df368b81b1Timo Sirainen return index_mailbox_sync_init(box, flags, ret < 0);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}