maildir-sync-index.c revision f23ede27743c1aa03eacbfc634d6a10de9110c91
5f5870385cff47efd2f58e7892f251cf13761528Timo Sirainen/* Copyright (C) 2007 Timo Sirainen */
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen#include "lib.h"
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen#include "ioloop.h"
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen#include "array.h"
5d60e31c7b701b606067a20bc88dcc8a6de7bbd6Timo Sirainen#include "maildir-storage.h"
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen#include "index-sync-changes.h"
9f0f2de10e4ea0c99052bf4b2bef8179f2536228Timo Sirainen#include "maildir-uidlist.h"
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen#include "maildir-keywords.h"
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen#include "maildir-filename.h"
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen#include "maildir-sync.h"
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen
d477acb83e14a776ece4ca94dcd1869e75d0c6eeTimo Sirainen#include <stdio.h>
9dd1c256910f1fb42823116a641e7edb3ad11970Timo Sirainen#include <unistd.h>
9dd1c256910f1fb42823116a641e7edb3ad11970Timo Sirainen
d477acb83e14a776ece4ca94dcd1869e75d0c6eeTimo Sirainenstruct maildir_index_sync_context {
9f0f2de10e4ea0c99052bf4b2bef8179f2536228Timo Sirainen struct maildir_mailbox *mbox;
9f0f2de10e4ea0c99052bf4b2bef8179f2536228Timo Sirainen struct maildir_sync_context *maildir_sync_ctx;
daa7e7459749ae8f82cd3eed9c44522d81c609a3Timo Sirainen
bbadd5331f534017cf62d5183003b3d9fdad079eTimo Sirainen struct mail_index_view *view;
373492be949e159fda651807b3acda2c5c077027Timo Sirainen struct mail_index_sync_ctx *sync_ctx;
72f5f2c5c6905b5d3f389b424313e2c450dfad96Timo Sirainen struct maildir_keywords_sync_ctx *keywords_sync_ctx;
9f0f2de10e4ea0c99052bf4b2bef8179f2536228Timo Sirainen struct mail_index_transaction *trans;
9f0f2de10e4ea0c99052bf4b2bef8179f2536228Timo Sirainen
9f0f2de10e4ea0c99052bf4b2bef8179f2536228Timo Sirainen struct maildir_uidlist_sync_ctx *uidlist_sync_ctx;
9f0f2de10e4ea0c99052bf4b2bef8179f2536228Timo Sirainen struct index_sync_changes_context *sync_changes;
9f0f2de10e4ea0c99052bf4b2bef8179f2536228Timo Sirainen enum mail_flags flags;
373492be949e159fda651807b3acda2c5c077027Timo Sirainen ARRAY_TYPE(keyword_indexes) keywords;
bbadd5331f534017cf62d5183003b3d9fdad079eTimo Sirainen
bbadd5331f534017cf62d5183003b3d9fdad079eTimo Sirainen uint32_t seq, uid;
9f0f2de10e4ea0c99052bf4b2bef8179f2536228Timo Sirainen
9f0f2de10e4ea0c99052bf4b2bef8179f2536228Timo Sirainen bool changed;
9f0f2de10e4ea0c99052bf4b2bef8179f2536228Timo Sirainen};
9f0f2de10e4ea0c99052bf4b2bef8179f2536228Timo Sirainen
9f0f2de10e4ea0c99052bf4b2bef8179f2536228Timo Sirainenstruct maildir_keywords_sync_ctx *
9f0f2de10e4ea0c99052bf4b2bef8179f2536228Timo Sirainenmaildir_sync_get_keywords_sync_ctx(struct maildir_index_sync_context *ctx)
9f0f2de10e4ea0c99052bf4b2bef8179f2536228Timo Sirainen{
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen return ctx->keywords_sync_ctx;
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen}
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainenstatic int maildir_expunge(struct maildir_mailbox *mbox, const char *path,
635df5b4cbcd7b24c825e01d9dd66d3a4274c4c7Timo Sirainen struct maildir_index_sync_context *ctx)
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen{
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen struct mailbox *box = &mbox->ibox.box;
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen if (unlink(path) == 0) {
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen if (box->v.sync_notify != NULL) {
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen box->v.sync_notify(box, ctx->uid,
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen MAILBOX_SYNC_TYPE_EXPUNGE);
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen }
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen mail_index_expunge(ctx->trans, ctx->seq);
51fb710488efa419a2964335c30451c62b9633b1Timo Sirainen ctx->changed = TRUE;
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen return 1;
93a7d1ee4b518b5c85f9721dc6539e4dab6aae00Timo Sirainen }
f7f25f9e1a38678d0e97d2e609beac16285fac6bTimo Sirainen if (errno == ENOENT)
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen return 0;
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen mail_storage_set_critical(&mbox->storage->storage,
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen "unlink(%s) failed: %m", path);
35fcdde46a71ac151c2518d48c841019f1181bb2Timo Sirainen return -1;
35fcdde46a71ac151c2518d48c841019f1181bb2Timo Sirainen}
35fcdde46a71ac151c2518d48c841019f1181bb2Timo Sirainen
9f0f2de10e4ea0c99052bf4b2bef8179f2536228Timo Sirainenstatic int maildir_sync_flags(struct maildir_mailbox *mbox, const char *path,
9f0f2de10e4ea0c99052bf4b2bef8179f2536228Timo Sirainen struct maildir_index_sync_context *ctx)
9f0f2de10e4ea0c99052bf4b2bef8179f2536228Timo Sirainen{
9f0f2de10e4ea0c99052bf4b2bef8179f2536228Timo Sirainen struct mailbox *box = &mbox->ibox.box;
635df5b4cbcd7b24c825e01d9dd66d3a4274c4c7Timo Sirainen const char *dir, *fname, *newfname, *newpath;
9f0f2de10e4ea0c99052bf4b2bef8179f2536228Timo Sirainen enum mailbox_sync_type sync_type;
9f0f2de10e4ea0c99052bf4b2bef8179f2536228Timo Sirainen uint8_t flags8;
9f0f2de10e4ea0c99052bf4b2bef8179f2536228Timo Sirainen
9f0f2de10e4ea0c99052bf4b2bef8179f2536228Timo Sirainen fname = strrchr(path, '/');
9f0f2de10e4ea0c99052bf4b2bef8179f2536228Timo Sirainen i_assert(fname != NULL);
9f0f2de10e4ea0c99052bf4b2bef8179f2536228Timo Sirainen fname++;
9f0f2de10e4ea0c99052bf4b2bef8179f2536228Timo Sirainen dir = t_strdup_until(path, fname);
9f0f2de10e4ea0c99052bf4b2bef8179f2536228Timo Sirainen
9f0f2de10e4ea0c99052bf4b2bef8179f2536228Timo Sirainen /* get the current flags and keywords */
9f0f2de10e4ea0c99052bf4b2bef8179f2536228Timo Sirainen maildir_filename_get_flags(ctx->keywords_sync_ctx,
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen fname, &ctx->flags, &ctx->keywords);
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen /* apply changes */
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen flags8 = ctx->flags;
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen index_sync_changes_apply(ctx->sync_changes, NULL,
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen &flags8, &ctx->keywords, &sync_type);
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen ctx->flags = flags8;
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen /* and try renaming with the new name */
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen newfname = maildir_filename_set_flags(ctx->keywords_sync_ctx, fname,
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen ctx->flags, &ctx->keywords);
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen newpath = t_strconcat(dir, newfname, NULL);
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen if (rename(path, newpath) == 0) {
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen if (box->v.sync_notify != NULL)
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen box->v.sync_notify(box, ctx->uid, sync_type);
ba8498efbf886ca8b69fdb20c0ba2f5dba9416e3Timo Sirainen ctx->changed = TRUE;
93a7d1ee4b518b5c85f9721dc6539e4dab6aae00Timo Sirainen return 1;
f7f25f9e1a38678d0e97d2e609beac16285fac6bTimo Sirainen }
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen if (errno == ENOENT)
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen return 0;
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen if (!ENOSPACE(errno) && errno != EACCES) {
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen mail_storage_set_critical(box->storage,
9f0f2de10e4ea0c99052bf4b2bef8179f2536228Timo Sirainen "rename(%s, %s) failed: %m", path, newpath);
9f0f2de10e4ea0c99052bf4b2bef8179f2536228Timo Sirainen }
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen return -1;
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen}
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainenstatic void maildir_handle_uid_insertion(struct maildir_index_sync_context *ctx,
7744586e3e0fd60158abfbb03a233d3bd8d6c48bTimo Sirainen enum maildir_uidlist_rec_flag uflags,
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen const char *filename, uint32_t uid)
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen{
04052d7cacaa866a3f00afb4e104fa46c04c1dd7Timo Sirainen int ret;
04052d7cacaa866a3f00afb4e104fa46c04c1dd7Timo Sirainen
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen if ((uflags & MAILDIR_UIDLIST_REC_FLAG_NONSYNCED) != 0) {
380dbb60ae291cbe39d1f710284562ca9167150bTimo Sirainen /* partial syncing */
380dbb60ae291cbe39d1f710284562ca9167150bTimo Sirainen return;
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen }
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen /* most likely a race condition: we read the maildir, then someone else
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen expunged messages and committed changes to index. so, this message
1b823b2b7790a1e1b7974fcf11a4c48a28e70f37Timo Sirainen shouldn't actually exist. */
3cf67672fdc87583cb23ce088c95bb5dee60e74dTimo Sirainen if ((uflags & MAILDIR_UIDLIST_REC_FLAG_RACING) == 0) {
3cf67672fdc87583cb23ce088c95bb5dee60e74dTimo Sirainen /* mark it racy and check in next sync */
04052d7cacaa866a3f00afb4e104fa46c04c1dd7Timo Sirainen ctx->mbox->maildir_hdr.cur_check_time = 0;
04052d7cacaa866a3f00afb4e104fa46c04c1dd7Timo Sirainen maildir_uidlist_add_flags(ctx->mbox->uidlist, filename,
3cf67672fdc87583cb23ce088c95bb5dee60e74dTimo Sirainen MAILDIR_UIDLIST_REC_FLAG_RACING);
3cf67672fdc87583cb23ce088c95bb5dee60e74dTimo Sirainen return;
3cf67672fdc87583cb23ce088c95bb5dee60e74dTimo Sirainen }
3cf67672fdc87583cb23ce088c95bb5dee60e74dTimo Sirainen
3cf67672fdc87583cb23ce088c95bb5dee60e74dTimo Sirainen if (ctx->uidlist_sync_ctx == NULL) {
7744586e3e0fd60158abfbb03a233d3bd8d6c48bTimo Sirainen ret = maildir_uidlist_sync_init(ctx->mbox->uidlist,
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen MAILDIR_UIDLIST_SYNC_PARTIAL |
1b823b2b7790a1e1b7974fcf11a4c48a28e70f37Timo Sirainen MAILDIR_UIDLIST_SYNC_KEEP_STATE,
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen &ctx->uidlist_sync_ctx);
9dd1c256910f1fb42823116a641e7edb3ad11970Timo Sirainen i_assert(ret > 0);
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen }
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen uflags &= MAILDIR_UIDLIST_REC_FLAG_NEW_DIR;
9dd1c256910f1fb42823116a641e7edb3ad11970Timo Sirainen maildir_uidlist_sync_remove(ctx->uidlist_sync_ctx, filename);
9dd1c256910f1fb42823116a641e7edb3ad11970Timo Sirainen ret = maildir_uidlist_sync_next(ctx->uidlist_sync_ctx,
9dd1c256910f1fb42823116a641e7edb3ad11970Timo Sirainen filename, uflags);
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen i_assert(ret > 0);
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen /* give the new UID to it immediately */
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen maildir_uidlist_sync_finish(ctx->uidlist_sync_ctx);
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen i_warning("Maildir %s: Expunged message reappeared, giving a new UID "
7744586e3e0fd60158abfbb03a233d3bd8d6c48bTimo Sirainen "(old uid=%u, file=%s)", ctx->mbox->path, uid, filename);
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen}
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen
04052d7cacaa866a3f00afb4e104fa46c04c1dd7Timo Sirainenint maildir_sync_index_begin(struct maildir_mailbox *mbox,
04052d7cacaa866a3f00afb4e104fa46c04c1dd7Timo Sirainen struct maildir_sync_context *maildir_sync_ctx,
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen struct maildir_index_sync_context **ctx_r)
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen{
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen struct maildir_index_sync_context *ctx;
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen struct mail_index_sync_ctx *sync_ctx;
1b823b2b7790a1e1b7974fcf11a4c48a28e70f37Timo Sirainen struct mail_index_view *view;
3cf67672fdc87583cb23ce088c95bb5dee60e74dTimo Sirainen struct mail_index_transaction *trans;
04052d7cacaa866a3f00afb4e104fa46c04c1dd7Timo Sirainen enum mail_index_sync_flags sync_flags;
04052d7cacaa866a3f00afb4e104fa46c04c1dd7Timo Sirainen
04052d7cacaa866a3f00afb4e104fa46c04c1dd7Timo Sirainen sync_flags = 0;
3cf67672fdc87583cb23ce088c95bb5dee60e74dTimo Sirainen /* don't drop recent messages if we're saving messages */
3cf67672fdc87583cb23ce088c95bb5dee60e74dTimo Sirainen if (!mbox->ibox.keep_recent && maildir_sync_ctx != NULL)
7744586e3e0fd60158abfbb03a233d3bd8d6c48bTimo Sirainen sync_flags |= MAIL_INDEX_SYNC_FLAG_DROP_RECENT;
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen
1b823b2b7790a1e1b7974fcf11a4c48a28e70f37Timo Sirainen if (mail_index_sync_begin(mbox->ibox.index, &sync_ctx, &view, &trans,
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen (uint32_t)-1, (uoff_t)-1, sync_flags) <= 0) {
9dd1c256910f1fb42823116a641e7edb3ad11970Timo Sirainen mail_storage_set_index_error(&mbox->ibox);
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen return -1;
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen }
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen
9dd1c256910f1fb42823116a641e7edb3ad11970Timo Sirainen ctx = i_new(struct maildir_index_sync_context, 1);
9dd1c256910f1fb42823116a641e7edb3ad11970Timo Sirainen ctx->mbox = mbox;
9dd1c256910f1fb42823116a641e7edb3ad11970Timo Sirainen ctx->maildir_sync_ctx = maildir_sync_ctx;
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen ctx->sync_ctx = sync_ctx;
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen ctx->view = view;
57d2429fae575e96ca276355af675deb66b76d00Timo Sirainen ctx->trans = trans;
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen ctx->keywords_sync_ctx =
401b0787fff2dc986a5321ddb32acb1947ff66b0Timo Sirainen maildir_keywords_sync_init(mbox->keywords, mbox->ibox.index);
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen ctx->sync_changes = index_sync_changes_init(&mbox->ibox, ctx->sync_ctx,
57d2429fae575e96ca276355af675deb66b76d00Timo Sirainen ctx->view, ctx->trans,
401b0787fff2dc986a5321ddb32acb1947ff66b0Timo Sirainen mbox->ibox.readonly);
401b0787fff2dc986a5321ddb32acb1947ff66b0Timo Sirainen
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen *ctx_r = ctx;
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen return 0;
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen}
7744586e3e0fd60158abfbb03a233d3bd8d6c48bTimo Sirainen
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainenint maildir_sync_index_finish(struct maildir_index_sync_context **_ctx,
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen bool failed, bool cancel)
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen{
61618d4c58080570f689614fec204ae14e90cef2Timo Sirainen struct maildir_index_sync_context *ctx = *_ctx;
50e20db49f29917fe9adcf1b56b11badf28bd0e4Timo Sirainen struct maildir_mailbox *mbox = ctx->mbox;
50e20db49f29917fe9adcf1b56b11badf28bd0e4Timo Sirainen int ret = failed ? -1 : 0;
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen *_ctx = NULL;
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen if (ret < 0 || cancel)
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen mail_index_sync_rollback(&ctx->sync_ctx);
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen else {
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen /* Set syncing_commit=TRUE so that if any sync callbacks try
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen to access mails which got lost (eg. expunge callback trying
738cfeb96c4b9cd92aa3c791d77734c2745cdd1aTimo Sirainen to open the file which was just unlinked) we don't try to
50e20db49f29917fe9adcf1b56b11badf28bd0e4Timo Sirainen start a second index sync and crash. */
a7f5035eebbd138a5436a2eb2ce1fa5fd3d269fbTimo Sirainen mbox->syncing_commit = TRUE;
a7f5035eebbd138a5436a2eb2ce1fa5fd3d269fbTimo Sirainen if (mail_index_sync_commit(&ctx->sync_ctx) < 0) {
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen mail_storage_set_index_error(&mbox->ibox);
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen ret = -1;
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen } else {
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen mbox->ibox.commit_log_file_seq = 0;
c6f894e1522f7b0b6068c228900914073c145175Timo Sirainen mbox->ibox.commit_log_file_offset = 0;
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen }
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen mbox->syncing_commit = FALSE;
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen }
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen maildir_keywords_sync_deinit(ctx->keywords_sync_ctx);
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen ctx->keywords_sync_ctx = NULL;
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen index_sync_changes_deinit(&ctx->sync_changes);
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen i_free(ctx);
1da01eaa962be13cee75771064e2256b1a82d90aTimo Sirainen return ret;
401b0787fff2dc986a5321ddb32acb1947ff66b0Timo Sirainen}
401b0787fff2dc986a5321ddb32acb1947ff66b0Timo Sirainen
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainenstatic void
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainenmaildir_index_update_ext_header(struct maildir_mailbox *mbox,
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen struct mail_index_transaction *trans)
7744586e3e0fd60158abfbb03a233d3bd8d6c48bTimo Sirainen{
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen const void *data;
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen size_t data_size;
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen if (mail_index_get_header_ext(mbox->ibox.view, mbox->maildir_ext_id,
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen &data, &data_size) < 0)
f2df3069766c747cbf020fea5d3a4261949064b0Timo Sirainen data_size = 0;
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen if (data_size == sizeof(mbox->maildir_hdr) &&
062ea54b7775d0c92ed67b9b1f4d93fa8ec80c84Timo Sirainen memcmp(data, &mbox->maildir_hdr, data_size) == 0) {
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen /* nothing changed */
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen } else {
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen mail_index_update_header_ext(trans, mbox->maildir_ext_id, 0,
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen &mbox->maildir_hdr,
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen sizeof(mbox->maildir_hdr));
738cfeb96c4b9cd92aa3c791d77734c2745cdd1aTimo Sirainen }
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen}
a7f5035eebbd138a5436a2eb2ce1fa5fd3d269fbTimo Sirainen
a7f5035eebbd138a5436a2eb2ce1fa5fd3d269fbTimo Sirainenint maildir_sync_index(struct maildir_index_sync_context *ctx,
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen bool partial)
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen{
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen struct maildir_mailbox *mbox = ctx->mbox;
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen struct mail_index_view *view = ctx->view;
c6f894e1522f7b0b6068c228900914073c145175Timo Sirainen struct maildir_uidlist_iter_ctx *iter;
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen struct mail_index_transaction *trans = ctx->trans;
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen const struct mail_index_header *hdr;
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen struct mail_index_header empty_hdr;
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen const struct mail_index_record *rec;
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen uint32_t seq, uid, prev_uid;
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen enum maildir_uidlist_rec_flag uflags;
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen const char *filename;
401b0787fff2dc986a5321ddb32acb1947ff66b0Timo Sirainen ARRAY_TYPE(keyword_indexes) idx_keywords;
401b0787fff2dc986a5321ddb32acb1947ff66b0Timo Sirainen uint32_t uid_validity, next_uid, hdr_next_uid, last_nonrecent_uid;
1da01eaa962be13cee75771064e2256b1a82d90aTimo Sirainen unsigned int changes = 0;
401b0787fff2dc986a5321ddb32acb1947ff66b0Timo Sirainen int ret = 0;
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen bool recent, expunged, full_rescan = FALSE;
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen
7744586e3e0fd60158abfbb03a233d3bd8d6c48bTimo Sirainen i_assert(!mbox->syncing_commit);
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen i_assert(maildir_uidlist_is_locked(mbox->uidlist));
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen hdr = mail_index_get_header(view);
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen uid_validity = maildir_uidlist_get_uid_validity(mbox->uidlist);
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen if (uid_validity != hdr->uid_validity &&
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen uid_validity != 0 && hdr->uid_validity != 0) {
383d0e8c24451468d6bea17e4b55d74de744abe6Timo Sirainen /* uidvalidity changed and index isn't being synced for the
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen first time, reset the index so we can add all messages as
383d0e8c24451468d6bea17e4b55d74de744abe6Timo Sirainen new */
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen i_warning("Maildir %s: UIDVALIDITY changed (%u -> %u)",
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen mbox->path, hdr->uid_validity, uid_validity);
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen mail_index_reset(trans);
d477acb83e14a776ece4ca94dcd1869e75d0c6eeTimo Sirainen maildir_uidlist_set_next_uid(mbox->uidlist, 1, TRUE);
738cfeb96c4b9cd92aa3c791d77734c2745cdd1aTimo Sirainen
738cfeb96c4b9cd92aa3c791d77734c2745cdd1aTimo Sirainen memset(&empty_hdr, 0, sizeof(empty_hdr));
738cfeb96c4b9cd92aa3c791d77734c2745cdd1aTimo Sirainen empty_hdr.next_uid = 1;
738cfeb96c4b9cd92aa3c791d77734c2745cdd1aTimo Sirainen hdr = &empty_hdr;
738cfeb96c4b9cd92aa3c791d77734c2745cdd1aTimo Sirainen }
738cfeb96c4b9cd92aa3c791d77734c2745cdd1aTimo Sirainen hdr_next_uid = hdr->next_uid;
738cfeb96c4b9cd92aa3c791d77734c2745cdd1aTimo Sirainen
738cfeb96c4b9cd92aa3c791d77734c2745cdd1aTimo Sirainen mbox->syncing_commit = TRUE;
738cfeb96c4b9cd92aa3c791d77734c2745cdd1aTimo Sirainen seq = prev_uid = last_nonrecent_uid = 0;
738cfeb96c4b9cd92aa3c791d77734c2745cdd1aTimo Sirainen t_array_init(&ctx->keywords, MAILDIR_MAX_KEYWORDS);
738cfeb96c4b9cd92aa3c791d77734c2745cdd1aTimo Sirainen t_array_init(&idx_keywords, MAILDIR_MAX_KEYWORDS);
738cfeb96c4b9cd92aa3c791d77734c2745cdd1aTimo Sirainen iter = maildir_uidlist_iter_init(mbox->uidlist);
738cfeb96c4b9cd92aa3c791d77734c2745cdd1aTimo Sirainen while (maildir_uidlist_iter_next(iter, &uid, &uflags, &filename)) {
738cfeb96c4b9cd92aa3c791d77734c2745cdd1aTimo Sirainen maildir_filename_get_flags(ctx->keywords_sync_ctx, filename,
738cfeb96c4b9cd92aa3c791d77734c2745cdd1aTimo Sirainen &ctx->flags, &ctx->keywords);
738cfeb96c4b9cd92aa3c791d77734c2745cdd1aTimo Sirainen
738cfeb96c4b9cd92aa3c791d77734c2745cdd1aTimo Sirainen i_assert(uid > prev_uid);
738cfeb96c4b9cd92aa3c791d77734c2745cdd1aTimo Sirainen prev_uid = uid;
738cfeb96c4b9cd92aa3c791d77734c2745cdd1aTimo Sirainen
738cfeb96c4b9cd92aa3c791d77734c2745cdd1aTimo Sirainen /* the private flags are kept only in indexes. don't use them
738cfeb96c4b9cd92aa3c791d77734c2745cdd1aTimo Sirainen at all even for newly seen mails */
738cfeb96c4b9cd92aa3c791d77734c2745cdd1aTimo Sirainen ctx->flags &= ~mbox->ibox.box.private_flags_mask;
738cfeb96c4b9cd92aa3c791d77734c2745cdd1aTimo Sirainen
738cfeb96c4b9cd92aa3c791d77734c2745cdd1aTimo Sirainen __again:
738cfeb96c4b9cd92aa3c791d77734c2745cdd1aTimo Sirainen ctx->seq = ++seq;
738cfeb96c4b9cd92aa3c791d77734c2745cdd1aTimo Sirainen ctx->uid = uid;
738cfeb96c4b9cd92aa3c791d77734c2745cdd1aTimo Sirainen
738cfeb96c4b9cd92aa3c791d77734c2745cdd1aTimo Sirainen if ((uflags & MAILDIR_UIDLIST_REC_FLAG_RECENT) == 0 &&
738cfeb96c4b9cd92aa3c791d77734c2745cdd1aTimo Sirainen (uflags & MAILDIR_UIDLIST_REC_FLAG_NONSYNCED) == 0)
738cfeb96c4b9cd92aa3c791d77734c2745cdd1aTimo Sirainen last_nonrecent_uid = uid;
738cfeb96c4b9cd92aa3c791d77734c2745cdd1aTimo Sirainen recent = (uflags & MAILDIR_UIDLIST_REC_FLAG_RECENT) != 0 &&
7289c5600711b45f30fe289ab5b0293b51d87041Timo Sirainen uid >= hdr->first_recent_uid;
4fc74bba3548987b7e8597491cd9fafc1f701be6Timo Sirainen
d477acb83e14a776ece4ca94dcd1869e75d0c6eeTimo Sirainen if (seq > hdr->messages_count) {
d477acb83e14a776ece4ca94dcd1869e75d0c6eeTimo Sirainen if (uid < hdr_next_uid) {
7289c5600711b45f30fe289ab5b0293b51d87041Timo Sirainen maildir_handle_uid_insertion(ctx, uflags,
d477acb83e14a776ece4ca94dcd1869e75d0c6eeTimo Sirainen filename, uid);
15f526e5ac611b4532568d131fcd0abf664abe41Timo Sirainen seq--;
15f526e5ac611b4532568d131fcd0abf664abe41Timo Sirainen continue;
15f526e5ac611b4532568d131fcd0abf664abe41Timo Sirainen }
15f526e5ac611b4532568d131fcd0abf664abe41Timo Sirainen
7289c5600711b45f30fe289ab5b0293b51d87041Timo Sirainen hdr_next_uid = uid + 1;
f93c833d644ecff0b0f80bee4f1cdde3e697b5c8Timo Sirainen mail_index_append(trans, uid, &seq);
f93c833d644ecff0b0f80bee4f1cdde3e697b5c8Timo Sirainen mail_index_update_flags(trans, seq, MODIFY_REPLACE,
f93c833d644ecff0b0f80bee4f1cdde3e697b5c8Timo Sirainen ctx->flags);
f93c833d644ecff0b0f80bee4f1cdde3e697b5c8Timo Sirainen if (array_count(&ctx->keywords) > 0) {
f93c833d644ecff0b0f80bee4f1cdde3e697b5c8Timo Sirainen struct mail_keywords *kw;
6bd263caf006edc75205f446fa0283c6f364941bTimo Sirainen
4fc74bba3548987b7e8597491cd9fafc1f701be6Timo Sirainen kw = mail_index_keywords_create_from_indexes(
4fc74bba3548987b7e8597491cd9fafc1f701be6Timo Sirainen trans, &ctx->keywords);
4fc74bba3548987b7e8597491cd9fafc1f701be6Timo Sirainen mail_index_update_keywords(trans, seq,
4fc74bba3548987b7e8597491cd9fafc1f701be6Timo Sirainen MODIFY_REPLACE, kw);
4fc74bba3548987b7e8597491cd9fafc1f701be6Timo Sirainen mail_index_keywords_free(&kw);
4fc74bba3548987b7e8597491cd9fafc1f701be6Timo Sirainen }
4fc74bba3548987b7e8597491cd9fafc1f701be6Timo Sirainen if (recent)
4fc74bba3548987b7e8597491cd9fafc1f701be6Timo Sirainen index_mailbox_set_recent_uid(&mbox->ibox, uid);
7289c5600711b45f30fe289ab5b0293b51d87041Timo Sirainen continue;
7289c5600711b45f30fe289ab5b0293b51d87041Timo Sirainen }
7289c5600711b45f30fe289ab5b0293b51d87041Timo Sirainen
7289c5600711b45f30fe289ab5b0293b51d87041Timo Sirainen if (mail_index_lookup(view, seq, &rec) < 0) {
7289c5600711b45f30fe289ab5b0293b51d87041Timo Sirainen mail_storage_set_index_error(&mbox->ibox);
0f62889d833767acf9c2ad010c3269806b4cfae3Timo Sirainen ret = -1;
7289c5600711b45f30fe289ab5b0293b51d87041Timo Sirainen break;
7289c5600711b45f30fe289ab5b0293b51d87041Timo Sirainen }
7289c5600711b45f30fe289ab5b0293b51d87041Timo Sirainen
7289c5600711b45f30fe289ab5b0293b51d87041Timo Sirainen if (uid > rec->uid) {
7289c5600711b45f30fe289ab5b0293b51d87041Timo Sirainen /* expunged */
7289c5600711b45f30fe289ab5b0293b51d87041Timo Sirainen mail_index_expunge(trans, seq);
7289c5600711b45f30fe289ab5b0293b51d87041Timo Sirainen goto __again;
7289c5600711b45f30fe289ab5b0293b51d87041Timo Sirainen }
7289c5600711b45f30fe289ab5b0293b51d87041Timo Sirainen
7289c5600711b45f30fe289ab5b0293b51d87041Timo Sirainen if (uid < rec->uid) {
738cfeb96c4b9cd92aa3c791d77734c2745cdd1aTimo Sirainen maildir_handle_uid_insertion(ctx, uflags,
738cfeb96c4b9cd92aa3c791d77734c2745cdd1aTimo Sirainen filename, uid);
738cfeb96c4b9cd92aa3c791d77734c2745cdd1aTimo Sirainen seq--;
d477acb83e14a776ece4ca94dcd1869e75d0c6eeTimo Sirainen continue;
d477acb83e14a776ece4ca94dcd1869e75d0c6eeTimo Sirainen }
9dd1c256910f1fb42823116a641e7edb3ad11970Timo Sirainen
9dd1c256910f1fb42823116a641e7edb3ad11970Timo Sirainen if (index_sync_changes_read(ctx->sync_changes, rec->uid,
9dd1c256910f1fb42823116a641e7edb3ad11970Timo Sirainen &expunged) < 0) {
9dd1c256910f1fb42823116a641e7edb3ad11970Timo Sirainen ret = -1;
9dd1c256910f1fb42823116a641e7edb3ad11970Timo Sirainen break;
9dd1c256910f1fb42823116a641e7edb3ad11970Timo Sirainen }
9dd1c256910f1fb42823116a641e7edb3ad11970Timo Sirainen
9dd1c256910f1fb42823116a641e7edb3ad11970Timo Sirainen if (expunged) {
9dd1c256910f1fb42823116a641e7edb3ad11970Timo Sirainen if (maildir_file_do(mbox, ctx->uid,
9dd1c256910f1fb42823116a641e7edb3ad11970Timo Sirainen maildir_expunge, ctx) >= 0) {
9dd1c256910f1fb42823116a641e7edb3ad11970Timo Sirainen /* successful expunge */
9dd1c256910f1fb42823116a641e7edb3ad11970Timo Sirainen mail_index_expunge(trans, seq);
9dd1c256910f1fb42823116a641e7edb3ad11970Timo Sirainen }
9dd1c256910f1fb42823116a641e7edb3ad11970Timo Sirainen if ((++changes % MAILDIR_SLOW_MOVE_COUNT) == 0)
9dd1c256910f1fb42823116a641e7edb3ad11970Timo Sirainen maildir_sync_notify(ctx->maildir_sync_ctx);
9dd1c256910f1fb42823116a641e7edb3ad11970Timo Sirainen continue;
9dd1c256910f1fb42823116a641e7edb3ad11970Timo Sirainen }
9dd1c256910f1fb42823116a641e7edb3ad11970Timo Sirainen
9dd1c256910f1fb42823116a641e7edb3ad11970Timo Sirainen if (recent)
9dd1c256910f1fb42823116a641e7edb3ad11970Timo Sirainen index_mailbox_set_recent_uid(&mbox->ibox, uid);
9dd1c256910f1fb42823116a641e7edb3ad11970Timo Sirainen
272aca0a772140d3a45a425a3fd67854ae2ccec2Timo Sirainen /* the private flags are stored only in indexes, keep them */
9dd1c256910f1fb42823116a641e7edb3ad11970Timo Sirainen ctx->flags |= rec->flags & mbox->ibox.box.private_flags_mask;
9dd1c256910f1fb42823116a641e7edb3ad11970Timo Sirainen
9dd1c256910f1fb42823116a641e7edb3ad11970Timo Sirainen if ((uflags & MAILDIR_UIDLIST_REC_FLAG_NONSYNCED) != 0) {
9dd1c256910f1fb42823116a641e7edb3ad11970Timo Sirainen /* partial syncing */
d477acb83e14a776ece4ca94dcd1869e75d0c6eeTimo Sirainen if ((uflags & MAILDIR_UIDLIST_REC_FLAG_NEW_DIR) != 0) {
d477acb83e14a776ece4ca94dcd1869e75d0c6eeTimo Sirainen /* we last saw this mail in new/, but it's
1d22eaac93de41319918a1fc6de42bb302e25c1aTimo Sirainen not there anymore. possibly expunged,
1d22eaac93de41319918a1fc6de42bb302e25c1aTimo Sirainen make sure. */
5d60e31c7b701b606067a20bc88dcc8a6de7bbd6Timo Sirainen full_rescan = TRUE;
5d60e31c7b701b606067a20bc88dcc8a6de7bbd6Timo Sirainen }
5d60e31c7b701b606067a20bc88dcc8a6de7bbd6Timo Sirainen continue;
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen }
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
2024157e8de36edd31f5fd72f5ea7364a0955fa7Timo Sirainen if (index_sync_changes_have(ctx->sync_changes)) {
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen /* apply flag changes to maildir */
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if (maildir_file_do(mbox, ctx->uid,
9ed2951bd0bb1878a27437d7c00611b2baadd614Timo Sirainen maildir_sync_flags, ctx) < 0)
5d60e31c7b701b606067a20bc88dcc8a6de7bbd6Timo Sirainen ctx->flags |= MAIL_INDEX_MAIL_FLAG_DIRTY;
e9371f899a3d4207a0ffd3923ea5ec7250cf5e75Timo Sirainen if ((++changes % MAILDIR_SLOW_MOVE_COUNT) == 0)
b215a8a123623782554a83f3025ef4e771bd8f01Timo Sirainen maildir_sync_notify(ctx->maildir_sync_ctx);
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen }
9ed2951bd0bb1878a27437d7c00611b2baadd614Timo Sirainen
9ed2951bd0bb1878a27437d7c00611b2baadd614Timo Sirainen if ((rec->flags & MAIL_INDEX_MAIL_FLAG_DIRTY) != 0) {
9ed2951bd0bb1878a27437d7c00611b2baadd614Timo Sirainen /* we haven't been able to update maildir with this
9ed2951bd0bb1878a27437d7c00611b2baadd614Timo Sirainen record's flag changes. don't sync them. */
9ed2951bd0bb1878a27437d7c00611b2baadd614Timo Sirainen continue;
5d60e31c7b701b606067a20bc88dcc8a6de7bbd6Timo Sirainen }
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
b215a8a123623782554a83f3025ef4e771bd8f01Timo Sirainen if (ctx->flags != (rec->flags & MAIL_FLAGS_NONRECENT)) {
e9371f899a3d4207a0ffd3923ea5ec7250cf5e75Timo Sirainen mail_index_update_flags(trans, seq, MODIFY_REPLACE,
5d60e31c7b701b606067a20bc88dcc8a6de7bbd6Timo Sirainen ctx->flags);
5d60e31c7b701b606067a20bc88dcc8a6de7bbd6Timo Sirainen }
5d60e31c7b701b606067a20bc88dcc8a6de7bbd6Timo Sirainen
5d60e31c7b701b606067a20bc88dcc8a6de7bbd6Timo Sirainen /* update keywords if they have changed */
e9371f899a3d4207a0ffd3923ea5ec7250cf5e75Timo Sirainen if (mail_index_lookup_keywords(view, seq, &idx_keywords) < 0) {
e9371f899a3d4207a0ffd3923ea5ec7250cf5e75Timo Sirainen mail_storage_set_index_error(&mbox->ibox);
e9371f899a3d4207a0ffd3923ea5ec7250cf5e75Timo Sirainen ret = -1;
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen break;
}
if (!index_keyword_array_cmp(&ctx->keywords, &idx_keywords)) {
struct mail_keywords *kw;
kw = mail_index_keywords_create_from_indexes(
trans, &ctx->keywords);
mail_index_update_keywords(trans, seq,
MODIFY_REPLACE, kw);
mail_index_keywords_free(&kw);
}
}
maildir_uidlist_iter_deinit(iter);
mbox->syncing_commit = FALSE;
if (ctx->uidlist_sync_ctx != NULL) {
if (maildir_uidlist_sync_deinit(&ctx->uidlist_sync_ctx) < 0)
ret = -1;
}
if (mbox->ibox.box.v.sync_notify != NULL)
mbox->ibox.box.v.sync_notify(&mbox->ibox.box, 0, 0);
if (!partial) {
/* expunge the rest */
for (seq++; seq <= hdr->messages_count; seq++)
mail_index_expunge(trans, seq);
}
if (ctx->changed)
mbox->maildir_hdr.cur_mtime = time(NULL);
maildir_index_update_ext_header(mbox, trans);
if (uid_validity == 0) {
uid_validity = hdr->uid_validity != 0 ?
hdr->uid_validity : (uint32_t)ioloop_time;
maildir_uidlist_set_uid_validity(mbox->uidlist, uid_validity);
}
maildir_uidlist_set_next_uid(mbox->uidlist, hdr_next_uid, FALSE);
if (uid_validity != hdr->uid_validity) {
mail_index_update_header(trans,
offsetof(struct mail_index_header, uid_validity),
&uid_validity, sizeof(uid_validity), TRUE);
}
next_uid = maildir_uidlist_get_next_uid(mbox->uidlist);
if (hdr_next_uid < next_uid) {
mail_index_update_header(trans,
offsetof(struct mail_index_header, next_uid),
&next_uid, sizeof(next_uid), FALSE);
}
if (ctx->mbox->ibox.keep_recent &&
hdr->first_recent_uid < last_nonrecent_uid + 1) {
uint32_t first_recent_uid = last_nonrecent_uid + 1;
mail_index_update_header(ctx->trans,
offsetof(struct mail_index_header, first_recent_uid),
&first_recent_uid, sizeof(first_recent_uid), FALSE);
}
return ret < 0 ? -1 : (full_rescan ? 0 : 1);
}