mbox-sync.c revision 4b058f90f9e8a2c6b2eed275de4eb8cc5195a71d
45312f52ff3a3d4c137447be4c7556500c2f8bf2Timo 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"
16f816d3f3c32ae3351834253f52ddd0212bcbf3Timo Sirainen#include "buffer.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "istream.h"
98c1cf256927e254f0c092acd2ddcd7ea50bd009Timo Sirainen#include "file-set-size.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "str.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "write-full.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "istream-raw-mbox.h"
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen#include "mbox-storage.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "mbox-file.h"
98c1cf256927e254f0c092acd2ddcd7ea50bd009Timo Sirainen#include "mbox-lock.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "mbox-sync-private.h"
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen
022412398e56a8f31ef111cfd7271498d64af9a9Timo Sirainen#include <stddef.h>
98c1cf256927e254f0c092acd2ddcd7ea50bd009Timo Sirainen#include <stdlib.h>
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen#include <sys/stat.h>
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#define MBOX_SYNC_SECS 1
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainenint mbox_sync_seek(struct mbox_sync_context *sync_ctx, uoff_t from_offset)
7a6b45405fb1544ac476e6eb1402a70cc1ddcdcfTimo Sirainen{
e05ea8311ae16687295048e88ca205dfe29fbcbfTimo Sirainen if (istream_raw_mbox_seek(sync_ctx->input, from_offset) < 0) {
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen mail_storage_set_critical(sync_ctx->ibox->box.storage,
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen "Unexpectedly lost From-line at offset %"PRIuUOFF_T
98c1cf256927e254f0c092acd2ddcd7ea50bd009Timo Sirainen " from mbox file %s", from_offset,
98c1cf256927e254f0c092acd2ddcd7ea50bd009Timo Sirainen sync_ctx->ibox->path);
f7d43647acc6dc80064c8c4cacf5bf86f754c530Timo Sirainen return -1;
98c1cf256927e254f0c092acd2ddcd7ea50bd009Timo Sirainen }
98c1cf256927e254f0c092acd2ddcd7ea50bd009Timo Sirainen return 0;
98c1cf256927e254f0c092acd2ddcd7ea50bd009Timo Sirainen}
98c1cf256927e254f0c092acd2ddcd7ea50bd009Timo Sirainen
98c1cf256927e254f0c092acd2ddcd7ea50bd009Timo Sirainenstatic void mbox_sync_buffer_delete_old(buffer_t *syncs_buf, uint32_t uid)
a2637488c8d514ec1ac3914811deee814f9761b3Timo Sirainen{
a2637488c8d514ec1ac3914811deee814f9761b3Timo Sirainen struct mail_index_sync_rec *sync;
a2637488c8d514ec1ac3914811deee814f9761b3Timo Sirainen size_t size, src, dest;
a2637488c8d514ec1ac3914811deee814f9761b3Timo Sirainen
a2637488c8d514ec1ac3914811deee814f9761b3Timo Sirainen sync = buffer_get_modifyable_data(syncs_buf, &size);
b6d817f0effeff645aadc01fd468a7d4084ba1f2Timo Sirainen size /= sizeof(*sync);
a2637488c8d514ec1ac3914811deee814f9761b3Timo Sirainen
a2637488c8d514ec1ac3914811deee814f9761b3Timo Sirainen for (src = dest = 0; src < size; src++) {
a2637488c8d514ec1ac3914811deee814f9761b3Timo Sirainen if (uid <= sync[src].uid2) {
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen /* keep it */
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen if (src != dest)
a2637488c8d514ec1ac3914811deee814f9761b3Timo Sirainen sync[dest] = sync[src];
a2637488c8d514ec1ac3914811deee814f9761b3Timo Sirainen dest++;
a2637488c8d514ec1ac3914811deee814f9761b3Timo Sirainen }
a2637488c8d514ec1ac3914811deee814f9761b3Timo Sirainen }
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen buffer_set_used_size(syncs_buf, dest * sizeof(*sync));
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen}
a2637488c8d514ec1ac3914811deee814f9761b3Timo Sirainen
a2637488c8d514ec1ac3914811deee814f9761b3Timo Sirainenstatic int
a2637488c8d514ec1ac3914811deee814f9761b3Timo Sirainenmbox_sync_read_next_mail(struct mbox_sync_context *sync_ctx,
02b79f9c2636da1829eee5b92753602bba8b67edTimo Sirainen struct mbox_sync_mail_context *mail_ctx)
02b79f9c2636da1829eee5b92753602bba8b67edTimo Sirainen{
02b79f9c2636da1829eee5b92753602bba8b67edTimo Sirainen /* get EOF */
a2637488c8d514ec1ac3914811deee814f9761b3Timo Sirainen (void)istream_raw_mbox_get_header_offset(sync_ctx->input);
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen if (istream_raw_mbox_is_eof(sync_ctx->input))
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen return 0;
02b79f9c2636da1829eee5b92753602bba8b67edTimo Sirainen
02b79f9c2636da1829eee5b92753602bba8b67edTimo Sirainen memset(mail_ctx, 0, sizeof(*mail_ctx));
02b79f9c2636da1829eee5b92753602bba8b67edTimo Sirainen mail_ctx->sync_ctx = sync_ctx;
02b79f9c2636da1829eee5b92753602bba8b67edTimo Sirainen mail_ctx->seq = ++sync_ctx->seq;
02b79f9c2636da1829eee5b92753602bba8b67edTimo Sirainen mail_ctx->header = sync_ctx->header;
a2637488c8d514ec1ac3914811deee814f9761b3Timo Sirainen mail_ctx->uidl = sync_ctx->uidl;
299183fbb6ec5d0828a0880da372540421ac4665Timo Sirainen str_truncate(mail_ctx->uidl, 0);
299183fbb6ec5d0828a0880da372540421ac4665Timo Sirainen
299183fbb6ec5d0828a0880da372540421ac4665Timo Sirainen mail_ctx->mail.from_offset =
a2637488c8d514ec1ac3914811deee814f9761b3Timo Sirainen istream_raw_mbox_get_start_offset(sync_ctx->input);
a2637488c8d514ec1ac3914811deee814f9761b3Timo Sirainen mail_ctx->mail.offset =
299183fbb6ec5d0828a0880da372540421ac4665Timo Sirainen istream_raw_mbox_get_header_offset(sync_ctx->input);
299183fbb6ec5d0828a0880da372540421ac4665Timo Sirainen
a2637488c8d514ec1ac3914811deee814f9761b3Timo Sirainen if (mail_ctx->seq == 1)
299183fbb6ec5d0828a0880da372540421ac4665Timo Sirainen sync_ctx->seen_first_mail = TRUE;
299183fbb6ec5d0828a0880da372540421ac4665Timo Sirainen if (mail_ctx->seq > 1 && sync_ctx->dest_first_mail) {
299183fbb6ec5d0828a0880da372540421ac4665Timo Sirainen /* First message was expunged and this is the next one.
299183fbb6ec5d0828a0880da372540421ac4665Timo Sirainen Skip \n header */
6288d3611eda14a017dae9927b73f46afb646c96Timo Sirainen mail_ctx->mail.from_offset++;
a2637488c8d514ec1ac3914811deee814f9761b3Timo Sirainen }
299183fbb6ec5d0828a0880da372540421ac4665Timo Sirainen
299183fbb6ec5d0828a0880da372540421ac4665Timo Sirainen mbox_sync_parse_next_mail(sync_ctx->input, mail_ctx);
299183fbb6ec5d0828a0880da372540421ac4665Timo Sirainen i_assert(sync_ctx->input->v_offset != mail_ctx->mail.from_offset ||
299183fbb6ec5d0828a0880da372540421ac4665Timo Sirainen sync_ctx->input->eof);
299183fbb6ec5d0828a0880da372540421ac4665Timo Sirainen
299183fbb6ec5d0828a0880da372540421ac4665Timo Sirainen mail_ctx->mail.body_size =
299183fbb6ec5d0828a0880da372540421ac4665Timo Sirainen istream_raw_mbox_get_body_size(sync_ctx->input,
299183fbb6ec5d0828a0880da372540421ac4665Timo Sirainen mail_ctx->content_length);
299183fbb6ec5d0828a0880da372540421ac4665Timo Sirainen i_assert(mail_ctx->mail.body_size < OFF_T_MAX);
299183fbb6ec5d0828a0880da372540421ac4665Timo Sirainen
299183fbb6ec5d0828a0880da372540421ac4665Timo Sirainen if ((mail_ctx->mail.flags & MBOX_NONRECENT) == 0 && !mail_ctx->pseudo) {
299183fbb6ec5d0828a0880da372540421ac4665Timo Sirainen if (!sync_ctx->ibox->keep_recent) {
299183fbb6ec5d0828a0880da372540421ac4665Timo Sirainen /* need to add 'O' flag to Status-header */
299183fbb6ec5d0828a0880da372540421ac4665Timo Sirainen mail_ctx->need_rewrite = TRUE;
299183fbb6ec5d0828a0880da372540421ac4665Timo Sirainen }
299183fbb6ec5d0828a0880da372540421ac4665Timo Sirainen mail_ctx->recent = TRUE;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen }
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen return 1;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen}
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen
9e59a1f3f095b3099478562cf3f3970a24736970Timo Sirainenstatic int mbox_sync_buf_have_expunges(buffer_t *syncs_buf)
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen{
178511b57faa7c3f8203dd8b7e4059d00cbfc23aTimo Sirainen const struct mail_index_sync_rec *sync;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen size_t size, i;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
2e937ed8585299b2e879a28314902a5f644813d2Timo Sirainen sync = buffer_get_data(syncs_buf, &size);
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen size /= sizeof(*sync);
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen for (i = 0; i < size; i++) {
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen if (sync[i].type == MAIL_INDEX_SYNC_TYPE_EXPUNGE)
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen return TRUE;
4d25408732be27e91f0430f71e87242760c2517cTimo Sirainen }
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen return FALSE;
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen}
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainenstatic int mbox_sync_read_index_syncs(struct mbox_sync_context *sync_ctx,
e5c08648676d1989f6e70b95e5990c26b3e8b96bTimo Sirainen uint32_t uid, int *sync_expunge_r)
4d25408732be27e91f0430f71e87242760c2517cTimo Sirainen{
c3412ddeb9abc13f99d3caf50faf76cd99f7e9d2Timo Sirainen struct mail_index_sync_rec *sync_rec = &sync_ctx->sync_rec;
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen int ret;
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen *sync_expunge_r = FALSE;
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen
02b79f9c2636da1829eee5b92753602bba8b67edTimo Sirainen if (sync_ctx->index_sync_ctx == NULL)
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen return 0;
1e76a5b92f9d82d557f81f080f3dfad1c9d8f200Timo Sirainen
1e76a5b92f9d82d557f81f080f3dfad1c9d8f200Timo Sirainen if (uid == 0) {
ced118ac5caf6fe83d34339c2c65c63b2aa768acTimo Sirainen /* nothing for this or the future ones */
9a06cabdfdf4d5e2f19a07e506c3c7d08a7e7038Timo Sirainen uid = (uint32_t)-1;
9a06cabdfdf4d5e2f19a07e506c3c7d08a7e7038Timo Sirainen }
9a06cabdfdf4d5e2f19a07e506c3c7d08a7e7038Timo Sirainen
e8a35266a5ceacdfafeeffd6bddae77931ff97ebTimo Sirainen mbox_sync_buffer_delete_old(sync_ctx->syncs, uid);
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen while (uid >= sync_rec->uid1) {
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen if (uid <= sync_rec->uid2 &&
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen sync_rec->type != MAIL_INDEX_SYNC_TYPE_APPEND &&
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen (sync_rec->type != MAIL_INDEX_SYNC_TYPE_EXPUNGE ||
b08b33d1f5ce3721dc2d83586c9cb0ca141331fdTimo Sirainen !sync_ctx->ibox->mbox_readonly)) {
b08b33d1f5ce3721dc2d83586c9cb0ca141331fdTimo Sirainen buffer_append(sync_ctx->syncs, sync_rec,
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen sizeof(*sync_rec));
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen if (sync_rec->type == MAIL_INDEX_SYNC_TYPE_EXPUNGE)
f6699a08521aacc4c2bb5b6175691dad5f715f8cTimo Sirainen *sync_expunge_r = TRUE;
6843896c40bee4f9b6680ca7ced598c446e9f999Timo Sirainen }
6843896c40bee4f9b6680ca7ced598c446e9f999Timo Sirainen
6843896c40bee4f9b6680ca7ced598c446e9f999Timo Sirainen ret = mail_index_sync_next(sync_ctx->index_sync_ctx, sync_rec);
6843896c40bee4f9b6680ca7ced598c446e9f999Timo Sirainen if (ret < 0) {
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen mail_storage_set_index_error(sync_ctx->ibox);
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen return -1;
42456ec33fe65feb411890f99d436071e0185ee3Timo Sirainen }
022412398e56a8f31ef111cfd7271498d64af9a9Timo Sirainen
022412398e56a8f31ef111cfd7271498d64af9a9Timo Sirainen if (ret == 0) {
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen memset(sync_rec, 0, sizeof(*sync_rec));
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen break;
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen }
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen if (sync_rec->type == MAIL_INDEX_SYNC_TYPE_APPEND) {
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen if (sync_rec->uid2 >= sync_ctx->next_uid) {
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen sync_ctx->next_uid = sync_rec->uid2 + 1;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen sync_ctx->update_base_uid_last = sync_rec->uid2;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen }
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen memset(sync_rec, 0, sizeof(*sync_rec));
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen }
f6699a08521aacc4c2bb5b6175691dad5f715f8cTimo Sirainen }
f6699a08521aacc4c2bb5b6175691dad5f715f8cTimo Sirainen
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen if (!*sync_expunge_r)
f6699a08521aacc4c2bb5b6175691dad5f715f8cTimo Sirainen *sync_expunge_r = mbox_sync_buf_have_expunges(sync_ctx->syncs);
f6699a08521aacc4c2bb5b6175691dad5f715f8cTimo Sirainen
df4018ae2f0a95be602f724ca70df7e0e3bd6a7dTimo Sirainen return 0;
df4018ae2f0a95be602f724ca70df7e0e3bd6a7dTimo Sirainen}
a393d9d6dabdc46cf724f8cb004a652b4036d53dTimo Sirainen
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainenstatic void mbox_sync_apply_index_syncs(buffer_t *syncs_buf, uint8_t *flags,
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen keywords_mask_t keywords)
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen{
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen const struct mail_index_sync_rec *sync;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen size_t size, i;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
a393d9d6dabdc46cf724f8cb004a652b4036d53dTimo Sirainen sync = buffer_get_data(syncs_buf, &size);
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen size /= sizeof(*sync);
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen for (i = 0; i < size; i++) {
2bf7bb14894faf721518e2122a14a2389ef94078Timo Sirainen if (sync[i].type != MAIL_INDEX_SYNC_TYPE_FLAGS)
9a06cabdfdf4d5e2f19a07e506c3c7d08a7e7038Timo Sirainen continue;
a2637488c8d514ec1ac3914811deee814f9761b3Timo Sirainen mail_index_sync_flags_apply(&sync[i], flags, keywords);
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen }
2bf7bb14894faf721518e2122a14a2389ef94078Timo Sirainen}
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen
2bf7bb14894faf721518e2122a14a2389ef94078Timo Sirainenstatic int
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainenmbox_sync_read_index_rec(struct mbox_sync_context *sync_ctx,
9a06cabdfdf4d5e2f19a07e506c3c7d08a7e7038Timo Sirainen uint32_t uid, const struct mail_index_record **rec_r)
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen{
a2637488c8d514ec1ac3914811deee814f9761b3Timo Sirainen const struct mail_index_record *rec = NULL;
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen uint32_t messages_count;
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen int ret = 0;
2bf7bb14894faf721518e2122a14a2389ef94078Timo Sirainen
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen messages_count = mail_index_view_get_message_count(sync_ctx->sync_view);
9a06cabdfdf4d5e2f19a07e506c3c7d08a7e7038Timo Sirainen while (sync_ctx->idx_seq <= messages_count) {
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen ret = mail_index_lookup(sync_ctx->sync_view,
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen sync_ctx->idx_seq, &rec);
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen if (ret < 0) {
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen mail_storage_set_index_error(sync_ctx->ibox);
6843896c40bee4f9b6680ca7ced598c446e9f999Timo Sirainen return -1;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen }
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen if (uid <= rec->uid)
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen break;
73b50eecfc31750a312e2f940023f522eb07178cTimo 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 }
f6699a08521aacc4c2bb5b6175691dad5f715f8cTimo Sirainen
f6699a08521aacc4c2bb5b6175691dad5f715f8cTimo Sirainen if (ret == 0 && uid < sync_ctx->hdr->next_uid) {
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen /* this UID was already in index and it was expunged */
f6699a08521aacc4c2bb5b6175691dad5f715f8cTimo Sirainen mail_storage_set_critical(sync_ctx->ibox->box.storage,
f6699a08521aacc4c2bb5b6175691dad5f715f8cTimo Sirainen "mbox sync: Expunged message reappeared in mailbox %s "
df4018ae2f0a95be602f724ca70df7e0e3bd6a7dTimo Sirainen "(UID %u < %u)", sync_ctx->ibox->path, uid,
df4018ae2f0a95be602f724ca70df7e0e3bd6a7dTimo Sirainen sync_ctx->hdr->next_uid);
7f3be7d885c75cdd77f536929a45bc9764595960Timo Sirainen ret = 0;
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen } else if (rec != NULL && rec->uid != uid) {
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen /* new UID in the middle of the mailbox - shouldn't happen */
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen mail_storage_set_critical(sync_ctx->ibox->box.storage,
ea5f188fc29dfaa0c4071e6413e16e1d04263722Timo Sirainen "mbox sync: UID inserted in the middle of mailbox %s "
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen "(%u > %u)", sync_ctx->ibox->path, rec->uid, uid);
f0f9c8e94abac18f8acd91b9e724c4c32863723aTimo Sirainen ret = 0; rec = NULL;
7f3be7d885c75cdd77f536929a45bc9764595960Timo Sirainen } else {
7f3be7d885c75cdd77f536929a45bc9764595960Timo Sirainen ret = 1;
7f3be7d885c75cdd77f536929a45bc9764595960Timo Sirainen }
7f3be7d885c75cdd77f536929a45bc9764595960Timo Sirainen
7f3be7d885c75cdd77f536929a45bc9764595960Timo Sirainen *rec_r = rec;
7f3be7d885c75cdd77f536929a45bc9764595960Timo Sirainen return ret;
7f3be7d885c75cdd77f536929a45bc9764595960Timo Sirainen}
7f3be7d885c75cdd77f536929a45bc9764595960Timo 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)
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen{
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen const struct mail_index_record *rec = NULL;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen uint32_t messages_count;
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainen const void *data;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen int ret;
4d25408732be27e91f0430f71e87242760c2517cTimo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen messages_count = mail_index_view_get_message_count(sync_ctx->sync_view);
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen while (sync_ctx->idx_seq <= messages_count) {
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen ret = mail_index_lookup(sync_ctx->sync_view,
4d25408732be27e91f0430f71e87242760c2517cTimo Sirainen sync_ctx->idx_seq, &rec);
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen if (ret < 0) {
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen mail_storage_set_index_error(sync_ctx->ibox);
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen return -1;
4d25408732be27e91f0430f71e87242760c2517cTimo Sirainen }
4d25408732be27e91f0430f71e87242760c2517cTimo Sirainen
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen if (mail_index_lookup_ext(sync_ctx->sync_view,
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen sync_ctx->idx_seq,
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen sync_ctx->ibox->md5hdr_ext_idx,
8af07808ba203f8709e2ff9eaf2291e1c4a4d53dTimo Sirainen &data) < 0) {
7797aa2479e99aeb71057b7a2584b2cb72e4d3f8Timo Sirainen mail_storage_set_index_error(sync_ctx->ibox);
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen return -1;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen }
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen if (data != NULL && memcmp(data, hdr_md5_sum, 16) == 0)
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen break;
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen /* externally expunged message, remove from index */
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen mail_index_expunge(sync_ctx->t, sync_ctx->idx_seq);
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen sync_ctx->idx_seq++;
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen rec = NULL;
61f5256ef248d35459b53534ae428bf6d016e1c5Timo Sirainen }
61f5256ef248d35459b53534ae428bf6d016e1c5Timo Sirainen
61f5256ef248d35459b53534ae428bf6d016e1c5Timo Sirainen *rec_r = rec;
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen return 0;
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen}
84ed9f8f3d0e5ed47607ef417618e49e4f865557Timo Sirainen
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainenstatic int
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainenmbox_sync_update_from_offset(struct mbox_sync_context *sync_ctx,
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen struct mbox_sync_mail *mail,
a0b0d629931773c17a236f6214adbe0e13b9b3fdTimo Sirainen int nocheck)
a0b0d629931773c17a236f6214adbe0e13b9b3fdTimo Sirainen{
a0b0d629931773c17a236f6214adbe0e13b9b3fdTimo Sirainen const void *data;
a0b0d629931773c17a236f6214adbe0e13b9b3fdTimo Sirainen uint64_t offset;
a0b0d629931773c17a236f6214adbe0e13b9b3fdTimo Sirainen
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen if (!nocheck) {
ea5f188fc29dfaa0c4071e6413e16e1d04263722Timo Sirainen /* see if from_offset needs updating */
a0b0d629931773c17a236f6214adbe0e13b9b3fdTimo Sirainen if (mail_index_lookup_ext(sync_ctx->sync_view,
a0b0d629931773c17a236f6214adbe0e13b9b3fdTimo Sirainen sync_ctx->idx_seq,
a0b0d629931773c17a236f6214adbe0e13b9b3fdTimo Sirainen sync_ctx->ibox->mbox_ext_idx,
ea5f188fc29dfaa0c4071e6413e16e1d04263722Timo Sirainen &data) < 0) {
a0b0d629931773c17a236f6214adbe0e13b9b3fdTimo Sirainen mail_storage_set_index_error(sync_ctx->ibox);
a0b0d629931773c17a236f6214adbe0e13b9b3fdTimo Sirainen return -1;
a0b0d629931773c17a236f6214adbe0e13b9b3fdTimo Sirainen }
a0b0d629931773c17a236f6214adbe0e13b9b3fdTimo Sirainen
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen if (data != NULL &&
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen *((const uint64_t *)data) == mail->from_offset)
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen return 0;
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen }
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen offset = mail->from_offset;
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen mail_index_update_ext(sync_ctx->t, sync_ctx->idx_seq,
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen sync_ctx->ibox->mbox_ext_idx, &offset);
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen return 0;
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen}
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainenstatic int mbox_sync_update_index(struct mbox_sync_context *sync_ctx,
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen struct mbox_sync_mail_context *mail_ctx,
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen const struct mail_index_record *rec)
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen{
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen struct mbox_sync_mail *mail = &mail_ctx->mail;
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen keywords_mask_t idx_keywords;
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen uint8_t idx_flags, mbox_flags;
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen if (rec == NULL) {
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen /* new message */
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen mail_index_append(sync_ctx->t, mail->uid, &sync_ctx->idx_seq);
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen mbox_flags = mail->flags & (MAIL_FLAGS_MASK^MAIL_RECENT);
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen if (mail_ctx->dirty)
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen mbox_flags |= MAIL_INDEX_MAIL_FLAG_DIRTY;
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen if (sync_ctx->ibox->keep_recent &&
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen (mail->flags & MBOX_NONRECENT) == 0)
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen mbox_flags |= MAIL_RECENT;
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen mail_index_update_flags(sync_ctx->t, sync_ctx->idx_seq,
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen MODIFY_REPLACE, mbox_flags,
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen mail->keywords);
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen if (sync_ctx->ibox->md5hdr_ext_idx != 0) {
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen mail_index_update_ext(sync_ctx->t, sync_ctx->idx_seq,
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen sync_ctx->ibox->md5hdr_ext_idx,
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen mail_ctx->hdr_md5_sum);
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen }
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen if (str_len(mail_ctx->uidl) > 0) {
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen /*FIXME:mail_cache_add(sync_ctx->cache_trans,
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen MAIL_CACHE_UID_STRING,
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen str_data(mail_ctx->uidl),
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen str_len(mail_ctx->uidl));*/
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen }
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen } else {
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen /* see if flags changed */
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen idx_flags = rec->flags;
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen memcpy(idx_keywords, rec->keywords, INDEX_KEYWORDS_BYTE_COUNT);
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen mbox_sync_apply_index_syncs(sync_ctx->syncs,
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen &idx_flags, idx_keywords);
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen if ((idx_flags & MAIL_INDEX_MAIL_FLAG_DIRTY) != 0) {
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen /* flags are dirty, ignore whatever was in the file.
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen but remove recent flag if needed. */
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen mbox_flags = idx_flags;
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen if (!sync_ctx->ibox->keep_recent)
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen mbox_flags &= ~MAIL_RECENT;
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen } else {
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen mbox_flags = (rec->flags & ~MAIL_FLAGS_MASK) |
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen (mail->flags & MAIL_FLAGS_MASK);
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen mbox_flags ^= MAIL_RECENT;
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen }
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen if (mail_ctx->dirty)
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen mbox_flags |= MAIL_INDEX_MAIL_FLAG_DIRTY;
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen else if (!sync_ctx->delay_writes)
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen mbox_flags &= ~MAIL_INDEX_MAIL_FLAG_DIRTY;
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen if ((idx_flags & ~MAIL_INDEX_MAIL_FLAG_DIRTY) ==
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen (mbox_flags & ~MAIL_INDEX_MAIL_FLAG_DIRTY) &&
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen memcmp(idx_keywords, mail->keywords,
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen INDEX_KEYWORDS_BYTE_COUNT) == 0) {
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen if (idx_flags != mbox_flags) {
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen /* dirty flag state changed */
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen int dirty = (mbox_flags &
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen MAIL_INDEX_MAIL_FLAG_DIRTY) != 0;
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen memset(idx_keywords, 0,
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen INDEX_KEYWORDS_BYTE_COUNT);
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen mail_index_update_flags(sync_ctx->t,
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen sync_ctx->idx_seq,
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen dirty ? MODIFY_ADD : MODIFY_REMOVE,
5137d2d80255938a0f5fb8f3c1a21b34cf11ada3Timo Sirainen MAIL_INDEX_MAIL_FLAG_DIRTY,
33d63688ed8b26dc333e3c2edbfb2fe6e412604dTimo Sirainen idx_keywords);
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen }
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen } else if ((idx_flags & ~MAIL_RECENT) !=
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen (mbox_flags & ~MAIL_RECENT) ||
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen memcmp(idx_keywords, mail->keywords,
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen INDEX_KEYWORDS_BYTE_COUNT) != 0) {
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen mail_index_update_flags(sync_ctx->t, sync_ctx->idx_seq,
d0d7fcf3ce44f26fdf34c1542a25cec644c5c4c7Timo Sirainen MODIFY_REPLACE, mbox_flags,
5d98a279f2726a8c38ef1e8e3c54d6c62d523a65Timo Sirainen mail->keywords);
5d98a279f2726a8c38ef1e8e3c54d6c62d523a65Timo Sirainen } else if (((idx_flags ^ mbox_flags) & MAIL_RECENT) != 0) {
5d98a279f2726a8c38ef1e8e3c54d6c62d523a65Timo Sirainen /* drop recent flag */
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen memset(idx_keywords, 0, INDEX_KEYWORDS_BYTE_COUNT);
d0d7fcf3ce44f26fdf34c1542a25cec644c5c4c7Timo Sirainen mail_index_update_flags(sync_ctx->t, sync_ctx->idx_seq,
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen MODIFY_REMOVE, MAIL_RECENT,
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen idx_keywords);
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen }
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen }
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen if (mail_ctx->recent)
7f3be7d885c75cdd77f536929a45bc9764595960Timo Sirainen index_mailbox_set_recent(sync_ctx->ibox, sync_ctx->idx_seq);
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen
7797aa2479e99aeb71057b7a2584b2cb72e4d3f8Timo Sirainen /* update from_offsets, but not if we're going to rewrite this message.
ea5f188fc29dfaa0c4071e6413e16e1d04263722Timo Sirainen rewriting would just move it anyway. */
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen if (sync_ctx->need_space_seq == 0) {
7f3be7d885c75cdd77f536929a45bc9764595960Timo Sirainen int nocheck = rec == NULL || sync_ctx->expunged_space > 0;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen if (mbox_sync_update_from_offset(sync_ctx, mail, nocheck) < 0)
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen return -1;
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen }
3f26c5aced2e71efc783f26bb8a7ac53f7504622Timo Sirainen return 0;
3f26c5aced2e71efc783f26bb8a7ac53f7504622Timo Sirainen}
3f26c5aced2e71efc783f26bb8a7ac53f7504622Timo Sirainen
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainenstatic int mbox_read_from_line(struct mbox_sync_mail_context *ctx)
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen{
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen struct istream *input = ctx->sync_ctx->file_input;
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen const unsigned char *data;
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen size_t size, from_line_size;
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen buffer_set_used_size(ctx->sync_ctx->from_line, 0);
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen from_line_size = ctx->hdr_offset - ctx->mail.from_offset;
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen i_stream_seek(input, ctx->mail.from_offset);
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen for (;;) {
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen data = i_stream_get_data(input, &size);
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen if (size >= from_line_size)
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen size = from_line_size;
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen buffer_append(ctx->sync_ctx->from_line, data, size);
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen i_stream_skip(input, size);
a0b0d629931773c17a236f6214adbe0e13b9b3fdTimo Sirainen from_line_size -= size;
a0b0d629931773c17a236f6214adbe0e13b9b3fdTimo Sirainen
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen if (from_line_size == 0)
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen break;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen if (i_stream_read(input) < 0)
279cc94ab086f6a3cb764b1b98ff6b936efa3eaeTimo Sirainen return -1;
279cc94ab086f6a3cb764b1b98ff6b936efa3eaeTimo Sirainen }
279cc94ab086f6a3cb764b1b98ff6b936efa3eaeTimo Sirainen
1d3f7c1278168d5b1cbfa9a2cc9929a0909056b4Timo Sirainen return 0;
279cc94ab086f6a3cb764b1b98ff6b936efa3eaeTimo Sirainen}
e8a35266a5ceacdfafeeffd6bddae77931ff97ebTimo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainenstatic int
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainenmbox_write_from_line(struct mbox_sync_mail_context *ctx)
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen{
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainen string_t *str = ctx->sync_ctx->from_line;
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen if (pwrite_full(ctx->sync_ctx->fd, str_data(str), str_len(str),
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo 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
4d25408732be27e91f0430f71e87242760c2517cTimo Sirainenstatic void update_from_offsets(struct mbox_sync_context *sync_ctx)
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen{
4d25408732be27e91f0430f71e87242760c2517cTimo Sirainen const struct mbox_sync_mail *mails;
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen uint32_t idx, ext_idx;
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen uint64_t offset;
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen size_t size;
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen ext_idx = sync_ctx->ibox->mbox_ext_idx;
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen mails = buffer_get_modifyable_data(sync_ctx->mails, &size);
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen size /= sizeof(*mails);
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen for (idx = 0; idx < size; idx++) {
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen if (mails[idx].idx_seq == 0 ||
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen (mails[idx].flags & MBOX_EXPUNGED) != 0)
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen continue;
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen offset = mails[idx].from_offset;
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen mail_index_update_ext(sync_ctx->t, mails[idx].idx_seq,
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen ext_idx, &offset);
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen }
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen}
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainenstatic void mbox_sync_handle_expunge(struct mbox_sync_mail_context *mail_ctx)
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen{
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen mail_ctx->mail.flags = MBOX_EXPUNGED;
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen mail_ctx->mail.offset = mail_ctx->mail.from_offset;
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen mail_ctx->mail.space =
16aba431c576c1dbd99cbaae4f9d65eea9ad73c2Timo Sirainen mail_ctx->body_offset - mail_ctx->mail.from_offset +
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen mail_ctx->mail.body_size;
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen mail_ctx->mail.body_size = 0;
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen if (mail_ctx->sync_ctx->dest_first_mail) {
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen /* expunging first message, fix space to contain next
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen message's \n header too since it will be removed. */
16aba431c576c1dbd99cbaae4f9d65eea9ad73c2Timo Sirainen mail_ctx->mail.space++;
16aba431c576c1dbd99cbaae4f9d65eea9ad73c2Timo Sirainen }
16aba431c576c1dbd99cbaae4f9d65eea9ad73c2Timo Sirainen
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen mail_ctx->sync_ctx->expunged_space += mail_ctx->mail.space;
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen}
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen
16aba431c576c1dbd99cbaae4f9d65eea9ad73c2Timo Sirainenstatic int mbox_sync_handle_header(struct mbox_sync_mail_context *mail_ctx)
a2637488c8d514ec1ac3914811deee814f9761b3Timo Sirainen{
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen struct mbox_sync_context *sync_ctx = mail_ctx->sync_ctx;
16aba431c576c1dbd99cbaae4f9d65eea9ad73c2Timo Sirainen off_t move_diff;
16aba431c576c1dbd99cbaae4f9d65eea9ad73c2Timo Sirainen int ret;
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen if (sync_ctx->expunged_space > 0 && sync_ctx->need_space_seq == 0) {
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen /* move the header backwards to fill expunged space */
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen move_diff = -sync_ctx->expunged_space;
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen /* read the From-line before rewriting overwrites it */
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen if (mbox_read_from_line(mail_ctx) < 0)
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen return -1;
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen mbox_sync_update_header(mail_ctx, sync_ctx->syncs);
a2637488c8d514ec1ac3914811deee814f9761b3Timo Sirainen ret = mbox_sync_try_rewrite(mail_ctx, move_diff);
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen if (ret < 0)
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen return -1;
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen if (ret > 0) {
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen /* rewrite successful, write From-line to
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen new location */
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen mail_ctx->mail.from_offset += move_diff;
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen mail_ctx->mail.offset += move_diff;
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen if (mbox_write_from_line(mail_ctx) < 0)
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen return -1;
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen }
299183fbb6ec5d0828a0880da372540421ac4665Timo Sirainen } else if (mail_ctx->need_rewrite ||
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen buffer_get_used_size(sync_ctx->syncs) != 0 ||
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen (mail_ctx->seq == 1 &&
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen sync_ctx->update_base_uid_last != 0)) {
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen mbox_sync_update_header(mail_ctx, sync_ctx->syncs);
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen if (sync_ctx->delay_writes) {
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen /* mark it dirty and do it later */
064bfeee2f9156683b191cc0f3f7b242720942f7Timo Sirainen mail_ctx->dirty = TRUE;
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen return 0;
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen }
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen
b225c3c65f360d7b833f09f9b2fb3035ed5ea600Timo Sirainen if ((ret = mbox_sync_try_rewrite(mail_ctx, 0)) < 0)
064bfeee2f9156683b191cc0f3f7b242720942f7Timo Sirainen return -1;
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen } else {
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen /* nothing to do */
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen return 0;
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen }
299183fbb6ec5d0828a0880da372540421ac4665Timo Sirainen
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen if (ret == 0 && sync_ctx->need_space_seq == 0) {
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen /* first mail with no space to write it */
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen sync_ctx->need_space_seq = sync_ctx->seq;
8907d617ce7c4f390c0f42f6f694db2fecdd5775Timo Sirainen sync_ctx->space_diff = 0;
01cbf4ac5d44137ab434791be7f838d98d0fcf3bTimo Sirainen
01cbf4ac5d44137ab434791be7f838d98d0fcf3bTimo Sirainen if (sync_ctx->expunged_space > 0) {
39775ad03c459efe64cce924658da5094ba417e1Timo Sirainen /* create dummy message to describe the expunged data */
39775ad03c459efe64cce924658da5094ba417e1Timo Sirainen struct mbox_sync_mail mail;
ab3c1eab9ca13916358a9e8b12df8212fefb7dbfTimo Sirainen
01cbf4ac5d44137ab434791be7f838d98d0fcf3bTimo Sirainen memset(&mail, 0, sizeof(mail));
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen mail.flags = MBOX_EXPUNGED;
3021a062b16ff0138408be6107d6bcd0ced280b9Timo Sirainen mail.offset = mail_ctx->mail.from_offset -
39775ad03c459efe64cce924658da5094ba417e1Timo Sirainen sync_ctx->expunged_space;
39775ad03c459efe64cce924658da5094ba417e1Timo Sirainen mail.space = sync_ctx->expunged_space;
1e76a5b92f9d82d557f81f080f3dfad1c9d8f200Timo Sirainen
e5c08648676d1989f6e70b95e5990c26b3e8b96bTimo Sirainen sync_ctx->need_space_seq--;
e5c08648676d1989f6e70b95e5990c26b3e8b96bTimo Sirainen buffer_append(sync_ctx->mails, &mail, sizeof(mail));
e05ea8311ae16687295048e88ca205dfe29fbcbfTimo Sirainen }
39775ad03c459efe64cce924658da5094ba417e1Timo Sirainen }
39775ad03c459efe64cce924658da5094ba417e1Timo Sirainen return 0;
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen}
01cbf4ac5d44137ab434791be7f838d98d0fcf3bTimo Sirainen
01cbf4ac5d44137ab434791be7f838d98d0fcf3bTimo Sirainenstatic int
01cbf4ac5d44137ab434791be7f838d98d0fcf3bTimo Sirainenmbox_sync_handle_missing_space(struct mbox_sync_mail_context *mail_ctx)
8907d617ce7c4f390c0f42f6f694db2fecdd5775Timo Sirainen{
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen struct mbox_sync_context *sync_ctx = mail_ctx->sync_ctx;
c35d0c3eb4ba89432896e1f9770ab31cc63c232bTimo Sirainen uoff_t end_offset, move_diff, extra_space, needed_space;
5137d2d80255938a0f5fb8f3c1a21b34cf11ada3Timo Sirainen uint32_t last_seq;
5137d2d80255938a0f5fb8f3c1a21b34cf11ada3Timo Sirainen
5137d2d80255938a0f5fb8f3c1a21b34cf11ada3Timo Sirainen buffer_append(sync_ctx->mails, &mail_ctx->mail, sizeof(mail_ctx->mail));
5137d2d80255938a0f5fb8f3c1a21b34cf11ada3Timo Sirainen
5137d2d80255938a0f5fb8f3c1a21b34cf11ada3Timo Sirainen sync_ctx->space_diff += mail_ctx->mail.space;
5137d2d80255938a0f5fb8f3c1a21b34cf11ada3Timo Sirainen if (sync_ctx->space_diff < 0)
e063aca6bc2f08bec516d4b631052ea9191f011dTimo Sirainen return 0;
c35d0c3eb4ba89432896e1f9770ab31cc63c232bTimo Sirainen
1e76a5b92f9d82d557f81f080f3dfad1c9d8f200Timo Sirainen /* we have enough space now */
4d25408732be27e91f0430f71e87242760c2517cTimo Sirainen if (mail_ctx->mail.uid == 0) {
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen /* this message was expunged. fill more or less of the space. */
4d25408732be27e91f0430f71e87242760c2517cTimo Sirainen extra_space = MBOX_HEADER_PADDING *
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen (sync_ctx->seq - sync_ctx->need_space_seq + 1);
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen needed_space = mail_ctx->mail.space - sync_ctx->space_diff;
5137d2d80255938a0f5fb8f3c1a21b34cf11ada3Timo Sirainen if ((uoff_t)sync_ctx->space_diff > needed_space + extra_space) {
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen /* don't waste too much on padding */
c35d0c3eb4ba89432896e1f9770ab31cc63c232bTimo Sirainen sync_ctx->expunged_space = mail_ctx->mail.space -
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen (needed_space + extra_space);
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen sync_ctx->space_diff = needed_space + extra_space;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen } else {
c35d0c3eb4ba89432896e1f9770ab31cc63c232bTimo Sirainen extra_space = sync_ctx->space_diff - needed_space;
c35d0c3eb4ba89432896e1f9770ab31cc63c232bTimo Sirainen }
c35d0c3eb4ba89432896e1f9770ab31cc63c232bTimo Sirainen last_seq = sync_ctx->seq - 1;
c35d0c3eb4ba89432896e1f9770ab31cc63c232bTimo Sirainen buffer_set_used_size(sync_ctx->mails, sync_ctx->mails->used -
2be66b9eddad3841a1195fe9aeb1eaf0f28f1116Timo Sirainen sizeof(mail_ctx->mail));
2be66b9eddad3841a1195fe9aeb1eaf0f28f1116Timo Sirainen end_offset = mail_ctx->mail.from_offset;
c35d0c3eb4ba89432896e1f9770ab31cc63c232bTimo Sirainen move_diff = sync_ctx->space_diff;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen } else {
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen /* this message gave enough space from headers. rewriting stops
c35d0c3eb4ba89432896e1f9770ab31cc63c232bTimo Sirainen at the end of this message's headers. */
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen sync_ctx->expunged_space = 0;
b2ecd50bb98c44816cb07c17aa17fae2b425f941Timo Sirainen last_seq = sync_ctx->seq;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen end_offset = mail_ctx->body_offset;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen move_diff = 0;
c35d0c3eb4ba89432896e1f9770ab31cc63c232bTimo Sirainen extra_space = sync_ctx->space_diff;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen }
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen if (mbox_sync_rewrite(sync_ctx, end_offset, move_diff, extra_space,
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen sync_ctx->need_space_seq, last_seq) < 0)
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen return -1;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
b2ecd50bb98c44816cb07c17aa17fae2b425f941Timo Sirainen update_from_offsets(sync_ctx);
c35d0c3eb4ba89432896e1f9770ab31cc63c232bTimo Sirainen
7fd72a47d7ddfbd38c8697e228b6951f495dfb61Timo Sirainen /* mail_ctx may contain wrong data after rewrite, so make sure we
7fd72a47d7ddfbd38c8697e228b6951f495dfb61Timo Sirainen don't try to access it */
7fd72a47d7ddfbd38c8697e228b6951f495dfb61Timo Sirainen memset(mail_ctx, 0, sizeof(*mail_ctx));
7fd72a47d7ddfbd38c8697e228b6951f495dfb61Timo Sirainen
7fd72a47d7ddfbd38c8697e228b6951f495dfb61Timo Sirainen sync_ctx->need_space_seq = 0;
c35d0c3eb4ba89432896e1f9770ab31cc63c232bTimo Sirainen sync_ctx->space_diff = 0;
c35d0c3eb4ba89432896e1f9770ab31cc63c232bTimo Sirainen buffer_set_used_size(sync_ctx->mails, 0);
7fd72a47d7ddfbd38c8697e228b6951f495dfb61Timo Sirainen return 0;
7fd72a47d7ddfbd38c8697e228b6951f495dfb61Timo Sirainen}
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainenstatic int
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainenmbox_sync_seek_to_seq(struct mbox_sync_context *sync_ctx, uint32_t seq)
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen{
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen struct index_mailbox *ibox = sync_ctx->ibox;
6a1e4eb2c6a267bec1e8704ce9137bebb7792702Timo Sirainen uoff_t old_offset;
60d3fa9883237e896a8704275b6116fa46f7ffdaTimo Sirainen uint32_t uid;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen int ret, deleted;
659fe5d24825b160cae512538088020d97a60239Timo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen if (seq == 0) {
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen if (istream_raw_mbox_seek(ibox->mbox_stream, 0) < 0) {
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen mail_storage_set_error(ibox->box.storage,
c35d0c3eb4ba89432896e1f9770ab31cc63c232bTimo Sirainen "Mailbox isn't a valid mbox file");
c35d0c3eb4ba89432896e1f9770ab31cc63c232bTimo Sirainen return -1;
c35d0c3eb4ba89432896e1f9770ab31cc63c232bTimo Sirainen }
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen seq++;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen } else {
064bfeee2f9156683b191cc0f3f7b242720942f7Timo Sirainen old_offset = istream_raw_mbox_get_start_offset(sync_ctx->input);
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
7fd72a47d7ddfbd38c8697e228b6951f495dfb61Timo Sirainen ret = mbox_file_seek(ibox, sync_ctx->sync_view, seq, &deleted);
7fd72a47d7ddfbd38c8697e228b6951f495dfb61Timo Sirainen if (ret < 0) {
7fd72a47d7ddfbd38c8697e228b6951f495dfb61Timo Sirainen mail_storage_set_index_error(ibox);
7fd72a47d7ddfbd38c8697e228b6951f495dfb61Timo Sirainen return -1;
c35d0c3eb4ba89432896e1f9770ab31cc63c232bTimo Sirainen }
7fd72a47d7ddfbd38c8697e228b6951f495dfb61Timo Sirainen
b2ecd50bb98c44816cb07c17aa17fae2b425f941Timo Sirainen if (ret == 0) {
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen if (istream_raw_mbox_seek(ibox->mbox_stream,
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen old_offset) < 0) {
7a6b45405fb1544ac476e6eb1402a70cc1ddcdcfTimo Sirainen mail_storage_set_critical(ibox->box.storage,
7a6b45405fb1544ac476e6eb1402a70cc1ddcdcfTimo Sirainen "Error seeking back to original "
7a6b45405fb1544ac476e6eb1402a70cc1ddcdcfTimo Sirainen "offset %s in mbox file %s",
7a6b45405fb1544ac476e6eb1402a70cc1ddcdcfTimo Sirainen dec2str(old_offset), ibox->path);
7a6b45405fb1544ac476e6eb1402a70cc1ddcdcfTimo Sirainen return -1;
7a6b45405fb1544ac476e6eb1402a70cc1ddcdcfTimo Sirainen }
6a1e4eb2c6a267bec1e8704ce9137bebb7792702Timo Sirainen return 0;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen }
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen }
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen if (seq <= 1)
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen uid = 0;
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen else if (mail_index_lookup_uid(sync_ctx->sync_view, seq-1, &uid) < 0) {
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen mail_storage_set_index_error(ibox);
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen return -1;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen }
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen sync_ctx->prev_msg_uid = uid;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen /* set to -1, since it's always increased later */
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen sync_ctx->seq = seq-1;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen if (sync_ctx->seq == 0 &&
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen istream_raw_mbox_get_start_offset(sync_ctx->input) != 0) {
1e76a5b92f9d82d557f81f080f3dfad1c9d8f200Timo Sirainen /* this mbox has pseudo mail which contains the X-IMAP header */
36816b5af1472ae76a1909ae3cf29fd614b2ebfcTimo Sirainen sync_ctx->seq++;
829c036d4ddfbd9ea49bd8a7c54e3057177d346eTimo Sirainen }
36816b5af1472ae76a1909ae3cf29fd614b2ebfcTimo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen sync_ctx->idx_seq = seq;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen sync_ctx->dest_first_mail = sync_ctx->seq == 0;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen (void)istream_raw_mbox_get_body_offset(sync_ctx->input);
dc8552739fa29f011ab71ec383ec6d580a5a9661Timo Sirainen return 1;
dc8552739fa29f011ab71ec383ec6d580a5a9661Timo Sirainen}
8d5991f5c4a8840bf1ea754093dbec505564ab78Timo Sirainen
dc8552739fa29f011ab71ec383ec6d580a5a9661Timo Sirainenstatic int
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainenmbox_sync_seek_to_uid(struct mbox_sync_context *sync_ctx, uint32_t uid)
39775ad03c459efe64cce924658da5094ba417e1Timo Sirainen{
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen uint32_t seq1, seq2;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen uoff_t file_size;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen if (mail_index_lookup_uid_range(sync_ctx->sync_view, uid, (uint32_t)-1,
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen &seq1, &seq2) < 0) {
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen mail_storage_set_index_error(sync_ctx->ibox);
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen return -1;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen }
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
4214b59ac7f3899f8d887d055ef519f5a622d249Timo Sirainen if (seq1 == 0) {
7a6b45405fb1544ac476e6eb1402a70cc1ddcdcfTimo Sirainen /* doesn't exist anymore, seek to end of file */
f5b4979e2780c4df112a300967d647e2fdd73511Timo Sirainen file_size = i_stream_get_size(sync_ctx->ibox->mbox_file_stream);
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen if (istream_raw_mbox_seek(sync_ctx->ibox->mbox_stream,
2cb565cd978aafd5714792b5161889986d49e431Timo Sirainen file_size) < 0) {
2cb565cd978aafd5714792b5161889986d49e431Timo Sirainen mail_storage_set_critical(sync_ctx->ibox->box.storage,
343a527f805ca5cce78496b959d6def70e5d0cd4Timo Sirainen "Error seeking to end of mbox file %s",
5486e1e123484f3a8d7d895e8ac41156f2a96305Timo Sirainen sync_ctx->ibox->path);
5486e1e123484f3a8d7d895e8ac41156f2a96305Timo Sirainen return -1;
5486e1e123484f3a8d7d895e8ac41156f2a96305Timo Sirainen }
5486e1e123484f3a8d7d895e8ac41156f2a96305Timo Sirainen return 1;
f5b4979e2780c4df112a300967d647e2fdd73511Timo Sirainen }
5486e1e123484f3a8d7d895e8ac41156f2a96305Timo Sirainen
5486e1e123484f3a8d7d895e8ac41156f2a96305Timo Sirainen return mbox_sync_seek_to_seq(sync_ctx, seq1);
5486e1e123484f3a8d7d895e8ac41156f2a96305Timo Sirainen}
5486e1e123484f3a8d7d895e8ac41156f2a96305Timo Sirainen
6e4cd4ba520bc22ce375de378f4751136ebcf75aTimo Sirainenstatic int mbox_sync_loop(struct mbox_sync_context *sync_ctx,
b2ecd50bb98c44816cb07c17aa17fae2b425f941Timo Sirainen struct mbox_sync_mail_context *mail_ctx,
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen uint32_t min_message_count, int partial)
dc8552739fa29f011ab71ec383ec6d580a5a9661Timo Sirainen{
dc8552739fa29f011ab71ec383ec6d580a5a9661Timo Sirainen const struct mail_index_record *rec;
dc8552739fa29f011ab71ec383ec6d580a5a9661Timo Sirainen uint32_t uid, messages_count;
dc8552739fa29f011ab71ec383ec6d580a5a9661Timo Sirainen uoff_t offset;
dc8552739fa29f011ab71ec383ec6d580a5a9661Timo Sirainen int ret, expunged;
dc8552739fa29f011ab71ec383ec6d580a5a9661Timo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen messages_count = mail_index_view_get_message_count(sync_ctx->sync_view);
dc8552739fa29f011ab71ec383ec6d580a5a9661Timo Sirainen
b2ecd50bb98c44816cb07c17aa17fae2b425f941Timo Sirainen if (!mail_index_sync_have_more(sync_ctx->index_sync_ctx) ||
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen (!partial && min_message_count != 0)) {
6a1e4eb2c6a267bec1e8704ce9137bebb7792702Timo Sirainen ret = mbox_sync_seek_to_seq(sync_ctx, partial ?
4214b59ac7f3899f8d887d055ef519f5a622d249Timo Sirainen messages_count : 0);
4214b59ac7f3899f8d887d055ef519f5a622d249Timo Sirainen } else {
4214b59ac7f3899f8d887d055ef519f5a622d249Timo Sirainen /* we sync only what we need to. jump to first record that
4214b59ac7f3899f8d887d055ef519f5a622d249Timo Sirainen needs updating */
8d5991f5c4a8840bf1ea754093dbec505564ab78Timo Sirainen const struct mail_index_sync_rec *sync_rec;
6a1e4eb2c6a267bec1e8704ce9137bebb7792702Timo Sirainen size_t size;
6a1e4eb2c6a267bec1e8704ce9137bebb7792702Timo Sirainen
4214b59ac7f3899f8d887d055ef519f5a622d249Timo Sirainen if (buffer_get_used_size(sync_ctx->syncs) == 0 &&
4214b59ac7f3899f8d887d055ef519f5a622d249Timo Sirainen sync_ctx->sync_rec.uid1 == 0) {
6a1e4eb2c6a267bec1e8704ce9137bebb7792702Timo Sirainen if (mbox_sync_read_index_syncs(sync_ctx, 1,
930dcf1576f99057ad572420d9c75f3212e46a2eTimo Sirainen &expunged) < 0)
930dcf1576f99057ad572420d9c75f3212e46a2eTimo Sirainen return -1;
930dcf1576f99057ad572420d9c75f3212e46a2eTimo Sirainen
6a1e4eb2c6a267bec1e8704ce9137bebb7792702Timo Sirainen if (buffer_get_used_size(sync_ctx->syncs) == 0 &&
930dcf1576f99057ad572420d9c75f3212e46a2eTimo Sirainen sync_ctx->sync_rec.uid1 == 0) {
c9a03c8a03a782488981f81bd7c6b5e01ff55f06Timo Sirainen /* nothing to do */
829c036d4ddfbd9ea49bd8a7c54e3057177d346eTimo Sirainen return 1;
6a1e4eb2c6a267bec1e8704ce9137bebb7792702Timo Sirainen }
7a6b45405fb1544ac476e6eb1402a70cc1ddcdcfTimo Sirainen }
39775ad03c459efe64cce924658da5094ba417e1Timo Sirainen
39775ad03c459efe64cce924658da5094ba417e1Timo Sirainen sync_rec = buffer_get_data(sync_ctx->syncs, &size);
6a1e4eb2c6a267bec1e8704ce9137bebb7792702Timo Sirainen if (size == 0)
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen sync_rec = &sync_ctx->sync_rec;
6a1e4eb2c6a267bec1e8704ce9137bebb7792702Timo Sirainen
6a1e4eb2c6a267bec1e8704ce9137bebb7792702Timo Sirainen ret = mbox_sync_seek_to_uid(sync_ctx, sync_rec->uid1);
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen }
7a6b45405fb1544ac476e6eb1402a70cc1ddcdcfTimo Sirainen
6a1e4eb2c6a267bec1e8704ce9137bebb7792702Timo Sirainen if (ret <= 0)
6a1e4eb2c6a267bec1e8704ce9137bebb7792702Timo Sirainen return ret;
6a1e4eb2c6a267bec1e8704ce9137bebb7792702Timo Sirainen
6a1e4eb2c6a267bec1e8704ce9137bebb7792702Timo Sirainen while ((ret = mbox_sync_read_next_mail(sync_ctx, mail_ctx)) > 0) {
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen uid = mail_ctx->mail.uid;
b2ecd50bb98c44816cb07c17aa17fae2b425f941Timo Sirainen
a2637488c8d514ec1ac3914811deee814f9761b3Timo Sirainen if (mail_ctx->seq == 1 && sync_ctx->base_uid_validity != 0 &&
a614397cf1a4dde152eb1a38493a6ec3d817da16Timo Sirainen sync_ctx->hdr->uid_validity != 0 &&
a614397cf1a4dde152eb1a38493a6ec3d817da16Timo Sirainen sync_ctx->base_uid_validity !=
a614397cf1a4dde152eb1a38493a6ec3d817da16Timo Sirainen sync_ctx->hdr->uid_validity) {
a614397cf1a4dde152eb1a38493a6ec3d817da16Timo Sirainen mail_storage_set_critical(sync_ctx->ibox->box.storage,
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen "UIDVALIDITY changed (%u -> %u) "
b2ecd50bb98c44816cb07c17aa17fae2b425f941Timo Sirainen "in mbox file %s",
8907d617ce7c4f390c0f42f6f694db2fecdd5775Timo Sirainen sync_ctx->hdr->uid_validity,
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen sync_ctx->base_uid_validity,
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen sync_ctx->ibox->path);
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen mail_index_mark_corrupted(sync_ctx->ibox->index);
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen return -1;
01cbf4ac5d44137ab434791be7f838d98d0fcf3bTimo Sirainen }
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
6a1e4eb2c6a267bec1e8704ce9137bebb7792702Timo Sirainen if (mail_ctx->uid_broken && partial) {
39775ad03c459efe64cce924658da5094ba417e1Timo Sirainen /* UID ordering problems, resync everything to make
343a527f805ca5cce78496b959d6def70e5d0cd4Timo Sirainen sure we get everything right */
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen return 0;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen }
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen if (mail_ctx->pseudo)
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen uid = 0;
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen rec = NULL;
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen if (uid != 0) {
319944c0f35b311c998854e96d6463a084fd90aeTimo Sirainen ret = mbox_sync_read_index_rec(sync_ctx, uid, &rec);
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainen if (ret < 0)
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainen return -1;
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen if (ret == 0)
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen uid = 0;
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen }
e5afebd2df1d4990f7bec2a839260ff2e6d78168Timo Sirainen
ccc895c0358108d2304239063e940b7d75f364abTimo Sirainen if (uid == 0 && !mail_ctx->pseudo &&
ff7056842f14fd3b30a2d327dfab165b9d15dd30Timo Sirainen (sync_ctx->delay_writes ||
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen sync_ctx->idx_seq <= messages_count)) {
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen /* If we can't use/store X-UID header, use MD5 sum.
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen Also check for existing MD5 sums when we're actually
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen able to write X-UIDs. */
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen if (sync_ctx->ibox->md5hdr_ext_idx == 0) {
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen sync_ctx->ibox->md5hdr_ext_idx =
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen mail_index_ext_register(
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen sync_ctx->ibox->index,
f12aabfeba81f0d741971d2b7e4a5008eb4383caTimo Sirainen "header-md5", 0, 16, 1);
f12aabfeba81f0d741971d2b7e4a5008eb4383caTimo Sirainen }
f12aabfeba81f0d741971d2b7e4a5008eb4383caTimo Sirainen
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen if (mbox_sync_find_index_md5(sync_ctx,
f12aabfeba81f0d741971d2b7e4a5008eb4383caTimo Sirainen mail_ctx->hdr_md5_sum,
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen &rec) < 0)
f12aabfeba81f0d741971d2b7e4a5008eb4383caTimo Sirainen return -1;
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen if (rec != NULL)
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen uid = mail_ctx->mail.uid = rec->uid;
a2637488c8d514ec1ac3914811deee814f9761b3Timo Sirainen }
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen if (!mail_ctx->pseudo) {
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen /* get all sync records related to this message */
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen if (mbox_sync_read_index_syncs(sync_ctx, uid,
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen &expunged) < 0)
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen return -1;
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen } else {
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen expunged = FALSE;
319944c0f35b311c998854e96d6463a084fd90aeTimo Sirainen }
319944c0f35b311c998854e96d6463a084fd90aeTimo Sirainen
88187ee880b4829443e0d55ea7d145d9d5880217Timo Sirainen if (uid == 0 && !mail_ctx->pseudo) {
88187ee880b4829443e0d55ea7d145d9d5880217Timo Sirainen /* missing/broken X-UID. all the rest of the mails
319944c0f35b311c998854e96d6463a084fd90aeTimo Sirainen need new UIDs. */
319944c0f35b311c998854e96d6463a084fd90aeTimo Sirainen while (sync_ctx->idx_seq <= messages_count) {
319944c0f35b311c998854e96d6463a084fd90aeTimo Sirainen mail_index_expunge(sync_ctx->t,
a393d9d6dabdc46cf724f8cb004a652b4036d53dTimo Sirainen sync_ctx->idx_seq++);
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen }
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen mail_ctx->need_rewrite = TRUE;
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen mail_ctx->mail.uid = sync_ctx->next_uid++;
cece2b9cd692c06025cc0a7a0ff54d996a8c90efTimo Sirainen sync_ctx->prev_msg_uid = mail_ctx->mail.uid;
cece2b9cd692c06025cc0a7a0ff54d996a8c90efTimo Sirainen }
cece2b9cd692c06025cc0a7a0ff54d996a8c90efTimo Sirainen
cece2b9cd692c06025cc0a7a0ff54d996a8c90efTimo Sirainen mail_ctx->mail.idx_seq = sync_ctx->idx_seq;
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen
f0569d9fbb25c8437760be69f194595a841ad711Timo Sirainen if (!expunged) {
db7c9201c88e3d9bee10485194ee5b0c67249916Timo Sirainen if (mbox_sync_handle_header(mail_ctx) < 0)
755fe6da51ab7f54aa1d86913cb344bffef60e79Timo Sirainen return -1;
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen sync_ctx->dest_first_mail = FALSE;
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen } else {
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen mail_ctx->mail.uid = 0;
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen mbox_sync_handle_expunge(mail_ctx);
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen }
a10e5606a9e93f49cf13b3a35c8dc3f5d6ab5909Timo Sirainen
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen if (!mail_ctx->pseudo) {
4b9f99761df5014c659cd87fddaf6854af428cfcTimo Sirainen if (!expunged) {
4b9f99761df5014c659cd87fddaf6854af428cfcTimo Sirainen if (mbox_sync_update_index(sync_ctx, mail_ctx,
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen rec) < 0)
f6699a08521aacc4c2bb5b6175691dad5f715f8cTimo Sirainen return -1;
f6699a08521aacc4c2bb5b6175691dad5f715f8cTimo Sirainen }
3da614c39dd29f536c485089e67839b4cf89fed3Timo Sirainen sync_ctx->idx_seq++;
3da614c39dd29f536c485089e67839b4cf89fed3Timo Sirainen }
0a6f8311541ae59381171620b77f82be58be562eTimo Sirainen
4b9f99761df5014c659cd87fddaf6854af428cfcTimo Sirainen istream_raw_mbox_next(sync_ctx->input,
4b9f99761df5014c659cd87fddaf6854af428cfcTimo Sirainen mail_ctx->mail.body_size);
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen offset = istream_raw_mbox_get_start_offset(sync_ctx->input);
4b9f99761df5014c659cd87fddaf6854af428cfcTimo Sirainen
b225c3c65f360d7b833f09f9b2fb3035ed5ea600Timo Sirainen if (sync_ctx->need_space_seq != 0) {
b225c3c65f360d7b833f09f9b2fb3035ed5ea600Timo Sirainen if (mbox_sync_handle_missing_space(mail_ctx) < 0)
4b9f99761df5014c659cd87fddaf6854af428cfcTimo Sirainen return -1;
b225c3c65f360d7b833f09f9b2fb3035ed5ea600Timo Sirainen if (mbox_sync_seek(sync_ctx, offset) < 0)
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen return -1;
4b9f99761df5014c659cd87fddaf6854af428cfcTimo Sirainen } else if (sync_ctx->expunged_space > 0) {
a2637488c8d514ec1ac3914811deee814f9761b3Timo Sirainen if (!expunged) {
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen /* move the body */
0a6f8311541ae59381171620b77f82be58be562eTimo Sirainen if (mbox_move(sync_ctx,
0a6f8311541ae59381171620b77f82be58be562eTimo Sirainen mail_ctx->body_offset -
a10e5606a9e93f49cf13b3a35c8dc3f5d6ab5909Timo Sirainen sync_ctx->expunged_space,
df4018ae2f0a95be602f724ca70df7e0e3bd6a7dTimo Sirainen mail_ctx->body_offset,
0a6f8311541ae59381171620b77f82be58be562eTimo Sirainen mail_ctx->mail.body_size) < 0)
0a6f8311541ae59381171620b77f82be58be562eTimo Sirainen return -1;
0a6f8311541ae59381171620b77f82be58be562eTimo Sirainen if (mbox_sync_seek(sync_ctx, offset) < 0)
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen return -1;
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen }
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen } else if (sync_ctx->seq >= min_message_count) {
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen mbox_sync_buffer_delete_old(sync_ctx->syncs, uid);
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainen if (buffer_get_used_size(sync_ctx->syncs) == 0) {
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainen /* if there's no sync records left,
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen we can stop */
022412398e56a8f31ef111cfd7271498d64af9a9Timo Sirainen if (sync_ctx->sync_rec.uid1 == 0)
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen break;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
f6699a08521aacc4c2bb5b6175691dad5f715f8cTimo Sirainen /* we can skip forward to next record which
f6699a08521aacc4c2bb5b6175691dad5f715f8cTimo Sirainen needs updating. if it failes because the
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen offset is dirty, just ignore and continue
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen from where we are now. */
022412398e56a8f31ef111cfd7271498d64af9a9Timo Sirainen uid = sync_ctx->sync_rec.uid1;
022412398e56a8f31ef111cfd7271498d64af9a9Timo Sirainen if (mbox_sync_seek_to_uid(sync_ctx, uid) < 0)
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen return -1;
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen }
1d3f7c1278168d5b1cbfa9a2cc9929a0909056b4Timo Sirainen }
ced118ac5caf6fe83d34339c2c65c63b2aa768acTimo Sirainen }
1d3f7c1278168d5b1cbfa9a2cc9929a0909056b4Timo Sirainen
1d3f7c1278168d5b1cbfa9a2cc9929a0909056b4Timo Sirainen if (istream_raw_mbox_is_eof(sync_ctx->input)) {
1d3f7c1278168d5b1cbfa9a2cc9929a0909056b4Timo Sirainen /* rest of the messages in index don't exist -> expunge them */
1d3f7c1278168d5b1cbfa9a2cc9929a0909056b4Timo Sirainen while (sync_ctx->idx_seq <= messages_count)
022412398e56a8f31ef111cfd7271498d64af9a9Timo Sirainen mail_index_expunge(sync_ctx->t, sync_ctx->idx_seq++);
1d3f7c1278168d5b1cbfa9a2cc9929a0909056b4Timo Sirainen }
1d3f7c1278168d5b1cbfa9a2cc9929a0909056b4Timo Sirainen
1d3f7c1278168d5b1cbfa9a2cc9929a0909056b4Timo Sirainen if (!partial)
ced118ac5caf6fe83d34339c2c65c63b2aa768acTimo Sirainen sync_ctx->ibox->mbox_sync_dirty = FALSE;
1d3f7c1278168d5b1cbfa9a2cc9929a0909056b4Timo Sirainen
1d3f7c1278168d5b1cbfa9a2cc9929a0909056b4Timo Sirainen return 1;
1d3f7c1278168d5b1cbfa9a2cc9929a0909056b4Timo Sirainen}
1d3f7c1278168d5b1cbfa9a2cc9929a0909056b4Timo Sirainen
022412398e56a8f31ef111cfd7271498d64af9a9Timo Sirainenstatic int mbox_sync_handle_eof_updates(struct mbox_sync_context *sync_ctx,
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen struct mbox_sync_mail_context *mail_ctx)
022412398e56a8f31ef111cfd7271498d64af9a9Timo Sirainen{
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen uoff_t offset, padding, trailer_size, old_file_size;
022412398e56a8f31ef111cfd7271498d64af9a9Timo Sirainen
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen if (!istream_raw_mbox_is_eof(sync_ctx->input)) {
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen i_assert(sync_ctx->need_space_seq == 0);
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen i_assert(sync_ctx->expunged_space == 0);
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen return 0;
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen }
690bafa70767e3f6e98bbfd62ad4a26be2387ea9Timo Sirainen
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen trailer_size = i_stream_get_size(sync_ctx->file_input) -
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen sync_ctx->file_input->v_offset;
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen if (sync_ctx->need_space_seq != 0) {
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen i_assert(sync_ctx->space_diff < 0);
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen padding = MBOX_HEADER_PADDING *
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen (sync_ctx->seq - sync_ctx->need_space_seq + 1);
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen sync_ctx->space_diff -= padding;
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen sync_ctx->space_diff += sync_ctx->expunged_space;
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen if (sync_ctx->expunged_space <= -sync_ctx->space_diff)
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen sync_ctx->expunged_space = 0;
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen else
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen sync_ctx->expunged_space -= -sync_ctx->space_diff;
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen if (mail_ctx->have_eoh && !mail_ctx->updated)
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen str_append_c(mail_ctx->header, '\n');
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen
755fe6da51ab7f54aa1d86913cb344bffef60e79Timo Sirainen i_assert(sync_ctx->space_diff < 0);
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen old_file_size = i_stream_get_size(sync_ctx->file_input);
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen if (file_set_size(sync_ctx->fd,
17ad2164c747cedbf81dae1893063e71a3df0356Timo Sirainen old_file_size + -sync_ctx->space_diff) < 0) {
17ad2164c747cedbf81dae1893063e71a3df0356Timo Sirainen mbox_set_syscall_error(sync_ctx->ibox,
17ad2164c747cedbf81dae1893063e71a3df0356Timo Sirainen "file_set_size()");
17ad2164c747cedbf81dae1893063e71a3df0356Timo Sirainen return -1;
17ad2164c747cedbf81dae1893063e71a3df0356Timo Sirainen }
17ad2164c747cedbf81dae1893063e71a3df0356Timo Sirainen istream_raw_mbox_flush(sync_ctx->input);
17ad2164c747cedbf81dae1893063e71a3df0356Timo Sirainen
17ad2164c747cedbf81dae1893063e71a3df0356Timo Sirainen if (mbox_sync_rewrite(sync_ctx, old_file_size,
17ad2164c747cedbf81dae1893063e71a3df0356Timo Sirainen -sync_ctx->space_diff, padding,
17ad2164c747cedbf81dae1893063e71a3df0356Timo Sirainen sync_ctx->need_space_seq,
17ad2164c747cedbf81dae1893063e71a3df0356Timo Sirainen sync_ctx->seq) < 0)
17ad2164c747cedbf81dae1893063e71a3df0356Timo Sirainen return -1;
17ad2164c747cedbf81dae1893063e71a3df0356Timo Sirainen
17ad2164c747cedbf81dae1893063e71a3df0356Timo Sirainen update_from_offsets(sync_ctx);
17ad2164c747cedbf81dae1893063e71a3df0356Timo Sirainen
17ad2164c747cedbf81dae1893063e71a3df0356Timo Sirainen sync_ctx->need_space_seq = 0;
17ad2164c747cedbf81dae1893063e71a3df0356Timo Sirainen buffer_set_used_size(sync_ctx->mails, 0);
17ad2164c747cedbf81dae1893063e71a3df0356Timo Sirainen }
17ad2164c747cedbf81dae1893063e71a3df0356Timo Sirainen
17ad2164c747cedbf81dae1893063e71a3df0356Timo Sirainen if (sync_ctx->expunged_space > 0) {
f6699a08521aacc4c2bb5b6175691dad5f715f8cTimo Sirainen /* copy trailer, then truncate the file */
f6699a08521aacc4c2bb5b6175691dad5f715f8cTimo Sirainen offset = i_stream_get_size(sync_ctx->file_input) -
f6699a08521aacc4c2bb5b6175691dad5f715f8cTimo Sirainen sync_ctx->expunged_space - trailer_size;
f6699a08521aacc4c2bb5b6175691dad5f715f8cTimo Sirainen
f6699a08521aacc4c2bb5b6175691dad5f715f8cTimo Sirainen if (mbox_move(sync_ctx, offset,
f6699a08521aacc4c2bb5b6175691dad5f715f8cTimo Sirainen offset + sync_ctx->expunged_space,
f6699a08521aacc4c2bb5b6175691dad5f715f8cTimo Sirainen trailer_size) < 0)
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen return -1;
f6699a08521aacc4c2bb5b6175691dad5f715f8cTimo Sirainen if (ftruncate(sync_ctx->fd, offset + trailer_size) < 0) {
f6699a08521aacc4c2bb5b6175691dad5f715f8cTimo Sirainen mbox_set_syscall_error(sync_ctx->ibox, "ftruncate()");
f6699a08521aacc4c2bb5b6175691dad5f715f8cTimo Sirainen return -1;
17ad2164c747cedbf81dae1893063e71a3df0356Timo Sirainen }
17ad2164c747cedbf81dae1893063e71a3df0356Timo Sirainen
f6699a08521aacc4c2bb5b6175691dad5f715f8cTimo Sirainen sync_ctx->expunged_space = 0;
f6699a08521aacc4c2bb5b6175691dad5f715f8cTimo Sirainen istream_raw_mbox_flush(sync_ctx->input);
f6699a08521aacc4c2bb5b6175691dad5f715f8cTimo Sirainen }
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen return 0;
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen}
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainen
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainenstatic int mbox_sync_update_index_header(struct mbox_sync_context *sync_ctx)
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen{
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen struct stat st;
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainen if (fstat(sync_ctx->fd, &st) < 0) {
d31c4d7c161f9d7efa59964c7c958e83e05b218cTimo Sirainen mbox_set_syscall_error(sync_ctx->ibox, "fstat()");
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen return -1;
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen }
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen
755fe6da51ab7f54aa1d86913cb344bffef60e79Timo Sirainen if ((sync_ctx->base_uid_validity != 0 &&
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen sync_ctx->base_uid_validity != sync_ctx->hdr->uid_validity) ||
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen (sync_ctx->hdr->uid_validity == 0 && sync_ctx->seen_first_mail)) {
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen if (sync_ctx->base_uid_validity == 0) {
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen /* we didn't rewrite X-IMAPbase header because
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen a) mbox is read-only, b) we're lazy-writing */
71a74e26cf070a205d31cf6c6fae003f90027b63Timo Sirainen i_assert(sync_ctx->delay_writes);
a486ed03dce069ff60ab5a65d0ae24a1862f22fcTimo Sirainen sync_ctx->base_uid_validity = time(NULL);
a486ed03dce069ff60ab5a65d0ae24a1862f22fcTimo Sirainen }
a486ed03dce069ff60ab5a65d0ae24a1862f22fcTimo Sirainen mail_index_update_header(sync_ctx->t,
a486ed03dce069ff60ab5a65d0ae24a1862f22fcTimo Sirainen offsetof(struct mail_index_header, uid_validity),
a486ed03dce069ff60ab5a65d0ae24a1862f22fcTimo Sirainen &sync_ctx->base_uid_validity,
a486ed03dce069ff60ab5a65d0ae24a1862f22fcTimo Sirainen sizeof(sync_ctx->base_uid_validity));
a486ed03dce069ff60ab5a65d0ae24a1862f22fcTimo Sirainen }
a486ed03dce069ff60ab5a65d0ae24a1862f22fcTimo Sirainen
d31c4d7c161f9d7efa59964c7c958e83e05b218cTimo Sirainen if (istream_raw_mbox_is_eof(sync_ctx->input) &&
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen sync_ctx->next_uid != sync_ctx->hdr->next_uid) {
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen i_assert(sync_ctx->next_uid != 0);
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen mail_index_update_header(sync_ctx->t,
f6699a08521aacc4c2bb5b6175691dad5f715f8cTimo Sirainen offsetof(struct mail_index_header, next_uid),
17ad2164c747cedbf81dae1893063e71a3df0356Timo Sirainen &sync_ctx->next_uid, sizeof(sync_ctx->next_uid));
690bafa70767e3f6e98bbfd62ad4a26be2387ea9Timo Sirainen }
f6699a08521aacc4c2bb5b6175691dad5f715f8cTimo Sirainen
f6699a08521aacc4c2bb5b6175691dad5f715f8cTimo Sirainen if ((uint32_t)st.st_mtime != sync_ctx->hdr->sync_stamp &&
319944c0f35b311c998854e96d6463a084fd90aeTimo Sirainen !sync_ctx->ibox->mbox_sync_dirty) {
319944c0f35b311c998854e96d6463a084fd90aeTimo Sirainen uint32_t sync_stamp = st.st_mtime;
912e870dcab2dadac8a6b20b42367999cdd8b5a1Timo Sirainen
319944c0f35b311c998854e96d6463a084fd90aeTimo Sirainen mail_index_update_header(sync_ctx->t,
319944c0f35b311c998854e96d6463a084fd90aeTimo Sirainen offsetof(struct mail_index_header, sync_stamp),
690bafa70767e3f6e98bbfd62ad4a26be2387ea9Timo Sirainen &sync_stamp, sizeof(sync_stamp));
b8765f6093ab35fc2345293d78132d35794cbff5Timo Sirainen }
b8765f6093ab35fc2345293d78132d35794cbff5Timo Sirainen if ((uint64_t)st.st_size != sync_ctx->hdr->sync_size &&
a2637488c8d514ec1ac3914811deee814f9761b3Timo Sirainen !sync_ctx->ibox->mbox_sync_dirty) {
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen uint64_t sync_size = st.st_size;
b8765f6093ab35fc2345293d78132d35794cbff5Timo Sirainen
690bafa70767e3f6e98bbfd62ad4a26be2387ea9Timo Sirainen mail_index_update_header(sync_ctx->t,
319944c0f35b311c998854e96d6463a084fd90aeTimo Sirainen offsetof(struct mail_index_header, sync_size),
319944c0f35b311c998854e96d6463a084fd90aeTimo Sirainen &sync_size, sizeof(sync_size));
d31c4d7c161f9d7efa59964c7c958e83e05b218cTimo Sirainen }
d31c4d7c161f9d7efa59964c7c958e83e05b218cTimo Sirainen
319944c0f35b311c998854e96d6463a084fd90aeTimo Sirainen sync_ctx->ibox->mbox_dirty_stamp = st.st_mtime;
1e76a5b92f9d82d557f81f080f3dfad1c9d8f200Timo Sirainen sync_ctx->ibox->mbox_dirty_size = st.st_size;
907723f35f4d3dfc774ca42d00a8a7b8ef90dd5dTimo Sirainen
907723f35f4d3dfc774ca42d00a8a7b8ef90dd5dTimo Sirainen return 0;
2ae575a66f2a302f047f6de062a70b75f8bebc7bTimo Sirainen}
cdaf255d6a3daeef0ac85edaa60bfa6d1f945bffTimo Sirainen
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainenstatic void mbox_sync_restart(struct mbox_sync_context *sync_ctx)
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen{
6843896c40bee4f9b6680ca7ced598c446e9f999Timo Sirainen sync_ctx->base_uid_validity = 0;
7f3be7d885c75cdd77f536929a45bc9764595960Timo Sirainen sync_ctx->base_uid_last = 0;
2ae575a66f2a302f047f6de062a70b75f8bebc7bTimo Sirainen
2ae575a66f2a302f047f6de062a70b75f8bebc7bTimo Sirainen sync_ctx->next_uid = sync_ctx->hdr->next_uid;
2ae575a66f2a302f047f6de062a70b75f8bebc7bTimo Sirainen sync_ctx->prev_msg_uid = 0;
cdaf255d6a3daeef0ac85edaa60bfa6d1f945bffTimo Sirainen sync_ctx->seq = 0;
1e76a5b92f9d82d557f81f080f3dfad1c9d8f200Timo Sirainen sync_ctx->idx_seq = 1;
2ae575a66f2a302f047f6de062a70b75f8bebc7bTimo Sirainen
2ae575a66f2a302f047f6de062a70b75f8bebc7bTimo Sirainen sync_ctx->dest_first_mail = TRUE;
7a6b45405fb1544ac476e6eb1402a70cc1ddcdcfTimo Sirainen sync_ctx->seen_first_mail = FALSE;
7a6b45405fb1544ac476e6eb1402a70cc1ddcdcfTimo Sirainen}
7a6b45405fb1544ac476e6eb1402a70cc1ddcdcfTimo Sirainen
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainenstatic int mbox_sync_do(struct mbox_sync_context *sync_ctx,
7f3be7d885c75cdd77f536929a45bc9764595960Timo Sirainen enum mbox_sync_flags flags)
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen{
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen struct mbox_sync_mail_context mail_ctx;
7f3be7d885c75cdd77f536929a45bc9764595960Timo Sirainen struct stat st;
7a6b45405fb1544ac476e6eb1402a70cc1ddcdcfTimo Sirainen uint32_t min_msg_count;
7a6b45405fb1544ac476e6eb1402a70cc1ddcdcfTimo Sirainen int ret, partial;
7a6b45405fb1544ac476e6eb1402a70cc1ddcdcfTimo Sirainen
c9fe52d819c608b890620f7fe36ff509b14eb350Timo Sirainen partial = FALSE;
c9fe52d819c608b890620f7fe36ff509b14eb350Timo Sirainen
c9fe52d819c608b890620f7fe36ff509b14eb350Timo Sirainen if ((flags & MBOX_SYNC_HEADER) != 0)
b08b33d1f5ce3721dc2d83586c9cb0ca141331fdTimo Sirainen min_msg_count = 1;
b08b33d1f5ce3721dc2d83586c9cb0ca141331fdTimo Sirainen else {
b08b33d1f5ce3721dc2d83586c9cb0ca141331fdTimo Sirainen if (fstat(sync_ctx->fd, &st) < 0) {
c9fe52d819c608b890620f7fe36ff509b14eb350Timo Sirainen mbox_set_syscall_error(sync_ctx->ibox, "stat()");
1e76a5b92f9d82d557f81f080f3dfad1c9d8f200Timo Sirainen return -1;
c9fe52d819c608b890620f7fe36ff509b14eb350Timo Sirainen }
c9fe52d819c608b890620f7fe36ff509b14eb350Timo Sirainen
c9fe52d819c608b890620f7fe36ff509b14eb350Timo Sirainen if ((uint32_t)st.st_mtime == sync_ctx->hdr->sync_stamp &&
e9d68b41c007f0e545de361f8012f6f231bfec8bTimo Sirainen (uint64_t)st.st_size == sync_ctx->hdr->sync_size) {
c9fe52d819c608b890620f7fe36ff509b14eb350Timo Sirainen /* file is fully synced */
c9fe52d819c608b890620f7fe36ff509b14eb350Timo Sirainen sync_ctx->ibox->mbox_sync_dirty = FALSE;
e9d68b41c007f0e545de361f8012f6f231bfec8bTimo Sirainen min_msg_count = 0;
e9d68b41c007f0e545de361f8012f6f231bfec8bTimo Sirainen } else if ((flags & MBOX_SYNC_UNDIRTY) != 0 ||
7f3be7d885c75cdd77f536929a45bc9764595960Timo Sirainen (uint64_t)st.st_size == sync_ctx->hdr->sync_size) {
7f3be7d885c75cdd77f536929a45bc9764595960Timo Sirainen /* we want to do full syncing. always do this if
1e76a5b92f9d82d557f81f080f3dfad1c9d8f200Timo Sirainen file size hasn't changed but timestamp has. it most
71a74e26cf070a205d31cf6c6fae003f90027b63Timo Sirainen likely means that someone had modified some header
71a74e26cf070a205d31cf6c6fae003f90027b63Timo Sirainen and we probably want to know about it */
a393d9d6dabdc46cf724f8cb004a652b4036d53dTimo Sirainen min_msg_count = (uint32_t)-1;
71a74e26cf070a205d31cf6c6fae003f90027b63Timo Sirainen sync_ctx->ibox->mbox_sync_dirty = TRUE;
71a74e26cf070a205d31cf6c6fae003f90027b63Timo Sirainen } else {
71a74e26cf070a205d31cf6c6fae003f90027b63Timo Sirainen /* see if we can delay syncing the whole file.
a486ed03dce069ff60ab5a65d0ae24a1862f22fcTimo Sirainen normally we only notice expunges and appends
a486ed03dce069ff60ab5a65d0ae24a1862f22fcTimo Sirainen in partial syncing. */
a486ed03dce069ff60ab5a65d0ae24a1862f22fcTimo Sirainen partial = TRUE;
a486ed03dce069ff60ab5a65d0ae24a1862f22fcTimo Sirainen min_msg_count = (uint32_t)-1;
a486ed03dce069ff60ab5a65d0ae24a1862f22fcTimo Sirainen sync_ctx->ibox->mbox_sync_dirty = TRUE;
a486ed03dce069ff60ab5a65d0ae24a1862f22fcTimo Sirainen }
ccc895c0358108d2304239063e940b7d75f364abTimo Sirainen }
a486ed03dce069ff60ab5a65d0ae24a1862f22fcTimo Sirainen
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen mbox_sync_restart(sync_ctx);
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen ret = mbox_sync_loop(sync_ctx, &mail_ctx, min_msg_count, partial);
a486ed03dce069ff60ab5a65d0ae24a1862f22fcTimo Sirainen if (ret <= 0) {
a486ed03dce069ff60ab5a65d0ae24a1862f22fcTimo Sirainen if (ret < 0)
a486ed03dce069ff60ab5a65d0ae24a1862f22fcTimo Sirainen return -1;
a486ed03dce069ff60ab5a65d0ae24a1862f22fcTimo Sirainen
6843896c40bee4f9b6680ca7ced598c446e9f999Timo Sirainen /* partial syncing didn't work, do it again */
6843896c40bee4f9b6680ca7ced598c446e9f999Timo Sirainen mbox_sync_restart(sync_ctx);
6843896c40bee4f9b6680ca7ced598c446e9f999Timo Sirainen
1dd9801f7ace40777ecf8ed9a98c093bc40467a4Timo Sirainen mail_index_transaction_rollback(sync_ctx->t);
6843896c40bee4f9b6680ca7ced598c446e9f999Timo Sirainen sync_ctx->t = mail_index_transaction_begin(sync_ctx->sync_view,
1e76a5b92f9d82d557f81f080f3dfad1c9d8f200Timo Sirainen FALSE);
b428c5993b01f4cffacdd24377ca2873fcc12184Timo Sirainen
d0e5f8252516c4d4df2fbcdae4d37f9e5f931199Timo Sirainen ret = mbox_sync_loop(sync_ctx, &mail_ctx, (uint32_t)-1, FALSE);
f0569d9fbb25c8437760be69f194595a841ad711Timo Sirainen if (ret <= 0) {
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen i_assert(ret != 0);
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen return -1;
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen }
8907d617ce7c4f390c0f42f6f694db2fecdd5775Timo Sirainen }
8907d617ce7c4f390c0f42f6f694db2fecdd5775Timo Sirainen
f0569d9fbb25c8437760be69f194595a841ad711Timo Sirainen if (mbox_sync_handle_eof_updates(sync_ctx, &mail_ctx) < 0)
f0569d9fbb25c8437760be69f194595a841ad711Timo Sirainen return -1;
8907d617ce7c4f390c0f42f6f694db2fecdd5775Timo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen /* only syncs left should be just appends (and their updates)
b2ecd50bb98c44816cb07c17aa17fae2b425f941Timo Sirainen which weren't synced yet for some reason (crash). we'll just
1e76a5b92f9d82d557f81f080f3dfad1c9d8f200Timo Sirainen ignore them, as we've overwritten them above. */
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen buffer_set_used_size(sync_ctx->syncs, 0);
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen memset(&sync_ctx->sync_rec, 0, sizeof(sync_ctx->sync_rec));
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen
907723f35f4d3dfc774ca42d00a8a7b8ef90dd5dTimo Sirainen if (mbox_sync_update_index_header(sync_ctx) < 0)
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen return -1;
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen return 0;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen}
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainenint mbox_sync_has_changed(struct index_mailbox *ibox, int leave_dirty)
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen{
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen const struct mail_index_header *hdr;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen struct stat st;
02b79f9c2636da1829eee5b92753602bba8b67edTimo Sirainen
02b79f9c2636da1829eee5b92753602bba8b67edTimo Sirainen if (mail_index_get_header(ibox->view, &hdr) < 0) {
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen mail_storage_set_index_error(ibox);
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen return -1;
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen }
a2637488c8d514ec1ac3914811deee814f9761b3Timo Sirainen
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen if (stat(ibox->path, &st) < 0) {
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen mbox_set_syscall_error(ibox, "stat()");
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen return -1;
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen }
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen if ((uint32_t)st.st_mtime == hdr->sync_stamp &&
02b79f9c2636da1829eee5b92753602bba8b67edTimo Sirainen (uint64_t)st.st_size == hdr->sync_size) {
02b79f9c2636da1829eee5b92753602bba8b67edTimo Sirainen /* fully synced */
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen ibox->mbox_sync_dirty = FALSE;
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen return 0;
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen }
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen if (!ibox->mbox_sync_dirty || !leave_dirty)
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen return 1;
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen return st.st_mtime != ibox->mbox_dirty_stamp ||
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen st.st_size != ibox->mbox_dirty_size;
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstatic int mbox_sync_update_imap_base(struct mbox_sync_context *sync_ctx)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
178511b57faa7c3f8203dd8b7e4059d00cbfc23aTimo Sirainen struct mbox_sync_mail_context mail_ctx;
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen
a393d9d6dabdc46cf724f8cb004a652b4036d53dTimo Sirainen if (mbox_sync_seek(sync_ctx, 0) < 0)
a393d9d6dabdc46cf724f8cb004a652b4036d53dTimo Sirainen return -1;
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen sync_ctx->t = mail_index_transaction_begin(sync_ctx->sync_view, FALSE);
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen sync_ctx->update_base_uid_last = sync_ctx->next_uid-1;
690bafa70767e3f6e98bbfd62ad4a26be2387ea9Timo Sirainen
690bafa70767e3f6e98bbfd62ad4a26be2387ea9Timo Sirainen mbox_sync_restart(sync_ctx);
d31c4d7c161f9d7efa59964c7c958e83e05b218cTimo Sirainen if (mbox_sync_loop(sync_ctx, &mail_ctx, 1, 0) < 0)
d31c4d7c161f9d7efa59964c7c958e83e05b218cTimo Sirainen return -1;
d31c4d7c161f9d7efa59964c7c958e83e05b218cTimo Sirainen
d31c4d7c161f9d7efa59964c7c958e83e05b218cTimo Sirainen if (mbox_sync_handle_eof_updates(sync_ctx, &mail_ctx) < 0)
d31c4d7c161f9d7efa59964c7c958e83e05b218cTimo Sirainen return -1;
690bafa70767e3f6e98bbfd62ad4a26be2387ea9Timo Sirainen
d31c4d7c161f9d7efa59964c7c958e83e05b218cTimo Sirainen if (mbox_sync_update_index_header(sync_ctx) < 0)
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen return -1;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
3cfff0ca01961d885bdbd6ef08d761880116af07Timo Sirainen return 0;
f7d43647acc6dc80064c8c4cacf5bf86f754c530Timo Sirainen}
98c1cf256927e254f0c092acd2ddcd7ea50bd009Timo Sirainen
98c1cf256927e254f0c092acd2ddcd7ea50bd009Timo Sirainenint mbox_sync(struct index_mailbox *ibox, enum mbox_sync_flags flags)
9d2040fbb941f411d57fd850b4cdc3b1cccc1168Timo Sirainen{
9d2040fbb941f411d57fd850b4cdc3b1cccc1168Timo Sirainen struct mail_index_sync_ctx *index_sync_ctx;
b225c3c65f360d7b833f09f9b2fb3035ed5ea600Timo Sirainen struct mail_index_view *sync_view;
b225c3c65f360d7b833f09f9b2fb3035ed5ea600Timo Sirainen struct mbox_sync_context sync_ctx;
9d2040fbb941f411d57fd850b4cdc3b1cccc1168Timo Sirainen uint32_t seq;
9d2040fbb941f411d57fd850b4cdc3b1cccc1168Timo Sirainen uoff_t offset;
9d2040fbb941f411d57fd850b4cdc3b1cccc1168Timo Sirainen unsigned int lock_id = 0;
98c1cf256927e254f0c092acd2ddcd7ea50bd009Timo Sirainen int ret, changed;
98c1cf256927e254f0c092acd2ddcd7ea50bd009Timo Sirainen
98c1cf256927e254f0c092acd2ddcd7ea50bd009Timo Sirainen ibox->sync_last_check = ioloop_time;
98c1cf256927e254f0c092acd2ddcd7ea50bd009Timo Sirainen
98c1cf256927e254f0c092acd2ddcd7ea50bd009Timo Sirainen if (!ibox->mbox_do_dirty_syncs)
98c1cf256927e254f0c092acd2ddcd7ea50bd009Timo Sirainen flags |= MBOX_SYNC_UNDIRTY;
98c1cf256927e254f0c092acd2ddcd7ea50bd009Timo Sirainen
98c1cf256927e254f0c092acd2ddcd7ea50bd009Timo Sirainen if ((flags & MBOX_SYNC_LOCK_READING) != 0) {
98c1cf256927e254f0c092acd2ddcd7ea50bd009Timo Sirainen if (mbox_lock(ibox, F_RDLCK, &lock_id) <= 0)
f7d43647acc6dc80064c8c4cacf5bf86f754c530Timo Sirainen return -1;
f7d43647acc6dc80064c8c4cacf5bf86f754c530Timo Sirainen }
98c1cf256927e254f0c092acd2ddcd7ea50bd009Timo Sirainen
98c1cf256927e254f0c092acd2ddcd7ea50bd009Timo Sirainen if ((flags & MBOX_SYNC_HEADER) != 0)
98c1cf256927e254f0c092acd2ddcd7ea50bd009Timo Sirainen changed = 1;
9d2040fbb941f411d57fd850b4cdc3b1cccc1168Timo Sirainen else {
98c1cf256927e254f0c092acd2ddcd7ea50bd009Timo Sirainen int leave_dirty = (flags & MBOX_SYNC_UNDIRTY) == 0;
b225c3c65f360d7b833f09f9b2fb3035ed5ea600Timo Sirainen if ((changed = mbox_sync_has_changed(ibox, leave_dirty)) < 0) {
b225c3c65f360d7b833f09f9b2fb3035ed5ea600Timo Sirainen if ((flags & MBOX_SYNC_LOCK_READING) != 0)
98c1cf256927e254f0c092acd2ddcd7ea50bd009Timo Sirainen (void)mbox_unlock(ibox, lock_id);
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen return -1;
98c1cf256927e254f0c092acd2ddcd7ea50bd009Timo Sirainen }
98c1cf256927e254f0c092acd2ddcd7ea50bd009Timo Sirainen }
98c1cf256927e254f0c092acd2ddcd7ea50bd009Timo Sirainen
98c1cf256927e254f0c092acd2ddcd7ea50bd009Timo Sirainen if ((flags & MBOX_SYNC_LOCK_READING) != 0) {
98c1cf256927e254f0c092acd2ddcd7ea50bd009Timo Sirainen /* we just want to lock it for reading. if mbox hasn't been
b8bbfab97eed17fcb00b5a86128e1d7a3babc35cTimo Sirainen modified don't do any syncing. */
b8bbfab97eed17fcb00b5a86128e1d7a3babc35cTimo Sirainen if (!changed)
98c1cf256927e254f0c092acd2ddcd7ea50bd009Timo Sirainen return 0;
2be66b9eddad3841a1195fe9aeb1eaf0f28f1116Timo Sirainen
2be66b9eddad3841a1195fe9aeb1eaf0f28f1116Timo Sirainen /* have to sync to make sure offsets have stayed the same */
2be66b9eddad3841a1195fe9aeb1eaf0f28f1116Timo Sirainen (void)mbox_unlock(ibox, lock_id);
98c1cf256927e254f0c092acd2ddcd7ea50bd009Timo Sirainen lock_id = 0;
98c1cf256927e254f0c092acd2ddcd7ea50bd009Timo Sirainen }
98c1cf256927e254f0c092acd2ddcd7ea50bd009Timo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen__again:
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen if (changed) {
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen /* we're most likely modifying the mbox while syncing, just
f5b919e9b07dfd9d2401b998ef8759e5f0312719Timo Sirainen lock it for writing immediately. the mbox must be locked
4b9f99761df5014c659cd87fddaf6854af428cfcTimo Sirainen before index syncing is started to avoid deadlocks, so we
33ae95df45c9b5ec51332a6b39eb5322038686b9Timo Sirainen don't have much choice either (well, easy ones anyway). */
178511b57faa7c3f8203dd8b7e4059d00cbfc23aTimo Sirainen int lock_type = ibox->mbox_readonly ? F_RDLCK : F_WRLCK;
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen if (mbox_lock(ibox, lock_type, &lock_id) <= 0)
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen return -1;
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen }
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen if ((flags & MBOX_SYNC_LAST_COMMIT) != 0) {
4b9f99761df5014c659cd87fddaf6854af428cfcTimo Sirainen seq = ibox->commit_log_file_seq;
4b9f99761df5014c659cd87fddaf6854af428cfcTimo Sirainen offset = ibox->commit_log_file_offset;
4b9f99761df5014c659cd87fddaf6854af428cfcTimo Sirainen } else {
b225c3c65f360d7b833f09f9b2fb3035ed5ea600Timo Sirainen seq = (uint32_t)-1;
b225c3c65f360d7b833f09f9b2fb3035ed5ea600Timo Sirainen offset = (uoff_t)-1;
4b9f99761df5014c659cd87fddaf6854af428cfcTimo Sirainen }
8166e8a706078efc71923719ca285e84902883c0Timo Sirainen
8166e8a706078efc71923719ca285e84902883c0Timo Sirainen ret = mail_index_sync_begin(ibox->index, &index_sync_ctx, &sync_view,
8166e8a706078efc71923719ca285e84902883c0Timo Sirainen seq, offset, !ibox->keep_recent,
8166e8a706078efc71923719ca285e84902883c0Timo Sirainen (flags & MBOX_SYNC_REWRITE) != 0);
09b9cbde9e7a0f9adea1fb054a7c62f35ad901e1Timo Sirainen if (ret <= 0) {
a2637488c8d514ec1ac3914811deee814f9761b3Timo Sirainen if (ret < 0)
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen mail_storage_set_index_error(ibox);
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen if (lock_id != 0)
09b9cbde9e7a0f9adea1fb054a7c62f35ad901e1Timo Sirainen (void)mbox_unlock(ibox, lock_id);
09b9cbde9e7a0f9adea1fb054a7c62f35ad901e1Timo Sirainen return ret;
09b9cbde9e7a0f9adea1fb054a7c62f35ad901e1Timo Sirainen }
5edfc0f1c3c55e906d8316d9cdeaa3b0c7000c19Timo Sirainen
686cb2418d4daa7bc747d3551783c1895e7c41b9Timo Sirainen if (!changed && !mail_index_sync_have_more(index_sync_ctx)) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen /* nothing to do */
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen if (lock_id != 0)
b225c3c65f360d7b833f09f9b2fb3035ed5ea600Timo Sirainen (void)mbox_unlock(ibox, lock_id);
b225c3c65f360d7b833f09f9b2fb3035ed5ea600Timo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen /* index may need to do internal syncing though, so commit
f16c114c20bbd7d292d93415d1e56c8dd6abd3e7Timo Sirainen instead of rollbacking. */
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen if (mail_index_sync_commit(index_sync_ctx) < 0) {
f16c114c20bbd7d292d93415d1e56c8dd6abd3e7Timo Sirainen mail_storage_set_index_error(ibox);
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen return -1;
f5b919e9b07dfd9d2401b998ef8759e5f0312719Timo Sirainen }
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen return 0;
f5b919e9b07dfd9d2401b998ef8759e5f0312719Timo Sirainen }
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen if (lock_id == 0) {
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen /* ok, we have something to do but no locks. we'll have to
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen restart syncing to avoid deadlocking. */
6a1e4eb2c6a267bec1e8704ce9137bebb7792702Timo Sirainen mail_index_sync_rollback(index_sync_ctx);
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen changed = 1;
b225c3c65f360d7b833f09f9b2fb3035ed5ea600Timo Sirainen goto __again;
f5b919e9b07dfd9d2401b998ef8759e5f0312719Timo Sirainen }
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen
6a1e4eb2c6a267bec1e8704ce9137bebb7792702Timo Sirainen if (mbox_file_open_stream(ibox) < 0) {
b8bbfab97eed17fcb00b5a86128e1d7a3babc35cTimo Sirainen mail_index_sync_rollback(index_sync_ctx);
b8bbfab97eed17fcb00b5a86128e1d7a3babc35cTimo Sirainen (void)mbox_unlock(ibox, lock_id);
b8bbfab97eed17fcb00b5a86128e1d7a3babc35cTimo Sirainen return -1;
b8bbfab97eed17fcb00b5a86128e1d7a3babc35cTimo Sirainen }
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen memset(&sync_ctx, 0, sizeof(sync_ctx));
299183fbb6ec5d0828a0880da372540421ac4665Timo Sirainen sync_ctx.ibox = ibox;
6a1e4eb2c6a267bec1e8704ce9137bebb7792702Timo Sirainen sync_ctx.from_line = str_new(default_pool, 256);
f4b93a46e140823a64d88763ea6ef9f03c49844eTimo Sirainen sync_ctx.header = str_new(default_pool, 4096);
6a1e4eb2c6a267bec1e8704ce9137bebb7792702Timo Sirainen sync_ctx.uidl = str_new(default_pool, 128);
6a1e4eb2c6a267bec1e8704ce9137bebb7792702Timo Sirainen
6a1e4eb2c6a267bec1e8704ce9137bebb7792702Timo Sirainen sync_ctx.index_sync_ctx = index_sync_ctx;
6a1e4eb2c6a267bec1e8704ce9137bebb7792702Timo Sirainen sync_ctx.sync_view = sync_view;
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen sync_ctx.t = mail_index_transaction_begin(sync_view, FALSE);
8907d617ce7c4f390c0f42f6f694db2fecdd5775Timo Sirainen
99be58a447b69d62cbd9e764000a06226b9c9c89Timo Sirainen sync_ctx.mails = buffer_create_dynamic(default_pool, 4096);
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen sync_ctx.syncs = buffer_create_dynamic(default_pool, 256);
39775ad03c459efe64cce924658da5094ba417e1Timo Sirainen
343a527f805ca5cce78496b959d6def70e5d0cd4Timo Sirainen ret = mail_index_get_header(sync_view, &sync_ctx.hdr);
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen i_assert(ret == 0);
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen sync_ctx.file_input = sync_ctx.ibox->mbox_file_stream;
b225c3c65f360d7b833f09f9b2fb3035ed5ea600Timo Sirainen sync_ctx.input = sync_ctx.ibox->mbox_stream;
b225c3c65f360d7b833f09f9b2fb3035ed5ea600Timo Sirainen sync_ctx.fd = sync_ctx.ibox->mbox_fd;
a2637488c8d514ec1ac3914811deee814f9761b3Timo Sirainen sync_ctx.flags = flags;
b225c3c65f360d7b833f09f9b2fb3035ed5ea600Timo Sirainen sync_ctx.delay_writes = sync_ctx.ibox->mbox_readonly ||
299183fbb6ec5d0828a0880da372540421ac4665Timo Sirainen sync_ctx.ibox->readonly ||
299183fbb6ec5d0828a0880da372540421ac4665Timo Sirainen ((flags & MBOX_SYNC_REWRITE) == 0 &&
b397a802ec245a9169dab6b62efa4f7f877c07f6Timo Sirainen getenv("MBOX_LAZY_WRITES") != NULL);
b397a802ec245a9169dab6b62efa4f7f877c07f6Timo Sirainen
b397a802ec245a9169dab6b62efa4f7f877c07f6Timo Sirainen
b397a802ec245a9169dab6b62efa4f7f877c07f6Timo Sirainen if (mbox_sync_do(&sync_ctx, flags) < 0)
988922bdf2d461021d210697f1f118956ca388e1Timo Sirainen ret = -1;
988922bdf2d461021d210697f1f118956ca388e1Timo Sirainen
988922bdf2d461021d210697f1f118956ca388e1Timo Sirainen if (ret < 0)
988922bdf2d461021d210697f1f118956ca388e1Timo Sirainen mail_index_transaction_rollback(sync_ctx.t);
988922bdf2d461021d210697f1f118956ca388e1Timo Sirainen else if (mail_index_transaction_commit(sync_ctx.t, &seq, &offset) < 0) {
988922bdf2d461021d210697f1f118956ca388e1Timo Sirainen mail_storage_set_index_error(ibox);
b397a802ec245a9169dab6b62efa4f7f877c07f6Timo Sirainen ret = -1;
b397a802ec245a9169dab6b62efa4f7f877c07f6Timo Sirainen } else {
5edfc0f1c3c55e906d8316d9cdeaa3b0c7000c19Timo Sirainen ibox->commit_log_file_seq = 0;
5edfc0f1c3c55e906d8316d9cdeaa3b0c7000c19Timo Sirainen ibox->commit_log_file_offset = 0;
eb276c05bf6b0a383c772d61e31cf09a8dbd36c7Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen sync_ctx.t = NULL;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen if (ret < 0)
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen mail_index_sync_rollback(index_sync_ctx);
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen else if (mail_index_sync_commit(index_sync_ctx) < 0) {
b225c3c65f360d7b833f09f9b2fb3035ed5ea600Timo Sirainen mail_storage_set_index_error(ibox);
b225c3c65f360d7b833f09f9b2fb3035ed5ea600Timo Sirainen ret = -1;
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen }
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen if (sync_ctx.seen_first_mail &&
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen sync_ctx.base_uid_last != sync_ctx.next_uid-1 &&
98c1cf256927e254f0c092acd2ddcd7ea50bd009Timo Sirainen ret == 0 && !sync_ctx.delay_writes) {
f7d43647acc6dc80064c8c4cacf5bf86f754c530Timo Sirainen /* rewrite X-IMAPbase header. do it after mail_index_sync_end()
98c1cf256927e254f0c092acd2ddcd7ea50bd009Timo Sirainen so previous transactions have been committed. */
98c1cf256927e254f0c092acd2ddcd7ea50bd009Timo Sirainen /* FIXME: ugly .. */
98c1cf256927e254f0c092acd2ddcd7ea50bd009Timo Sirainen ret = mail_index_sync_begin(ibox->index,
db7c9201c88e3d9bee10485194ee5b0c67249916Timo Sirainen &sync_ctx.index_sync_ctx,
299183fbb6ec5d0828a0880da372540421ac4665Timo Sirainen &sync_ctx.sync_view,
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen (uint32_t)-1, (uoff_t)-1,
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen FALSE, FALSE);
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen if (ret < 0)
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen mail_storage_set_index_error(ibox);
690bafa70767e3f6e98bbfd62ad4a26be2387ea9Timo Sirainen else {
690bafa70767e3f6e98bbfd62ad4a26be2387ea9Timo Sirainen (void)mail_index_get_header(sync_ctx.sync_view,
690bafa70767e3f6e98bbfd62ad4a26be2387ea9Timo Sirainen &sync_ctx.hdr);
17ad2164c747cedbf81dae1893063e71a3df0356Timo Sirainen if ((ret = mbox_sync_update_imap_base(&sync_ctx)) < 0)
690bafa70767e3f6e98bbfd62ad4a26be2387ea9Timo Sirainen mail_index_transaction_rollback(sync_ctx.t);
690bafa70767e3f6e98bbfd62ad4a26be2387ea9Timo Sirainen else if (mail_index_transaction_commit(sync_ctx.t,
690bafa70767e3f6e98bbfd62ad4a26be2387ea9Timo Sirainen &seq,
690bafa70767e3f6e98bbfd62ad4a26be2387ea9Timo Sirainen &offset) < 0) {
17ad2164c747cedbf81dae1893063e71a3df0356Timo Sirainen mail_storage_set_index_error(ibox);
17ad2164c747cedbf81dae1893063e71a3df0356Timo Sirainen ret = -1;
17ad2164c747cedbf81dae1893063e71a3df0356Timo Sirainen }
17ad2164c747cedbf81dae1893063e71a3df0356Timo Sirainen
c0bfb67ba32064347bac3241f1aac9b8a809e2f1Timo Sirainen if (mail_index_sync_commit(sync_ctx.
17ad2164c747cedbf81dae1893063e71a3df0356Timo Sirainen index_sync_ctx) < 0) {
c0bfb67ba32064347bac3241f1aac9b8a809e2f1Timo Sirainen mail_storage_set_index_error(ibox);
690bafa70767e3f6e98bbfd62ad4a26be2387ea9Timo Sirainen ret = -1;
690bafa70767e3f6e98bbfd62ad4a26be2387ea9Timo Sirainen }
690bafa70767e3f6e98bbfd62ad4a26be2387ea9Timo Sirainen }
690bafa70767e3f6e98bbfd62ad4a26be2387ea9Timo Sirainen }
690bafa70767e3f6e98bbfd62ad4a26be2387ea9Timo Sirainen
690bafa70767e3f6e98bbfd62ad4a26be2387ea9Timo Sirainen if (ret == 0 && ibox->mbox_lock_type == F_WRLCK) {
690bafa70767e3f6e98bbfd62ad4a26be2387ea9Timo Sirainen if (fsync(ibox->mbox_fd) < 0) {
690bafa70767e3f6e98bbfd62ad4a26be2387ea9Timo Sirainen mbox_set_syscall_error(ibox, "fsync()");
690bafa70767e3f6e98bbfd62ad4a26be2387ea9Timo Sirainen ret = -1;
690bafa70767e3f6e98bbfd62ad4a26be2387ea9Timo Sirainen }
af6d4a24cb6d18e50d172540cf49b1448a6f9872Timo Sirainen }
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
279cc94ab086f6a3cb764b1b98ff6b936efa3eaeTimo Sirainen if (lock_id != 0 && ibox->mbox_lock_type != F_RDLCK) {
b225c3c65f360d7b833f09f9b2fb3035ed5ea600Timo Sirainen /* drop to read lock */
279cc94ab086f6a3cb764b1b98ff6b936efa3eaeTimo Sirainen unsigned int read_lock_id = 0;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
7d207b1e77a7b5e3fda640e353acfc86d261fedfTimo Sirainen if (mbox_lock(ibox, F_RDLCK, &read_lock_id) <= 0)
b225c3c65f360d7b833f09f9b2fb3035ed5ea600Timo Sirainen ret = -1;
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen else {
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen if (mbox_unlock(ibox, lock_id) < 0)
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen ret = -1;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen lock_id = read_lock_id;
e05ea8311ae16687295048e88ca205dfe29fbcbfTimo Sirainen }
690bafa70767e3f6e98bbfd62ad4a26be2387ea9Timo Sirainen }
e05ea8311ae16687295048e88ca205dfe29fbcbfTimo Sirainen
e05ea8311ae16687295048e88ca205dfe29fbcbfTimo Sirainen if (lock_id != 0 && (flags & MBOX_SYNC_LOCK_READING) == 0) {
e05ea8311ae16687295048e88ca205dfe29fbcbfTimo Sirainen /* FIXME: keep the lock MBOX_SYNC_SECS+1 to make sure we
e05ea8311ae16687295048e88ca205dfe29fbcbfTimo Sirainen notice changes made by others .. and this has to be done
e05ea8311ae16687295048e88ca205dfe29fbcbfTimo Sirainen even if lock_reading is set.. except if
e05ea8311ae16687295048e88ca205dfe29fbcbfTimo Sirainen mbox_sync_dirty = TRUE */
e05ea8311ae16687295048e88ca205dfe29fbcbfTimo Sirainen if (mbox_unlock(ibox, lock_id) < 0)
e05ea8311ae16687295048e88ca205dfe29fbcbfTimo Sirainen ret = -1;
e05ea8311ae16687295048e88ca205dfe29fbcbfTimo Sirainen }
e05ea8311ae16687295048e88ca205dfe29fbcbfTimo Sirainen
e05ea8311ae16687295048e88ca205dfe29fbcbfTimo Sirainen str_free(sync_ctx.uidl);
e05ea8311ae16687295048e88ca205dfe29fbcbfTimo Sirainen str_free(sync_ctx.header);
e05ea8311ae16687295048e88ca205dfe29fbcbfTimo Sirainen str_free(sync_ctx.from_line);
e05ea8311ae16687295048e88ca205dfe29fbcbfTimo Sirainen buffer_free(sync_ctx.mails);
e05ea8311ae16687295048e88ca205dfe29fbcbfTimo Sirainen buffer_free(sync_ctx.syncs);
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen return ret;
e05ea8311ae16687295048e88ca205dfe29fbcbfTimo Sirainen}
e05ea8311ae16687295048e88ca205dfe29fbcbfTimo Sirainen
e05ea8311ae16687295048e88ca205dfe29fbcbfTimo Sirainenstruct mailbox_sync_context *
e05ea8311ae16687295048e88ca205dfe29fbcbfTimo Sirainenmbox_storage_sync_init(struct mailbox *box, enum mailbox_sync_flags flags)
e05ea8311ae16687295048e88ca205dfe29fbcbfTimo Sirainen{
e05ea8311ae16687295048e88ca205dfe29fbcbfTimo Sirainen struct index_mailbox *ibox = (struct index_mailbox *)box;
e05ea8311ae16687295048e88ca205dfe29fbcbfTimo Sirainen enum mbox_sync_flags mbox_sync_flags = 0;
e05ea8311ae16687295048e88ca205dfe29fbcbfTimo Sirainen int ret = 0;
e05ea8311ae16687295048e88ca205dfe29fbcbfTimo Sirainen
e05ea8311ae16687295048e88ca205dfe29fbcbfTimo Sirainen if ((flags & MAILBOX_SYNC_FLAG_FAST) == 0 ||
e05ea8311ae16687295048e88ca205dfe29fbcbfTimo Sirainen ibox->sync_last_check + MAILBOX_FULL_SYNC_INTERVAL <= ioloop_time) {
e05ea8311ae16687295048e88ca205dfe29fbcbfTimo Sirainen if ((flags & MAILBOX_SYNC_FLAG_FULL_READ) != 0)
e05ea8311ae16687295048e88ca205dfe29fbcbfTimo Sirainen mbox_sync_flags |= MBOX_SYNC_UNDIRTY;
e05ea8311ae16687295048e88ca205dfe29fbcbfTimo Sirainen if ((flags & MAILBOX_SYNC_FLAG_FULL_WRITE) != 0)
690bafa70767e3f6e98bbfd62ad4a26be2387ea9Timo Sirainen mbox_sync_flags |= MBOX_SYNC_REWRITE;
690bafa70767e3f6e98bbfd62ad4a26be2387ea9Timo Sirainen ret = mbox_sync(ibox, mbox_sync_flags);
690bafa70767e3f6e98bbfd62ad4a26be2387ea9Timo Sirainen }
690bafa70767e3f6e98bbfd62ad4a26be2387ea9Timo Sirainen
dc42ce2d44e84d9d05a9310c11f8764f319eb3abTimo Sirainen return index_mailbox_sync_init(box, flags, ret < 0);
dc42ce2d44e84d9d05a9310c11f8764f319eb3abTimo Sirainen}
8166e8a706078efc71923719ca285e84902883c0Timo Sirainen