maildir-sync-index.c revision 3759cb2dfce3b479a59e2f62ee0cc9ddd4a85924
02c335c23bf5fa225a467c19f2c063fb0dc7b8c3Timo Sirainen/* Copyright (c) 2007 Dovecot authors, see the included COPYING file */
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainen
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainen#include "lib.h"
498eecf19b1b408d5321cb048697744d7cee90b2Timo Sirainen#include "ioloop.h"
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainen#include "array.h"
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainen#include "maildir-storage.h"
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainen#include "index-sync-changes.h"
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainen#include "maildir-uidlist.h"
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainen#include "maildir-keywords.h"
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainen#include "maildir-filename.h"
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainen#include "maildir-sync.h"
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainen
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainen#include <stdio.h>
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainen#include <unistd.h>
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainen
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainenstruct maildir_index_sync_context {
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainen struct maildir_mailbox *mbox;
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainen struct maildir_sync_context *maildir_sync_ctx;
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainen
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainen struct mail_index_view *view;
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainen struct mail_index_sync_ctx *sync_ctx;
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainen struct maildir_keywords_sync_ctx *keywords_sync_ctx;
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainen struct mail_index_transaction *trans;
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainen
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainen struct maildir_uidlist_sync_ctx *uidlist_sync_ctx;
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainen struct index_sync_changes_context *sync_changes;
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainen enum mail_flags flags;
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainen ARRAY_TYPE(keyword_indexes) keywords;
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainen
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainen uint32_t seq, uid;
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainen
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainen bool changed;
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainen};
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainen
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainenstruct maildir_keywords_sync_ctx *
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainenmaildir_sync_get_keywords_sync_ctx(struct maildir_index_sync_context *ctx)
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainen{
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainen return ctx->keywords_sync_ctx;
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainen}
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainen
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainenstatic int maildir_expunge(struct maildir_mailbox *mbox, const char *path,
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainen struct maildir_index_sync_context *ctx)
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainen{
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainen struct mailbox *box = &mbox->ibox.box;
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainen
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainen if (unlink(path) == 0) {
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainen if (box->v.sync_notify != NULL) {
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainen box->v.sync_notify(box, ctx->uid,
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainen MAILBOX_SYNC_TYPE_EXPUNGE);
23bdbb7b1831785c6ba6df190f6369da882d2b9dTimo Sirainen }
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainen mail_index_expunge(ctx->trans, ctx->seq);
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainen ctx->changed = TRUE;
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainen return 1;
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainen }
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainen if (errno == ENOENT)
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainen return 0;
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainen
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainen mail_storage_set_critical(&mbox->storage->storage,
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainen "unlink(%s) failed: %m", path);
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainen return -1;
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainen}
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainen
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainenstatic int maildir_sync_flags(struct maildir_mailbox *mbox, const char *path,
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainen struct maildir_index_sync_context *ctx)
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainen{
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainen struct mailbox *box = &mbox->ibox.box;
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainen const char *dir, *fname, *newfname, *newpath;
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainen enum mailbox_sync_type sync_type;
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainen uint8_t flags8;
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainen
aeaf818613081b9a9ff8c9fd4306e8dbfab4fd86Timo Sirainen fname = strrchr(path, '/');
aeaf818613081b9a9ff8c9fd4306e8dbfab4fd86Timo Sirainen i_assert(fname != NULL);
aeaf818613081b9a9ff8c9fd4306e8dbfab4fd86Timo Sirainen fname++;
aeaf818613081b9a9ff8c9fd4306e8dbfab4fd86Timo Sirainen dir = t_strdup_until(path, fname);
aeaf818613081b9a9ff8c9fd4306e8dbfab4fd86Timo Sirainen
aeaf818613081b9a9ff8c9fd4306e8dbfab4fd86Timo Sirainen /* get the current flags and keywords */
aeaf818613081b9a9ff8c9fd4306e8dbfab4fd86Timo Sirainen maildir_filename_get_flags(ctx->keywords_sync_ctx,
aeaf818613081b9a9ff8c9fd4306e8dbfab4fd86Timo Sirainen fname, &ctx->flags, &ctx->keywords);
aeaf818613081b9a9ff8c9fd4306e8dbfab4fd86Timo Sirainen
aeaf818613081b9a9ff8c9fd4306e8dbfab4fd86Timo Sirainen /* apply changes */
aeaf818613081b9a9ff8c9fd4306e8dbfab4fd86Timo Sirainen flags8 = ctx->flags;
aeaf818613081b9a9ff8c9fd4306e8dbfab4fd86Timo Sirainen index_sync_changes_apply(ctx->sync_changes, NULL,
aeaf818613081b9a9ff8c9fd4306e8dbfab4fd86Timo Sirainen &flags8, &ctx->keywords, &sync_type);
aeaf818613081b9a9ff8c9fd4306e8dbfab4fd86Timo Sirainen ctx->flags = flags8;
aeaf818613081b9a9ff8c9fd4306e8dbfab4fd86Timo Sirainen
aeaf818613081b9a9ff8c9fd4306e8dbfab4fd86Timo Sirainen /* and try renaming with the new name */
aeaf818613081b9a9ff8c9fd4306e8dbfab4fd86Timo Sirainen newfname = maildir_filename_set_flags(ctx->keywords_sync_ctx, fname,
aeaf818613081b9a9ff8c9fd4306e8dbfab4fd86Timo Sirainen ctx->flags, &ctx->keywords);
aeaf818613081b9a9ff8c9fd4306e8dbfab4fd86Timo Sirainen newpath = t_strconcat(dir, newfname, NULL);
aeaf818613081b9a9ff8c9fd4306e8dbfab4fd86Timo Sirainen if (rename(path, newpath) == 0) {
aeaf818613081b9a9ff8c9fd4306e8dbfab4fd86Timo Sirainen if (box->v.sync_notify != NULL)
aeaf818613081b9a9ff8c9fd4306e8dbfab4fd86Timo Sirainen box->v.sync_notify(box, ctx->uid, sync_type);
aeaf818613081b9a9ff8c9fd4306e8dbfab4fd86Timo Sirainen ctx->changed = TRUE;
aeaf818613081b9a9ff8c9fd4306e8dbfab4fd86Timo Sirainen return 1;
aeaf818613081b9a9ff8c9fd4306e8dbfab4fd86Timo Sirainen }
aeaf818613081b9a9ff8c9fd4306e8dbfab4fd86Timo Sirainen if (errno == ENOENT)
11d72d764c104b4f1a8c44ec8a5fee420517645bTimo Sirainen return 0;
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainen
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainen if (!ENOSPACE(errno) && errno != EACCES) {
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainen mail_storage_set_critical(box->storage,
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainen "rename(%s, %s) failed: %m", path, newpath);
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainen }
11d72d764c104b4f1a8c44ec8a5fee420517645bTimo Sirainen return -1;
498eecf19b1b408d5321cb048697744d7cee90b2Timo Sirainen}
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainen
12e5ac049bd74f8b98d9dc62adcb0bf3217beef6Martti Rannanjärvistatic void maildir_handle_uid_insertion(struct maildir_index_sync_context *ctx,
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainen enum maildir_uidlist_rec_flag uflags,
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainen const char *filename, uint32_t uid)
11d72d764c104b4f1a8c44ec8a5fee420517645bTimo Sirainen{
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainen int ret;
11d72d764c104b4f1a8c44ec8a5fee420517645bTimo Sirainen
498eecf19b1b408d5321cb048697744d7cee90b2Timo Sirainen if ((uflags & MAILDIR_UIDLIST_REC_FLAG_NONSYNCED) != 0) {
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainen /* partial syncing */
11d72d764c104b4f1a8c44ec8a5fee420517645bTimo Sirainen return;
498eecf19b1b408d5321cb048697744d7cee90b2Timo Sirainen }
498eecf19b1b408d5321cb048697744d7cee90b2Timo Sirainen
498eecf19b1b408d5321cb048697744d7cee90b2Timo Sirainen /* most likely a race condition: we read the maildir, then someone else
498eecf19b1b408d5321cb048697744d7cee90b2Timo Sirainen expunged messages and committed changes to index. so, this message
498eecf19b1b408d5321cb048697744d7cee90b2Timo Sirainen shouldn't actually exist. */
498eecf19b1b408d5321cb048697744d7cee90b2Timo Sirainen if ((uflags & MAILDIR_UIDLIST_REC_FLAG_RACING) == 0) {
d4488f314d0c799c5f5b8a7890e17eef868f7a2cMartti Rannanjärvi /* mark it racy and check in next sync */
498eecf19b1b408d5321cb048697744d7cee90b2Timo Sirainen ctx->mbox->maildir_hdr.cur_check_time = 0;
498eecf19b1b408d5321cb048697744d7cee90b2Timo Sirainen maildir_uidlist_add_flags(ctx->mbox->uidlist, filename,
498eecf19b1b408d5321cb048697744d7cee90b2Timo Sirainen MAILDIR_UIDLIST_REC_FLAG_RACING);
11d72d764c104b4f1a8c44ec8a5fee420517645bTimo Sirainen return;
12e5ac049bd74f8b98d9dc62adcb0bf3217beef6Martti Rannanjärvi }
498eecf19b1b408d5321cb048697744d7cee90b2Timo Sirainen
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainen if (ctx->uidlist_sync_ctx == NULL) {
11d72d764c104b4f1a8c44ec8a5fee420517645bTimo Sirainen ret = maildir_uidlist_sync_init(ctx->mbox->uidlist,
11d72d764c104b4f1a8c44ec8a5fee420517645bTimo Sirainen MAILDIR_UIDLIST_SYNC_PARTIAL |
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainen MAILDIR_UIDLIST_SYNC_KEEP_STATE,
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainen &ctx->uidlist_sync_ctx);
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainen i_assert(ret > 0);
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainen }
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainen
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainen uflags &= MAILDIR_UIDLIST_REC_FLAG_NEW_DIR;
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainen maildir_uidlist_sync_remove(ctx->uidlist_sync_ctx, filename);
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainen ret = maildir_uidlist_sync_next(ctx->uidlist_sync_ctx,
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainen filename, uflags);
5f237cf1915127fe143ac4c1d3cb4d1139f3b97dTimo Sirainen i_assert(ret > 0);
5f237cf1915127fe143ac4c1d3cb4d1139f3b97dTimo Sirainen
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainen /* give the new UID to it immediately */
12e5ac049bd74f8b98d9dc62adcb0bf3217beef6Martti Rannanjärvi maildir_uidlist_sync_finish(ctx->uidlist_sync_ctx);
11d72d764c104b4f1a8c44ec8a5fee420517645bTimo Sirainen
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainen i_warning("Maildir %s: Expunged message reappeared, giving a new UID "
11d72d764c104b4f1a8c44ec8a5fee420517645bTimo Sirainen "(old uid=%u, file=%s)", ctx->mbox->path, uid, filename);
11d72d764c104b4f1a8c44ec8a5fee420517645bTimo Sirainen}
11d72d764c104b4f1a8c44ec8a5fee420517645bTimo Sirainen
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainenint maildir_sync_index_begin(struct maildir_mailbox *mbox,
5f237cf1915127fe143ac4c1d3cb4d1139f3b97dTimo Sirainen struct maildir_sync_context *maildir_sync_ctx,
11d72d764c104b4f1a8c44ec8a5fee420517645bTimo Sirainen struct maildir_index_sync_context **ctx_r)
11d72d764c104b4f1a8c44ec8a5fee420517645bTimo Sirainen{
11d72d764c104b4f1a8c44ec8a5fee420517645bTimo Sirainen struct maildir_index_sync_context *ctx;
11d72d764c104b4f1a8c44ec8a5fee420517645bTimo Sirainen struct mail_index_sync_ctx *sync_ctx;
11d72d764c104b4f1a8c44ec8a5fee420517645bTimo Sirainen struct mail_index_view *view;
11d72d764c104b4f1a8c44ec8a5fee420517645bTimo Sirainen struct mail_index_transaction *trans;
11d72d764c104b4f1a8c44ec8a5fee420517645bTimo Sirainen enum mail_index_sync_flags sync_flags;
11d72d764c104b4f1a8c44ec8a5fee420517645bTimo Sirainen
5f237cf1915127fe143ac4c1d3cb4d1139f3b97dTimo Sirainen sync_flags = 0;
5f237cf1915127fe143ac4c1d3cb4d1139f3b97dTimo Sirainen /* don't drop recent messages if we're saving messages */
11d72d764c104b4f1a8c44ec8a5fee420517645bTimo Sirainen if (!mbox->ibox.keep_recent && maildir_sync_ctx != NULL)
12e5ac049bd74f8b98d9dc62adcb0bf3217beef6Martti Rannanjärvi sync_flags |= MAIL_INDEX_SYNC_FLAG_DROP_RECENT;
11d72d764c104b4f1a8c44ec8a5fee420517645bTimo Sirainen
11d72d764c104b4f1a8c44ec8a5fee420517645bTimo Sirainen if (mail_index_sync_begin(mbox->ibox.index, &sync_ctx, &view, &trans,
11d72d764c104b4f1a8c44ec8a5fee420517645bTimo Sirainen sync_flags) < 0) {
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainen mail_storage_set_index_error(&mbox->ibox);
11d72d764c104b4f1a8c44ec8a5fee420517645bTimo Sirainen return -1;
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainen }
39025a2dabfcfaeee3790988b9ea00d19887a3d3Timo Sirainen
7d800c558b4a40f11748d4ebfc2bf89eb743f03cTimo Sirainen ctx = i_new(struct maildir_index_sync_context, 1);
7d800c558b4a40f11748d4ebfc2bf89eb743f03cTimo Sirainen ctx->mbox = mbox;
7d800c558b4a40f11748d4ebfc2bf89eb743f03cTimo Sirainen ctx->maildir_sync_ctx = maildir_sync_ctx;
7d800c558b4a40f11748d4ebfc2bf89eb743f03cTimo Sirainen ctx->sync_ctx = sync_ctx;
7d800c558b4a40f11748d4ebfc2bf89eb743f03cTimo Sirainen ctx->view = view;
7d800c558b4a40f11748d4ebfc2bf89eb743f03cTimo Sirainen ctx->trans = trans;
7d800c558b4a40f11748d4ebfc2bf89eb743f03cTimo Sirainen ctx->keywords_sync_ctx =
7d800c558b4a40f11748d4ebfc2bf89eb743f03cTimo Sirainen maildir_keywords_sync_init(mbox->keywords, mbox->ibox.index);
7d800c558b4a40f11748d4ebfc2bf89eb743f03cTimo Sirainen
7d800c558b4a40f11748d4ebfc2bf89eb743f03cTimo Sirainen ctx->sync_changes = index_sync_changes_init(&mbox->ibox, ctx->sync_ctx,
7d800c558b4a40f11748d4ebfc2bf89eb743f03cTimo Sirainen ctx->view, ctx->trans,
7d800c558b4a40f11748d4ebfc2bf89eb743f03cTimo Sirainen mbox->ibox.readonly);
7d800c558b4a40f11748d4ebfc2bf89eb743f03cTimo Sirainen
7d800c558b4a40f11748d4ebfc2bf89eb743f03cTimo Sirainen *ctx_r = ctx;
7d800c558b4a40f11748d4ebfc2bf89eb743f03cTimo Sirainen return 0;
7d800c558b4a40f11748d4ebfc2bf89eb743f03cTimo Sirainen}
7d800c558b4a40f11748d4ebfc2bf89eb743f03cTimo Sirainen
7d800c558b4a40f11748d4ebfc2bf89eb743f03cTimo Sirainenint maildir_sync_index_finish(struct maildir_index_sync_context **_ctx,
7d800c558b4a40f11748d4ebfc2bf89eb743f03cTimo Sirainen bool failed, bool cancel)
7d800c558b4a40f11748d4ebfc2bf89eb743f03cTimo Sirainen{
7d800c558b4a40f11748d4ebfc2bf89eb743f03cTimo Sirainen struct maildir_index_sync_context *ctx = *_ctx;
7d800c558b4a40f11748d4ebfc2bf89eb743f03cTimo Sirainen struct maildir_mailbox *mbox = ctx->mbox;
7d800c558b4a40f11748d4ebfc2bf89eb743f03cTimo Sirainen int ret = failed ? -1 : 0;
7d800c558b4a40f11748d4ebfc2bf89eb743f03cTimo Sirainen
7d800c558b4a40f11748d4ebfc2bf89eb743f03cTimo Sirainen *_ctx = NULL;
7d800c558b4a40f11748d4ebfc2bf89eb743f03cTimo Sirainen
7d800c558b4a40f11748d4ebfc2bf89eb743f03cTimo Sirainen if (ret < 0 || cancel)
12e5ac049bd74f8b98d9dc62adcb0bf3217beef6Martti Rannanjärvi mail_index_sync_rollback(&ctx->sync_ctx);
7d800c558b4a40f11748d4ebfc2bf89eb743f03cTimo Sirainen else {
7d800c558b4a40f11748d4ebfc2bf89eb743f03cTimo Sirainen /* Set syncing_commit=TRUE so that if any sync callbacks try
aeaf818613081b9a9ff8c9fd4306e8dbfab4fd86Timo Sirainen to access mails which got lost (eg. expunge callback trying
aeaf818613081b9a9ff8c9fd4306e8dbfab4fd86Timo Sirainen to open the file which was just unlinked) we don't try to
aeaf818613081b9a9ff8c9fd4306e8dbfab4fd86Timo Sirainen start a second index sync and crash. */
f148466c7b648669b99bf20c651ae7fc81d28659Timo Sirainen mbox->syncing_commit = TRUE;
f148466c7b648669b99bf20c651ae7fc81d28659Timo Sirainen if (mail_index_sync_commit(&ctx->sync_ctx) < 0) {
f148466c7b648669b99bf20c651ae7fc81d28659Timo Sirainen mail_storage_set_index_error(&mbox->ibox);
aeaf818613081b9a9ff8c9fd4306e8dbfab4fd86Timo Sirainen ret = -1;
7d800c558b4a40f11748d4ebfc2bf89eb743f03cTimo Sirainen } else {
7d800c558b4a40f11748d4ebfc2bf89eb743f03cTimo Sirainen mbox->ibox.commit_log_file_seq = 0;
7d800c558b4a40f11748d4ebfc2bf89eb743f03cTimo Sirainen mbox->ibox.commit_log_file_offset = 0;
aeaf818613081b9a9ff8c9fd4306e8dbfab4fd86Timo Sirainen }
7d800c558b4a40f11748d4ebfc2bf89eb743f03cTimo Sirainen mbox->syncing_commit = FALSE;
7d800c558b4a40f11748d4ebfc2bf89eb743f03cTimo Sirainen }
7d800c558b4a40f11748d4ebfc2bf89eb743f03cTimo Sirainen
aeaf818613081b9a9ff8c9fd4306e8dbfab4fd86Timo Sirainen maildir_keywords_sync_deinit(&ctx->keywords_sync_ctx);
7d800c558b4a40f11748d4ebfc2bf89eb743f03cTimo Sirainen index_sync_changes_deinit(&ctx->sync_changes);
7d800c558b4a40f11748d4ebfc2bf89eb743f03cTimo Sirainen i_free(ctx);
7d800c558b4a40f11748d4ebfc2bf89eb743f03cTimo Sirainen return ret;
aeaf818613081b9a9ff8c9fd4306e8dbfab4fd86Timo Sirainen}
7d800c558b4a40f11748d4ebfc2bf89eb743f03cTimo Sirainen
7d800c558b4a40f11748d4ebfc2bf89eb743f03cTimo Sirainenstatic bool
7d800c558b4a40f11748d4ebfc2bf89eb743f03cTimo Sirainenmaildir_index_header_has_changed(const struct maildir_index_header *old_hdr,
7d800c558b4a40f11748d4ebfc2bf89eb743f03cTimo Sirainen const struct maildir_index_header *new_hdr)
7d800c558b4a40f11748d4ebfc2bf89eb743f03cTimo Sirainen{
7d800c558b4a40f11748d4ebfc2bf89eb743f03cTimo Sirainen#define DIR_DELAYED_REFRESH(hdr, name) \
7d800c558b4a40f11748d4ebfc2bf89eb743f03cTimo Sirainen ((hdr)->name ## _check_time <= \
7d800c558b4a40f11748d4ebfc2bf89eb743f03cTimo Sirainen (hdr)->name ## _mtime + MAILDIR_SYNC_SECS)
7d800c558b4a40f11748d4ebfc2bf89eb743f03cTimo Sirainen
aeaf818613081b9a9ff8c9fd4306e8dbfab4fd86Timo Sirainen if (old_hdr->new_mtime != new_hdr->new_mtime ||
7d800c558b4a40f11748d4ebfc2bf89eb743f03cTimo Sirainen old_hdr->cur_mtime != new_hdr->cur_mtime ||
7d800c558b4a40f11748d4ebfc2bf89eb743f03cTimo Sirainen old_hdr->new_mtime_nsecs != new_hdr->new_mtime_nsecs ||
7d800c558b4a40f11748d4ebfc2bf89eb743f03cTimo Sirainen old_hdr->cur_mtime_nsecs != new_hdr->cur_mtime_nsecs)
7d800c558b4a40f11748d4ebfc2bf89eb743f03cTimo Sirainen return TRUE;
7d800c558b4a40f11748d4ebfc2bf89eb743f03cTimo Sirainen
6df4a174b4cbdc439ed435a0cdc71d4a0126d54aTimo Sirainen return DIR_DELAYED_REFRESH(old_hdr, new) !=
6df4a174b4cbdc439ed435a0cdc71d4a0126d54aTimo Sirainen DIR_DELAYED_REFRESH(new_hdr, new) ||
6df4a174b4cbdc439ed435a0cdc71d4a0126d54aTimo Sirainen DIR_DELAYED_REFRESH(old_hdr, cur) !=
6df4a174b4cbdc439ed435a0cdc71d4a0126d54aTimo Sirainen DIR_DELAYED_REFRESH(new_hdr, cur);
6df4a174b4cbdc439ed435a0cdc71d4a0126d54aTimo Sirainen}
6df4a174b4cbdc439ed435a0cdc71d4a0126d54aTimo Sirainen
6df4a174b4cbdc439ed435a0cdc71d4a0126d54aTimo Sirainenstatic void
6df4a174b4cbdc439ed435a0cdc71d4a0126d54aTimo Sirainenmaildir_index_update_ext_header(struct maildir_mailbox *mbox,
6df4a174b4cbdc439ed435a0cdc71d4a0126d54aTimo Sirainen struct mail_index_transaction *trans)
6df4a174b4cbdc439ed435a0cdc71d4a0126d54aTimo Sirainen{
6df4a174b4cbdc439ed435a0cdc71d4a0126d54aTimo Sirainen const void *data;
6df4a174b4cbdc439ed435a0cdc71d4a0126d54aTimo Sirainen size_t data_size;
6df4a174b4cbdc439ed435a0cdc71d4a0126d54aTimo Sirainen
6df4a174b4cbdc439ed435a0cdc71d4a0126d54aTimo Sirainen mail_index_get_header_ext(mbox->ibox.view, mbox->maildir_ext_id,
6df4a174b4cbdc439ed435a0cdc71d4a0126d54aTimo Sirainen &data, &data_size);
6df4a174b4cbdc439ed435a0cdc71d4a0126d54aTimo Sirainen if (data_size != sizeof(mbox->maildir_hdr) ||
6df4a174b4cbdc439ed435a0cdc71d4a0126d54aTimo Sirainen maildir_index_header_has_changed(data, &mbox->maildir_hdr)) {
6df4a174b4cbdc439ed435a0cdc71d4a0126d54aTimo Sirainen mail_index_update_header_ext(trans, mbox->maildir_ext_id, 0,
6df4a174b4cbdc439ed435a0cdc71d4a0126d54aTimo Sirainen &mbox->maildir_hdr,
6df4a174b4cbdc439ed435a0cdc71d4a0126d54aTimo Sirainen sizeof(mbox->maildir_hdr));
6df4a174b4cbdc439ed435a0cdc71d4a0126d54aTimo Sirainen }
6df4a174b4cbdc439ed435a0cdc71d4a0126d54aTimo Sirainen}
6df4a174b4cbdc439ed435a0cdc71d4a0126d54aTimo Sirainen
6df4a174b4cbdc439ed435a0cdc71d4a0126d54aTimo Sirainenint maildir_sync_index(struct maildir_index_sync_context *ctx,
6df4a174b4cbdc439ed435a0cdc71d4a0126d54aTimo Sirainen bool partial)
6df4a174b4cbdc439ed435a0cdc71d4a0126d54aTimo Sirainen{
12e5ac049bd74f8b98d9dc62adcb0bf3217beef6Martti Rannanjärvi struct maildir_mailbox *mbox = ctx->mbox;
6df4a174b4cbdc439ed435a0cdc71d4a0126d54aTimo Sirainen struct mail_index_view *view = ctx->view;
6df4a174b4cbdc439ed435a0cdc71d4a0126d54aTimo Sirainen struct mail_index_view *view2;
6df4a174b4cbdc439ed435a0cdc71d4a0126d54aTimo Sirainen struct maildir_uidlist_iter_ctx *iter;
6df4a174b4cbdc439ed435a0cdc71d4a0126d54aTimo Sirainen struct mail_index_transaction *trans = ctx->trans;
6df4a174b4cbdc439ed435a0cdc71d4a0126d54aTimo Sirainen const struct mail_index_header *hdr;
6df4a174b4cbdc439ed435a0cdc71d4a0126d54aTimo Sirainen struct mail_index_header empty_hdr;
6df4a174b4cbdc439ed435a0cdc71d4a0126d54aTimo Sirainen const struct mail_index_record *rec;
6df4a174b4cbdc439ed435a0cdc71d4a0126d54aTimo Sirainen uint32_t seq, seq2, uid, prev_uid;
6df4a174b4cbdc439ed435a0cdc71d4a0126d54aTimo Sirainen enum maildir_uidlist_rec_flag uflags;
6df4a174b4cbdc439ed435a0cdc71d4a0126d54aTimo Sirainen const char *filename;
6df4a174b4cbdc439ed435a0cdc71d4a0126d54aTimo Sirainen ARRAY_TYPE(keyword_indexes) idx_keywords;
6df4a174b4cbdc439ed435a0cdc71d4a0126d54aTimo Sirainen uint32_t uid_validity, next_uid, hdr_next_uid, first_recent_uid;
6df4a174b4cbdc439ed435a0cdc71d4a0126d54aTimo Sirainen unsigned int changes = 0;
6df4a174b4cbdc439ed435a0cdc71d4a0126d54aTimo Sirainen int ret = 0;
6df4a174b4cbdc439ed435a0cdc71d4a0126d54aTimo Sirainen bool expunged, full_rescan = FALSE;
6df4a174b4cbdc439ed435a0cdc71d4a0126d54aTimo Sirainen
6df4a174b4cbdc439ed435a0cdc71d4a0126d54aTimo Sirainen i_assert(!mbox->syncing_commit);
6df4a174b4cbdc439ed435a0cdc71d4a0126d54aTimo Sirainen i_assert(maildir_uidlist_is_locked(mbox->uidlist));
6df4a174b4cbdc439ed435a0cdc71d4a0126d54aTimo Sirainen
6df4a174b4cbdc439ed435a0cdc71d4a0126d54aTimo Sirainen hdr = mail_index_get_header(view);
6df4a174b4cbdc439ed435a0cdc71d4a0126d54aTimo Sirainen uid_validity = maildir_uidlist_get_uid_validity(mbox->uidlist);
6df4a174b4cbdc439ed435a0cdc71d4a0126d54aTimo Sirainen if (uid_validity != hdr->uid_validity &&
6df4a174b4cbdc439ed435a0cdc71d4a0126d54aTimo Sirainen uid_validity != 0 && hdr->uid_validity != 0) {
6df4a174b4cbdc439ed435a0cdc71d4a0126d54aTimo Sirainen /* uidvalidity changed and index isn't being synced for the
6df4a174b4cbdc439ed435a0cdc71d4a0126d54aTimo Sirainen first time, reset the index so we can add all messages as
6df4a174b4cbdc439ed435a0cdc71d4a0126d54aTimo Sirainen new */
6df4a174b4cbdc439ed435a0cdc71d4a0126d54aTimo Sirainen i_warning("Maildir %s: UIDVALIDITY changed (%u -> %u)",
6df4a174b4cbdc439ed435a0cdc71d4a0126d54aTimo Sirainen mbox->path, hdr->uid_validity, uid_validity);
aeaf818613081b9a9ff8c9fd4306e8dbfab4fd86Timo Sirainen mail_index_reset(trans);
6df4a174b4cbdc439ed435a0cdc71d4a0126d54aTimo Sirainen maildir_uidlist_set_next_uid(mbox->uidlist, 1, TRUE);
6df4a174b4cbdc439ed435a0cdc71d4a0126d54aTimo Sirainen
6df4a174b4cbdc439ed435a0cdc71d4a0126d54aTimo Sirainen memset(&empty_hdr, 0, sizeof(empty_hdr));
6df4a174b4cbdc439ed435a0cdc71d4a0126d54aTimo Sirainen empty_hdr.next_uid = 1;
6df4a174b4cbdc439ed435a0cdc71d4a0126d54aTimo Sirainen hdr = &empty_hdr;
6df4a174b4cbdc439ed435a0cdc71d4a0126d54aTimo Sirainen }
6df4a174b4cbdc439ed435a0cdc71d4a0126d54aTimo Sirainen hdr_next_uid = hdr->next_uid;
6df4a174b4cbdc439ed435a0cdc71d4a0126d54aTimo Sirainen
6df4a174b4cbdc439ed435a0cdc71d4a0126d54aTimo Sirainen mbox->syncing_commit = TRUE;
6df4a174b4cbdc439ed435a0cdc71d4a0126d54aTimo Sirainen seq = prev_uid = 0; first_recent_uid = hdr->first_recent_uid;
6df4a174b4cbdc439ed435a0cdc71d4a0126d54aTimo Sirainen t_array_init(&ctx->keywords, MAILDIR_MAX_KEYWORDS);
6df4a174b4cbdc439ed435a0cdc71d4a0126d54aTimo Sirainen t_array_init(&idx_keywords, MAILDIR_MAX_KEYWORDS);
6df4a174b4cbdc439ed435a0cdc71d4a0126d54aTimo Sirainen iter = maildir_uidlist_iter_init(mbox->uidlist);
6df4a174b4cbdc439ed435a0cdc71d4a0126d54aTimo Sirainen while (maildir_uidlist_iter_next(iter, &uid, &uflags, &filename)) {
6df4a174b4cbdc439ed435a0cdc71d4a0126d54aTimo Sirainen maildir_filename_get_flags(ctx->keywords_sync_ctx, filename,
6df4a174b4cbdc439ed435a0cdc71d4a0126d54aTimo Sirainen &ctx->flags, &ctx->keywords);
6df4a174b4cbdc439ed435a0cdc71d4a0126d54aTimo Sirainen
6df4a174b4cbdc439ed435a0cdc71d4a0126d54aTimo Sirainen i_assert(uid > prev_uid);
6df4a174b4cbdc439ed435a0cdc71d4a0126d54aTimo Sirainen prev_uid = uid;
6df4a174b4cbdc439ed435a0cdc71d4a0126d54aTimo Sirainen
6df4a174b4cbdc439ed435a0cdc71d4a0126d54aTimo Sirainen /* the private flags are kept only in indexes. don't use them
6df4a174b4cbdc439ed435a0cdc71d4a0126d54aTimo Sirainen at all even for newly seen mails */
6df4a174b4cbdc439ed435a0cdc71d4a0126d54aTimo Sirainen ctx->flags &= ~mbox->ibox.box.private_flags_mask;
12e5ac049bd74f8b98d9dc62adcb0bf3217beef6Martti Rannanjärvi
6df4a174b4cbdc439ed435a0cdc71d4a0126d54aTimo Sirainen again:
6df4a174b4cbdc439ed435a0cdc71d4a0126d54aTimo Sirainen ctx->seq = ++seq;
6df4a174b4cbdc439ed435a0cdc71d4a0126d54aTimo Sirainen ctx->uid = uid;
6df4a174b4cbdc439ed435a0cdc71d4a0126d54aTimo Sirainen
6df4a174b4cbdc439ed435a0cdc71d4a0126d54aTimo Sirainen if (seq > hdr->messages_count) {
6df4a174b4cbdc439ed435a0cdc71d4a0126d54aTimo Sirainen if (uid < hdr_next_uid) {
6df4a174b4cbdc439ed435a0cdc71d4a0126d54aTimo Sirainen maildir_handle_uid_insertion(ctx, uflags,
6df4a174b4cbdc439ed435a0cdc71d4a0126d54aTimo Sirainen filename, uid);
6df4a174b4cbdc439ed435a0cdc71d4a0126d54aTimo Sirainen seq--;
6df4a174b4cbdc439ed435a0cdc71d4a0126d54aTimo Sirainen continue;
aeaf818613081b9a9ff8c9fd4306e8dbfab4fd86Timo Sirainen }
6df4a174b4cbdc439ed435a0cdc71d4a0126d54aTimo Sirainen
6df4a174b4cbdc439ed435a0cdc71d4a0126d54aTimo Sirainen /* Trust uidlist recent flags only for newly added
6df4a174b4cbdc439ed435a0cdc71d4a0126d54aTimo Sirainen messages. When saving/copying messages with flags
6df4a174b4cbdc439ed435a0cdc71d4a0126d54aTimo Sirainen they're stored to cur/ and uidlist treats them
6df4a174b4cbdc439ed435a0cdc71d4a0126d54aTimo Sirainen as non-recent. */
7195d775e5e943af90d24a615847c733a104e3d4Timo Sirainen if ((uflags & MAILDIR_UIDLIST_REC_FLAG_RECENT) != 0) {
7195d775e5e943af90d24a615847c733a104e3d4Timo Sirainen if (uid > first_recent_uid)
7195d775e5e943af90d24a615847c733a104e3d4Timo Sirainen first_recent_uid = uid;
7195d775e5e943af90d24a615847c733a104e3d4Timo Sirainen } else {
7195d775e5e943af90d24a615847c733a104e3d4Timo Sirainen if (uid >= first_recent_uid)
7195d775e5e943af90d24a615847c733a104e3d4Timo Sirainen first_recent_uid = uid + 1;
7195d775e5e943af90d24a615847c733a104e3d4Timo Sirainen }
7195d775e5e943af90d24a615847c733a104e3d4Timo Sirainen
7195d775e5e943af90d24a615847c733a104e3d4Timo Sirainen hdr_next_uid = uid + 1;
7195d775e5e943af90d24a615847c733a104e3d4Timo Sirainen mail_index_append(trans, uid, &seq);
7195d775e5e943af90d24a615847c733a104e3d4Timo Sirainen mail_index_update_flags(trans, seq, MODIFY_REPLACE,
7195d775e5e943af90d24a615847c733a104e3d4Timo Sirainen ctx->flags);
7195d775e5e943af90d24a615847c733a104e3d4Timo Sirainen if (array_count(&ctx->keywords) > 0) {
aeaf818613081b9a9ff8c9fd4306e8dbfab4fd86Timo Sirainen struct mail_keywords *kw;
7195d775e5e943af90d24a615847c733a104e3d4Timo Sirainen
7195d775e5e943af90d24a615847c733a104e3d4Timo Sirainen kw = mail_index_keywords_create_from_indexes(
7195d775e5e943af90d24a615847c733a104e3d4Timo Sirainen mbox->ibox.index, &ctx->keywords);
7195d775e5e943af90d24a615847c733a104e3d4Timo Sirainen mail_index_update_keywords(trans, seq,
7195d775e5e943af90d24a615847c733a104e3d4Timo Sirainen MODIFY_REPLACE, kw);
7195d775e5e943af90d24a615847c733a104e3d4Timo Sirainen mail_index_keywords_free(&kw);
12e5ac049bd74f8b98d9dc62adcb0bf3217beef6Martti Rannanjärvi }
7195d775e5e943af90d24a615847c733a104e3d4Timo Sirainen continue;
7195d775e5e943af90d24a615847c733a104e3d4Timo Sirainen }
7195d775e5e943af90d24a615847c733a104e3d4Timo Sirainen
7195d775e5e943af90d24a615847c733a104e3d4Timo Sirainen rec = mail_index_lookup(view, seq);
7195d775e5e943af90d24a615847c733a104e3d4Timo Sirainen if (uid > rec->uid) {
7195d775e5e943af90d24a615847c733a104e3d4Timo Sirainen /* expunged */
7195d775e5e943af90d24a615847c733a104e3d4Timo Sirainen mail_index_expunge(trans, seq);
7195d775e5e943af90d24a615847c733a104e3d4Timo Sirainen goto again;
7195d775e5e943af90d24a615847c733a104e3d4Timo Sirainen }
7195d775e5e943af90d24a615847c733a104e3d4Timo Sirainen
7195d775e5e943af90d24a615847c733a104e3d4Timo Sirainen if (uid < rec->uid) {
aeaf818613081b9a9ff8c9fd4306e8dbfab4fd86Timo Sirainen maildir_handle_uid_insertion(ctx, uflags,
7195d775e5e943af90d24a615847c733a104e3d4Timo Sirainen filename, uid);
7195d775e5e943af90d24a615847c733a104e3d4Timo Sirainen seq--;
7195d775e5e943af90d24a615847c733a104e3d4Timo Sirainen continue;
7195d775e5e943af90d24a615847c733a104e3d4Timo Sirainen }
7195d775e5e943af90d24a615847c733a104e3d4Timo Sirainen
7a12331c6360968b141a0888e0bf04dd24145f23Timo Sirainen index_sync_changes_read(ctx->sync_changes, rec->uid, &expunged);
7a12331c6360968b141a0888e0bf04dd24145f23Timo Sirainen if (expunged) {
7a12331c6360968b141a0888e0bf04dd24145f23Timo Sirainen if (maildir_file_do(mbox, ctx->uid,
7a12331c6360968b141a0888e0bf04dd24145f23Timo Sirainen maildir_expunge, ctx) >= 0) {
7a12331c6360968b141a0888e0bf04dd24145f23Timo Sirainen /* successful expunge */
7a12331c6360968b141a0888e0bf04dd24145f23Timo Sirainen mail_index_expunge(trans, seq);
7a12331c6360968b141a0888e0bf04dd24145f23Timo Sirainen }
7a12331c6360968b141a0888e0bf04dd24145f23Timo Sirainen if ((++changes % MAILDIR_SLOW_MOVE_COUNT) == 0)
7a12331c6360968b141a0888e0bf04dd24145f23Timo Sirainen maildir_sync_notify(ctx->maildir_sync_ctx);
7a12331c6360968b141a0888e0bf04dd24145f23Timo Sirainen continue;
7a12331c6360968b141a0888e0bf04dd24145f23Timo Sirainen }
7a12331c6360968b141a0888e0bf04dd24145f23Timo Sirainen
7a12331c6360968b141a0888e0bf04dd24145f23Timo Sirainen /* the private flags are stored only in indexes, keep them */
7a12331c6360968b141a0888e0bf04dd24145f23Timo Sirainen ctx->flags |= rec->flags & mbox->ibox.box.private_flags_mask;
7a12331c6360968b141a0888e0bf04dd24145f23Timo Sirainen
7a12331c6360968b141a0888e0bf04dd24145f23Timo Sirainen if (index_sync_changes_have(ctx->sync_changes)) {
7a12331c6360968b141a0888e0bf04dd24145f23Timo Sirainen /* apply flag changes to maildir */
7a12331c6360968b141a0888e0bf04dd24145f23Timo Sirainen if (maildir_file_do(mbox, ctx->uid,
7a12331c6360968b141a0888e0bf04dd24145f23Timo Sirainen maildir_sync_flags, ctx) < 0)
7a12331c6360968b141a0888e0bf04dd24145f23Timo Sirainen ctx->flags |= MAIL_INDEX_MAIL_FLAG_DIRTY;
7a12331c6360968b141a0888e0bf04dd24145f23Timo Sirainen if ((++changes % MAILDIR_SLOW_MOVE_COUNT) == 0)
7a12331c6360968b141a0888e0bf04dd24145f23Timo Sirainen maildir_sync_notify(ctx->maildir_sync_ctx);
7a12331c6360968b141a0888e0bf04dd24145f23Timo Sirainen }
7a12331c6360968b141a0888e0bf04dd24145f23Timo Sirainen
7a12331c6360968b141a0888e0bf04dd24145f23Timo Sirainen if ((uflags & MAILDIR_UIDLIST_REC_FLAG_NONSYNCED) != 0) {
7a12331c6360968b141a0888e0bf04dd24145f23Timo Sirainen /* partial syncing */
12e5ac049bd74f8b98d9dc62adcb0bf3217beef6Martti Rannanjärvi if ((uflags & MAILDIR_UIDLIST_REC_FLAG_NEW_DIR) != 0) {
7a12331c6360968b141a0888e0bf04dd24145f23Timo Sirainen /* we last saw this mail in new/, but it's
7a12331c6360968b141a0888e0bf04dd24145f23Timo Sirainen not there anymore. possibly expunged,
7a12331c6360968b141a0888e0bf04dd24145f23Timo Sirainen make sure. */
7a12331c6360968b141a0888e0bf04dd24145f23Timo Sirainen full_rescan = TRUE;
7a12331c6360968b141a0888e0bf04dd24145f23Timo Sirainen }
7a12331c6360968b141a0888e0bf04dd24145f23Timo Sirainen continue;
7a12331c6360968b141a0888e0bf04dd24145f23Timo Sirainen }
7a12331c6360968b141a0888e0bf04dd24145f23Timo Sirainen
7a12331c6360968b141a0888e0bf04dd24145f23Timo Sirainen if ((rec->flags & MAIL_INDEX_MAIL_FLAG_DIRTY) != 0) {
7a12331c6360968b141a0888e0bf04dd24145f23Timo Sirainen /* we haven't been able to update maildir with this
7a12331c6360968b141a0888e0bf04dd24145f23Timo Sirainen record's flag changes. don't sync them. */
7a12331c6360968b141a0888e0bf04dd24145f23Timo Sirainen continue;
7a12331c6360968b141a0888e0bf04dd24145f23Timo Sirainen }
7a12331c6360968b141a0888e0bf04dd24145f23Timo Sirainen
7a12331c6360968b141a0888e0bf04dd24145f23Timo Sirainen if (ctx->flags != (rec->flags & MAIL_FLAGS_NONRECENT)) {
7a12331c6360968b141a0888e0bf04dd24145f23Timo Sirainen mail_index_update_flags(trans, seq, MODIFY_REPLACE,
7a12331c6360968b141a0888e0bf04dd24145f23Timo Sirainen ctx->flags);
7a12331c6360968b141a0888e0bf04dd24145f23Timo Sirainen }
7a12331c6360968b141a0888e0bf04dd24145f23Timo Sirainen
7a12331c6360968b141a0888e0bf04dd24145f23Timo Sirainen /* update keywords if they have changed */
7a12331c6360968b141a0888e0bf04dd24145f23Timo Sirainen mail_index_lookup_keywords(view, seq, &idx_keywords);
7a12331c6360968b141a0888e0bf04dd24145f23Timo Sirainen if (!index_keyword_array_cmp(&ctx->keywords, &idx_keywords)) {
7a12331c6360968b141a0888e0bf04dd24145f23Timo Sirainen struct mail_keywords *kw;
7a12331c6360968b141a0888e0bf04dd24145f23Timo Sirainen
7a12331c6360968b141a0888e0bf04dd24145f23Timo Sirainen kw = mail_index_keywords_create_from_indexes(
aeaf818613081b9a9ff8c9fd4306e8dbfab4fd86Timo Sirainen mbox->ibox.index, &ctx->keywords);
7a12331c6360968b141a0888e0bf04dd24145f23Timo Sirainen mail_index_update_keywords(trans, seq,
7a12331c6360968b141a0888e0bf04dd24145f23Timo Sirainen MODIFY_REPLACE, kw);
7a12331c6360968b141a0888e0bf04dd24145f23Timo Sirainen mail_index_keywords_free(&kw);
7a12331c6360968b141a0888e0bf04dd24145f23Timo Sirainen }
7a12331c6360968b141a0888e0bf04dd24145f23Timo Sirainen }
7195d775e5e943af90d24a615847c733a104e3d4Timo Sirainen maildir_uidlist_iter_deinit(&iter);
7195d775e5e943af90d24a615847c733a104e3d4Timo Sirainen mbox->syncing_commit = FALSE;
7195d775e5e943af90d24a615847c733a104e3d4Timo Sirainen
7195d775e5e943af90d24a615847c733a104e3d4Timo Sirainen if (!partial) {
7195d775e5e943af90d24a615847c733a104e3d4Timo Sirainen /* expunge the rest */
7195d775e5e943af90d24a615847c733a104e3d4Timo Sirainen for (seq++; seq <= hdr->messages_count; seq++)
7195d775e5e943af90d24a615847c733a104e3d4Timo Sirainen mail_index_expunge(trans, seq);
7195d775e5e943af90d24a615847c733a104e3d4Timo Sirainen }
7195d775e5e943af90d24a615847c733a104e3d4Timo Sirainen
7195d775e5e943af90d24a615847c733a104e3d4Timo Sirainen /* add \Recent flags. use updated view so it contains newly
7195d775e5e943af90d24a615847c733a104e3d4Timo Sirainen appended messages. */
7195d775e5e943af90d24a615847c733a104e3d4Timo Sirainen view2 = mail_index_transaction_open_updated_view(trans);
7195d775e5e943af90d24a615847c733a104e3d4Timo Sirainen if (mail_index_lookup_seq_range(view2, first_recent_uid, (uint32_t)-1,
7195d775e5e943af90d24a615847c733a104e3d4Timo Sirainen &seq, &seq2))
7195d775e5e943af90d24a615847c733a104e3d4Timo Sirainen index_mailbox_set_recent_seq(&mbox->ibox, view2, seq, seq2);
7195d775e5e943af90d24a615847c733a104e3d4Timo Sirainen mail_index_view_close(&view2);
7195d775e5e943af90d24a615847c733a104e3d4Timo Sirainen
7195d775e5e943af90d24a615847c733a104e3d4Timo Sirainen if (ctx->uidlist_sync_ctx != NULL) {
7195d775e5e943af90d24a615847c733a104e3d4Timo Sirainen if (maildir_uidlist_sync_deinit(&ctx->uidlist_sync_ctx) < 0)
7195d775e5e943af90d24a615847c733a104e3d4Timo Sirainen ret = -1;
7195d775e5e943af90d24a615847c733a104e3d4Timo Sirainen }
7195d775e5e943af90d24a615847c733a104e3d4Timo Sirainen
7195d775e5e943af90d24a615847c733a104e3d4Timo Sirainen if (mbox->ibox.box.v.sync_notify != NULL)
7195d775e5e943af90d24a615847c733a104e3d4Timo Sirainen mbox->ibox.box.v.sync_notify(&mbox->ibox.box, 0, 0);
7195d775e5e943af90d24a615847c733a104e3d4Timo Sirainen
7195d775e5e943af90d24a615847c733a104e3d4Timo Sirainen if (ctx->changed)
12e5ac049bd74f8b98d9dc62adcb0bf3217beef6Martti Rannanjärvi mbox->maildir_hdr.cur_mtime = time(NULL);
7195d775e5e943af90d24a615847c733a104e3d4Timo Sirainen maildir_index_update_ext_header(mbox, trans);
7195d775e5e943af90d24a615847c733a104e3d4Timo Sirainen
7195d775e5e943af90d24a615847c733a104e3d4Timo Sirainen if (uid_validity == 0) {
7195d775e5e943af90d24a615847c733a104e3d4Timo Sirainen uid_validity = hdr->uid_validity != 0 ?
7195d775e5e943af90d24a615847c733a104e3d4Timo Sirainen hdr->uid_validity : (uint32_t)ioloop_time;
7195d775e5e943af90d24a615847c733a104e3d4Timo Sirainen maildir_uidlist_set_uid_validity(mbox->uidlist, uid_validity);
7195d775e5e943af90d24a615847c733a104e3d4Timo Sirainen }
7195d775e5e943af90d24a615847c733a104e3d4Timo Sirainen maildir_uidlist_set_next_uid(mbox->uidlist, hdr_next_uid, FALSE);
7195d775e5e943af90d24a615847c733a104e3d4Timo Sirainen
7195d775e5e943af90d24a615847c733a104e3d4Timo Sirainen if (uid_validity != hdr->uid_validity) {
7195d775e5e943af90d24a615847c733a104e3d4Timo Sirainen mail_index_update_header(trans,
7195d775e5e943af90d24a615847c733a104e3d4Timo Sirainen offsetof(struct mail_index_header, uid_validity),
7195d775e5e943af90d24a615847c733a104e3d4Timo Sirainen &uid_validity, sizeof(uid_validity), TRUE);
7195d775e5e943af90d24a615847c733a104e3d4Timo Sirainen }
7195d775e5e943af90d24a615847c733a104e3d4Timo Sirainen
7195d775e5e943af90d24a615847c733a104e3d4Timo Sirainen next_uid = maildir_uidlist_get_next_uid(mbox->uidlist);
7195d775e5e943af90d24a615847c733a104e3d4Timo Sirainen if (hdr_next_uid < next_uid) {
7195d775e5e943af90d24a615847c733a104e3d4Timo Sirainen mail_index_update_header(trans,
7195d775e5e943af90d24a615847c733a104e3d4Timo Sirainen offsetof(struct mail_index_header, next_uid),
7195d775e5e943af90d24a615847c733a104e3d4Timo Sirainen &next_uid, sizeof(next_uid), FALSE);
7195d775e5e943af90d24a615847c733a104e3d4Timo Sirainen }
7195d775e5e943af90d24a615847c733a104e3d4Timo Sirainen
7195d775e5e943af90d24a615847c733a104e3d4Timo Sirainen i_assert(hdr->first_recent_uid <= first_recent_uid);
7195d775e5e943af90d24a615847c733a104e3d4Timo Sirainen if (hdr->first_recent_uid < first_recent_uid) {
7195d775e5e943af90d24a615847c733a104e3d4Timo Sirainen mail_index_update_header(ctx->trans,
aeaf818613081b9a9ff8c9fd4306e8dbfab4fd86Timo Sirainen offsetof(struct mail_index_header, first_recent_uid),
7195d775e5e943af90d24a615847c733a104e3d4Timo Sirainen &first_recent_uid, sizeof(first_recent_uid), FALSE);
7195d775e5e943af90d24a615847c733a104e3d4Timo Sirainen }
7195d775e5e943af90d24a615847c733a104e3d4Timo Sirainen return ret < 0 ? -1 : (full_rescan ? 0 : 1);
7195d775e5e943af90d24a615847c733a104e3d4Timo Sirainen}
7195d775e5e943af90d24a615847c733a104e3d4Timo Sirainen
7a12331c6360968b141a0888e0bf04dd24145f23Timo Sirainenstatic unsigned int maildir_list_get_ext_id(struct maildir_storage *storage,
7a12331c6360968b141a0888e0bf04dd24145f23Timo Sirainen struct mail_index_view *view)
7a12331c6360968b141a0888e0bf04dd24145f23Timo Sirainen{
7a12331c6360968b141a0888e0bf04dd24145f23Timo Sirainen if (storage->maildir_list_ext_id == (uint32_t)-1) {
7a12331c6360968b141a0888e0bf04dd24145f23Timo Sirainen storage->maildir_list_ext_id =
7a12331c6360968b141a0888e0bf04dd24145f23Timo Sirainen mail_index_ext_register(mail_index_view_get_index(view),
7a12331c6360968b141a0888e0bf04dd24145f23Timo Sirainen "maildir", 0,
7a12331c6360968b141a0888e0bf04dd24145f23Timo Sirainen sizeof(struct maildir_list_index_record),
7a12331c6360968b141a0888e0bf04dd24145f23Timo Sirainen sizeof(uint32_t));
7a12331c6360968b141a0888e0bf04dd24145f23Timo Sirainen }
7a12331c6360968b141a0888e0bf04dd24145f23Timo Sirainen return storage->maildir_list_ext_id;
7a12331c6360968b141a0888e0bf04dd24145f23Timo Sirainen}
7a12331c6360968b141a0888e0bf04dd24145f23Timo Sirainen
7a12331c6360968b141a0888e0bf04dd24145f23Timo Sirainenint maildir_list_index_has_changed(struct mailbox *box,
7a12331c6360968b141a0888e0bf04dd24145f23Timo Sirainen struct mail_index_view *list_view,
7a12331c6360968b141a0888e0bf04dd24145f23Timo Sirainen uint32_t seq)
7a12331c6360968b141a0888e0bf04dd24145f23Timo Sirainen{
7a12331c6360968b141a0888e0bf04dd24145f23Timo Sirainen struct maildir_mailbox *mbox = (struct maildir_mailbox *)box;
7a12331c6360968b141a0888e0bf04dd24145f23Timo Sirainen const struct maildir_list_index_record *rec;
7a12331c6360968b141a0888e0bf04dd24145f23Timo Sirainen const void *data;
7a12331c6360968b141a0888e0bf04dd24145f23Timo Sirainen const char *root_dir, *new_dir, *cur_dir;
7a12331c6360968b141a0888e0bf04dd24145f23Timo Sirainen struct stat st;
7a12331c6360968b141a0888e0bf04dd24145f23Timo Sirainen uint32_t ext_id;
7a12331c6360968b141a0888e0bf04dd24145f23Timo Sirainen bool expunged;
7a12331c6360968b141a0888e0bf04dd24145f23Timo Sirainen
7a12331c6360968b141a0888e0bf04dd24145f23Timo Sirainen ext_id = maildir_list_get_ext_id(mbox->storage, list_view);
12e5ac049bd74f8b98d9dc62adcb0bf3217beef6Martti Rannanjärvi mail_index_lookup_ext(list_view, seq, ext_id, &data, &expunged);
7a12331c6360968b141a0888e0bf04dd24145f23Timo Sirainen rec = data;
7a12331c6360968b141a0888e0bf04dd24145f23Timo Sirainen
7a12331c6360968b141a0888e0bf04dd24145f23Timo Sirainen if (rec == NULL || expunged ||
7a12331c6360968b141a0888e0bf04dd24145f23Timo Sirainen rec->new_mtime == 0 || rec->cur_mtime == 0) {
7a12331c6360968b141a0888e0bf04dd24145f23Timo Sirainen /* doesn't exist, not synced or dirty-synced */
7a12331c6360968b141a0888e0bf04dd24145f23Timo Sirainen return 1;
7a12331c6360968b141a0888e0bf04dd24145f23Timo Sirainen }
7a12331c6360968b141a0888e0bf04dd24145f23Timo Sirainen
7a12331c6360968b141a0888e0bf04dd24145f23Timo Sirainen root_dir = mailbox_list_get_path(mail_storage_get_list(box->storage),
7a12331c6360968b141a0888e0bf04dd24145f23Timo Sirainen box->name,
7a12331c6360968b141a0888e0bf04dd24145f23Timo Sirainen MAILBOX_LIST_PATH_TYPE_MAILBOX);
7a12331c6360968b141a0888e0bf04dd24145f23Timo Sirainen
7a12331c6360968b141a0888e0bf04dd24145f23Timo Sirainen /* check if new/ changed */
7a12331c6360968b141a0888e0bf04dd24145f23Timo Sirainen new_dir = t_strconcat(root_dir, "/new", NULL);
7a12331c6360968b141a0888e0bf04dd24145f23Timo Sirainen if (stat(new_dir, &st) < 0) {
7a12331c6360968b141a0888e0bf04dd24145f23Timo Sirainen mail_storage_set_critical(box->storage,
7a12331c6360968b141a0888e0bf04dd24145f23Timo Sirainen "stat(%s) failed: %m", new_dir);
7a12331c6360968b141a0888e0bf04dd24145f23Timo Sirainen return -1;
7a12331c6360968b141a0888e0bf04dd24145f23Timo Sirainen }
7a12331c6360968b141a0888e0bf04dd24145f23Timo Sirainen if ((time_t)rec->new_mtime != st.st_mtime)
7a12331c6360968b141a0888e0bf04dd24145f23Timo Sirainen return 1;
7a12331c6360968b141a0888e0bf04dd24145f23Timo Sirainen
7a12331c6360968b141a0888e0bf04dd24145f23Timo Sirainen /* check if cur/ changed */
7a12331c6360968b141a0888e0bf04dd24145f23Timo Sirainen cur_dir = t_strconcat(root_dir, "/cur", NULL);
7a12331c6360968b141a0888e0bf04dd24145f23Timo Sirainen if (stat(cur_dir, &st) < 0) {
aeaf818613081b9a9ff8c9fd4306e8dbfab4fd86Timo Sirainen mail_storage_set_critical(box->storage,
7a12331c6360968b141a0888e0bf04dd24145f23Timo Sirainen "stat(%s) failed: %m", cur_dir);
7a12331c6360968b141a0888e0bf04dd24145f23Timo Sirainen return -1;
7a12331c6360968b141a0888e0bf04dd24145f23Timo Sirainen }
7a12331c6360968b141a0888e0bf04dd24145f23Timo Sirainen if ((time_t)rec->cur_mtime != st.st_mtime)
7a12331c6360968b141a0888e0bf04dd24145f23Timo Sirainen return 1;
12fd7a30563f3256642070ef9528dda0d089cb41Timo Sirainen return 0;
12fd7a30563f3256642070ef9528dda0d089cb41Timo Sirainen}
12fd7a30563f3256642070ef9528dda0d089cb41Timo Sirainen
12fd7a30563f3256642070ef9528dda0d089cb41Timo Sirainenint maildir_list_index_update_sync(struct mailbox *box,
12fd7a30563f3256642070ef9528dda0d089cb41Timo Sirainen struct mail_index_transaction *trans,
12fd7a30563f3256642070ef9528dda0d089cb41Timo Sirainen uint32_t seq)
12fd7a30563f3256642070ef9528dda0d089cb41Timo Sirainen{
12fd7a30563f3256642070ef9528dda0d089cb41Timo Sirainen struct maildir_mailbox *mbox = (struct maildir_mailbox *)box;
12fd7a30563f3256642070ef9528dda0d089cb41Timo Sirainen struct mail_index_view *list_view;
12fd7a30563f3256642070ef9528dda0d089cb41Timo Sirainen const struct maildir_index_header *mhdr = &mbox->maildir_hdr;
12fd7a30563f3256642070ef9528dda0d089cb41Timo Sirainen const struct maildir_list_index_record *old_rec;
12fd7a30563f3256642070ef9528dda0d089cb41Timo Sirainen struct maildir_list_index_record new_rec;
12fd7a30563f3256642070ef9528dda0d089cb41Timo Sirainen const void *data;
12fd7a30563f3256642070ef9528dda0d089cb41Timo Sirainen uint32_t ext_id;
12fd7a30563f3256642070ef9528dda0d089cb41Timo Sirainen bool expunged;
12fd7a30563f3256642070ef9528dda0d089cb41Timo Sirainen
12fd7a30563f3256642070ef9528dda0d089cb41Timo Sirainen /* get the current record */
12fd7a30563f3256642070ef9528dda0d089cb41Timo Sirainen list_view = mail_index_transaction_get_view(trans);
12fd7a30563f3256642070ef9528dda0d089cb41Timo Sirainen ext_id = maildir_list_get_ext_id(mbox->storage, list_view);
12fd7a30563f3256642070ef9528dda0d089cb41Timo Sirainen mail_index_lookup_ext(list_view, seq, ext_id, &data, &expunged);
12fd7a30563f3256642070ef9528dda0d089cb41Timo Sirainen if (expunged)
12fd7a30563f3256642070ef9528dda0d089cb41Timo Sirainen return 0;
12fd7a30563f3256642070ef9528dda0d089cb41Timo Sirainen old_rec = data;
12fd7a30563f3256642070ef9528dda0d089cb41Timo Sirainen
12fd7a30563f3256642070ef9528dda0d089cb41Timo Sirainen memset(&new_rec, 0, sizeof(new_rec));
12fd7a30563f3256642070ef9528dda0d089cb41Timo Sirainen if (mhdr->new_check_time <= mhdr->new_mtime + MAILDIR_SYNC_SECS ||
12fd7a30563f3256642070ef9528dda0d089cb41Timo Sirainen mhdr->cur_check_time <= mhdr->cur_mtime + MAILDIR_SYNC_SECS) {
12fd7a30563f3256642070ef9528dda0d089cb41Timo Sirainen /* dirty, we need a refresh next time */
12fd7a30563f3256642070ef9528dda0d089cb41Timo Sirainen } else {
12fd7a30563f3256642070ef9528dda0d089cb41Timo Sirainen new_rec.new_mtime = mhdr->new_mtime;
12fd7a30563f3256642070ef9528dda0d089cb41Timo Sirainen new_rec.cur_mtime = mhdr->cur_mtime;
12fd7a30563f3256642070ef9528dda0d089cb41Timo Sirainen }
12fd7a30563f3256642070ef9528dda0d089cb41Timo Sirainen
12fd7a30563f3256642070ef9528dda0d089cb41Timo Sirainen if (old_rec == NULL ||
12fd7a30563f3256642070ef9528dda0d089cb41Timo Sirainen memcmp(old_rec, &new_rec, sizeof(old_rec)) != 0) {
12fd7a30563f3256642070ef9528dda0d089cb41Timo Sirainen mail_index_update_ext(trans, seq,
12fd7a30563f3256642070ef9528dda0d089cb41Timo Sirainen mbox->storage->maildir_list_ext_id,
12fd7a30563f3256642070ef9528dda0d089cb41Timo Sirainen &new_rec, NULL);
12fd7a30563f3256642070ef9528dda0d089cb41Timo Sirainen }
12fd7a30563f3256642070ef9528dda0d089cb41Timo Sirainen return 0;
12fd7a30563f3256642070ef9528dda0d089cb41Timo Sirainen}
12fd7a30563f3256642070ef9528dda0d089cb41Timo Sirainen