mbox-sync.c revision f6699a08521aacc4c2bb5b6175691dad5f715f8c
5a580c3a38ced62d4bcc95b8ac7c4f2935b5d294Timo 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 "array.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "buffer.h"
98c1cf256927e254f0c092acd2ddcd7ea50bd009Timo Sirainen#include "hostpid.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "istream.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "file-set-size.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "str.h"
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen#include "read-full.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "write-full.h"
98c1cf256927e254f0c092acd2ddcd7ea50bd009Timo Sirainen#include "message-date.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "istream-raw-mbox.h"
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen#include "mbox-storage.h"
022412398e56a8f31ef111cfd7271498d64af9a9Timo Sirainen#include "mbox-from.h"
1a073dd6184645b026583274e05afba10dcc20bbTimo Sirainen#include "mbox-file.h"
98c1cf256927e254f0c092acd2ddcd7ea50bd009Timo Sirainen#include "mbox-lock.h"
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen#include "mbox-sync-private.h"
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include <stddef.h>
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include <stdlib.h>
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen#include <utime.h>
7a6b45405fb1544ac476e6eb1402a70cc1ddcdcfTimo Sirainen#include <sys/stat.h>
e05ea8311ae16687295048e88ca205dfe29fbcbfTimo Sirainen
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen/* The text below was taken exactly as c-client wrote it to my mailbox,
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen so it's probably copyrighted by University of Washington. */
98c1cf256927e254f0c092acd2ddcd7ea50bd009Timo Sirainen#define PSEUDO_MESSAGE_BODY \
98c1cf256927e254f0c092acd2ddcd7ea50bd009Timo Sirainen"This text is part of the internal format of your mail folder, and is not\n" \
f7d43647acc6dc80064c8c4cacf5bf86f754c530Timo Sirainen"a real message. It is created automatically by the mail system software.\n" \
98c1cf256927e254f0c092acd2ddcd7ea50bd009Timo Sirainen"If deleted, important folder data will be lost, and it will be re-created\n" \
98c1cf256927e254f0c092acd2ddcd7ea50bd009Timo Sirainen"with the data reset to initial values.\n"
98c1cf256927e254f0c092acd2ddcd7ea50bd009Timo Sirainen
98c1cf256927e254f0c092acd2ddcd7ea50bd009Timo Sirainenvoid mbox_sync_set_critical(struct mbox_sync_context *sync_ctx,
98c1cf256927e254f0c092acd2ddcd7ea50bd009Timo Sirainen const char *fmt, ...)
a2637488c8d514ec1ac3914811deee814f9761b3Timo Sirainen{
a2637488c8d514ec1ac3914811deee814f9761b3Timo Sirainen va_list va;
a2637488c8d514ec1ac3914811deee814f9761b3Timo Sirainen
a2637488c8d514ec1ac3914811deee814f9761b3Timo Sirainen if (sync_ctx->ext_modified) {
a2637488c8d514ec1ac3914811deee814f9761b3Timo Sirainen mail_storage_set_critical(&sync_ctx->mbox->storage->storage,
b6d817f0effeff645aadc01fd468a7d4084ba1f2Timo Sirainen "mbox file %s was modified while we were syncing, "
a2637488c8d514ec1ac3914811deee814f9761b3Timo Sirainen "check your locking settings", sync_ctx->mbox->path);
a2637488c8d514ec1ac3914811deee814f9761b3Timo Sirainen }
a2637488c8d514ec1ac3914811deee814f9761b3Timo Sirainen
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen va_start(va, fmt);
ca98892a6b8a30ffc1fe26fcf02c7d59e3204e7eTimo Sirainen mail_storage_set_critical(&sync_ctx->mbox->storage->storage,
a2637488c8d514ec1ac3914811deee814f9761b3Timo Sirainen "%s", t_strdup_vprintf(fmt, va));
a2637488c8d514ec1ac3914811deee814f9761b3Timo Sirainen va_end(va);
a2637488c8d514ec1ac3914811deee814f9761b3Timo Sirainen}
a2637488c8d514ec1ac3914811deee814f9761b3Timo Sirainen
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainenint mbox_sync_seek(struct mbox_sync_context *sync_ctx, uoff_t from_offset)
ca98892a6b8a30ffc1fe26fcf02c7d59e3204e7eTimo Sirainen{
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen if (istream_raw_mbox_seek(sync_ctx->input, from_offset) < 0) {
a2637488c8d514ec1ac3914811deee814f9761b3Timo Sirainen mbox_sync_set_critical(sync_ctx,
a2637488c8d514ec1ac3914811deee814f9761b3Timo Sirainen "Unexpectedly lost From-line at offset %"PRIuUOFF_T
a2637488c8d514ec1ac3914811deee814f9761b3Timo Sirainen " from mbox file %s", from_offset,
02b79f9c2636da1829eee5b92753602bba8b67edTimo Sirainen sync_ctx->mbox->path);
02b79f9c2636da1829eee5b92753602bba8b67edTimo Sirainen return -1;
02b79f9c2636da1829eee5b92753602bba8b67edTimo Sirainen }
a2637488c8d514ec1ac3914811deee814f9761b3Timo Sirainen return 0;
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen}
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen
02b79f9c2636da1829eee5b92753602bba8b67edTimo Sirainenvoid mbox_sync_file_update_ext_modified(struct mbox_sync_context *sync_ctx)
02b79f9c2636da1829eee5b92753602bba8b67edTimo Sirainen{
02b79f9c2636da1829eee5b92753602bba8b67edTimo Sirainen struct stat st;
02b79f9c2636da1829eee5b92753602bba8b67edTimo Sirainen
02b79f9c2636da1829eee5b92753602bba8b67edTimo Sirainen /* Do this even if ext_modified is already set. Expunging code relies
a2637488c8d514ec1ac3914811deee814f9761b3Timo Sirainen on last_stat being updated. */
299183fbb6ec5d0828a0880da372540421ac4665Timo Sirainen if (fstat(sync_ctx->write_fd, &st) < 0) {
299183fbb6ec5d0828a0880da372540421ac4665Timo Sirainen mbox_set_syscall_error(sync_ctx->mbox, "fstat()");
299183fbb6ec5d0828a0880da372540421ac4665Timo Sirainen return;
a2637488c8d514ec1ac3914811deee814f9761b3Timo Sirainen }
a2637488c8d514ec1ac3914811deee814f9761b3Timo Sirainen
299183fbb6ec5d0828a0880da372540421ac4665Timo Sirainen if (st.st_size != sync_ctx->last_stat.st_size ||
299183fbb6ec5d0828a0880da372540421ac4665Timo Sirainen (sync_ctx->last_stat.st_mtime != 0 &&
a2637488c8d514ec1ac3914811deee814f9761b3Timo Sirainen !CMP_ST_MTIME(&st, &sync_ctx->last_stat)))
299183fbb6ec5d0828a0880da372540421ac4665Timo Sirainen sync_ctx->ext_modified = TRUE;
299183fbb6ec5d0828a0880da372540421ac4665Timo Sirainen
299183fbb6ec5d0828a0880da372540421ac4665Timo Sirainen sync_ctx->last_stat = st;
299183fbb6ec5d0828a0880da372540421ac4665Timo Sirainen}
6288d3611eda14a017dae9927b73f46afb646c96Timo Sirainen
a2637488c8d514ec1ac3914811deee814f9761b3Timo Sirainenvoid mbox_sync_file_updated(struct mbox_sync_context *sync_ctx, bool dirty)
299183fbb6ec5d0828a0880da372540421ac4665Timo Sirainen{
299183fbb6ec5d0828a0880da372540421ac4665Timo Sirainen if (dirty) {
299183fbb6ec5d0828a0880da372540421ac4665Timo Sirainen /* just mark the stat as dirty. */
299183fbb6ec5d0828a0880da372540421ac4665Timo Sirainen sync_ctx->last_stat.st_mtime = 0;
299183fbb6ec5d0828a0880da372540421ac4665Timo Sirainen return;
299183fbb6ec5d0828a0880da372540421ac4665Timo Sirainen }
299183fbb6ec5d0828a0880da372540421ac4665Timo Sirainen if (fstat(sync_ctx->write_fd, &sync_ctx->last_stat) < 0)
299183fbb6ec5d0828a0880da372540421ac4665Timo Sirainen mbox_set_syscall_error(sync_ctx->mbox, "fstat()");
299183fbb6ec5d0828a0880da372540421ac4665Timo Sirainen i_stream_sync(sync_ctx->input);
299183fbb6ec5d0828a0880da372540421ac4665Timo Sirainen}
299183fbb6ec5d0828a0880da372540421ac4665Timo Sirainen
299183fbb6ec5d0828a0880da372540421ac4665Timo Sirainenstatic void mbox_sync_array_delete_to(ARRAY_TYPE(sync_recs) *syncs_arr,
299183fbb6ec5d0828a0880da372540421ac4665Timo Sirainen uint32_t last_uid)
299183fbb6ec5d0828a0880da372540421ac4665Timo Sirainen{
299183fbb6ec5d0828a0880da372540421ac4665Timo Sirainen struct mail_index_sync_rec *syncs;
299183fbb6ec5d0828a0880da372540421ac4665Timo Sirainen unsigned int src, dest, count;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen syncs = array_get_modifiable(syncs_arr, &count);
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen for (src = dest = 0; src < count; src++) {
9e59a1f3f095b3099478562cf3f3970a24736970Timo Sirainen i_assert(last_uid >= syncs[src].uid1);
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen if (last_uid <= syncs[src].uid2) {
178511b57faa7c3f8203dd8b7e4059d00cbfc23aTimo Sirainen /* keep it */
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen if (src != dest)
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen syncs[dest] = syncs[src];
2e937ed8585299b2e879a28314902a5f644813d2Timo Sirainen dest++;
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen }
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen }
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen array_delete(syncs_arr, dest, count - dest);
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen}
4d25408732be27e91f0430f71e87242760c2517cTimo Sirainen
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainenstatic int
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainenmbox_sync_read_next_mail(struct mbox_sync_context *sync_ctx,
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen struct mbox_sync_mail_context *mail_ctx)
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen{
e5c08648676d1989f6e70b95e5990c26b3e8b96bTimo Sirainen /* get EOF */
4d25408732be27e91f0430f71e87242760c2517cTimo Sirainen (void)istream_raw_mbox_get_header_offset(sync_ctx->input);
c3412ddeb9abc13f99d3caf50faf76cd99f7e9d2Timo Sirainen if (istream_raw_mbox_is_eof(sync_ctx->input))
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen return 0;
6f25019b337e27600159b596824da08732965576Timo Sirainen
6f25019b337e27600159b596824da08732965576Timo Sirainen p_clear(sync_ctx->mail_keyword_pool);
6f25019b337e27600159b596824da08732965576Timo Sirainen memset(mail_ctx, 0, sizeof(*mail_ctx));
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen mail_ctx->sync_ctx = sync_ctx;
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen mail_ctx->seq = ++sync_ctx->seq;
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen mail_ctx->header = sync_ctx->header;
02b79f9c2636da1829eee5b92753602bba8b67edTimo Sirainen
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen mail_ctx->mail.from_offset =
1e76a5b92f9d82d557f81f080f3dfad1c9d8f200Timo Sirainen istream_raw_mbox_get_start_offset(sync_ctx->input);
1e76a5b92f9d82d557f81f080f3dfad1c9d8f200Timo Sirainen mail_ctx->mail.offset =
ced118ac5caf6fe83d34339c2c65c63b2aa768acTimo Sirainen istream_raw_mbox_get_header_offset(sync_ctx->input);
9a06cabdfdf4d5e2f19a07e506c3c7d08a7e7038Timo Sirainen
9a06cabdfdf4d5e2f19a07e506c3c7d08a7e7038Timo Sirainen mbox_sync_parse_next_mail(sync_ctx->input, mail_ctx);
9a06cabdfdf4d5e2f19a07e506c3c7d08a7e7038Timo Sirainen i_assert(sync_ctx->input->v_offset != mail_ctx->mail.from_offset ||
e8a35266a5ceacdfafeeffd6bddae77931ff97ebTimo Sirainen sync_ctx->input->eof);
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen mail_ctx->mail.body_size =
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen istream_raw_mbox_get_body_size(sync_ctx->input,
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen mail_ctx->content_length);
b08b33d1f5ce3721dc2d83586c9cb0ca141331fdTimo Sirainen i_assert(mail_ctx->mail.body_size < OFF_T_MAX);
b08b33d1f5ce3721dc2d83586c9cb0ca141331fdTimo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen if ((mail_ctx->mail.flags & MAIL_RECENT) != 0 &&
de62ce819d59a529530da4b57be1b8d6dad13d6bTimo Sirainen !mail_ctx->mail.pseudo) {
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen if (!sync_ctx->mbox->ibox.keep_recent) {
f6699a08521aacc4c2bb5b6175691dad5f715f8cTimo Sirainen /* need to add 'O' flag to Status-header */
6843896c40bee4f9b6680ca7ced598c446e9f999Timo Sirainen mail_ctx->need_rewrite = TRUE;
6843896c40bee4f9b6680ca7ced598c446e9f999Timo Sirainen }
6843896c40bee4f9b6680ca7ced598c446e9f999Timo Sirainen mail_ctx->recent = TRUE;
6843896c40bee4f9b6680ca7ced598c446e9f999Timo Sirainen }
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen return 1;
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen}
f140f88a5ab3e2194f214c11f9f418559e949c83Timo Sirainen
022412398e56a8f31ef111cfd7271498d64af9a9Timo Sirainenstatic bool mbox_sync_buf_have_expunges(ARRAY_TYPE(sync_recs) *syncs_arr)
022412398e56a8f31ef111cfd7271498d64af9a9Timo Sirainen{
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen const struct mail_index_sync_rec *syncs;
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen unsigned int i, count;
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen syncs = array_get(syncs_arr, &count);
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen for (i = 0; i < count; i++) {
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen if (syncs[i].type == MAIL_INDEX_SYNC_TYPE_EXPUNGE)
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen return TRUE;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen }
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen return FALSE;
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen}
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
f6699a08521aacc4c2bb5b6175691dad5f715f8cTimo Sirainenstatic int mbox_sync_read_index_syncs(struct mbox_sync_context *sync_ctx,
f6699a08521aacc4c2bb5b6175691dad5f715f8cTimo Sirainen uint32_t uid, bool *sync_expunge_r)
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen{
f6699a08521aacc4c2bb5b6175691dad5f715f8cTimo Sirainen struct mail_index_sync_rec *sync_rec = &sync_ctx->sync_rec;
f6699a08521aacc4c2bb5b6175691dad5f715f8cTimo Sirainen int ret;
df4018ae2f0a95be602f724ca70df7e0e3bd6a7dTimo Sirainen
df4018ae2f0a95be602f724ca70df7e0e3bd6a7dTimo Sirainen *sync_expunge_r = FALSE;
a393d9d6dabdc46cf724f8cb004a652b4036d53dTimo Sirainen
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen if (sync_ctx->index_sync_ctx == NULL)
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen return 0;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen if (uid == 0 || sync_ctx->index_reset) {
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen /* nothing for this or the future ones */
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen uid = (uint32_t)-1;
a393d9d6dabdc46cf724f8cb004a652b4036d53dTimo Sirainen }
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen mbox_sync_array_delete_to(&sync_ctx->syncs, uid);
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen while (uid >= sync_rec->uid1) {
2bf7bb14894faf721518e2122a14a2389ef94078Timo Sirainen if (uid <= sync_rec->uid2 &&
9a06cabdfdf4d5e2f19a07e506c3c7d08a7e7038Timo Sirainen sync_rec->type != MAIL_INDEX_SYNC_TYPE_APPEND &&
a2637488c8d514ec1ac3914811deee814f9761b3Timo Sirainen (sync_rec->type != MAIL_INDEX_SYNC_TYPE_EXPUNGE ||
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen !sync_ctx->mbox->mbox_readonly)) {
2bf7bb14894faf721518e2122a14a2389ef94078Timo Sirainen array_append(&sync_ctx->syncs, sync_rec, 1);
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen
2bf7bb14894faf721518e2122a14a2389ef94078Timo Sirainen if (sync_rec->type == MAIL_INDEX_SYNC_TYPE_EXPUNGE)
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen *sync_expunge_r = TRUE;
9a06cabdfdf4d5e2f19a07e506c3c7d08a7e7038Timo Sirainen }
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
a2637488c8d514ec1ac3914811deee814f9761b3Timo Sirainen ret = mail_index_sync_next(sync_ctx->index_sync_ctx, sync_rec);
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen if (ret < 0) {
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen mail_storage_set_index_error(&sync_ctx->mbox->ibox);
2bf7bb14894faf721518e2122a14a2389ef94078Timo Sirainen return -1;
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen }
9a06cabdfdf4d5e2f19a07e506c3c7d08a7e7038Timo Sirainen
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen if (ret == 0) {
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen memset(sync_rec, 0, sizeof(*sync_rec));
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen break;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen }
6843896c40bee4f9b6680ca7ced598c446e9f999Timo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen switch (sync_rec->type) {
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen case MAIL_INDEX_SYNC_TYPE_APPEND:
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen if (sync_rec->uid2 >= sync_ctx->next_uid)
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen sync_ctx->next_uid = sync_rec->uid2 + 1;
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen memset(sync_rec, 0, sizeof(*sync_rec));
7f3be7d885c75cdd77f536929a45bc9764595960Timo Sirainen break;
7f3be7d885c75cdd77f536929a45bc9764595960Timo Sirainen case MAIL_INDEX_SYNC_TYPE_EXPUNGE:
7f3be7d885c75cdd77f536929a45bc9764595960Timo Sirainen break;
7f3be7d885c75cdd77f536929a45bc9764595960Timo Sirainen case MAIL_INDEX_SYNC_TYPE_FLAGS:
7f3be7d885c75cdd77f536929a45bc9764595960Timo Sirainen case MAIL_INDEX_SYNC_TYPE_KEYWORD_ADD:
f6699a08521aacc4c2bb5b6175691dad5f715f8cTimo Sirainen case MAIL_INDEX_SYNC_TYPE_KEYWORD_REMOVE:
f6699a08521aacc4c2bb5b6175691dad5f715f8cTimo Sirainen case MAIL_INDEX_SYNC_TYPE_KEYWORD_RESET:
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen if (sync_ctx->delay_writes) {
f6699a08521aacc4c2bb5b6175691dad5f715f8cTimo Sirainen /* we're not going to write these yet */
f6699a08521aacc4c2bb5b6175691dad5f715f8cTimo Sirainen uint32_t seq1, seq2;
df4018ae2f0a95be602f724ca70df7e0e3bd6a7dTimo Sirainen
df4018ae2f0a95be602f724ca70df7e0e3bd6a7dTimo Sirainen if (mail_index_lookup_uid_range(
7f3be7d885c75cdd77f536929a45bc9764595960Timo Sirainen sync_ctx->sync_view,
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen sync_rec->uid1, sync_rec->uid2,
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen &seq1, &seq2) < 0)
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen return -1;
ea5f188fc29dfaa0c4071e6413e16e1d04263722Timo Sirainen memset(sync_rec, 0, sizeof(*sync_rec));
03010dbaa74ec70f062994dfe3cd39bedc99a28bTimo Sirainen
f0f9c8e94abac18f8acd91b9e724c4c32863723aTimo Sirainen if (seq1 == 0)
7f3be7d885c75cdd77f536929a45bc9764595960Timo Sirainen break;
7f3be7d885c75cdd77f536929a45bc9764595960Timo Sirainen
7f3be7d885c75cdd77f536929a45bc9764595960Timo Sirainen mail_index_update_flags_range(sync_ctx->t,
7f3be7d885c75cdd77f536929a45bc9764595960Timo Sirainen seq1, seq2, MODIFY_ADD,
7f3be7d885c75cdd77f536929a45bc9764595960Timo Sirainen (enum mail_flags)
7f3be7d885c75cdd77f536929a45bc9764595960Timo Sirainen MAIL_INDEX_MAIL_FLAG_DIRTY);
7f3be7d885c75cdd77f536929a45bc9764595960Timo Sirainen }
7f3be7d885c75cdd77f536929a45bc9764595960Timo Sirainen break;
7f3be7d885c75cdd77f536929a45bc9764595960Timo Sirainen }
7f3be7d885c75cdd77f536929a45bc9764595960Timo Sirainen }
7f3be7d885c75cdd77f536929a45bc9764595960Timo Sirainen
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen if (!*sync_expunge_r)
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen *sync_expunge_r = mbox_sync_buf_have_expunges(&sync_ctx->syncs);
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainen return 0;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen}
4d25408732be27e91f0430f71e87242760c2517cTimo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainenvoid mbox_sync_apply_index_syncs(struct mbox_sync_context *sync_ctx,
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen struct mbox_sync_mail *mail,
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen enum mailbox_sync_type *sync_type_r)
4d25408732be27e91f0430f71e87242760c2517cTimo Sirainen{
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen const struct mail_index_sync_rec *syncs;
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen unsigned int i, count;
03010dbaa74ec70f062994dfe3cd39bedc99a28bTimo Sirainen enum mailbox_sync_type sync_type = 0;
4d25408732be27e91f0430f71e87242760c2517cTimo Sirainen
4d25408732be27e91f0430f71e87242760c2517cTimo Sirainen syncs = array_get(&sync_ctx->syncs, &count);
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen for (i = 0; i < count; i++) {
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen switch (syncs[i].type) {
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen case MAIL_INDEX_SYNC_TYPE_FLAGS:
8af07808ba203f8709e2ff9eaf2291e1c4a4d53dTimo Sirainen mail_index_sync_flags_apply(&syncs[i], &mail->flags);
7797aa2479e99aeb71057b7a2584b2cb72e4d3f8Timo Sirainen sync_type |= MAILBOX_SYNC_TYPE_FLAGS;
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen break;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen case MAIL_INDEX_SYNC_TYPE_KEYWORD_ADD:
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen case MAIL_INDEX_SYNC_TYPE_KEYWORD_REMOVE:
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen case MAIL_INDEX_SYNC_TYPE_KEYWORD_RESET:
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen if (!array_is_created(&mail->keywords)) {
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen /* no existing keywords */
ca98d6a1bbe73499da758a36bfab2963375c8d06Timo Sirainen if (syncs[i].type !=
d22301419109ed4a38351715e6760011421dadecTimo Sirainen MAIL_INDEX_SYNC_TYPE_KEYWORD_ADD)
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen break;
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen /* adding, create the array */
ca98d6a1bbe73499da758a36bfab2963375c8d06Timo Sirainen p_array_init(&mail->keywords,
ca98d6a1bbe73499da758a36bfab2963375c8d06Timo Sirainen sync_ctx->mail_keyword_pool,
ca98d6a1bbe73499da758a36bfab2963375c8d06Timo Sirainen I_MIN(10, count - i));
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen }
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen if (mail_index_sync_keywords_apply(&syncs[i],
84ed9f8f3d0e5ed47607ef417618e49e4f865557Timo Sirainen &mail->keywords))
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen sync_type |= MAILBOX_SYNC_TYPE_KEYWORDS;
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen break;
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen default:
a0b0d629931773c17a236f6214adbe0e13b9b3fdTimo Sirainen break;
a0b0d629931773c17a236f6214adbe0e13b9b3fdTimo Sirainen }
a0b0d629931773c17a236f6214adbe0e13b9b3fdTimo Sirainen }
a0b0d629931773c17a236f6214adbe0e13b9b3fdTimo Sirainen
a0b0d629931773c17a236f6214adbe0e13b9b3fdTimo Sirainen *sync_type_r = sync_type;
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen}
03010dbaa74ec70f062994dfe3cd39bedc99a28bTimo Sirainen
a0b0d629931773c17a236f6214adbe0e13b9b3fdTimo Sirainenstatic int
a0b0d629931773c17a236f6214adbe0e13b9b3fdTimo Sirainenmbox_sync_read_index_rec(struct mbox_sync_context *sync_ctx,
a0b0d629931773c17a236f6214adbe0e13b9b3fdTimo Sirainen uint32_t uid, const struct mail_index_record **rec_r)
ea5f188fc29dfaa0c4071e6413e16e1d04263722Timo Sirainen{
a0b0d629931773c17a236f6214adbe0e13b9b3fdTimo Sirainen const struct mail_index_record *rec = NULL;
a0b0d629931773c17a236f6214adbe0e13b9b3fdTimo Sirainen uint32_t messages_count;
a0b0d629931773c17a236f6214adbe0e13b9b3fdTimo Sirainen int ret = 0;
a0b0d629931773c17a236f6214adbe0e13b9b3fdTimo Sirainen
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen if (sync_ctx->index_reset) {
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen *rec_r = NULL;
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen return 1;
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen }
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen messages_count =
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen mail_index_view_get_messages_count(sync_ctx->sync_view);
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen while (sync_ctx->idx_seq <= messages_count) {
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen ret = mail_index_lookup(sync_ctx->sync_view,
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen sync_ctx->idx_seq, &rec);
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen if (ret < 0) {
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen mail_storage_set_index_error(&sync_ctx->mbox->ibox);
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen return -1;
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen }
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen i_assert(ret != 0); /* we should be looking at head index */
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen if (uid <= rec->uid)
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen break;
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen /* externally expunged message, remove from index */
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen mail_index_expunge(sync_ctx->t, sync_ctx->idx_seq);
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen sync_ctx->idx_seq++;
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen rec = NULL;
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen }
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen if (rec == NULL && uid < sync_ctx->idx_next_uid) {
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen /* this UID was already in index and it was expunged */
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen mbox_sync_set_critical(sync_ctx,
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen "mbox sync: Expunged message reappeared in mailbox %s "
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen "(UID %u < %u, seq=%u, idx_msgs=%u)",
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen sync_ctx->mbox->path, uid, sync_ctx->idx_next_uid,
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen sync_ctx->seq, messages_count);
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen ret = 0; rec = NULL;
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen } else if (rec != NULL && rec->uid != uid) {
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen /* new UID in the middle of the mailbox - shouldn't happen */
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen mbox_sync_set_critical(sync_ctx,
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen "mbox sync: UID inserted in the middle of mailbox %s "
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen "(%u > %u, seq=%u, idx_msgs=%u)", sync_ctx->mbox->path,
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen rec->uid, uid, sync_ctx->seq, messages_count);
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen ret = 0; rec = NULL;
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen } else {
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen ret = 1;
d22301419109ed4a38351715e6760011421dadecTimo Sirainen }
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen *rec_r = rec;
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen return ret;
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen}
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainenstatic int mbox_sync_find_index_md5(struct mbox_sync_context *sync_ctx,
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen unsigned char hdr_md5_sum[],
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen const struct mail_index_record **rec_r)
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen{
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen const struct mail_index_record *rec = NULL;
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen uint32_t messages_count;
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen const void *data;
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen int ret;
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen if (sync_ctx->index_reset) {
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen *rec_r = NULL;
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen return 0;
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen }
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen messages_count =
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen mail_index_view_get_messages_count(sync_ctx->sync_view);
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen while (sync_ctx->idx_seq <= messages_count) {
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen ret = mail_index_lookup(sync_ctx->sync_view,
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen sync_ctx->idx_seq, &rec);
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen if (ret < 0) {
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen mail_storage_set_index_error(&sync_ctx->mbox->ibox);
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen return -1;
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen }
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen if (mail_index_lookup_ext(sync_ctx->sync_view,
7e6749d69b9d3f87e598b8dc3346b82f3cb3b8e7Timo Sirainen sync_ctx->idx_seq,
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen sync_ctx->mbox->ibox.md5hdr_ext_idx,
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen &data) < 0) {
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen mail_storage_set_index_error(&sync_ctx->mbox->ibox);
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen return -1;
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen }
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen if (data != NULL && memcmp(data, hdr_md5_sum, 16) == 0)
5137d2d80255938a0f5fb8f3c1a21b34cf11ada3Timo Sirainen break;
33d63688ed8b26dc333e3c2edbfb2fe6e412604dTimo Sirainen
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen /* externally expunged message, remove from index */
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen mail_index_expunge(sync_ctx->t, sync_ctx->idx_seq);
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen sync_ctx->idx_seq++;
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen rec = NULL;
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen }
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen
d0d7fcf3ce44f26fdf34c1542a25cec644c5c4c7Timo Sirainen *rec_r = rec;
5d98a279f2726a8c38ef1e8e3c54d6c62d523a65Timo Sirainen return 0;
5d98a279f2726a8c38ef1e8e3c54d6c62d523a65Timo Sirainen}
5d98a279f2726a8c38ef1e8e3c54d6c62d523a65Timo Sirainen
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainenstatic int
d0d7fcf3ce44f26fdf34c1542a25cec644c5c4c7Timo Sirainenmbox_sync_update_from_offset(struct mbox_sync_context *sync_ctx,
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen struct mbox_sync_mail *mail,
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen bool nocheck)
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen{
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen const void *data;
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen uint64_t offset;
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen
7f3be7d885c75cdd77f536929a45bc9764595960Timo Sirainen if (!nocheck) {
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen /* see if from_offset needs updating */
7797aa2479e99aeb71057b7a2584b2cb72e4d3f8Timo Sirainen if (mail_index_lookup_ext(sync_ctx->sync_view,
ea5f188fc29dfaa0c4071e6413e16e1d04263722Timo Sirainen sync_ctx->idx_seq,
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen sync_ctx->mbox->mbox_ext_idx,
7f3be7d885c75cdd77f536929a45bc9764595960Timo Sirainen &data) < 0) {
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen mail_storage_set_index_error(&sync_ctx->mbox->ibox);
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen return -1;
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen }
3f26c5aced2e71efc783f26bb8a7ac53f7504622Timo Sirainen
3f26c5aced2e71efc783f26bb8a7ac53f7504622Timo Sirainen if (data != NULL &&
3f26c5aced2e71efc783f26bb8a7ac53f7504622Timo 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->mbox->mbox_ext_idx, &offset, NULL);
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen return 0;
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen}
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainenstatic void
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainenmbox_sync_update_index_keywords(struct mbox_sync_mail_context *mail_ctx)
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen{
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen struct mbox_sync_context *sync_ctx = mail_ctx->sync_ctx;
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen struct mail_keywords *keywords;
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen keywords = !array_is_created(&mail_ctx->mail.keywords) ?
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen mail_index_keywords_create(sync_ctx->t, NULL) :
a0b0d629931773c17a236f6214adbe0e13b9b3fdTimo Sirainen mail_index_keywords_create_from_indexes(sync_ctx->t,
a0b0d629931773c17a236f6214adbe0e13b9b3fdTimo Sirainen &mail_ctx->mail.keywords);
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen mail_index_update_keywords(sync_ctx->t, sync_ctx->idx_seq,
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen MODIFY_REPLACE, keywords);
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen mail_index_keywords_free(&keywords);
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen}
279cc94ab086f6a3cb764b1b98ff6b936efa3eaeTimo Sirainen
279cc94ab086f6a3cb764b1b98ff6b936efa3eaeTimo Sirainenstatic int
279cc94ab086f6a3cb764b1b98ff6b936efa3eaeTimo Sirainenmbox_sync_update_md5_if_changed(struct mbox_sync_mail_context *mail_ctx)
1d3f7c1278168d5b1cbfa9a2cc9929a0909056b4Timo Sirainen{
279cc94ab086f6a3cb764b1b98ff6b936efa3eaeTimo Sirainen struct mbox_sync_context *sync_ctx = mail_ctx->sync_ctx;
e8a35266a5ceacdfafeeffd6bddae77931ff97ebTimo Sirainen const void *ext_data;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen if (mail_index_lookup_ext(sync_ctx->sync_view, sync_ctx->idx_seq,
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen sync_ctx->mbox->ibox.md5hdr_ext_idx,
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainen &ext_data) < 0) {
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen mail_storage_set_index_error(&sync_ctx->mbox->ibox);
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen return -1;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen }
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen if (ext_data == NULL ||
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen memcmp(mail_ctx->hdr_md5_sum, ext_data, 16) != 0) {
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen mail_index_update_ext(sync_ctx->t, sync_ctx->idx_seq,
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen sync_ctx->mbox->ibox.md5hdr_ext_idx,
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen mail_ctx->hdr_md5_sum, NULL);
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen }
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen return 0;
4d25408732be27e91f0430f71e87242760c2517cTimo Sirainen}
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen
4d25408732be27e91f0430f71e87242760c2517cTimo Sirainenstatic int mbox_sync_update_index(struct mbox_sync_mail_context *mail_ctx,
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen const struct mail_index_record *rec)
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen{
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen struct mbox_sync_context *sync_ctx = mail_ctx->sync_ctx;
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen struct mbox_sync_mail *mail = &mail_ctx->mail;
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen struct mailbox *box = &sync_ctx->mbox->ibox.box;
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen uint8_t mbox_flags;
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen mbox_flags = mail->flags & MAIL_FLAGS_MASK;
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen if (mail_ctx->dirty)
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen mbox_flags |= MAIL_INDEX_MAIL_FLAG_DIRTY;
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen else if (!sync_ctx->delay_writes)
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen mbox_flags &= ~MAIL_INDEX_MAIL_FLAG_DIRTY;
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen if (rec == NULL) {
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen /* new message */
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen mail_index_append(sync_ctx->t, mail->uid, &sync_ctx->idx_seq);
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen mail_index_update_flags(sync_ctx->t, sync_ctx->idx_seq,
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen MODIFY_REPLACE, mbox_flags);
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen mbox_sync_update_index_keywords(mail_ctx);
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen if (sync_ctx->mbox->mbox_save_md5 != 0) {
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen mail_index_update_ext(sync_ctx->t, sync_ctx->idx_seq,
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen sync_ctx->mbox->ibox.md5hdr_ext_idx,
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen mail_ctx->hdr_md5_sum, NULL);
16aba431c576c1dbd99cbaae4f9d65eea9ad73c2Timo Sirainen }
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen } else {
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen /* see if we need to update flags in index file. the flags in
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen sync records are automatically applied to rec->flags at the
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen end of index syncing, so calculate those new flags first */
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen struct mbox_sync_mail idx_mail;
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen enum mailbox_sync_type sync_type;
16aba431c576c1dbd99cbaae4f9d65eea9ad73c2Timo Sirainen
16aba431c576c1dbd99cbaae4f9d65eea9ad73c2Timo Sirainen memset(&idx_mail, 0, sizeof(idx_mail));
16aba431c576c1dbd99cbaae4f9d65eea9ad73c2Timo Sirainen idx_mail.flags = rec->flags;
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen /* get old keywords */
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen t_push();
16aba431c576c1dbd99cbaae4f9d65eea9ad73c2Timo Sirainen t_array_init(&idx_mail.keywords, 32);
a2637488c8d514ec1ac3914811deee814f9761b3Timo Sirainen if (mail_index_lookup_keywords(sync_ctx->sync_view,
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen sync_ctx->idx_seq,
16aba431c576c1dbd99cbaae4f9d65eea9ad73c2Timo Sirainen &idx_mail.keywords) < 0) {
16aba431c576c1dbd99cbaae4f9d65eea9ad73c2Timo Sirainen mail_storage_set_index_error(&sync_ctx->mbox->ibox);
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen t_pop();
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen return -1;
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen }
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen mbox_sync_apply_index_syncs(sync_ctx, &idx_mail,
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen &sync_type);
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen if (sync_type != 0 && box->v.sync_notify != NULL)
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen box->v.sync_notify(box, rec->uid, sync_type);
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen#define SYNC_FLAGS (MAIL_RECENT | MAIL_INDEX_MAIL_FLAG_DIRTY)
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen if ((idx_mail.flags & MAIL_INDEX_MAIL_FLAG_DIRTY) != 0) {
a2637488c8d514ec1ac3914811deee814f9761b3Timo Sirainen /* flags are dirty. ignore whatever was in the mbox,
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen but update recent/dirty flag states if needed. */
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen mbox_flags &= SYNC_FLAGS;
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen mbox_flags |= idx_mail.flags & ~SYNC_FLAGS;
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen if (sync_ctx->delay_writes)
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen mbox_flags |= MAIL_INDEX_MAIL_FLAG_DIRTY;
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen } else {
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen /* keep index's internal flags */
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen mbox_flags &= MAIL_FLAGS_MASK | SYNC_FLAGS;
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen mbox_flags |= idx_mail.flags &
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen ~(MAIL_FLAGS_MASK | SYNC_FLAGS);
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen }
299183fbb6ec5d0828a0880da372540421ac4665Timo Sirainen
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen if ((idx_mail.flags & ~SYNC_FLAGS) !=
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen (mbox_flags & ~SYNC_FLAGS)) {
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen /* flags other than recent/dirty have changed */
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen mail_index_update_flags(sync_ctx->t, sync_ctx->idx_seq,
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen MODIFY_REPLACE, mbox_flags);
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen } else {
064bfeee2f9156683b191cc0f3f7b242720942f7Timo Sirainen if (((idx_mail.flags ^ mbox_flags) &
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen MAIL_RECENT) != 0) {
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen /* drop recent flag (it can only be dropped) */
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen mail_index_update_flags(sync_ctx->t,
b225c3c65f360d7b833f09f9b2fb3035ed5ea600Timo Sirainen sync_ctx->idx_seq,
064bfeee2f9156683b191cc0f3f7b242720942f7Timo Sirainen MODIFY_REMOVE, MAIL_RECENT);
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen }
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen if (((idx_mail.flags ^ mbox_flags) &
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen MAIL_INDEX_MAIL_FLAG_DIRTY) != 0) {
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen /* dirty flag state changed */
299183fbb6ec5d0828a0880da372540421ac4665Timo Sirainen bool dirty = (mbox_flags &
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen MAIL_INDEX_MAIL_FLAG_DIRTY) != 0;
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen mail_index_update_flags(sync_ctx->t,
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen sync_ctx->idx_seq,
8907d617ce7c4f390c0f42f6f694db2fecdd5775Timo Sirainen dirty ? MODIFY_ADD : MODIFY_REMOVE,
01cbf4ac5d44137ab434791be7f838d98d0fcf3bTimo Sirainen (enum mail_flags)
01cbf4ac5d44137ab434791be7f838d98d0fcf3bTimo Sirainen MAIL_INDEX_MAIL_FLAG_DIRTY);
39775ad03c459efe64cce924658da5094ba417e1Timo Sirainen }
39775ad03c459efe64cce924658da5094ba417e1Timo Sirainen }
ab3c1eab9ca13916358a9e8b12df8212fefb7dbfTimo Sirainen
01cbf4ac5d44137ab434791be7f838d98d0fcf3bTimo Sirainen if ((idx_mail.flags & MAIL_INDEX_MAIL_FLAG_DIRTY) == 0 &&
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen !index_keyword_array_cmp(&idx_mail.keywords,
3021a062b16ff0138408be6107d6bcd0ced280b9Timo Sirainen &mail_ctx->mail.keywords))
39775ad03c459efe64cce924658da5094ba417e1Timo Sirainen mbox_sync_update_index_keywords(mail_ctx);
39775ad03c459efe64cce924658da5094ba417e1Timo Sirainen t_pop();
1e76a5b92f9d82d557f81f080f3dfad1c9d8f200Timo Sirainen
e5c08648676d1989f6e70b95e5990c26b3e8b96bTimo Sirainen /* see if we need to update md5 sum. */
e5c08648676d1989f6e70b95e5990c26b3e8b96bTimo Sirainen if (sync_ctx->mbox->mbox_save_md5 != 0) {
e05ea8311ae16687295048e88ca205dfe29fbcbfTimo Sirainen if (mbox_sync_update_md5_if_changed(mail_ctx) < 0)
39775ad03c459efe64cce924658da5094ba417e1Timo Sirainen return -1;
39775ad03c459efe64cce924658da5094ba417e1Timo Sirainen }
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen }
01cbf4ac5d44137ab434791be7f838d98d0fcf3bTimo Sirainen
01cbf4ac5d44137ab434791be7f838d98d0fcf3bTimo Sirainen if (mail_ctx->recent &&
01cbf4ac5d44137ab434791be7f838d98d0fcf3bTimo Sirainen (rec == NULL || (rec->flags & MAIL_INDEX_MAIL_FLAG_DIRTY) == 0 ||
8907d617ce7c4f390c0f42f6f694db2fecdd5775Timo Sirainen (rec->flags & MAIL_RECENT) != 0)) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen index_mailbox_set_recent(&sync_ctx->mbox->ibox,
c35d0c3eb4ba89432896e1f9770ab31cc63c232bTimo Sirainen sync_ctx->idx_seq);
d22301419109ed4a38351715e6760011421dadecTimo Sirainen }
5137d2d80255938a0f5fb8f3c1a21b34cf11ada3Timo Sirainen
5137d2d80255938a0f5fb8f3c1a21b34cf11ada3Timo Sirainen /* update from_offsets, but not if we're going to rewrite this message.
5137d2d80255938a0f5fb8f3c1a21b34cf11ada3Timo Sirainen rewriting would just move it anyway. */
5137d2d80255938a0f5fb8f3c1a21b34cf11ada3Timo Sirainen if (sync_ctx->need_space_seq == 0) {
5137d2d80255938a0f5fb8f3c1a21b34cf11ada3Timo Sirainen bool nocheck = rec == NULL || sync_ctx->expunged_space > 0;
e063aca6bc2f08bec516d4b631052ea9191f011dTimo Sirainen if (mbox_sync_update_from_offset(sync_ctx, mail, nocheck) < 0)
c35d0c3eb4ba89432896e1f9770ab31cc63c232bTimo Sirainen return -1;
1e76a5b92f9d82d557f81f080f3dfad1c9d8f200Timo Sirainen }
4d25408732be27e91f0430f71e87242760c2517cTimo Sirainen return 0;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen}
4d25408732be27e91f0430f71e87242760c2517cTimo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainenstatic int mbox_read_from_line(struct mbox_sync_mail_context *ctx)
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen{
5137d2d80255938a0f5fb8f3c1a21b34cf11ada3Timo Sirainen struct istream *input = ctx->sync_ctx->file_input;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen const unsigned char *data;
c35d0c3eb4ba89432896e1f9770ab31cc63c232bTimo Sirainen size_t size, from_line_size;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen buffer_set_used_size(ctx->sync_ctx->from_line, 0);
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen from_line_size = ctx->hdr_offset - ctx->mail.from_offset;
c35d0c3eb4ba89432896e1f9770ab31cc63c232bTimo Sirainen
c35d0c3eb4ba89432896e1f9770ab31cc63c232bTimo Sirainen i_stream_seek(input, ctx->mail.from_offset);
c35d0c3eb4ba89432896e1f9770ab31cc63c232bTimo Sirainen for (;;) {
c35d0c3eb4ba89432896e1f9770ab31cc63c232bTimo Sirainen data = i_stream_get_data(input, &size);
2be66b9eddad3841a1195fe9aeb1eaf0f28f1116Timo Sirainen if (size >= from_line_size)
2be66b9eddad3841a1195fe9aeb1eaf0f28f1116Timo Sirainen size = from_line_size;
c35d0c3eb4ba89432896e1f9770ab31cc63c232bTimo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen buffer_append(ctx->sync_ctx->from_line, data, size);
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen i_stream_skip(input, size);
c35d0c3eb4ba89432896e1f9770ab31cc63c232bTimo Sirainen from_line_size -= size;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
b2ecd50bb98c44816cb07c17aa17fae2b425f941Timo Sirainen if (from_line_size == 0)
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen break;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen if (i_stream_read(input) < 0)
c35d0c3eb4ba89432896e1f9770ab31cc63c232bTimo Sirainen return -1;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen }
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen return 0;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen}
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainenstatic int mbox_rewrite_base_uid_last(struct mbox_sync_context *sync_ctx)
b2ecd50bb98c44816cb07c17aa17fae2b425f941Timo Sirainen{
c35d0c3eb4ba89432896e1f9770ab31cc63c232bTimo Sirainen unsigned char buf[10];
7fd72a47d7ddfbd38c8697e228b6951f495dfb61Timo Sirainen const char *str;
7fd72a47d7ddfbd38c8697e228b6951f495dfb61Timo Sirainen uint32_t uid_last;
7fd72a47d7ddfbd38c8697e228b6951f495dfb61Timo Sirainen unsigned int i;
7fd72a47d7ddfbd38c8697e228b6951f495dfb61Timo Sirainen int ret;
7fd72a47d7ddfbd38c8697e228b6951f495dfb61Timo Sirainen
c35d0c3eb4ba89432896e1f9770ab31cc63c232bTimo Sirainen i_assert(sync_ctx->base_uid_last_offset != 0);
c35d0c3eb4ba89432896e1f9770ab31cc63c232bTimo Sirainen
7fd72a47d7ddfbd38c8697e228b6951f495dfb61Timo Sirainen /* first check that the 10 bytes are there and they're exactly as
7fd72a47d7ddfbd38c8697e228b6951f495dfb61Timo Sirainen expected. just an extra safety check to make sure we never write
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen to wrong location in the mbox file. */
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen ret = pread_full(sync_ctx->write_fd, buf, sizeof(buf),
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen sync_ctx->base_uid_last_offset);
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen if (ret < 0) {
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen mbox_set_syscall_error(sync_ctx->mbox, "pread_full()");
6a1e4eb2c6a267bec1e8704ce9137bebb7792702Timo Sirainen return -1;
60d3fa9883237e896a8704275b6116fa46f7ffdaTimo Sirainen }
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen if (ret == 0) {
659fe5d24825b160cae512538088020d97a60239Timo Sirainen mbox_sync_set_critical(sync_ctx,
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen "X-IMAPbase uid-last unexpectedly points outside "
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen "mbox file %s", sync_ctx->mbox->path);
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen return -1;
c35d0c3eb4ba89432896e1f9770ab31cc63c232bTimo Sirainen }
c35d0c3eb4ba89432896e1f9770ab31cc63c232bTimo Sirainen
c35d0c3eb4ba89432896e1f9770ab31cc63c232bTimo Sirainen for (i = 0, uid_last = 0; i < sizeof(buf); i++) {
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen if (buf[i] < '0' || buf[i] > '9') {
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen uid_last = (uint32_t)-1;
064bfeee2f9156683b191cc0f3f7b242720942f7Timo Sirainen break;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen }
7fd72a47d7ddfbd38c8697e228b6951f495dfb61Timo Sirainen uid_last = uid_last * 10 + (buf[i] - '0');
7fd72a47d7ddfbd38c8697e228b6951f495dfb61Timo Sirainen }
7fd72a47d7ddfbd38c8697e228b6951f495dfb61Timo Sirainen
7fd72a47d7ddfbd38c8697e228b6951f495dfb61Timo Sirainen if (uid_last != sync_ctx->base_uid_last) {
c35d0c3eb4ba89432896e1f9770ab31cc63c232bTimo Sirainen mbox_sync_set_critical(sync_ctx,
7fd72a47d7ddfbd38c8697e228b6951f495dfb61Timo Sirainen "X-IMAPbase uid-last unexpectedly lost in mbox file %s",
b2ecd50bb98c44816cb07c17aa17fae2b425f941Timo Sirainen sync_ctx->mbox->path);
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen return -1;
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen }
7a6b45405fb1544ac476e6eb1402a70cc1ddcdcfTimo Sirainen
7a6b45405fb1544ac476e6eb1402a70cc1ddcdcfTimo Sirainen /* and write it */
7a6b45405fb1544ac476e6eb1402a70cc1ddcdcfTimo Sirainen str = t_strdup_printf("%010u", sync_ctx->next_uid - 1);
7a6b45405fb1544ac476e6eb1402a70cc1ddcdcfTimo Sirainen if (pwrite_full(sync_ctx->write_fd, str, 10,
7a6b45405fb1544ac476e6eb1402a70cc1ddcdcfTimo Sirainen sync_ctx->base_uid_last_offset) < 0) {
7a6b45405fb1544ac476e6eb1402a70cc1ddcdcfTimo Sirainen mbox_set_syscall_error(sync_ctx->mbox, "pwrite_full()");
6a1e4eb2c6a267bec1e8704ce9137bebb7792702Timo Sirainen return -1;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen }
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen mbox_sync_file_updated(sync_ctx, FALSE);
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen sync_ctx->base_uid_last = sync_ctx->next_uid - 1;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen return 0;
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen}
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainenstatic int
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainenmbox_write_from_line(struct mbox_sync_mail_context *ctx)
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen{
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen string_t *str = ctx->sync_ctx->from_line;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen if (pwrite_full(ctx->sync_ctx->write_fd, str_data(str), str_len(str),
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen ctx->mail.from_offset) < 0) {
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen mbox_set_syscall_error(ctx->sync_ctx->mbox, "pwrite_full()");
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen return -1;
1e76a5b92f9d82d557f81f080f3dfad1c9d8f200Timo Sirainen }
36816b5af1472ae76a1909ae3cf29fd614b2ebfcTimo Sirainen
829c036d4ddfbd9ea49bd8a7c54e3057177d346eTimo Sirainen mbox_sync_file_updated(ctx->sync_ctx, FALSE);
36816b5af1472ae76a1909ae3cf29fd614b2ebfcTimo Sirainen return 0;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen}
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainenstatic void update_from_offsets(struct mbox_sync_context *sync_ctx)
dc8552739fa29f011ab71ec383ec6d580a5a9661Timo Sirainen{
dc8552739fa29f011ab71ec383ec6d580a5a9661Timo Sirainen const struct mbox_sync_mail *mails;
8d5991f5c4a8840bf1ea754093dbec505564ab78Timo Sirainen unsigned int i, count;
dc8552739fa29f011ab71ec383ec6d580a5a9661Timo Sirainen uint32_t ext_idx;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen uint64_t offset;
39775ad03c459efe64cce924658da5094ba417e1Timo Sirainen
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen ext_idx = sync_ctx->mbox->mbox_ext_idx;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen mails = array_get(&sync_ctx->mails, &count);
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen for (i = 0; i < count; i++) {
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen if (mails[i].idx_seq == 0 || mails[i].expunged)
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen continue;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen sync_ctx->moved_offsets = TRUE;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen offset = mails[i].from_offset;
4214b59ac7f3899f8d887d055ef519f5a622d249Timo Sirainen mail_index_update_ext(sync_ctx->t, mails[i].idx_seq,
7a6b45405fb1544ac476e6eb1402a70cc1ddcdcfTimo Sirainen ext_idx, &offset, NULL);
f5b4979e2780c4df112a300967d647e2fdd73511Timo Sirainen }
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen}
2cb565cd978aafd5714792b5161889986d49e431Timo Sirainen
2cb565cd978aafd5714792b5161889986d49e431Timo Sirainenstatic void mbox_sync_handle_expunge(struct mbox_sync_mail_context *mail_ctx)
343a527f805ca5cce78496b959d6def70e5d0cd4Timo Sirainen{
5486e1e123484f3a8d7d895e8ac41156f2a96305Timo Sirainen struct mbox_sync_context *sync_ctx = mail_ctx->sync_ctx;
5486e1e123484f3a8d7d895e8ac41156f2a96305Timo Sirainen struct mailbox *box = &sync_ctx->mbox->ibox.box;
5486e1e123484f3a8d7d895e8ac41156f2a96305Timo Sirainen
5486e1e123484f3a8d7d895e8ac41156f2a96305Timo Sirainen if (box->v.sync_notify != NULL) {
f5b4979e2780c4df112a300967d647e2fdd73511Timo Sirainen box->v.sync_notify(box, mail_ctx->mail.uid,
5486e1e123484f3a8d7d895e8ac41156f2a96305Timo Sirainen MAILBOX_SYNC_TYPE_EXPUNGE);
5486e1e123484f3a8d7d895e8ac41156f2a96305Timo Sirainen }
5486e1e123484f3a8d7d895e8ac41156f2a96305Timo Sirainen mail_index_expunge(sync_ctx->t, mail_ctx->mail.idx_seq);
5486e1e123484f3a8d7d895e8ac41156f2a96305Timo Sirainen
6e4cd4ba520bc22ce375de378f4751136ebcf75aTimo Sirainen mail_ctx->mail.expunged = TRUE;
b2ecd50bb98c44816cb07c17aa17fae2b425f941Timo Sirainen mail_ctx->mail.offset = mail_ctx->mail.from_offset;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen mail_ctx->mail.space =
dc8552739fa29f011ab71ec383ec6d580a5a9661Timo Sirainen mail_ctx->body_offset - mail_ctx->mail.from_offset +
dc8552739fa29f011ab71ec383ec6d580a5a9661Timo Sirainen mail_ctx->mail.body_size;
dc8552739fa29f011ab71ec383ec6d580a5a9661Timo Sirainen mail_ctx->mail.body_size = 0;
dc8552739fa29f011ab71ec383ec6d580a5a9661Timo Sirainen mail_ctx->mail.uid = 0;
dc8552739fa29f011ab71ec383ec6d580a5a9661Timo Sirainen
dc8552739fa29f011ab71ec383ec6d580a5a9661Timo Sirainen if (sync_ctx->seq == 1) {
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen /* expunging first message, fix space to contain next
dc8552739fa29f011ab71ec383ec6d580a5a9661Timo Sirainen message's \n header too since it will be removed. */
b2ecd50bb98c44816cb07c17aa17fae2b425f941Timo Sirainen mail_ctx->mail.space++;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen if (istream_raw_mbox_has_crlf_ending(sync_ctx->input)) {
6a1e4eb2c6a267bec1e8704ce9137bebb7792702Timo Sirainen mail_ctx->mail.space++;
4214b59ac7f3899f8d887d055ef519f5a622d249Timo Sirainen sync_ctx->first_mail_crlf_expunged = TRUE;
4214b59ac7f3899f8d887d055ef519f5a622d249Timo Sirainen }
4214b59ac7f3899f8d887d055ef519f5a622d249Timo Sirainen
4214b59ac7f3899f8d887d055ef519f5a622d249Timo Sirainen /* uid-last offset is invalid now */
8d5991f5c4a8840bf1ea754093dbec505564ab78Timo Sirainen sync_ctx->base_uid_last_offset = 0;
6a1e4eb2c6a267bec1e8704ce9137bebb7792702Timo Sirainen }
6a1e4eb2c6a267bec1e8704ce9137bebb7792702Timo Sirainen
4214b59ac7f3899f8d887d055ef519f5a622d249Timo Sirainen sync_ctx->expunged_space += mail_ctx->mail.space;
4214b59ac7f3899f8d887d055ef519f5a622d249Timo Sirainen}
6a1e4eb2c6a267bec1e8704ce9137bebb7792702Timo Sirainen
930dcf1576f99057ad572420d9c75f3212e46a2eTimo Sirainenstatic int mbox_sync_handle_header(struct mbox_sync_mail_context *mail_ctx)
930dcf1576f99057ad572420d9c75f3212e46a2eTimo Sirainen{
930dcf1576f99057ad572420d9c75f3212e46a2eTimo Sirainen struct mbox_sync_context *sync_ctx = mail_ctx->sync_ctx;
6a1e4eb2c6a267bec1e8704ce9137bebb7792702Timo Sirainen uoff_t orig_from_offset;
930dcf1576f99057ad572420d9c75f3212e46a2eTimo Sirainen off_t move_diff;
c9a03c8a03a782488981f81bd7c6b5e01ff55f06Timo Sirainen int ret;
829c036d4ddfbd9ea49bd8a7c54e3057177d346eTimo Sirainen
6a1e4eb2c6a267bec1e8704ce9137bebb7792702Timo Sirainen if (sync_ctx->expunged_space > 0 && sync_ctx->need_space_seq == 0) {
7a6b45405fb1544ac476e6eb1402a70cc1ddcdcfTimo Sirainen /* move the header backwards to fill expunged space */
39775ad03c459efe64cce924658da5094ba417e1Timo Sirainen move_diff = -sync_ctx->expunged_space;
39775ad03c459efe64cce924658da5094ba417e1Timo Sirainen
6a1e4eb2c6a267bec1e8704ce9137bebb7792702Timo Sirainen orig_from_offset = mail_ctx->mail.from_offset;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen if (sync_ctx->dest_first_mail) {
6a1e4eb2c6a267bec1e8704ce9137bebb7792702Timo Sirainen /* we're moving this mail to beginning of file.
6a1e4eb2c6a267bec1e8704ce9137bebb7792702Timo Sirainen skip the initial \n (it's already counted in
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen expunged_space) */
7a6b45405fb1544ac476e6eb1402a70cc1ddcdcfTimo Sirainen mail_ctx->mail.from_offset++;
6a1e4eb2c6a267bec1e8704ce9137bebb7792702Timo Sirainen if (sync_ctx->first_mail_crlf_expunged)
6a1e4eb2c6a267bec1e8704ce9137bebb7792702Timo Sirainen mail_ctx->mail.from_offset++;
6a1e4eb2c6a267bec1e8704ce9137bebb7792702Timo Sirainen }
6a1e4eb2c6a267bec1e8704ce9137bebb7792702Timo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen /* read the From-line before rewriting overwrites it */
b2ecd50bb98c44816cb07c17aa17fae2b425f941Timo Sirainen if (mbox_read_from_line(mail_ctx) < 0)
a2637488c8d514ec1ac3914811deee814f9761b3Timo Sirainen return -1;
a614397cf1a4dde152eb1a38493a6ec3d817da16Timo Sirainen
a614397cf1a4dde152eb1a38493a6ec3d817da16Timo Sirainen mbox_sync_update_header(mail_ctx);
a614397cf1a4dde152eb1a38493a6ec3d817da16Timo Sirainen ret = mbox_sync_try_rewrite(mail_ctx, move_diff);
a614397cf1a4dde152eb1a38493a6ec3d817da16Timo Sirainen if (ret < 0)
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen return -1;
b2ecd50bb98c44816cb07c17aa17fae2b425f941Timo Sirainen
8907d617ce7c4f390c0f42f6f694db2fecdd5775Timo Sirainen if (ret > 0) {
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen /* rewrite successful, write From-line to
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen new location */
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen i_assert(move_diff > 0 ||
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen (off_t)mail_ctx->mail.from_offset >=
01cbf4ac5d44137ab434791be7f838d98d0fcf3bTimo Sirainen -move_diff);
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen mail_ctx->mail.from_offset += move_diff;
6a1e4eb2c6a267bec1e8704ce9137bebb7792702Timo Sirainen mail_ctx->mail.offset += move_diff;
39775ad03c459efe64cce924658da5094ba417e1Timo Sirainen if (mbox_write_from_line(mail_ctx) < 0)
343a527f805ca5cce78496b959d6def70e5d0cd4Timo Sirainen return -1;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen } else {
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen if (sync_ctx->dest_first_mail) {
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen /* didn't have enough space, move the offset
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen back so seeking into it doesn't fail */
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen mail_ctx->mail.from_offset = orig_from_offset;
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen }
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen }
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen } else if (mail_ctx->need_rewrite ||
319944c0f35b311c998854e96d6463a084fd90aeTimo Sirainen array_count(&sync_ctx->syncs) != 0) {
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainen mbox_sync_update_header(mail_ctx);
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainen if (sync_ctx->delay_writes) {
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen /* mark it dirty and do it later */
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen mail_ctx->dirty = TRUE;
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen return 0;
e5afebd2df1d4990f7bec2a839260ff2e6d78168Timo Sirainen }
ccc895c0358108d2304239063e940b7d75f364abTimo Sirainen
ff7056842f14fd3b30a2d327dfab165b9d15dd30Timo Sirainen if ((ret = mbox_sync_try_rewrite(mail_ctx, 0)) < 0)
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen return -1;
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen } else {
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen /* nothing to do */
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen return 0;
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen }
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen if (ret == 0 && sync_ctx->need_space_seq == 0) {
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen /* first mail with no space to write it */
f12aabfeba81f0d741971d2b7e4a5008eb4383caTimo Sirainen sync_ctx->need_space_seq = sync_ctx->seq;
f12aabfeba81f0d741971d2b7e4a5008eb4383caTimo Sirainen sync_ctx->space_diff = 0;
f12aabfeba81f0d741971d2b7e4a5008eb4383caTimo Sirainen
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen if (sync_ctx->expunged_space > 0) {
f12aabfeba81f0d741971d2b7e4a5008eb4383caTimo Sirainen /* create dummy message to describe the expunged data */
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen struct mbox_sync_mail mail;
f12aabfeba81f0d741971d2b7e4a5008eb4383caTimo Sirainen
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen memset(&mail, 0, sizeof(mail));
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen mail.expunged = TRUE;
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen mail.offset = mail.from_offset =
a2637488c8d514ec1ac3914811deee814f9761b3Timo Sirainen (sync_ctx->dest_first_mail ? 1 : 0) +
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen mail_ctx->mail.from_offset -
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen sync_ctx->expunged_space;
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen mail.space = sync_ctx->expunged_space;
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen sync_ctx->space_diff = sync_ctx->expunged_space;
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen sync_ctx->expunged_space = 0;
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen i_assert(sync_ctx->space_diff < -mail_ctx->mail.space);
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen
319944c0f35b311c998854e96d6463a084fd90aeTimo Sirainen sync_ctx->need_space_seq--;
319944c0f35b311c998854e96d6463a084fd90aeTimo Sirainen array_append(&sync_ctx->mails, &mail, 1);
88187ee880b4829443e0d55ea7d145d9d5880217Timo Sirainen }
88187ee880b4829443e0d55ea7d145d9d5880217Timo Sirainen }
319944c0f35b311c998854e96d6463a084fd90aeTimo Sirainen return 0;
319944c0f35b311c998854e96d6463a084fd90aeTimo Sirainen}
319944c0f35b311c998854e96d6463a084fd90aeTimo Sirainen
a393d9d6dabdc46cf724f8cb004a652b4036d53dTimo Sirainenstatic int
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainenmbox_sync_handle_missing_space(struct mbox_sync_mail_context *mail_ctx)
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen{
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen struct mbox_sync_context *sync_ctx = mail_ctx->sync_ctx;
cece2b9cd692c06025cc0a7a0ff54d996a8c90efTimo Sirainen uoff_t end_offset, move_diff, extra_space, needed_space;
cece2b9cd692c06025cc0a7a0ff54d996a8c90efTimo Sirainen uint32_t last_seq;
cece2b9cd692c06025cc0a7a0ff54d996a8c90efTimo Sirainen ARRAY_TYPE(keyword_indexes) keywords_copy;
cece2b9cd692c06025cc0a7a0ff54d996a8c90efTimo Sirainen
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen i_assert(mail_ctx->mail.uid == 0 || mail_ctx->mail.space > 0 ||
f0569d9fbb25c8437760be69f194595a841ad711Timo Sirainen mail_ctx->mail.offset == mail_ctx->hdr_offset);
db7c9201c88e3d9bee10485194ee5b0c67249916Timo Sirainen
755fe6da51ab7f54aa1d86913cb344bffef60e79Timo Sirainen if (array_is_created(&mail_ctx->mail.keywords)) {
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen /* mail's keywords are allocated from a pool that's cleared
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen for each mail. we'll need to copy it to something more
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen permanent. */
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen p_array_init(&keywords_copy, sync_ctx->saved_keywords_pool,
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen array_count(&mail_ctx->mail.keywords));
a10e5606a9e93f49cf13b3a35c8dc3f5d6ab5909Timo Sirainen array_append_array(&keywords_copy, &mail_ctx->mail.keywords);
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen mail_ctx->mail.keywords = keywords_copy;
4b9f99761df5014c659cd87fddaf6854af428cfcTimo Sirainen }
4b9f99761df5014c659cd87fddaf6854af428cfcTimo Sirainen array_append(&sync_ctx->mails, &mail_ctx->mail, 1);
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen
f6699a08521aacc4c2bb5b6175691dad5f715f8cTimo Sirainen sync_ctx->space_diff += mail_ctx->mail.space;
f6699a08521aacc4c2bb5b6175691dad5f715f8cTimo Sirainen if (sync_ctx->space_diff < 0) {
3da614c39dd29f536c485089e67839b4cf89fed3Timo Sirainen if (sync_ctx->expunged_space > 0) {
3da614c39dd29f536c485089e67839b4cf89fed3Timo Sirainen i_assert(sync_ctx->expunged_space ==
0a6f8311541ae59381171620b77f82be58be562eTimo Sirainen mail_ctx->mail.space);
4b9f99761df5014c659cd87fddaf6854af428cfcTimo Sirainen sync_ctx->expunged_space = 0;
4b9f99761df5014c659cd87fddaf6854af428cfcTimo Sirainen }
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen return 0;
4b9f99761df5014c659cd87fddaf6854af428cfcTimo Sirainen }
b225c3c65f360d7b833f09f9b2fb3035ed5ea600Timo Sirainen
b225c3c65f360d7b833f09f9b2fb3035ed5ea600Timo Sirainen /* we have enough space now */
4b9f99761df5014c659cd87fddaf6854af428cfcTimo Sirainen if (mail_ctx->mail.uid == 0) {
b225c3c65f360d7b833f09f9b2fb3035ed5ea600Timo Sirainen /* this message was expunged. fill more or less of the space.
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen space_diff now consists of a negative "bytes needed" sum,
4b9f99761df5014c659cd87fddaf6854af428cfcTimo Sirainen plus the expunged space of this message. so it contains how
a2637488c8d514ec1ac3914811deee814f9761b3Timo Sirainen many bytes of _extra_ space we have. */
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen i_assert(mail_ctx->mail.space >= sync_ctx->space_diff);
0a6f8311541ae59381171620b77f82be58be562eTimo Sirainen extra_space = MBOX_HEADER_PADDING *
0a6f8311541ae59381171620b77f82be58be562eTimo Sirainen (sync_ctx->seq - sync_ctx->need_space_seq + 1);
a10e5606a9e93f49cf13b3a35c8dc3f5d6ab5909Timo Sirainen needed_space = mail_ctx->mail.space - sync_ctx->space_diff;
df4018ae2f0a95be602f724ca70df7e0e3bd6a7dTimo Sirainen if ((uoff_t)sync_ctx->space_diff > needed_space + extra_space) {
0a6f8311541ae59381171620b77f82be58be562eTimo Sirainen /* don't waste too much on padding */
0a6f8311541ae59381171620b77f82be58be562eTimo Sirainen move_diff = needed_space + extra_space;
0a6f8311541ae59381171620b77f82be58be562eTimo Sirainen sync_ctx->expunged_space =
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen mail_ctx->mail.space - move_diff;
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen } else {
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen move_diff = mail_ctx->mail.space;
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen extra_space = sync_ctx->space_diff;
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainen sync_ctx->expunged_space = 0;
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainen }
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen last_seq = sync_ctx->seq - 1;
022412398e56a8f31ef111cfd7271498d64af9a9Timo Sirainen array_delete(&sync_ctx->mails,
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen array_count(&sync_ctx->mails) - 1, 1);
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen end_offset = mail_ctx->mail.from_offset;
f6699a08521aacc4c2bb5b6175691dad5f715f8cTimo Sirainen } else {
f6699a08521aacc4c2bb5b6175691dad5f715f8cTimo Sirainen /* this message gave enough space from headers. rewriting stops
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen at the end of this message's headers. */
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen sync_ctx->expunged_space = 0;
022412398e56a8f31ef111cfd7271498d64af9a9Timo Sirainen last_seq = sync_ctx->seq;
022412398e56a8f31ef111cfd7271498d64af9a9Timo Sirainen end_offset = mail_ctx->body_offset;
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen move_diff = 0;
1d3f7c1278168d5b1cbfa9a2cc9929a0909056b4Timo Sirainen extra_space = sync_ctx->space_diff;
ced118ac5caf6fe83d34339c2c65c63b2aa768acTimo Sirainen }
1d3f7c1278168d5b1cbfa9a2cc9929a0909056b4Timo Sirainen
1d3f7c1278168d5b1cbfa9a2cc9929a0909056b4Timo Sirainen mbox_sync_file_update_ext_modified(sync_ctx);
1d3f7c1278168d5b1cbfa9a2cc9929a0909056b4Timo Sirainen if (mbox_sync_rewrite(sync_ctx,
1d3f7c1278168d5b1cbfa9a2cc9929a0909056b4Timo Sirainen last_seq == sync_ctx->seq ? mail_ctx : NULL,
022412398e56a8f31ef111cfd7271498d64af9a9Timo Sirainen end_offset, move_diff, extra_space,
1d3f7c1278168d5b1cbfa9a2cc9929a0909056b4Timo Sirainen sync_ctx->need_space_seq, last_seq) < 0)
1d3f7c1278168d5b1cbfa9a2cc9929a0909056b4Timo Sirainen return -1;
1d3f7c1278168d5b1cbfa9a2cc9929a0909056b4Timo Sirainen
ced118ac5caf6fe83d34339c2c65c63b2aa768acTimo Sirainen update_from_offsets(sync_ctx);
1d3f7c1278168d5b1cbfa9a2cc9929a0909056b4Timo Sirainen
1d3f7c1278168d5b1cbfa9a2cc9929a0909056b4Timo Sirainen /* mail_ctx may contain wrong data after rewrite, so make sure we
1d3f7c1278168d5b1cbfa9a2cc9929a0909056b4Timo Sirainen don't try to access it */
1d3f7c1278168d5b1cbfa9a2cc9929a0909056b4Timo Sirainen memset(mail_ctx, 0, sizeof(*mail_ctx));
022412398e56a8f31ef111cfd7271498d64af9a9Timo Sirainen
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen sync_ctx->need_space_seq = 0;
022412398e56a8f31ef111cfd7271498d64af9a9Timo Sirainen sync_ctx->space_diff = 0;
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen array_clear(&sync_ctx->mails);
022412398e56a8f31ef111cfd7271498d64af9a9Timo Sirainen p_clear(sync_ctx->saved_keywords_pool);
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen return 0;
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen}
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainenstatic int
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainenmbox_sync_seek_to_seq(struct mbox_sync_context *sync_ctx, uint32_t seq)
690bafa70767e3f6e98bbfd62ad4a26be2387ea9Timo Sirainen{
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen struct mbox_mailbox *mbox = sync_ctx->mbox;
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen uoff_t old_offset;
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen uint32_t uid;
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen int ret;
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen bool deleted;
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen if (seq == 0) {
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen if (istream_raw_mbox_seek(mbox->mbox_stream, 0) < 0) {
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen mail_storage_set_error(&mbox->storage->storage,
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen MAIL_ERROR_NOTPOSSIBLE,
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen "Mailbox isn't a valid mbox file");
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen return -1;
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen }
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen seq++;
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen } else {
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen old_offset = istream_raw_mbox_get_start_offset(sync_ctx->input);
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen ret = mbox_file_seek(mbox, sync_ctx->sync_view, seq, &deleted);
755fe6da51ab7f54aa1d86913cb344bffef60e79Timo Sirainen if (ret < 0) {
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen if (deleted) {
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen mbox_sync_set_critical(sync_ctx,
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen "Message was expunged unexpectedly "
17ad2164c747cedbf81dae1893063e71a3df0356Timo Sirainen "in mbox file %s", mbox->path);
17ad2164c747cedbf81dae1893063e71a3df0356Timo Sirainen }
17ad2164c747cedbf81dae1893063e71a3df0356Timo Sirainen return -1;
17ad2164c747cedbf81dae1893063e71a3df0356Timo Sirainen }
17ad2164c747cedbf81dae1893063e71a3df0356Timo Sirainen if (ret == 0) {
17ad2164c747cedbf81dae1893063e71a3df0356Timo Sirainen if (istream_raw_mbox_seek(mbox->mbox_stream,
17ad2164c747cedbf81dae1893063e71a3df0356Timo Sirainen old_offset) < 0) {
17ad2164c747cedbf81dae1893063e71a3df0356Timo Sirainen mbox_sync_set_critical(sync_ctx,
17ad2164c747cedbf81dae1893063e71a3df0356Timo Sirainen "Error seeking back to original "
17ad2164c747cedbf81dae1893063e71a3df0356Timo Sirainen "offset %s in mbox file %s",
17ad2164c747cedbf81dae1893063e71a3df0356Timo Sirainen dec2str(old_offset), mbox->path);
bd5825f0890717a98a2dd3fc006ad1d1795e6deaTimo Sirainen return -1;
bd5825f0890717a98a2dd3fc006ad1d1795e6deaTimo Sirainen }
17ad2164c747cedbf81dae1893063e71a3df0356Timo Sirainen return 0;
8c73f1d91e6c953b072b47c0bbb5a1d46234ad81Timo Sirainen }
17ad2164c747cedbf81dae1893063e71a3df0356Timo Sirainen }
17ad2164c747cedbf81dae1893063e71a3df0356Timo Sirainen
17ad2164c747cedbf81dae1893063e71a3df0356Timo Sirainen if (seq <= 1)
17ad2164c747cedbf81dae1893063e71a3df0356Timo Sirainen uid = 0;
17ad2164c747cedbf81dae1893063e71a3df0356Timo Sirainen else if (mail_index_lookup_uid(sync_ctx->sync_view, seq-1, &uid) < 0) {
17ad2164c747cedbf81dae1893063e71a3df0356Timo Sirainen mail_storage_set_index_error(&mbox->ibox);
17ad2164c747cedbf81dae1893063e71a3df0356Timo Sirainen return -1;
f6699a08521aacc4c2bb5b6175691dad5f715f8cTimo Sirainen }
f6699a08521aacc4c2bb5b6175691dad5f715f8cTimo Sirainen
f6699a08521aacc4c2bb5b6175691dad5f715f8cTimo Sirainen sync_ctx->prev_msg_uid = uid;
f6699a08521aacc4c2bb5b6175691dad5f715f8cTimo Sirainen
f6699a08521aacc4c2bb5b6175691dad5f715f8cTimo Sirainen /* set to -1, since it's always increased later */
f6699a08521aacc4c2bb5b6175691dad5f715f8cTimo Sirainen sync_ctx->seq = seq-1;
f6699a08521aacc4c2bb5b6175691dad5f715f8cTimo Sirainen if (sync_ctx->seq == 0 &&
ca98892a6b8a30ffc1fe26fcf02c7d59e3204e7eTimo Sirainen istream_raw_mbox_get_start_offset(sync_ctx->input) != 0) {
f6699a08521aacc4c2bb5b6175691dad5f715f8cTimo Sirainen /* this mbox has pseudo mail which contains the X-IMAP header */
f6699a08521aacc4c2bb5b6175691dad5f715f8cTimo Sirainen sync_ctx->seq++;
f6699a08521aacc4c2bb5b6175691dad5f715f8cTimo Sirainen }
17ad2164c747cedbf81dae1893063e71a3df0356Timo Sirainen
17ad2164c747cedbf81dae1893063e71a3df0356Timo Sirainen sync_ctx->idx_seq = seq;
f6699a08521aacc4c2bb5b6175691dad5f715f8cTimo Sirainen sync_ctx->dest_first_mail = sync_ctx->seq == 0;
f6699a08521aacc4c2bb5b6175691dad5f715f8cTimo Sirainen (void)istream_raw_mbox_get_body_offset(sync_ctx->input);
f6699a08521aacc4c2bb5b6175691dad5f715f8cTimo Sirainen return 1;
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen}
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainenstatic int
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainenmbox_sync_seek_to_uid(struct mbox_sync_context *sync_ctx, uint32_t uid)
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen{
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen struct mail_index_view *sync_view = sync_ctx->sync_view;
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen uint32_t seq1, seq2;
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainen const struct stat *st;
d31c4d7c161f9d7efa59964c7c958e83e05b218cTimo Sirainen
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen i_assert(!sync_ctx->index_reset);
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen if (mail_index_lookup_uid_range(sync_view, uid, (uint32_t)-1,
755fe6da51ab7f54aa1d86913cb344bffef60e79Timo Sirainen &seq1, &seq2) < 0) {
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen mail_storage_set_index_error(&sync_ctx->mbox->ibox);
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen return -1;
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen }
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen if (seq1 == 0) {
71a74e26cf070a205d31cf6c6fae003f90027b63Timo Sirainen /* doesn't exist anymore, seek to end of file */
a486ed03dce069ff60ab5a65d0ae24a1862f22fcTimo Sirainen st = i_stream_stat(sync_ctx->file_input, TRUE);
a486ed03dce069ff60ab5a65d0ae24a1862f22fcTimo Sirainen if (st == NULL) {
a486ed03dce069ff60ab5a65d0ae24a1862f22fcTimo Sirainen mbox_set_syscall_error(sync_ctx->mbox,
a486ed03dce069ff60ab5a65d0ae24a1862f22fcTimo Sirainen "i_stream_stat()");
a486ed03dce069ff60ab5a65d0ae24a1862f22fcTimo Sirainen return -1;
a486ed03dce069ff60ab5a65d0ae24a1862f22fcTimo Sirainen }
a486ed03dce069ff60ab5a65d0ae24a1862f22fcTimo Sirainen
a486ed03dce069ff60ab5a65d0ae24a1862f22fcTimo Sirainen if (istream_raw_mbox_seek(sync_ctx->mbox->mbox_stream,
d31c4d7c161f9d7efa59964c7c958e83e05b218cTimo Sirainen st->st_size) < 0) {
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen mbox_sync_set_critical(sync_ctx,
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen "Error seeking to end of mbox file %s",
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen sync_ctx->mbox->path);
f6699a08521aacc4c2bb5b6175691dad5f715f8cTimo Sirainen return -1;
17ad2164c747cedbf81dae1893063e71a3df0356Timo Sirainen }
690bafa70767e3f6e98bbfd62ad4a26be2387ea9Timo Sirainen sync_ctx->idx_seq =
f6699a08521aacc4c2bb5b6175691dad5f715f8cTimo Sirainen mail_index_view_get_messages_count(sync_view) + 1;
f6699a08521aacc4c2bb5b6175691dad5f715f8cTimo Sirainen return 1;
319944c0f35b311c998854e96d6463a084fd90aeTimo Sirainen }
319944c0f35b311c998854e96d6463a084fd90aeTimo Sirainen
912e870dcab2dadac8a6b20b42367999cdd8b5a1Timo Sirainen return mbox_sync_seek_to_seq(sync_ctx, seq1);
319944c0f35b311c998854e96d6463a084fd90aeTimo Sirainen}
319944c0f35b311c998854e96d6463a084fd90aeTimo Sirainen
690bafa70767e3f6e98bbfd62ad4a26be2387ea9Timo Sirainenstatic int mbox_sync_partial_seek_next(struct mbox_sync_context *sync_ctx,
b8765f6093ab35fc2345293d78132d35794cbff5Timo Sirainen uint32_t next_uid, bool *partial,
b8765f6093ab35fc2345293d78132d35794cbff5Timo Sirainen bool *skipped_mails)
a2637488c8d514ec1ac3914811deee814f9761b3Timo Sirainen{
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen uint32_t messages_count;
b8765f6093ab35fc2345293d78132d35794cbff5Timo Sirainen int ret;
690bafa70767e3f6e98bbfd62ad4a26be2387ea9Timo Sirainen
319944c0f35b311c998854e96d6463a084fd90aeTimo Sirainen i_assert(!sync_ctx->index_reset);
319944c0f35b311c998854e96d6463a084fd90aeTimo Sirainen
d31c4d7c161f9d7efa59964c7c958e83e05b218cTimo Sirainen /* delete sync records up to next message. so if there's still
d31c4d7c161f9d7efa59964c7c958e83e05b218cTimo Sirainen something left in array, it means the next message needs modifying */
319944c0f35b311c998854e96d6463a084fd90aeTimo Sirainen mbox_sync_array_delete_to(&sync_ctx->syncs, next_uid);
1e76a5b92f9d82d557f81f080f3dfad1c9d8f200Timo Sirainen if (array_count(&sync_ctx->syncs) > 0)
907723f35f4d3dfc774ca42d00a8a7b8ef90dd5dTimo Sirainen return 1;
907723f35f4d3dfc774ca42d00a8a7b8ef90dd5dTimo Sirainen
2ae575a66f2a302f047f6de062a70b75f8bebc7bTimo Sirainen if (sync_ctx->sync_rec.uid1 != 0) {
cdaf255d6a3daeef0ac85edaa60bfa6d1f945bffTimo Sirainen /* we can skip forward to next record which needs updating. */
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen if (sync_ctx->sync_rec.uid1 != next_uid) {
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen *skipped_mails = TRUE;
6843896c40bee4f9b6680ca7ced598c446e9f999Timo Sirainen next_uid = sync_ctx->sync_rec.uid1;
7f3be7d885c75cdd77f536929a45bc9764595960Timo Sirainen }
2ae575a66f2a302f047f6de062a70b75f8bebc7bTimo Sirainen ret = mbox_sync_seek_to_uid(sync_ctx, next_uid);
2ae575a66f2a302f047f6de062a70b75f8bebc7bTimo Sirainen } else {
2ae575a66f2a302f047f6de062a70b75f8bebc7bTimo Sirainen /* if there's no sync records left, we can stop. except if
cdaf255d6a3daeef0ac85edaa60bfa6d1f945bffTimo Sirainen this is a dirty sync, check if there are new messages. */
1e76a5b92f9d82d557f81f080f3dfad1c9d8f200Timo Sirainen if (!sync_ctx->mbox->mbox_sync_dirty)
2ae575a66f2a302f047f6de062a70b75f8bebc7bTimo Sirainen return 0;
2ae575a66f2a302f047f6de062a70b75f8bebc7bTimo Sirainen
7a6b45405fb1544ac476e6eb1402a70cc1ddcdcfTimo Sirainen messages_count =
7a6b45405fb1544ac476e6eb1402a70cc1ddcdcfTimo Sirainen mail_index_view_get_messages_count(sync_ctx->sync_view);
7a6b45405fb1544ac476e6eb1402a70cc1ddcdcfTimo Sirainen if (sync_ctx->seq + 1 != messages_count) {
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen ret = mbox_sync_seek_to_seq(sync_ctx, messages_count);
7f3be7d885c75cdd77f536929a45bc9764595960Timo Sirainen *skipped_mails = TRUE;
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen } else {
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen ret = 1;
7f3be7d885c75cdd77f536929a45bc9764595960Timo Sirainen }
7a6b45405fb1544ac476e6eb1402a70cc1ddcdcfTimo Sirainen *partial = FALSE;
7a6b45405fb1544ac476e6eb1402a70cc1ddcdcfTimo Sirainen }
7a6b45405fb1544ac476e6eb1402a70cc1ddcdcfTimo Sirainen
c9fe52d819c608b890620f7fe36ff509b14eb350Timo Sirainen if (ret == 0) {
c9fe52d819c608b890620f7fe36ff509b14eb350Timo Sirainen /* seek failed because the offset is dirty. just ignore and
c9fe52d819c608b890620f7fe36ff509b14eb350Timo Sirainen continue from where we are now. */
b08b33d1f5ce3721dc2d83586c9cb0ca141331fdTimo Sirainen *partial = FALSE;
b08b33d1f5ce3721dc2d83586c9cb0ca141331fdTimo Sirainen ret = 1;
b08b33d1f5ce3721dc2d83586c9cb0ca141331fdTimo Sirainen }
c9fe52d819c608b890620f7fe36ff509b14eb350Timo Sirainen return ret;
1e76a5b92f9d82d557f81f080f3dfad1c9d8f200Timo Sirainen}
c9fe52d819c608b890620f7fe36ff509b14eb350Timo Sirainen
c9fe52d819c608b890620f7fe36ff509b14eb350Timo Sirainenstatic bool mbox_sync_uidvalidity_changed(struct mbox_sync_context *sync_ctx)
c9fe52d819c608b890620f7fe36ff509b14eb350Timo Sirainen{
e9d68b41c007f0e545de361f8012f6f231bfec8bTimo Sirainen if (sync_ctx->base_uid_validity != 0 &&
c9fe52d819c608b890620f7fe36ff509b14eb350Timo Sirainen sync_ctx->hdr->uid_validity != 0 &&
c9fe52d819c608b890620f7fe36ff509b14eb350Timo Sirainen sync_ctx->base_uid_validity != sync_ctx->hdr->uid_validity) {
e9d68b41c007f0e545de361f8012f6f231bfec8bTimo Sirainen i_warning("UIDVALIDITY changed (%u -> %u) in mbox file %s",
e9d68b41c007f0e545de361f8012f6f231bfec8bTimo Sirainen sync_ctx->hdr->uid_validity,
7f3be7d885c75cdd77f536929a45bc9764595960Timo Sirainen sync_ctx->base_uid_validity,
7f3be7d885c75cdd77f536929a45bc9764595960Timo Sirainen sync_ctx->mbox->path);
1e76a5b92f9d82d557f81f080f3dfad1c9d8f200Timo Sirainen sync_ctx->index_reset = TRUE;
71a74e26cf070a205d31cf6c6fae003f90027b63Timo Sirainen return TRUE;
71a74e26cf070a205d31cf6c6fae003f90027b63Timo Sirainen }
a393d9d6dabdc46cf724f8cb004a652b4036d53dTimo Sirainen return FALSE;
71a74e26cf070a205d31cf6c6fae003f90027b63Timo Sirainen}
71a74e26cf070a205d31cf6c6fae003f90027b63Timo Sirainen
71a74e26cf070a205d31cf6c6fae003f90027b63Timo Sirainenstatic int mbox_sync_loop(struct mbox_sync_context *sync_ctx,
a486ed03dce069ff60ab5a65d0ae24a1862f22fcTimo Sirainen struct mbox_sync_mail_context *mail_ctx,
a486ed03dce069ff60ab5a65d0ae24a1862f22fcTimo Sirainen bool partial)
a486ed03dce069ff60ab5a65d0ae24a1862f22fcTimo Sirainen{
a486ed03dce069ff60ab5a65d0ae24a1862f22fcTimo Sirainen const struct mail_index_record *rec;
a486ed03dce069ff60ab5a65d0ae24a1862f22fcTimo Sirainen uint32_t uid, messages_count;
a486ed03dce069ff60ab5a65d0ae24a1862f22fcTimo Sirainen uoff_t offset;
ccc895c0358108d2304239063e940b7d75f364abTimo Sirainen int ret;
a486ed03dce069ff60ab5a65d0ae24a1862f22fcTimo Sirainen bool expunged, skipped_mails, uids_broken;
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen
ca98892a6b8a30ffc1fe26fcf02c7d59e3204e7eTimo Sirainen messages_count =
a486ed03dce069ff60ab5a65d0ae24a1862f22fcTimo Sirainen mail_index_view_get_messages_count(sync_ctx->sync_view);
a486ed03dce069ff60ab5a65d0ae24a1862f22fcTimo Sirainen
a486ed03dce069ff60ab5a65d0ae24a1862f22fcTimo Sirainen /* always start from first message so we can read X-IMAP or
a486ed03dce069ff60ab5a65d0ae24a1862f22fcTimo Sirainen X-IMAPbase header */
6843896c40bee4f9b6680ca7ced598c446e9f999Timo Sirainen ret = mbox_sync_seek_to_seq(sync_ctx, 0);
6843896c40bee4f9b6680ca7ced598c446e9f999Timo Sirainen if (ret <= 0)
6843896c40bee4f9b6680ca7ced598c446e9f999Timo Sirainen return ret;
1dd9801f7ace40777ecf8ed9a98c093bc40467a4Timo Sirainen
6843896c40bee4f9b6680ca7ced598c446e9f999Timo Sirainen if (sync_ctx->renumber_uids) {
1e76a5b92f9d82d557f81f080f3dfad1c9d8f200Timo Sirainen /* expunge everything */
b428c5993b01f4cffacdd24377ca2873fcc12184Timo Sirainen while (sync_ctx->idx_seq <= messages_count) {
d0e5f8252516c4d4df2fbcdae4d37f9e5f931199Timo Sirainen mail_index_expunge(sync_ctx->t,
f0569d9fbb25c8437760be69f194595a841ad711Timo Sirainen sync_ctx->idx_seq++);
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen }
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen }
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen
8907d617ce7c4f390c0f42f6f694db2fecdd5775Timo Sirainen skipped_mails = uids_broken = FALSE;
8907d617ce7c4f390c0f42f6f694db2fecdd5775Timo Sirainen while ((ret = mbox_sync_read_next_mail(sync_ctx, mail_ctx)) > 0) {
f0569d9fbb25c8437760be69f194595a841ad711Timo Sirainen uid = mail_ctx->mail.uid;
f0569d9fbb25c8437760be69f194595a841ad711Timo Sirainen
8907d617ce7c4f390c0f42f6f694db2fecdd5775Timo Sirainen if (mail_ctx->seq == 1) {
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen if (mbox_sync_uidvalidity_changed(sync_ctx)) {
b2ecd50bb98c44816cb07c17aa17fae2b425f941Timo Sirainen sync_ctx->mbox->mbox_sync_dirty = TRUE;
1e76a5b92f9d82d557f81f080f3dfad1c9d8f200Timo Sirainen return 0;
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen }
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen }
1cd97699af9c77d8f5920832ec3374884544fd68Timo Sirainen
907723f35f4d3dfc774ca42d00a8a7b8ef90dd5dTimo Sirainen if (mail_ctx->mail.uid_broken && partial) {
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen /* UID ordering problems, resync everything to make
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen sure we get everything right */
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen if (sync_ctx->mbox->mbox_sync_dirty)
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen return 0;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen mbox_sync_set_critical(sync_ctx,
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen "UIDs broken with partial sync in mbox file %s",
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen sync_ctx->mbox->path);
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
02b79f9c2636da1829eee5b92753602bba8b67edTimo Sirainen sync_ctx->mbox->mbox_sync_dirty = TRUE;
02b79f9c2636da1829eee5b92753602bba8b67edTimo Sirainen return 0;
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen }
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen if (mail_ctx->mail.uid_broken)
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen uids_broken = TRUE;
a2637488c8d514ec1ac3914811deee814f9761b3Timo Sirainen
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen if (mail_ctx->mail.pseudo)
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen uid = 0;
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen rec = NULL; ret = 1;
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen if (uid != 0) {
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen ret = mbox_sync_read_index_rec(sync_ctx, uid, &rec);
02b79f9c2636da1829eee5b92753602bba8b67edTimo Sirainen if (ret < 0)
02b79f9c2636da1829eee5b92753602bba8b67edTimo Sirainen return -1;
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen }
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen if (ret == 0) {
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen /* UID found but it's broken */
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen uid = 0;
6f25019b337e27600159b596824da08732965576Timo Sirainen } else if (uid == 0 &&
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen !mail_ctx->mail.pseudo &&
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen (sync_ctx->delay_writes ||
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen sync_ctx->idx_seq <= messages_count)) {
6f25019b337e27600159b596824da08732965576Timo Sirainen /* If we can't use/store X-UID header, use MD5 sum.
6f25019b337e27600159b596824da08732965576Timo Sirainen Also check for existing MD5 sums when we're actually
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen able to write X-UIDs. */
178511b57faa7c3f8203dd8b7e4059d00cbfc23aTimo Sirainen sync_ctx->mbox->mbox_save_md5 = TRUE;
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen
a393d9d6dabdc46cf724f8cb004a652b4036d53dTimo Sirainen if (mbox_sync_find_index_md5(sync_ctx,
a393d9d6dabdc46cf724f8cb004a652b4036d53dTimo Sirainen mail_ctx->hdr_md5_sum,
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen &rec) < 0)
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen return -1;
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen
690bafa70767e3f6e98bbfd62ad4a26be2387ea9Timo Sirainen if (rec != NULL)
690bafa70767e3f6e98bbfd62ad4a26be2387ea9Timo Sirainen uid = mail_ctx->mail.uid = rec->uid;
d31c4d7c161f9d7efa59964c7c958e83e05b218cTimo Sirainen }
d31c4d7c161f9d7efa59964c7c958e83e05b218cTimo Sirainen
d31c4d7c161f9d7efa59964c7c958e83e05b218cTimo Sirainen /* get all sync records related to this message. with pseudo
d31c4d7c161f9d7efa59964c7c958e83e05b218cTimo Sirainen message just get the first sync record so we can jump to
d31c4d7c161f9d7efa59964c7c958e83e05b218cTimo Sirainen it with partial seeking. */
690bafa70767e3f6e98bbfd62ad4a26be2387ea9Timo Sirainen if (mbox_sync_read_index_syncs(sync_ctx,
d31c4d7c161f9d7efa59964c7c958e83e05b218cTimo Sirainen mail_ctx->mail.pseudo ? 1 : uid,
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen &expunged) < 0)
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen return -1;
3cfff0ca01961d885bdbd6ef08d761880116af07Timo Sirainen
f7d43647acc6dc80064c8c4cacf5bf86f754c530Timo Sirainen if (mail_ctx->mail.pseudo) {
98c1cf256927e254f0c092acd2ddcd7ea50bd009Timo Sirainen /* if it was set, it was for the next message */
98c1cf256927e254f0c092acd2ddcd7ea50bd009Timo Sirainen expunged = FALSE;
9d2040fbb941f411d57fd850b4cdc3b1cccc1168Timo Sirainen } else {
9d2040fbb941f411d57fd850b4cdc3b1cccc1168Timo Sirainen if (rec == NULL) {
b225c3c65f360d7b833f09f9b2fb3035ed5ea600Timo Sirainen /* message wasn't found from index. we have to
b225c3c65f360d7b833f09f9b2fb3035ed5ea600Timo Sirainen read everything from now on, no skipping */
eeeee5297c71eb8badfbdff5241ac05851f1c21fTimo Sirainen partial = FALSE;
eeeee5297c71eb8badfbdff5241ac05851f1c21fTimo Sirainen }
eeeee5297c71eb8badfbdff5241ac05851f1c21fTimo Sirainen }
eeeee5297c71eb8badfbdff5241ac05851f1c21fTimo Sirainen
eeeee5297c71eb8badfbdff5241ac05851f1c21fTimo Sirainen if (uid == 0 && !mail_ctx->mail.pseudo) {
eeeee5297c71eb8badfbdff5241ac05851f1c21fTimo Sirainen /* missing/broken X-UID. all the rest of the mails
eeeee5297c71eb8badfbdff5241ac05851f1c21fTimo Sirainen need new UIDs. */
eeeee5297c71eb8badfbdff5241ac05851f1c21fTimo Sirainen while (sync_ctx->idx_seq <= messages_count) {
eeeee5297c71eb8badfbdff5241ac05851f1c21fTimo Sirainen mail_index_expunge(sync_ctx->t,
eeeee5297c71eb8badfbdff5241ac05851f1c21fTimo Sirainen sync_ctx->idx_seq++);
9d2040fbb941f411d57fd850b4cdc3b1cccc1168Timo Sirainen }
9d2040fbb941f411d57fd850b4cdc3b1cccc1168Timo Sirainen
9d2040fbb941f411d57fd850b4cdc3b1cccc1168Timo Sirainen if (sync_ctx->next_uid == (uint32_t)-1) {
98c1cf256927e254f0c092acd2ddcd7ea50bd009Timo Sirainen /* oh no, we're out of UIDs. this shouldn't
98c1cf256927e254f0c092acd2ddcd7ea50bd009Timo Sirainen happen normally, so just try to get it fixed
98c1cf256927e254f0c092acd2ddcd7ea50bd009Timo Sirainen without crashing. */
98c1cf256927e254f0c092acd2ddcd7ea50bd009Timo Sirainen mail_storage_set_critical(
98c1cf256927e254f0c092acd2ddcd7ea50bd009Timo Sirainen &sync_ctx->mbox->storage->storage,
98c1cf256927e254f0c092acd2ddcd7ea50bd009Timo Sirainen "Out of UIDs, renumbering them in mbox "
98c1cf256927e254f0c092acd2ddcd7ea50bd009Timo Sirainen "file %s", sync_ctx->mbox->path);
98c1cf256927e254f0c092acd2ddcd7ea50bd009Timo Sirainen sync_ctx->renumber_uids = TRUE;
98c1cf256927e254f0c092acd2ddcd7ea50bd009Timo Sirainen return 0;
f7d43647acc6dc80064c8c4cacf5bf86f754c530Timo Sirainen }
f7d43647acc6dc80064c8c4cacf5bf86f754c530Timo Sirainen
98c1cf256927e254f0c092acd2ddcd7ea50bd009Timo Sirainen mail_ctx->need_rewrite = TRUE;
98c1cf256927e254f0c092acd2ddcd7ea50bd009Timo Sirainen mail_ctx->mail.uid = sync_ctx->next_uid++;
98c1cf256927e254f0c092acd2ddcd7ea50bd009Timo Sirainen }
9d2040fbb941f411d57fd850b4cdc3b1cccc1168Timo Sirainen sync_ctx->prev_msg_uid = mail_ctx->mail.uid;
98c1cf256927e254f0c092acd2ddcd7ea50bd009Timo Sirainen
b225c3c65f360d7b833f09f9b2fb3035ed5ea600Timo Sirainen if (!mail_ctx->mail.pseudo)
b225c3c65f360d7b833f09f9b2fb3035ed5ea600Timo Sirainen mail_ctx->mail.idx_seq = sync_ctx->idx_seq;
98c1cf256927e254f0c092acd2ddcd7ea50bd009Timo Sirainen
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen if (!expunged) {
98c1cf256927e254f0c092acd2ddcd7ea50bd009Timo Sirainen if (mbox_sync_handle_header(mail_ctx) < 0)
98c1cf256927e254f0c092acd2ddcd7ea50bd009Timo Sirainen return -1;
98c1cf256927e254f0c092acd2ddcd7ea50bd009Timo Sirainen sync_ctx->dest_first_mail = FALSE;
98c1cf256927e254f0c092acd2ddcd7ea50bd009Timo Sirainen } else {
98c1cf256927e254f0c092acd2ddcd7ea50bd009Timo Sirainen mbox_sync_handle_expunge(mail_ctx);
b8bbfab97eed17fcb00b5a86128e1d7a3babc35cTimo Sirainen }
b8bbfab97eed17fcb00b5a86128e1d7a3babc35cTimo Sirainen
98c1cf256927e254f0c092acd2ddcd7ea50bd009Timo Sirainen if (!mail_ctx->mail.pseudo) {
2be66b9eddad3841a1195fe9aeb1eaf0f28f1116Timo Sirainen if (!expunged) {
afe9987e8b791a6421332fcb334401b54a2169daTimo Sirainen if (mbox_sync_update_index(mail_ctx, rec) < 0)
2be66b9eddad3841a1195fe9aeb1eaf0f28f1116Timo Sirainen return -1;
2be66b9eddad3841a1195fe9aeb1eaf0f28f1116Timo Sirainen }
98c1cf256927e254f0c092acd2ddcd7ea50bd009Timo Sirainen sync_ctx->idx_seq++;
98c1cf256927e254f0c092acd2ddcd7ea50bd009Timo Sirainen }
98c1cf256927e254f0c092acd2ddcd7ea50bd009Timo Sirainen
a97a3ce5d82b16e8979de2d6cafbf6b0a129fe4eTimo Sirainen istream_raw_mbox_next(sync_ctx->input,
a97a3ce5d82b16e8979de2d6cafbf6b0a129fe4eTimo Sirainen mail_ctx->mail.body_size);
a97a3ce5d82b16e8979de2d6cafbf6b0a129fe4eTimo Sirainen offset = istream_raw_mbox_get_start_offset(sync_ctx->input);
a97a3ce5d82b16e8979de2d6cafbf6b0a129fe4eTimo Sirainen
a97a3ce5d82b16e8979de2d6cafbf6b0a129fe4eTimo Sirainen if (sync_ctx->need_space_seq != 0) {
a97a3ce5d82b16e8979de2d6cafbf6b0a129fe4eTimo Sirainen if (mbox_sync_handle_missing_space(mail_ctx) < 0)
a97a3ce5d82b16e8979de2d6cafbf6b0a129fe4eTimo Sirainen return -1;
a97a3ce5d82b16e8979de2d6cafbf6b0a129fe4eTimo Sirainen if (mbox_sync_seek(sync_ctx, offset) < 0)
a97a3ce5d82b16e8979de2d6cafbf6b0a129fe4eTimo Sirainen return -1;
a97a3ce5d82b16e8979de2d6cafbf6b0a129fe4eTimo Sirainen } else if (sync_ctx->expunged_space > 0) {
a97a3ce5d82b16e8979de2d6cafbf6b0a129fe4eTimo Sirainen if (!expunged) {
a97a3ce5d82b16e8979de2d6cafbf6b0a129fe4eTimo Sirainen /* move the body */
a97a3ce5d82b16e8979de2d6cafbf6b0a129fe4eTimo Sirainen mbox_sync_file_update_ext_modified(sync_ctx);
a97a3ce5d82b16e8979de2d6cafbf6b0a129fe4eTimo Sirainen if (mbox_move(sync_ctx,
a97a3ce5d82b16e8979de2d6cafbf6b0a129fe4eTimo Sirainen mail_ctx->body_offset -
a97a3ce5d82b16e8979de2d6cafbf6b0a129fe4eTimo Sirainen sync_ctx->expunged_space,
a97a3ce5d82b16e8979de2d6cafbf6b0a129fe4eTimo Sirainen mail_ctx->body_offset,
a97a3ce5d82b16e8979de2d6cafbf6b0a129fe4eTimo Sirainen mail_ctx->mail.body_size) < 0)
a97a3ce5d82b16e8979de2d6cafbf6b0a129fe4eTimo Sirainen return -1;
a97a3ce5d82b16e8979de2d6cafbf6b0a129fe4eTimo Sirainen if (mbox_sync_seek(sync_ctx, offset) < 0)
a97a3ce5d82b16e8979de2d6cafbf6b0a129fe4eTimo Sirainen return -1;
a97a3ce5d82b16e8979de2d6cafbf6b0a129fe4eTimo Sirainen }
a97a3ce5d82b16e8979de2d6cafbf6b0a129fe4eTimo Sirainen } else if (partial) {
a97a3ce5d82b16e8979de2d6cafbf6b0a129fe4eTimo Sirainen ret = mbox_sync_partial_seek_next(sync_ctx, uid + 1,
a97a3ce5d82b16e8979de2d6cafbf6b0a129fe4eTimo Sirainen &partial,
a97a3ce5d82b16e8979de2d6cafbf6b0a129fe4eTimo Sirainen &skipped_mails);
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen if (ret <= 0) {
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen if (ret < 0)
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen return -1;
f5b919e9b07dfd9d2401b998ef8759e5f0312719Timo Sirainen break;
4b9f99761df5014c659cd87fddaf6854af428cfcTimo Sirainen }
33ae95df45c9b5ec51332a6b39eb5322038686b9Timo Sirainen }
178511b57faa7c3f8203dd8b7e4059d00cbfc23aTimo Sirainen }
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen if (istream_raw_mbox_is_eof(sync_ctx->input)) {
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen /* rest of the messages in index don't exist -> expunge them */
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen while (sync_ctx->idx_seq <= messages_count)
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen mail_index_expunge(sync_ctx->t, sync_ctx->idx_seq++);
4b9f99761df5014c659cd87fddaf6854af428cfcTimo Sirainen }
4b9f99761df5014c659cd87fddaf6854af428cfcTimo Sirainen
4b9f99761df5014c659cd87fddaf6854af428cfcTimo Sirainen if (!skipped_mails)
b225c3c65f360d7b833f09f9b2fb3035ed5ea600Timo Sirainen sync_ctx->mbox->mbox_sync_dirty = FALSE;
b225c3c65f360d7b833f09f9b2fb3035ed5ea600Timo Sirainen
4b9f99761df5014c659cd87fddaf6854af428cfcTimo Sirainen if (uids_broken && sync_ctx->delay_writes) {
8166e8a706078efc71923719ca285e84902883c0Timo Sirainen /* once we get around to writing the changes, we'll need to do
8166e8a706078efc71923719ca285e84902883c0Timo Sirainen a full sync to avoid the "UIDs broken in partial sync"
8166e8a706078efc71923719ca285e84902883c0Timo Sirainen error */
8166e8a706078efc71923719ca285e84902883c0Timo Sirainen sync_ctx->mbox->mbox_sync_dirty = TRUE;
09b9cbde9e7a0f9adea1fb054a7c62f35ad901e1Timo Sirainen }
a2637488c8d514ec1ac3914811deee814f9761b3Timo Sirainen return 1;
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen}
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen
09b9cbde9e7a0f9adea1fb054a7c62f35ad901e1Timo Sirainenstatic int mbox_write_pseudo(struct mbox_sync_context *sync_ctx)
09b9cbde9e7a0f9adea1fb054a7c62f35ad901e1Timo Sirainen{
09b9cbde9e7a0f9adea1fb054a7c62f35ad901e1Timo Sirainen string_t *str;
5edfc0f1c3c55e906d8316d9cdeaa3b0c7000c19Timo Sirainen unsigned int uid_validity;
686cb2418d4daa7bc747d3551783c1895e7c41b9Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen i_assert(sync_ctx->write_fd != -1);
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
b225c3c65f360d7b833f09f9b2fb3035ed5ea600Timo Sirainen uid_validity = sync_ctx->base_uid_validity != 0 ?
b225c3c65f360d7b833f09f9b2fb3035ed5ea600Timo Sirainen sync_ctx->base_uid_validity : sync_ctx->hdr->uid_validity;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen i_assert(uid_validity != 0);
f16c114c20bbd7d292d93415d1e56c8dd6abd3e7Timo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen str = t_str_new(1024);
f16c114c20bbd7d292d93415d1e56c8dd6abd3e7Timo Sirainen str_printfa(str, "%sDate: %s\n"
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen "From: Mail System Internal Data <MAILER-DAEMON@%s>\n"
f5b919e9b07dfd9d2401b998ef8759e5f0312719Timo Sirainen "Subject: DON'T DELETE THIS MESSAGE -- FOLDER INTERNAL DATA"
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen "\nMessage-ID: <%s@%s>\n"
f5b919e9b07dfd9d2401b998ef8759e5f0312719Timo Sirainen "X-IMAP: %u %010u\n"
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen "Status: RO\n"
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen "\n"
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen PSEUDO_MESSAGE_BODY
e68309fcfa2eaa88217fd51e7b4900fc9c20ef5dTimo Sirainen "\n",
6a1e4eb2c6a267bec1e8704ce9137bebb7792702Timo Sirainen mbox_from_create("MAILER_DAEMON", ioloop_time),
fc1696e32dd732a5bbabc3c8f64810448e327043Timo Sirainen message_date_create(ioloop_time),
a97a3ce5d82b16e8979de2d6cafbf6b0a129fe4eTimo Sirainen my_hostname, dec2str(ioloop_time), my_hostname,
a97a3ce5d82b16e8979de2d6cafbf6b0a129fe4eTimo Sirainen uid_validity, sync_ctx->next_uid-1);
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
299183fbb6ec5d0828a0880da372540421ac4665Timo Sirainen if (pwrite_full(sync_ctx->write_fd,
6a1e4eb2c6a267bec1e8704ce9137bebb7792702Timo Sirainen str_data(str), str_len(str), 0) < 0) {
f4b93a46e140823a64d88763ea6ef9f03c49844eTimo Sirainen if (!ENOSPACE(errno)) {
6a1e4eb2c6a267bec1e8704ce9137bebb7792702Timo Sirainen mbox_set_syscall_error(sync_ctx->mbox,
6a1e4eb2c6a267bec1e8704ce9137bebb7792702Timo Sirainen "pwrite_full()");
6a1e4eb2c6a267bec1e8704ce9137bebb7792702Timo Sirainen return -1;
6a1e4eb2c6a267bec1e8704ce9137bebb7792702Timo Sirainen }
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen
8907d617ce7c4f390c0f42f6f694db2fecdd5775Timo Sirainen /* out of disk space, truncate to empty */
99be58a447b69d62cbd9e764000a06226b9c9c89Timo Sirainen if (ftruncate(sync_ctx->write_fd, 0) < 0)
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen mbox_set_syscall_error(sync_ctx->mbox, "ftruncate()");
39775ad03c459efe64cce924658da5094ba417e1Timo Sirainen }
343a527f805ca5cce78496b959d6def70e5d0cd4Timo Sirainen
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen sync_ctx->base_uid_last_offset = 0; /* don't bother calculating */
313fe89df4d91cd0cd7f3558dc6d7fd21ad39eeeTimo Sirainen sync_ctx->base_uid_last = sync_ctx->next_uid-1;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen return 0;
b225c3c65f360d7b833f09f9b2fb3035ed5ea600Timo Sirainen}
b225c3c65f360d7b833f09f9b2fb3035ed5ea600Timo Sirainen
a2637488c8d514ec1ac3914811deee814f9761b3Timo Sirainenstatic int mbox_sync_handle_eof_updates(struct mbox_sync_context *sync_ctx,
b225c3c65f360d7b833f09f9b2fb3035ed5ea600Timo Sirainen struct mbox_sync_mail_context *mail_ctx)
299183fbb6ec5d0828a0880da372540421ac4665Timo Sirainen{
299183fbb6ec5d0828a0880da372540421ac4665Timo Sirainen const struct stat *st;
b397a802ec245a9169dab6b62efa4f7f877c07f6Timo Sirainen uoff_t file_size, offset, padding, trailer_size;
b397a802ec245a9169dab6b62efa4f7f877c07f6Timo Sirainen
b397a802ec245a9169dab6b62efa4f7f877c07f6Timo Sirainen if (!istream_raw_mbox_is_eof(sync_ctx->input)) {
b397a802ec245a9169dab6b62efa4f7f877c07f6Timo Sirainen i_assert(sync_ctx->need_space_seq == 0);
988922bdf2d461021d210697f1f118956ca388e1Timo Sirainen i_assert(sync_ctx->expunged_space == 0);
988922bdf2d461021d210697f1f118956ca388e1Timo Sirainen return 0;
988922bdf2d461021d210697f1f118956ca388e1Timo Sirainen }
988922bdf2d461021d210697f1f118956ca388e1Timo Sirainen
988922bdf2d461021d210697f1f118956ca388e1Timo Sirainen st = i_stream_stat(sync_ctx->file_input, TRUE);
988922bdf2d461021d210697f1f118956ca388e1Timo Sirainen if (st == NULL) {
b397a802ec245a9169dab6b62efa4f7f877c07f6Timo Sirainen mbox_set_syscall_error(sync_ctx->mbox, "i_stream_stat()");
b397a802ec245a9169dab6b62efa4f7f877c07f6Timo Sirainen return -1;
5edfc0f1c3c55e906d8316d9cdeaa3b0c7000c19Timo Sirainen }
5edfc0f1c3c55e906d8316d9cdeaa3b0c7000c19Timo Sirainen file_size = st->st_size;
eb276c05bf6b0a383c772d61e31cf09a8dbd36c7Timo Sirainen if (file_size < sync_ctx->file_input->v_offset) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen mbox_sync_set_critical(sync_ctx,
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen "file size unexpectedly shrinked in mbox file %s "
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen "(%"PRIuUOFF_T" vs %"PRIuUOFF_T")",
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen sync_ctx->mbox->path, file_size,
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen sync_ctx->file_input->v_offset);
b225c3c65f360d7b833f09f9b2fb3035ed5ea600Timo Sirainen return -1;
b225c3c65f360d7b833f09f9b2fb3035ed5ea600Timo Sirainen }
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen trailer_size = file_size - sync_ctx->file_input->v_offset;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen i_assert(trailer_size <= 2);
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen if (sync_ctx->need_space_seq != 0) {
98c1cf256927e254f0c092acd2ddcd7ea50bd009Timo Sirainen i_assert(sync_ctx->write_fd != -1);
f7d43647acc6dc80064c8c4cacf5bf86f754c530Timo Sirainen
98c1cf256927e254f0c092acd2ddcd7ea50bd009Timo Sirainen i_assert(sync_ctx->space_diff < 0);
98c1cf256927e254f0c092acd2ddcd7ea50bd009Timo Sirainen padding = MBOX_HEADER_PADDING *
98c1cf256927e254f0c092acd2ddcd7ea50bd009Timo Sirainen (sync_ctx->seq - sync_ctx->need_space_seq + 1);
db7c9201c88e3d9bee10485194ee5b0c67249916Timo Sirainen sync_ctx->space_diff -= padding;
299183fbb6ec5d0828a0880da372540421ac4665Timo Sirainen
eeeee5297c71eb8badfbdff5241ac05851f1c21fTimo Sirainen i_assert(sync_ctx->expunged_space <= -sync_ctx->space_diff);
eeeee5297c71eb8badfbdff5241ac05851f1c21fTimo Sirainen sync_ctx->space_diff += sync_ctx->expunged_space;
eeeee5297c71eb8badfbdff5241ac05851f1c21fTimo Sirainen sync_ctx->expunged_space = 0;
eeeee5297c71eb8badfbdff5241ac05851f1c21fTimo Sirainen
eeeee5297c71eb8badfbdff5241ac05851f1c21fTimo Sirainen if (mail_ctx->have_eoh && !mail_ctx->updated)
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen str_append_c(mail_ctx->header, '\n');
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen i_assert(sync_ctx->space_diff < 0);
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
690bafa70767e3f6e98bbfd62ad4a26be2387ea9Timo Sirainen if (file_set_size(sync_ctx->write_fd,
bfa7ef85a07f07b7d2e72471a584689cfb6adc31Timo Sirainen file_size + -sync_ctx->space_diff) < 0) {
bfa7ef85a07f07b7d2e72471a584689cfb6adc31Timo Sirainen mbox_set_syscall_error(sync_ctx->mbox,
690bafa70767e3f6e98bbfd62ad4a26be2387ea9Timo Sirainen "file_set_size()");
bfa7ef85a07f07b7d2e72471a584689cfb6adc31Timo Sirainen if (ftruncate(sync_ctx->write_fd, file_size) < 0) {
690bafa70767e3f6e98bbfd62ad4a26be2387ea9Timo Sirainen mbox_set_syscall_error(sync_ctx->mbox,
690bafa70767e3f6e98bbfd62ad4a26be2387ea9Timo Sirainen "ftruncate()");
690bafa70767e3f6e98bbfd62ad4a26be2387ea9Timo Sirainen }
de62ce819d59a529530da4b57be1b8d6dad13d6bTimo Sirainen return -1;
17ad2164c747cedbf81dae1893063e71a3df0356Timo Sirainen }
17ad2164c747cedbf81dae1893063e71a3df0356Timo Sirainen mbox_sync_file_updated(sync_ctx, FALSE);
de62ce819d59a529530da4b57be1b8d6dad13d6bTimo Sirainen
de62ce819d59a529530da4b57be1b8d6dad13d6bTimo Sirainen if (mbox_sync_rewrite(sync_ctx, mail_ctx, file_size,
17ad2164c747cedbf81dae1893063e71a3df0356Timo Sirainen -sync_ctx->space_diff, padding,
c0bfb67ba32064347bac3241f1aac9b8a809e2f1Timo Sirainen sync_ctx->need_space_seq,
d22301419109ed4a38351715e6760011421dadecTimo Sirainen sync_ctx->seq) < 0)
690bafa70767e3f6e98bbfd62ad4a26be2387ea9Timo Sirainen return -1;
690bafa70767e3f6e98bbfd62ad4a26be2387ea9Timo Sirainen
690bafa70767e3f6e98bbfd62ad4a26be2387ea9Timo Sirainen update_from_offsets(sync_ctx);
f3480d03ed0e920d45fac9142503f774ddb1004bTimo Sirainen
f3480d03ed0e920d45fac9142503f774ddb1004bTimo Sirainen sync_ctx->need_space_seq = 0;
f3480d03ed0e920d45fac9142503f774ddb1004bTimo Sirainen array_clear(&sync_ctx->mails);
f3480d03ed0e920d45fac9142503f774ddb1004bTimo Sirainen p_clear(sync_ctx->saved_keywords_pool);
f3480d03ed0e920d45fac9142503f774ddb1004bTimo Sirainen }
f3480d03ed0e920d45fac9142503f774ddb1004bTimo Sirainen
f3480d03ed0e920d45fac9142503f774ddb1004bTimo Sirainen if (sync_ctx->expunged_space > 0) {
bfa7ef85a07f07b7d2e72471a584689cfb6adc31Timo Sirainen i_assert(sync_ctx->write_fd != -1);
690bafa70767e3f6e98bbfd62ad4a26be2387ea9Timo Sirainen
690bafa70767e3f6e98bbfd62ad4a26be2387ea9Timo Sirainen mbox_sync_file_update_ext_modified(sync_ctx);
690bafa70767e3f6e98bbfd62ad4a26be2387ea9Timo Sirainen
690bafa70767e3f6e98bbfd62ad4a26be2387ea9Timo Sirainen /* copy trailer, then truncate the file */
690bafa70767e3f6e98bbfd62ad4a26be2387ea9Timo Sirainen file_size = sync_ctx->last_stat.st_size;
1a073dd6184645b026583274e05afba10dcc20bbTimo Sirainen if (file_size == (uoff_t)sync_ctx->expunged_space) {
1a073dd6184645b026583274e05afba10dcc20bbTimo Sirainen /* everything deleted, the trailer_size still contains
1a073dd6184645b026583274e05afba10dcc20bbTimo Sirainen the \n trailer though */
1a073dd6184645b026583274e05afba10dcc20bbTimo Sirainen trailer_size = 0;
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen }
1a073dd6184645b026583274e05afba10dcc20bbTimo Sirainen
1a073dd6184645b026583274e05afba10dcc20bbTimo Sirainen i_assert(file_size >= sync_ctx->expunged_space + trailer_size);
1a073dd6184645b026583274e05afba10dcc20bbTimo Sirainen offset = file_size - sync_ctx->expunged_space - trailer_size;
1a073dd6184645b026583274e05afba10dcc20bbTimo Sirainen i_assert(offset == 0 || offset > 31);
af6d4a24cb6d18e50d172540cf49b1448a6f9872Timo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen if (mbox_move(sync_ctx, offset,
279cc94ab086f6a3cb764b1b98ff6b936efa3eaeTimo Sirainen offset + sync_ctx->expunged_space,
b225c3c65f360d7b833f09f9b2fb3035ed5ea600Timo Sirainen trailer_size) < 0)
279cc94ab086f6a3cb764b1b98ff6b936efa3eaeTimo Sirainen return -1;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen if (ftruncate(sync_ctx->write_fd,
01f4ee4a0243f3fe9af763e1a540cd5cff0d63f5Timo Sirainen offset + trailer_size) < 0) {
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen mbox_set_syscall_error(sync_ctx->mbox, "ftruncate()");
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen return -1;
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
e05ea8311ae16687295048e88ca205dfe29fbcbfTimo Sirainen if (offset == 0) {
690bafa70767e3f6e98bbfd62ad4a26be2387ea9Timo Sirainen if (mbox_write_pseudo(sync_ctx) < 0)
e05ea8311ae16687295048e88ca205dfe29fbcbfTimo Sirainen return -1;
e05ea8311ae16687295048e88ca205dfe29fbcbfTimo Sirainen }
e05ea8311ae16687295048e88ca205dfe29fbcbfTimo Sirainen
e05ea8311ae16687295048e88ca205dfe29fbcbfTimo Sirainen sync_ctx->expunged_space = 0;
e05ea8311ae16687295048e88ca205dfe29fbcbfTimo Sirainen mbox_sync_file_updated(sync_ctx, FALSE);
e05ea8311ae16687295048e88ca205dfe29fbcbfTimo Sirainen }
e05ea8311ae16687295048e88ca205dfe29fbcbfTimo Sirainen return 0;
e05ea8311ae16687295048e88ca205dfe29fbcbfTimo Sirainen}
e05ea8311ae16687295048e88ca205dfe29fbcbfTimo Sirainen
e05ea8311ae16687295048e88ca205dfe29fbcbfTimo Sirainenstatic int mbox_sync_update_index_header(struct mbox_sync_context *sync_ctx)
e05ea8311ae16687295048e88ca205dfe29fbcbfTimo Sirainen{
e05ea8311ae16687295048e88ca205dfe29fbcbfTimo Sirainen const struct stat *st;
e05ea8311ae16687295048e88ca205dfe29fbcbfTimo Sirainen
e05ea8311ae16687295048e88ca205dfe29fbcbfTimo Sirainen st = i_stream_stat(sync_ctx->file_input, FALSE);
e05ea8311ae16687295048e88ca205dfe29fbcbfTimo Sirainen if (st == NULL) {
ca98892a6b8a30ffc1fe26fcf02c7d59e3204e7eTimo Sirainen mbox_set_syscall_error(sync_ctx->mbox, "i_stream_stat()");
e05ea8311ae16687295048e88ca205dfe29fbcbfTimo Sirainen return -1;
e05ea8311ae16687295048e88ca205dfe29fbcbfTimo Sirainen }
e05ea8311ae16687295048e88ca205dfe29fbcbfTimo Sirainen
e05ea8311ae16687295048e88ca205dfe29fbcbfTimo Sirainen if (sync_ctx->moved_offsets &&
e05ea8311ae16687295048e88ca205dfe29fbcbfTimo Sirainen ((uint64_t)st->st_size == sync_ctx->hdr->sync_size ||
01f4ee4a0243f3fe9af763e1a540cd5cff0d63f5Timo Sirainen (uint64_t)st->st_size == sync_ctx->orig_size)) {
e05ea8311ae16687295048e88ca205dfe29fbcbfTimo Sirainen /* We moved messages inside the mbox file without changing
e05ea8311ae16687295048e88ca205dfe29fbcbfTimo Sirainen the file's size. If mtime doesn't change, another process
e05ea8311ae16687295048e88ca205dfe29fbcbfTimo Sirainen not using the same index file as us can't know that the file
e05ea8311ae16687295048e88ca205dfe29fbcbfTimo Sirainen was changed. So make sure the mtime changes. This should
e05ea8311ae16687295048e88ca205dfe29fbcbfTimo Sirainen happen rarely enough that the sleeping doesn't become a
e05ea8311ae16687295048e88ca205dfe29fbcbfTimo Sirainen performance problem.
e05ea8311ae16687295048e88ca205dfe29fbcbfTimo Sirainen
690bafa70767e3f6e98bbfd62ad4a26be2387ea9Timo Sirainen Note that to do this perfectly safe we should do this wait
690bafa70767e3f6e98bbfd62ad4a26be2387ea9Timo Sirainen whenever mails are moved or expunged, regardless of whether
bfa7ef85a07f07b7d2e72471a584689cfb6adc31Timo Sirainen the file's size changed. That however could become a
690bafa70767e3f6e98bbfd62ad4a26be2387ea9Timo Sirainen performance problem and the consequences of being wrong are
dc42ce2d44e84d9d05a9310c11f8764f319eb3abTimo Sirainen quite minimal (an extra logged error message). */
dc42ce2d44e84d9d05a9310c11f8764f319eb3abTimo Sirainen while (sync_ctx->orig_mtime == st->st_mtime) {
8166e8a706078efc71923719ca285e84902883c0Timo Sirainen usleep(500000);
dc42ce2d44e84d9d05a9310c11f8764f319eb3abTimo Sirainen if (utime(sync_ctx->mbox->path, NULL) < 0) {
06fc140d5f0b03524e63a15d45d1cdc8b691372cTimo Sirainen mbox_set_syscall_error(sync_ctx->mbox,
06fc140d5f0b03524e63a15d45d1cdc8b691372cTimo Sirainen "utime()");
06fc140d5f0b03524e63a15d45d1cdc8b691372cTimo Sirainen return -1;
1a073dd6184645b026583274e05afba10dcc20bbTimo Sirainen }
06fc140d5f0b03524e63a15d45d1cdc8b691372cTimo Sirainen
06fc140d5f0b03524e63a15d45d1cdc8b691372cTimo Sirainen st = i_stream_stat(sync_ctx->file_input, FALSE);
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen if (st == NULL) {
fcfd317f7eb1f0216764c75c5fab3555020552d4Timo Sirainen mbox_set_syscall_error(sync_ctx->mbox,
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen "i_stream_stat()");
aa38d1a0945f0bc13a225d043f53fad2eec666b1Timo Sirainen return -1;
fcfd317f7eb1f0216764c75c5fab3555020552d4Timo Sirainen }
9e59a1f3f095b3099478562cf3f3970a24736970Timo Sirainen }
178511b57faa7c3f8203dd8b7e4059d00cbfc23aTimo Sirainen }
b3febb0933fdce10394d25093e23ce0a5aadddd3Timo Sirainen
b3febb0933fdce10394d25093e23ce0a5aadddd3Timo Sirainen /* only reason not to have UID validity at this point is if the file
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen is entirely empty. In that case just make up a new one if needed. */
fcfd317f7eb1f0216764c75c5fab3555020552d4Timo Sirainen i_assert(sync_ctx->base_uid_validity != 0 || st->st_size == 0);
aa38d1a0945f0bc13a225d043f53fad2eec666b1Timo Sirainen
fcfd317f7eb1f0216764c75c5fab3555020552d4Timo Sirainen if (sync_ctx->base_uid_validity != sync_ctx->hdr->uid_validity ||
fcfd317f7eb1f0216764c75c5fab3555020552d4Timo Sirainen sync_ctx->base_uid_validity == 0) {
279cc94ab086f6a3cb764b1b98ff6b936efa3eaeTimo Sirainen if (sync_ctx->base_uid_validity == 0) {
279cc94ab086f6a3cb764b1b98ff6b936efa3eaeTimo Sirainen sync_ctx->base_uid_validity =
279cc94ab086f6a3cb764b1b98ff6b936efa3eaeTimo Sirainen sync_ctx->hdr->uid_validity != 0 ?
279cc94ab086f6a3cb764b1b98ff6b936efa3eaeTimo Sirainen sync_ctx->hdr->uid_validity :
279cc94ab086f6a3cb764b1b98ff6b936efa3eaeTimo Sirainen (unsigned int)ioloop_time;
279cc94ab086f6a3cb764b1b98ff6b936efa3eaeTimo Sirainen }
279cc94ab086f6a3cb764b1b98ff6b936efa3eaeTimo Sirainen
279cc94ab086f6a3cb764b1b98ff6b936efa3eaeTimo Sirainen mail_index_update_header(sync_ctx->t,
279cc94ab086f6a3cb764b1b98ff6b936efa3eaeTimo Sirainen offsetof(struct mail_index_header, uid_validity),
279cc94ab086f6a3cb764b1b98ff6b936efa3eaeTimo Sirainen &sync_ctx->base_uid_validity,
279cc94ab086f6a3cb764b1b98ff6b936efa3eaeTimo Sirainen sizeof(sync_ctx->base_uid_validity), TRUE);
d22301419109ed4a38351715e6760011421dadecTimo Sirainen }
279cc94ab086f6a3cb764b1b98ff6b936efa3eaeTimo Sirainen
279cc94ab086f6a3cb764b1b98ff6b936efa3eaeTimo Sirainen if (istream_raw_mbox_is_eof(sync_ctx->input) &&
279cc94ab086f6a3cb764b1b98ff6b936efa3eaeTimo Sirainen sync_ctx->next_uid != sync_ctx->hdr->next_uid) {
279cc94ab086f6a3cb764b1b98ff6b936efa3eaeTimo Sirainen i_assert(sync_ctx->next_uid != 0);
ced118ac5caf6fe83d34339c2c65c63b2aa768acTimo Sirainen mail_index_update_header(sync_ctx->t,
ed14c2db5436d6d89aa65bc8e09af0c316359553Timo Sirainen offsetof(struct mail_index_header, next_uid),
1d3f7c1278168d5b1cbfa9a2cc9929a0909056b4Timo Sirainen &sync_ctx->next_uid, sizeof(sync_ctx->next_uid), FALSE);
1d3f7c1278168d5b1cbfa9a2cc9929a0909056b4Timo Sirainen }
1d3f7c1278168d5b1cbfa9a2cc9929a0909056b4Timo Sirainen
1d3f7c1278168d5b1cbfa9a2cc9929a0909056b4Timo Sirainen if ((uint32_t)st->st_mtime != sync_ctx->hdr->sync_stamp &&
1d3f7c1278168d5b1cbfa9a2cc9929a0909056b4Timo Sirainen !sync_ctx->mbox->mbox_sync_dirty) {
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen uint32_t sync_stamp = st->st_mtime;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen mail_index_update_header(sync_ctx->t,
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen offsetof(struct mail_index_header, sync_stamp),
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen &sync_stamp, sizeof(sync_stamp), TRUE);
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen }
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen if ((uint64_t)st->st_size != sync_ctx->hdr->sync_size &&
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen !sync_ctx->mbox->mbox_sync_dirty) {
39775ad03c459efe64cce924658da5094ba417e1Timo Sirainen uint64_t sync_size = st->st_size;
343a527f805ca5cce78496b959d6def70e5d0cd4Timo Sirainen
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen mail_index_update_header(sync_ctx->t,
022412398e56a8f31ef111cfd7271498d64af9a9Timo Sirainen offsetof(struct mail_index_header, sync_size),
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen &sync_size, sizeof(sync_size), TRUE);
734f2ff794505007ac7310af12e1adef5643c36eTimo Sirainen }
c263e92d73889da530b308c9ab28b4b74031550eTimo Sirainen
f6699a08521aacc4c2bb5b6175691dad5f715f8cTimo Sirainen sync_ctx->mbox->mbox_dirty_stamp = st->st_mtime;
f6699a08521aacc4c2bb5b6175691dad5f715f8cTimo Sirainen sync_ctx->mbox->mbox_dirty_size = st->st_size;
f6699a08521aacc4c2bb5b6175691dad5f715f8cTimo Sirainen
f6699a08521aacc4c2bb5b6175691dad5f715f8cTimo Sirainen return 0;
d22301419109ed4a38351715e6760011421dadecTimo Sirainen}
f6699a08521aacc4c2bb5b6175691dad5f715f8cTimo Sirainen
f6699a08521aacc4c2bb5b6175691dad5f715f8cTimo Sirainenstatic void mbox_sync_restart(struct mbox_sync_context *sync_ctx)
f0569d9fbb25c8437760be69f194595a841ad711Timo Sirainen{
c263e92d73889da530b308c9ab28b4b74031550eTimo Sirainen sync_ctx->base_uid_validity = 0;
aa38d1a0945f0bc13a225d043f53fad2eec666b1Timo Sirainen sync_ctx->base_uid_last = 0;
a393d9d6dabdc46cf724f8cb004a652b4036d53dTimo Sirainen sync_ctx->base_uid_last_offset = 0;
c263e92d73889da530b308c9ab28b4b74031550eTimo Sirainen
c263e92d73889da530b308c9ab28b4b74031550eTimo Sirainen array_clear(&sync_ctx->mails);
c263e92d73889da530b308c9ab28b4b74031550eTimo Sirainen array_clear(&sync_ctx->syncs);
c263e92d73889da530b308c9ab28b4b74031550eTimo Sirainen p_clear(sync_ctx->saved_keywords_pool);
325f4573edfa5b751832ac01023f3e81be992bf0Timo Sirainen
9e59a1f3f095b3099478562cf3f3970a24736970Timo Sirainen memset(&sync_ctx->sync_rec, 0, sizeof(sync_ctx->sync_rec));
a2637488c8d514ec1ac3914811deee814f9761b3Timo Sirainen mail_index_sync_reset(sync_ctx->index_sync_ctx);
b6d817f0effeff645aadc01fd468a7d4084ba1f2Timo Sirainen mail_index_transaction_reset(sync_ctx->t);
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen if (sync_ctx->index_reset) {
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen mail_index_reset(sync_ctx->t);
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen sync_ctx->reset_hdr.next_uid = 1;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen sync_ctx->hdr = &sync_ctx->reset_hdr;
690bafa70767e3f6e98bbfd62ad4a26be2387ea9Timo Sirainen }
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
b225c3c65f360d7b833f09f9b2fb3035ed5ea600Timo Sirainen sync_ctx->prev_msg_uid = 0;
a486ed03dce069ff60ab5a65d0ae24a1862f22fcTimo Sirainen sync_ctx->next_uid = sync_ctx->hdr->next_uid;
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen sync_ctx->idx_next_uid = sync_ctx->hdr->next_uid;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen sync_ctx->seq = 0;
01f4ee4a0243f3fe9af763e1a540cd5cff0d63f5Timo Sirainen sync_ctx->idx_seq = 1;
34d2ee1fa2b299267fcefd378f80690e7f601dfbTimo Sirainen sync_ctx->need_space_seq = 0;
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen sync_ctx->expunged_space = 0;
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen sync_ctx->space_diff = 0;
299183fbb6ec5d0828a0880da372540421ac4665Timo Sirainen
e05ea8311ae16687295048e88ca205dfe29fbcbfTimo Sirainen sync_ctx->dest_first_mail = TRUE;
9d0e1fa945103f2875cdf6d18b2013809f566ea7Timo Sirainen sync_ctx->ext_modified = FALSE;
e05ea8311ae16687295048e88ca205dfe29fbcbfTimo Sirainen}
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen
6060b7c8edf8fce73470d0df6a2479b69b01c537Timo Sirainenstatic int mbox_sync_do(struct mbox_sync_context *sync_ctx,
6060b7c8edf8fce73470d0df6a2479b69b01c537Timo Sirainen enum mbox_sync_flags flags)
6060b7c8edf8fce73470d0df6a2479b69b01c537Timo Sirainen{
690bafa70767e3f6e98bbfd62ad4a26be2387ea9Timo Sirainen struct mbox_sync_mail_context mail_ctx;
690bafa70767e3f6e98bbfd62ad4a26be2387ea9Timo Sirainen const struct stat *st;
690bafa70767e3f6e98bbfd62ad4a26be2387ea9Timo Sirainen unsigned int i;
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen int ret, partial;
690bafa70767e3f6e98bbfd62ad4a26be2387ea9Timo Sirainen
690bafa70767e3f6e98bbfd62ad4a26be2387ea9Timo Sirainen st = i_stream_stat(sync_ctx->file_input, FALSE);
690bafa70767e3f6e98bbfd62ad4a26be2387ea9Timo Sirainen if (st == NULL) {
690bafa70767e3f6e98bbfd62ad4a26be2387ea9Timo Sirainen mbox_set_syscall_error(sync_ctx->mbox, "i_stream_stat()");
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen return -1;
690bafa70767e3f6e98bbfd62ad4a26be2387ea9Timo Sirainen }
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen sync_ctx->last_stat = *st;
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen sync_ctx->orig_size = st->st_size;
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen sync_ctx->orig_atime = st->st_atime;
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen sync_ctx->orig_mtime = st->st_mtime;
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen
690bafa70767e3f6e98bbfd62ad4a26be2387ea9Timo Sirainen if ((flags & MBOX_SYNC_FORCE_SYNC) != 0) {
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen /* forcing a full sync. assume file has changed. */
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen partial = FALSE;
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen sync_ctx->mbox->mbox_sync_dirty = TRUE;
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen } else if ((uint32_t)st->st_mtime == sync_ctx->hdr->sync_stamp &&
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen (uint64_t)st->st_size == sync_ctx->hdr->sync_size) {
690bafa70767e3f6e98bbfd62ad4a26be2387ea9Timo Sirainen /* file is fully synced */
345212e8f61ebf14ff4f80df26df9e655eb5121eTimo Sirainen partial = TRUE;
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen sync_ctx->mbox->mbox_sync_dirty = FALSE;
abe8230dd1dd37d7ccf0163100e934bb5e658c20Timo Sirainen } else if ((flags & MBOX_SYNC_UNDIRTY) != 0 ||
b6d817f0effeff645aadc01fd468a7d4084ba1f2Timo Sirainen (uint64_t)st->st_size == sync_ctx->hdr->sync_size) {
a486ed03dce069ff60ab5a65d0ae24a1862f22fcTimo Sirainen /* we want to do full syncing. always do this if
b6d817f0effeff645aadc01fd468a7d4084ba1f2Timo Sirainen file size hasn't changed but timestamp has. it most
a486ed03dce069ff60ab5a65d0ae24a1862f22fcTimo Sirainen likely means that someone had modified some header
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen and we probably want to know about it */
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen partial = FALSE;
b3febb0933fdce10394d25093e23ce0a5aadddd3Timo Sirainen sync_ctx->mbox->mbox_sync_dirty = TRUE;
b6d817f0effeff645aadc01fd468a7d4084ba1f2Timo Sirainen } else {
b6d817f0effeff645aadc01fd468a7d4084ba1f2Timo Sirainen /* see if we can delay syncing the whole file.
b6d817f0effeff645aadc01fd468a7d4084ba1f2Timo Sirainen normally we only notice expunges and appends
42456ec33fe65feb411890f99d436071e0185ee3Timo Sirainen in partial syncing. */
b6d817f0effeff645aadc01fd468a7d4084ba1f2Timo Sirainen partial = TRUE;
b6d817f0effeff645aadc01fd468a7d4084ba1f2Timo Sirainen sync_ctx->mbox->mbox_sync_dirty = TRUE;
c4f76f390c75aac7f41492db4c858576fcab54d3Timo Sirainen }
c4f76f390c75aac7f41492db4c858576fcab54d3Timo Sirainen
c4f76f390c75aac7f41492db4c858576fcab54d3Timo Sirainen mbox_sync_restart(sync_ctx);
b6d817f0effeff645aadc01fd468a7d4084ba1f2Timo Sirainen for (i = 0; i < 3; i++) {
b6d817f0effeff645aadc01fd468a7d4084ba1f2Timo Sirainen ret = mbox_sync_loop(sync_ctx, &mail_ctx, partial);
b6d817f0effeff645aadc01fd468a7d4084ba1f2Timo Sirainen if (ret > 0)
b6d817f0effeff645aadc01fd468a7d4084ba1f2Timo Sirainen break;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen if (ret < 0)
a486ed03dce069ff60ab5a65d0ae24a1862f22fcTimo Sirainen return -1;
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen /* partial syncing didn't work, do it again. we get here
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen also if we ran out of UIDs. */
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen i_assert(sync_ctx->mbox->mbox_sync_dirty);
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen mbox_sync_restart(sync_ctx);
db7c9201c88e3d9bee10485194ee5b0c67249916Timo Sirainen partial = FALSE;
db7c9201c88e3d9bee10485194ee5b0c67249916Timo Sirainen }
db7c9201c88e3d9bee10485194ee5b0c67249916Timo Sirainen
022412398e56a8f31ef111cfd7271498d64af9a9Timo Sirainen if (mbox_sync_handle_eof_updates(sync_ctx, &mail_ctx) < 0)
db7c9201c88e3d9bee10485194ee5b0c67249916Timo Sirainen return -1;
4ca7ca056c5039424c66581582052881854794a3Timo Sirainen
9638727fc341296ae5a7af630e176bc00f742f0bTimo Sirainen /* only syncs left should be just appends (and their updates)
4ca7ca056c5039424c66581582052881854794a3Timo Sirainen which weren't synced yet for some reason (crash). we'll just
4ca7ca056c5039424c66581582052881854794a3Timo Sirainen ignore them, as we've overwritten them above. */
4ca7ca056c5039424c66581582052881854794a3Timo Sirainen array_clear(&sync_ctx->syncs);
4ca7ca056c5039424c66581582052881854794a3Timo Sirainen memset(&sync_ctx->sync_rec, 0, sizeof(sync_ctx->sync_rec));
81ff42abb5db580f0553c6a4744cdb305089e0bcTimo Sirainen
81ff42abb5db580f0553c6a4744cdb305089e0bcTimo Sirainen if (mbox_sync_update_index_header(sync_ctx) < 0)
4ca7ca056c5039424c66581582052881854794a3Timo Sirainen return -1;
4ca7ca056c5039424c66581582052881854794a3Timo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen return 0;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen}
81ff42abb5db580f0553c6a4744cdb305089e0bcTimo Sirainen
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainenint mbox_sync_has_changed(struct mbox_mailbox *mbox, bool leave_dirty)
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen{
690bafa70767e3f6e98bbfd62ad4a26be2387ea9Timo Sirainen const struct mail_index_header *hdr;
690bafa70767e3f6e98bbfd62ad4a26be2387ea9Timo Sirainen const struct stat *st;
690bafa70767e3f6e98bbfd62ad4a26be2387ea9Timo Sirainen struct stat statbuf;
690bafa70767e3f6e98bbfd62ad4a26be2387ea9Timo Sirainen
690bafa70767e3f6e98bbfd62ad4a26be2387ea9Timo Sirainen if (mbox->mbox_file_stream != NULL && mbox->mbox_fd == -1) {
d22301419109ed4a38351715e6760011421dadecTimo Sirainen /* read-only stream */
1f1ee8db68d9ae1604350801cd8dc33ebe29fe8aTimo Sirainen st = i_stream_stat(mbox->mbox_file_stream, FALSE);
690bafa70767e3f6e98bbfd62ad4a26be2387ea9Timo Sirainen if (st == NULL) {
690bafa70767e3f6e98bbfd62ad4a26be2387ea9Timo Sirainen mbox_set_syscall_error(mbox, "i_stream_stat()");
690bafa70767e3f6e98bbfd62ad4a26be2387ea9Timo Sirainen return -1;
d22301419109ed4a38351715e6760011421dadecTimo Sirainen }
690bafa70767e3f6e98bbfd62ad4a26be2387ea9Timo Sirainen } else {
690bafa70767e3f6e98bbfd62ad4a26be2387ea9Timo Sirainen if (stat(mbox->path, &statbuf) < 0) {
8bf9b56dfb1913264e4fe2ee5932becbcbb459c5Timo Sirainen mbox_set_syscall_error(mbox, "stat()");
8bf9b56dfb1913264e4fe2ee5932becbcbb459c5Timo Sirainen return -1;
690bafa70767e3f6e98bbfd62ad4a26be2387ea9Timo Sirainen }
690bafa70767e3f6e98bbfd62ad4a26be2387ea9Timo Sirainen st = &statbuf;
690bafa70767e3f6e98bbfd62ad4a26be2387ea9Timo Sirainen }
690bafa70767e3f6e98bbfd62ad4a26be2387ea9Timo Sirainen
690bafa70767e3f6e98bbfd62ad4a26be2387ea9Timo Sirainen hdr = mail_index_get_header(mbox->ibox.view);
690bafa70767e3f6e98bbfd62ad4a26be2387ea9Timo Sirainen
690bafa70767e3f6e98bbfd62ad4a26be2387ea9Timo Sirainen if ((uint32_t)st->st_mtime == hdr->sync_stamp &&
690bafa70767e3f6e98bbfd62ad4a26be2387ea9Timo Sirainen (uint64_t)st->st_size == hdr->sync_size) {
690bafa70767e3f6e98bbfd62ad4a26be2387ea9Timo Sirainen /* fully synced */
bfa7ef85a07f07b7d2e72471a584689cfb6adc31Timo Sirainen mbox->mbox_sync_dirty = FALSE;
bfa7ef85a07f07b7d2e72471a584689cfb6adc31Timo Sirainen return 0;
bfa7ef85a07f07b7d2e72471a584689cfb6adc31Timo Sirainen }
bfa7ef85a07f07b7d2e72471a584689cfb6adc31Timo Sirainen
bfa7ef85a07f07b7d2e72471a584689cfb6adc31Timo Sirainen if (!mbox->mbox_sync_dirty || !leave_dirty) {
bfa7ef85a07f07b7d2e72471a584689cfb6adc31Timo Sirainen mbox->mbox_sync_dirty = TRUE;
bfa7ef85a07f07b7d2e72471a584689cfb6adc31Timo Sirainen return 1;
bfa7ef85a07f07b7d2e72471a584689cfb6adc31Timo Sirainen }
bfa7ef85a07f07b7d2e72471a584689cfb6adc31Timo Sirainen
bfa7ef85a07f07b7d2e72471a584689cfb6adc31Timo Sirainen return st->st_mtime != mbox->mbox_dirty_stamp ||
bfa7ef85a07f07b7d2e72471a584689cfb6adc31Timo Sirainen st->st_size != mbox->mbox_dirty_size;
bfa7ef85a07f07b7d2e72471a584689cfb6adc31Timo Sirainen}
bfa7ef85a07f07b7d2e72471a584689cfb6adc31Timo Sirainen
bfa7ef85a07f07b7d2e72471a584689cfb6adc31Timo Sirainenstatic void mbox_sync_context_free(struct mbox_sync_context *sync_ctx)
bfa7ef85a07f07b7d2e72471a584689cfb6adc31Timo Sirainen{
bfa7ef85a07f07b7d2e72471a584689cfb6adc31Timo Sirainen if (sync_ctx->index_sync_ctx != NULL)
b66d803de86bfb411165b3465b0d9ef64ecfe2a1Timo Sirainen mail_index_sync_rollback(&sync_ctx->index_sync_ctx);
bfa7ef85a07f07b7d2e72471a584689cfb6adc31Timo Sirainen pool_unref(sync_ctx->mail_keyword_pool);
bfa7ef85a07f07b7d2e72471a584689cfb6adc31Timo Sirainen pool_unref(sync_ctx->saved_keywords_pool);
bfa7ef85a07f07b7d2e72471a584689cfb6adc31Timo Sirainen str_free(&sync_ctx->header);
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainen str_free(&sync_ctx->from_line);
32d9a75612a5df455e4169b56538bb31dfe359e4Timo Sirainen array_free(&sync_ctx->mails);
32d9a75612a5df455e4169b56538bb31dfe359e4Timo Sirainen array_free(&sync_ctx->syncs);
32d9a75612a5df455e4169b56538bb31dfe359e4Timo Sirainen}
32d9a75612a5df455e4169b56538bb31dfe359e4Timo Sirainen
32d9a75612a5df455e4169b56538bb31dfe359e4Timo Sirainenstatic int mbox_sync_int(struct mbox_mailbox *mbox, enum mbox_sync_flags flags)
32d9a75612a5df455e4169b56538bb31dfe359e4Timo Sirainen{
32d9a75612a5df455e4169b56538bb31dfe359e4Timo Sirainen struct mail_index_sync_ctx *index_sync_ctx;
32d9a75612a5df455e4169b56538bb31dfe359e4Timo Sirainen struct mail_index_view *sync_view;
0b17b95357d5d73d941f1eb4ca9fc543bc510e42Timo Sirainen struct mail_index_transaction *trans;
04ab375449dd97eed50ada88dd0df2abab01cfeeTimo Sirainen struct mbox_sync_context sync_ctx;
04ab375449dd97eed50ada88dd0df2abab01cfeeTimo Sirainen enum mail_index_sync_flags sync_flags;
0b17b95357d5d73d941f1eb4ca9fc543bc510e42Timo Sirainen uint32_t seq;
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen uoff_t offset;
04ab375449dd97eed50ada88dd0df2abab01cfeeTimo Sirainen unsigned int lock_id = 0;
01f4ee4a0243f3fe9af763e1a540cd5cff0d63f5Timo Sirainen int ret, changed;
145ecefd208f5d7f6a52cb326a85f28d2154e217Timo Sirainen bool delay_writes;
d22301419109ed4a38351715e6760011421dadecTimo Sirainen
145ecefd208f5d7f6a52cb326a85f28d2154e217Timo Sirainen delay_writes = mbox->mbox_readonly ||
145ecefd208f5d7f6a52cb326a85f28d2154e217Timo Sirainen ((flags & MBOX_SYNC_REWRITE) == 0 &&
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen getenv("MBOX_LAZY_WRITES") != NULL);
04ab375449dd97eed50ada88dd0df2abab01cfeeTimo Sirainen
04ab375449dd97eed50ada88dd0df2abab01cfeeTimo Sirainen mbox->ibox.sync_last_check = ioloop_time;
04ab375449dd97eed50ada88dd0df2abab01cfeeTimo Sirainen
ca98892a6b8a30ffc1fe26fcf02c7d59e3204e7eTimo Sirainen if (!mbox->mbox_do_dirty_syncs)
145ecefd208f5d7f6a52cb326a85f28d2154e217Timo Sirainen flags |= MBOX_SYNC_UNDIRTY;
d22301419109ed4a38351715e6760011421dadecTimo Sirainen
145ecefd208f5d7f6a52cb326a85f28d2154e217Timo Sirainen if ((flags & MBOX_SYNC_LOCK_READING) != 0) {
145ecefd208f5d7f6a52cb326a85f28d2154e217Timo Sirainen if (mbox_lock(mbox, F_RDLCK, &lock_id) <= 0)
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen return -1;
04ab375449dd97eed50ada88dd0df2abab01cfeeTimo Sirainen }
04ab375449dd97eed50ada88dd0df2abab01cfeeTimo Sirainen
04ab375449dd97eed50ada88dd0df2abab01cfeeTimo Sirainen if ((flags & MBOX_SYNC_HEADER) != 0 ||
0b17b95357d5d73d941f1eb4ca9fc543bc510e42Timo Sirainen (flags & MBOX_SYNC_FORCE_SYNC) != 0)
32d9a75612a5df455e4169b56538bb31dfe359e4Timo Sirainen changed = 1;
0b17b95357d5d73d941f1eb4ca9fc543bc510e42Timo Sirainen else {
690bafa70767e3f6e98bbfd62ad4a26be2387ea9Timo Sirainen bool leave_dirty = (flags & MBOX_SYNC_UNDIRTY) == 0;
690bafa70767e3f6e98bbfd62ad4a26be2387ea9Timo Sirainen if ((changed = mbox_sync_has_changed(mbox, leave_dirty)) < 0) {
04ab375449dd97eed50ada88dd0df2abab01cfeeTimo Sirainen if ((flags & MBOX_SYNC_LOCK_READING) != 0)
de62ce819d59a529530da4b57be1b8d6dad13d6bTimo Sirainen (void)mbox_unlock(mbox, lock_id);
c0bfb67ba32064347bac3241f1aac9b8a809e2f1Timo Sirainen return -1;
c0bfb67ba32064347bac3241f1aac9b8a809e2f1Timo Sirainen }
c0bfb67ba32064347bac3241f1aac9b8a809e2f1Timo Sirainen }
c0bfb67ba32064347bac3241f1aac9b8a809e2f1Timo Sirainen
690bafa70767e3f6e98bbfd62ad4a26be2387ea9Timo Sirainen if ((flags & MBOX_SYNC_LOCK_READING) != 0) {
690bafa70767e3f6e98bbfd62ad4a26be2387ea9Timo Sirainen /* we just want to lock it for reading. if mbox hasn't been
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen modified don't do any syncing. */
690bafa70767e3f6e98bbfd62ad4a26be2387ea9Timo Sirainen if (!changed)
690bafa70767e3f6e98bbfd62ad4a26be2387ea9Timo Sirainen return 0;
690bafa70767e3f6e98bbfd62ad4a26be2387ea9Timo Sirainen
e05ea8311ae16687295048e88ca205dfe29fbcbfTimo Sirainen /* have to sync to make sure offsets have stayed the same */
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen (void)mbox_unlock(mbox, lock_id);
690bafa70767e3f6e98bbfd62ad4a26be2387ea9Timo Sirainen lock_id = 0;
690bafa70767e3f6e98bbfd62ad4a26be2387ea9Timo Sirainen }
0b17b95357d5d73d941f1eb4ca9fc543bc510e42Timo Sirainen
0b17b95357d5d73d941f1eb4ca9fc543bc510e42Timo Sirainen /* reopen input stream to make sure it has nothing buffered */
ccb70ccfd9a25e490aab46d15d9b8323ad9ea3bfTimo Sirainen mbox_file_close_stream(mbox);
ccb70ccfd9a25e490aab46d15d9b8323ad9ea3bfTimo Sirainen
022412398e56a8f31ef111cfd7271498d64af9a9Timo Sirainen__again:
ccb70ccfd9a25e490aab46d15d9b8323ad9ea3bfTimo Sirainen if (changed) {
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen /* we're most likely modifying the mbox while syncing, just
648d24583c1574441c4fa0331a90bd4d6e7996c5Timo Sirainen lock it for writing immediately. the mbox must be locked
648d24583c1574441c4fa0331a90bd4d6e7996c5Timo Sirainen before index syncing is started to avoid deadlocks, so we
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen don't have much choice either (well, easy ones anyway). */
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen int lock_type = mbox->mbox_readonly ? F_RDLCK : F_WRLCK;
ccb70ccfd9a25e490aab46d15d9b8323ad9ea3bfTimo Sirainen if (mbox_lock(mbox, lock_type, &lock_id) <= 0)
ccb70ccfd9a25e490aab46d15d9b8323ad9ea3bfTimo Sirainen return -1;
ccb70ccfd9a25e490aab46d15d9b8323ad9ea3bfTimo Sirainen }
73247459cf41eb1e5ae5bc61354db46d3b05ee75Timo Sirainen
73247459cf41eb1e5ae5bc61354db46d3b05ee75Timo Sirainen if ((flags & MBOX_SYNC_LAST_COMMIT) != 0) {
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen seq = mbox->ibox.commit_log_file_seq;
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen offset = mbox->ibox.commit_log_file_offset;
0b17b95357d5d73d941f1eb4ca9fc543bc510e42Timo Sirainen } else {
aa0647f2debf0d48d504a321186f66c85596aaf4Timo Sirainen seq = (uint32_t)-1;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen offset = (uoff_t)-1;
2d39dc1a453546892109b35c0d9770369011a13dTimo Sirainen }
dcd50ecbfe796bd76f2d63483c534cc0e4e94164Timo Sirainen
f140f88a5ab3e2194f214c11f9f418559e949c83Timo Sirainen sync_flags = 0;
ccb70ccfd9a25e490aab46d15d9b8323ad9ea3bfTimo Sirainen if (!mbox->ibox.keep_recent)
c000c8eca8f24b2a0c76393ec4bbf76a505a4983Timo Sirainen sync_flags |= MAIL_INDEX_SYNC_FLAG_DROP_RECENT;
f140f88a5ab3e2194f214c11f9f418559e949c83Timo Sirainen if ((flags & MBOX_SYNC_REWRITE) != 0)
f140f88a5ab3e2194f214c11f9f418559e949c83Timo Sirainen sync_flags |= MAIL_INDEX_SYNC_FLAG_FLUSH_DIRTY;
ccb70ccfd9a25e490aab46d15d9b8323ad9ea3bfTimo Sirainen ret = mail_index_sync_begin(mbox->ibox.index, &index_sync_ctx,
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen &sync_view, &trans, seq, offset,
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen sync_flags);
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen if (ret <= 0) {
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen if (ret < 0)
d252f81a2ff1bdd5439f9d2b3df715b70a4bcd3dTimo Sirainen mail_storage_set_index_error(&mbox->ibox);
d252f81a2ff1bdd5439f9d2b3df715b70a4bcd3dTimo Sirainen if (lock_id != 0)
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen (void)mbox_unlock(mbox, lock_id);
73247459cf41eb1e5ae5bc61354db46d3b05ee75Timo Sirainen return ret;
63a61b7a739ae0f3f520215137d9c50f94d0f34fTimo Sirainen }
63a61b7a739ae0f3f520215137d9c50f94d0f34fTimo Sirainen
63a61b7a739ae0f3f520215137d9c50f94d0f34fTimo Sirainen if (!changed && !mail_index_sync_have_more(index_sync_ctx)) {
6060b7c8edf8fce73470d0df6a2479b69b01c537Timo Sirainen /* nothing to do */
690bafa70767e3f6e98bbfd62ad4a26be2387ea9Timo Sirainen __nothing_to_do:
690bafa70767e3f6e98bbfd62ad4a26be2387ea9Timo Sirainen if (lock_id != 0)
690bafa70767e3f6e98bbfd62ad4a26be2387ea9Timo Sirainen (void)mbox_unlock(mbox, lock_id);
d9de52132072d80b8c268094b879c0ef5a108db3Timo Sirainen
690bafa70767e3f6e98bbfd62ad4a26be2387ea9Timo Sirainen /* index may need to do internal syncing though, so commit
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainen instead of rollbacking. */
73247459cf41eb1e5ae5bc61354db46d3b05ee75Timo Sirainen if (mail_index_sync_commit(&index_sync_ctx) < 0) {
345212e8f61ebf14ff4f80df26df9e655eb5121eTimo Sirainen mail_storage_set_index_error(&mbox->ibox);
63a61b7a739ae0f3f520215137d9c50f94d0f34fTimo Sirainen return -1;
345212e8f61ebf14ff4f80df26df9e655eb5121eTimo Sirainen }
f1901fd21906911f7be075c965ac882f6a87b4c3Timo Sirainen return 0;
d9de52132072d80b8c268094b879c0ef5a108db3Timo Sirainen }
d9de52132072d80b8c268094b879c0ef5a108db3Timo Sirainen
d9de52132072d80b8c268094b879c0ef5a108db3Timo Sirainen memset(&sync_ctx, 0, sizeof(sync_ctx));
d9de52132072d80b8c268094b879c0ef5a108db3Timo Sirainen sync_ctx.mbox = mbox;
d9de52132072d80b8c268094b879c0ef5a108db3Timo Sirainen
d9de52132072d80b8c268094b879c0ef5a108db3Timo Sirainen sync_ctx.hdr = mail_index_get_header(sync_view);
b66d803de86bfb411165b3465b0d9ef64ecfe2a1Timo Sirainen sync_ctx.from_line = str_new(default_pool, 256);
73247459cf41eb1e5ae5bc61354db46d3b05ee75Timo Sirainen sync_ctx.header = str_new(default_pool, 4096);
d9de52132072d80b8c268094b879c0ef5a108db3Timo Sirainen
d9de52132072d80b8c268094b879c0ef5a108db3Timo Sirainen sync_ctx.index_sync_ctx = index_sync_ctx;
5b8ae5496ae0b23e84f620bb0f85d7e87a5e11fdTimo Sirainen sync_ctx.sync_view = sync_view;
5b8ae5496ae0b23e84f620bb0f85d7e87a5e11fdTimo Sirainen sync_ctx.t = trans;
5b8ae5496ae0b23e84f620bb0f85d7e87a5e11fdTimo Sirainen sync_ctx.mail_keyword_pool =
5b8ae5496ae0b23e84f620bb0f85d7e87a5e11fdTimo Sirainen pool_alloconly_create("mbox keywords", 256);
5b8ae5496ae0b23e84f620bb0f85d7e87a5e11fdTimo Sirainen sync_ctx.saved_keywords_pool =
f2b79667fc7a8f7c2c72cad18bd71d49730e36f6Timo Sirainen pool_alloconly_create("mbox saved keywords", 4096);
7e0bb2b365cc38645313a3513fa79bd32d34b63cTimo Sirainen
d9de52132072d80b8c268094b879c0ef5a108db3Timo Sirainen /* make sure we've read the latest keywords in index */
d9de52132072d80b8c268094b879c0ef5a108db3Timo Sirainen (void)mail_index_get_keywords(mbox->ibox.index);
d9de52132072d80b8c268094b879c0ef5a108db3Timo Sirainen
d9de52132072d80b8c268094b879c0ef5a108db3Timo Sirainen i_array_init(&sync_ctx.mails, 64);
d9de52132072d80b8c268094b879c0ef5a108db3Timo Sirainen i_array_init(&sync_ctx.syncs, 32);
f140f88a5ab3e2194f214c11f9f418559e949c83Timo Sirainen
30975737820f5855e2c26d81b574ae5f03a05407Timo Sirainen sync_ctx.flags = flags;
73247459cf41eb1e5ae5bc61354db46d3b05ee75Timo Sirainen sync_ctx.delay_writes = delay_writes || sync_ctx.mbox->mbox_readonly;
30975737820f5855e2c26d81b574ae5f03a05407Timo Sirainen
30975737820f5855e2c26d81b574ae5f03a05407Timo Sirainen if (!changed && delay_writes) {
30975737820f5855e2c26d81b574ae5f03a05407Timo Sirainen /* if we have only flag changes, we don't need to open the
30975737820f5855e2c26d81b574ae5f03a05407Timo Sirainen mbox file */
73247459cf41eb1e5ae5bc61354db46d3b05ee75Timo Sirainen bool expunged;
30975737820f5855e2c26d81b574ae5f03a05407Timo Sirainen
c000c8eca8f24b2a0c76393ec4bbf76a505a4983Timo Sirainen if (mbox_sync_read_index_syncs(&sync_ctx, 1, &expunged) < 0)
c000c8eca8f24b2a0c76393ec4bbf76a505a4983Timo Sirainen return -1;
c4f76f390c75aac7f41492db4c858576fcab54d3Timo Sirainen if (sync_ctx.sync_rec.uid1 == 0) {
30975737820f5855e2c26d81b574ae5f03a05407Timo Sirainen sync_ctx.index_sync_ctx = NULL;
d9de52132072d80b8c268094b879c0ef5a108db3Timo Sirainen mbox_sync_context_free(&sync_ctx);
d9de52132072d80b8c268094b879c0ef5a108db3Timo Sirainen goto __nothing_to_do;
3f91e60401495a4046c73992fabaa5e77200a451Timo Sirainen }
2d39dc1a453546892109b35c0d9770369011a13dTimo Sirainen }
2d39dc1a453546892109b35c0d9770369011a13dTimo Sirainen
8f8315e4b4e27ead12dd1c3da65bf4dee3762f18Timo Sirainen if (lock_id == 0) {
d22301419109ed4a38351715e6760011421dadecTimo Sirainen /* ok, we have something to do but no locks. we'll have to
fa3be6b0d9d9fc0264a8434e17e26ad26c739daeTimo Sirainen restart syncing to avoid deadlocking. */
0b17b95357d5d73d941f1eb4ca9fc543bc510e42Timo Sirainen mbox_sync_context_free(&sync_ctx);
0b17b95357d5d73d941f1eb4ca9fc543bc510e42Timo Sirainen changed = 1;
1f1ee8db68d9ae1604350801cd8dc33ebe29fe8aTimo Sirainen goto __again;
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen }
0b17b95357d5d73d941f1eb4ca9fc543bc510e42Timo Sirainen
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen if (mbox_file_open_stream(mbox) < 0) {
4145cbac82bfc0c8bfeceeca0ef841700117930cTimo Sirainen mbox_sync_context_free(&sync_ctx);
1d3f7c1278168d5b1cbfa9a2cc9929a0909056b4Timo Sirainen (void)mbox_unlock(mbox, lock_id);
1d3f7c1278168d5b1cbfa9a2cc9929a0909056b4Timo Sirainen return -1;
1d3f7c1278168d5b1cbfa9a2cc9929a0909056b4Timo Sirainen }
1d3f7c1278168d5b1cbfa9a2cc9929a0909056b4Timo Sirainen
1d3f7c1278168d5b1cbfa9a2cc9929a0909056b4Timo Sirainen sync_ctx.file_input = sync_ctx.mbox->mbox_file_stream;
1d3f7c1278168d5b1cbfa9a2cc9929a0909056b4Timo Sirainen sync_ctx.input = sync_ctx.mbox->mbox_stream;
88553367d677170a4b703b9d52aac9eabf91c656Timo Sirainen sync_ctx.write_fd = sync_ctx.mbox->mbox_lock_type != F_WRLCK ? -1 :
d9de52132072d80b8c268094b879c0ef5a108db3Timo Sirainen sync_ctx.mbox->mbox_fd;
7e0bb2b365cc38645313a3513fa79bd32d34b63cTimo Sirainen
4d10cf8c7879ccd377e7fb136913b2a258ba8d93Timo Sirainen ret = mbox_sync_do(&sync_ctx, flags);
4d10cf8c7879ccd377e7fb136913b2a258ba8d93Timo Sirainen
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen if (ret < 0)
1f1ee8db68d9ae1604350801cd8dc33ebe29fe8aTimo Sirainen mail_index_sync_rollback(&index_sync_ctx);
4d10cf8c7879ccd377e7fb136913b2a258ba8d93Timo Sirainen else if (mail_index_sync_commit(&index_sync_ctx) < 0) {
4d10cf8c7879ccd377e7fb136913b2a258ba8d93Timo Sirainen mail_storage_set_index_error(&mbox->ibox);
88553367d677170a4b703b9d52aac9eabf91c656Timo Sirainen ret = -1;
88553367d677170a4b703b9d52aac9eabf91c656Timo Sirainen } else {
88553367d677170a4b703b9d52aac9eabf91c656Timo Sirainen mbox->ibox.commit_log_file_seq = 0;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen mbox->ibox.commit_log_file_offset = 0;
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen }
ced118ac5caf6fe83d34339c2c65c63b2aa768acTimo Sirainen sync_ctx.t = NULL;
4145cbac82bfc0c8bfeceeca0ef841700117930cTimo Sirainen sync_ctx.index_sync_ctx = NULL;
de4288b7369945a31c4001add9445fd0195a358dTimo Sirainen
b20fb5b1df9d604a7541f5118fc5b4b466d211efTimo Sirainen if (sync_ctx.base_uid_last != sync_ctx.next_uid-1 &&
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen ret == 0 && !sync_ctx.delay_writes &&
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen sync_ctx.base_uid_last_offset != 0) {
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen /* Rewrite uid_last in X-IMAPbase header if we've seen it
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen (ie. the file isn't empty) */
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen ret = mbox_rewrite_base_uid_last(&sync_ctx);
aa0647f2debf0d48d504a321186f66c85596aaf4Timo Sirainen }
2e937ed8585299b2e879a28314902a5f644813d2Timo Sirainen
76e3062a60f585a638e0933bb71d3c8c9b0d8e2aTimo Sirainen if (ret == 0 && mbox->mbox_fd != -1 && mbox->ibox.keep_recent) {
343a527f805ca5cce78496b959d6def70e5d0cd4Timo Sirainen /* try to set atime back to its original value */
343a527f805ca5cce78496b959d6def70e5d0cd4Timo Sirainen struct utimbuf buf;
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen struct stat st;
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen
d22301419109ed4a38351715e6760011421dadecTimo Sirainen if (fstat(mbox->mbox_fd, &st) < 0)
33ae95df45c9b5ec51332a6b39eb5322038686b9Timo Sirainen mbox_set_syscall_error(mbox, "fstat()");
91dca97b367c54a139c268b56a0c67f564bd9197Timo Sirainen else {
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen buf.modtime = st.st_mtime;
ccb70ccfd9a25e490aab46d15d9b8323ad9ea3bfTimo Sirainen buf.actime = sync_ctx.orig_atime;
f140f88a5ab3e2194f214c11f9f418559e949c83Timo Sirainen if (utime(mbox->path, &buf) < 0)
f140f88a5ab3e2194f214c11f9f418559e949c83Timo Sirainen mbox_set_syscall_error(mbox, "utime()");
ccb70ccfd9a25e490aab46d15d9b8323ad9ea3bfTimo Sirainen }
022412398e56a8f31ef111cfd7271498d64af9a9Timo Sirainen }
d22301419109ed4a38351715e6760011421dadecTimo Sirainen
022412398e56a8f31ef111cfd7271498d64af9a9Timo Sirainen i_assert(lock_id != 0);
022412398e56a8f31ef111cfd7271498d64af9a9Timo Sirainen
ccb70ccfd9a25e490aab46d15d9b8323ad9ea3bfTimo Sirainen if (mbox->mbox_lock_type != F_RDLCK) {
ccb70ccfd9a25e490aab46d15d9b8323ad9ea3bfTimo Sirainen /* drop to read lock */
ccb70ccfd9a25e490aab46d15d9b8323ad9ea3bfTimo Sirainen unsigned int read_lock_id = 0;
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainen
022412398e56a8f31ef111cfd7271498d64af9a9Timo Sirainen if (mbox_lock(mbox, F_RDLCK, &read_lock_id) <= 0)
ccb70ccfd9a25e490aab46d15d9b8323ad9ea3bfTimo Sirainen ret = -1;
b08b33d1f5ce3721dc2d83586c9cb0ca141331fdTimo Sirainen else {
30975737820f5855e2c26d81b574ae5f03a05407Timo Sirainen if (mbox_unlock(mbox, lock_id) < 0)
30975737820f5855e2c26d81b574ae5f03a05407Timo Sirainen ret = -1;
022412398e56a8f31ef111cfd7271498d64af9a9Timo Sirainen lock_id = read_lock_id;
ccb70ccfd9a25e490aab46d15d9b8323ad9ea3bfTimo Sirainen }
ccb70ccfd9a25e490aab46d15d9b8323ad9ea3bfTimo Sirainen }
7e0bb2b365cc38645313a3513fa79bd32d34b63cTimo Sirainen
ccb70ccfd9a25e490aab46d15d9b8323ad9ea3bfTimo Sirainen if ((flags & MBOX_SYNC_LOCK_READING) == 0) {
ccb70ccfd9a25e490aab46d15d9b8323ad9ea3bfTimo Sirainen if (mbox_unlock(mbox, lock_id) < 0)
ccb70ccfd9a25e490aab46d15d9b8323ad9ea3bfTimo Sirainen ret = -1;
73247459cf41eb1e5ae5bc61354db46d3b05ee75Timo Sirainen }
ccb70ccfd9a25e490aab46d15d9b8323ad9ea3bfTimo Sirainen
ccb70ccfd9a25e490aab46d15d9b8323ad9ea3bfTimo Sirainen mbox_sync_context_free(&sync_ctx);
ccb70ccfd9a25e490aab46d15d9b8323ad9ea3bfTimo Sirainen return ret;
ccb70ccfd9a25e490aab46d15d9b8323ad9ea3bfTimo Sirainen}
7e0bb2b365cc38645313a3513fa79bd32d34b63cTimo Sirainen
ccb70ccfd9a25e490aab46d15d9b8323ad9ea3bfTimo Sirainenint mbox_sync(struct mbox_mailbox *mbox, enum mbox_sync_flags flags)
ccb70ccfd9a25e490aab46d15d9b8323ad9ea3bfTimo Sirainen{
ccb70ccfd9a25e490aab46d15d9b8323ad9ea3bfTimo Sirainen int ret;
ccb70ccfd9a25e490aab46d15d9b8323ad9ea3bfTimo Sirainen
ccb70ccfd9a25e490aab46d15d9b8323ad9ea3bfTimo Sirainen mbox->syncing = TRUE;
ccb70ccfd9a25e490aab46d15d9b8323ad9ea3bfTimo Sirainen ret = mbox_sync_int(mbox, flags);
ccb70ccfd9a25e490aab46d15d9b8323ad9ea3bfTimo Sirainen mbox->syncing = FALSE;
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen if (mbox->ibox.box.v.sync_notify != NULL)
d6e2b2761c8e0b6923c883fb2ead2665ee954be5Timo Sirainen mbox->ibox.box.v.sync_notify(&mbox->ibox.box, 0, 0);
b5e6f6f27c1461f0f9f202615eeb738a645188c3Timo Sirainen return ret;
7a6b45405fb1544ac476e6eb1402a70cc1ddcdcfTimo Sirainen}
de4288b7369945a31c4001add9445fd0195a358dTimo Sirainen
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainenstruct mailbox_sync_context *
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainenmbox_storage_sync_init(struct mailbox *box, enum mailbox_sync_flags flags)
aa0647f2debf0d48d504a321186f66c85596aaf4Timo Sirainen{
aa0647f2debf0d48d504a321186f66c85596aaf4Timo Sirainen struct mbox_mailbox *mbox = (struct mbox_mailbox *)box;
1f1ee8db68d9ae1604350801cd8dc33ebe29fe8aTimo Sirainen enum mbox_sync_flags mbox_sync_flags = 0;
dda2c506c8fc8ac2f88272de4523ded42baa0aa0Timo Sirainen int ret = 0;
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen
b3febb0933fdce10394d25093e23ce0a5aadddd3Timo Sirainen if (!box->opened)
ccb70ccfd9a25e490aab46d15d9b8323ad9ea3bfTimo Sirainen index_storage_mailbox_open(&mbox->ibox);
b3febb0933fdce10394d25093e23ce0a5aadddd3Timo Sirainen
ced118ac5caf6fe83d34339c2c65c63b2aa768acTimo Sirainen if ((flags & MAILBOX_SYNC_FLAG_FAST) == 0 ||
f140f88a5ab3e2194f214c11f9f418559e949c83Timo Sirainen mbox->ibox.sync_last_check + MAILBOX_FULL_SYNC_INTERVAL <=
205debb6e5882687f43a98fec7bb577173b2fe28Timo Sirainen ioloop_time) {
205debb6e5882687f43a98fec7bb577173b2fe28Timo Sirainen if ((flags & MAILBOX_SYNC_FLAG_FULL_READ) != 0 &&
205debb6e5882687f43a98fec7bb577173b2fe28Timo Sirainen !mbox->mbox_very_dirty_syncs)
9d0e1fa945103f2875cdf6d18b2013809f566ea7Timo Sirainen mbox_sync_flags |= MBOX_SYNC_UNDIRTY;
9d0e1fa945103f2875cdf6d18b2013809f566ea7Timo Sirainen if ((flags & MAILBOX_SYNC_FLAG_FULL_WRITE) != 0)
9d0e1fa945103f2875cdf6d18b2013809f566ea7Timo Sirainen mbox_sync_flags |= MBOX_SYNC_REWRITE;
9d0e1fa945103f2875cdf6d18b2013809f566ea7Timo Sirainen ret = mbox_sync(mbox, mbox_sync_flags);
9d0e1fa945103f2875cdf6d18b2013809f566ea7Timo Sirainen }
9d0e1fa945103f2875cdf6d18b2013809f566ea7Timo Sirainen
9d0e1fa945103f2875cdf6d18b2013809f566ea7Timo Sirainen return index_mailbox_sync_init(box, flags, ret < 0);
9d0e1fa945103f2875cdf6d18b2013809f566ea7Timo Sirainen}
ca98892a6b8a30ffc1fe26fcf02c7d59e3204e7eTimo Sirainen