maildir-sync-index.c revision f6f021c133f680cf3d559187524fd9abcbaae9b9
2e37d45867d081db150ab78dad303b9077aea24fTimo Sirainen/* Copyright (c) 2007-2010 Dovecot authors, see the included COPYING file */
91b203fd2132510a47a4b34252c0ae0efd688a19Timo Sirainen struct maildir_sync_context *maildir_sync_ctx;
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen struct maildir_keywords_sync_ctx *keywords_sync_ctx;
5694eeb99b69dea8033ca77ad69743c6b4871370Timo Sirainen struct maildir_uidlist_sync_ctx *uidlist_sync_ctx;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen struct index_sync_changes_context *sync_changes;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen ARRAY_TYPE(keyword_indexes) keywords, idx_keywords;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen unsigned int flag_change_count, expunge_count, new_msgs_count;
de486b59018016977015ef42e6071155b60e82e1Timo Sirainenmaildir_sync_get_keywords_sync_ctx(struct maildir_index_sync_context *ctx)
de486b59018016977015ef42e6071155b60e82e1Timo Sirainenvoid maildir_sync_set_new_msgs_count(struct maildir_index_sync_context *ctx,
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen unsigned int count)
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainenmaildir_expunge_is_valid_guid(struct maildir_index_sync_context *ctx,
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainen uint8_t expunged_guid_128[MAIL_GUID_128_SIZE])
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainen if (mail_guid_128_is_empty(expunged_guid_128)) {
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen /* no GUID associated with expunge */
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen guid = maildir_uidlist_lookup_ext(ctx->mbox->uidlist, uid,
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen if (memcmp(guid_128, expunged_guid_128, sizeof(guid_128)) == 0)
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen mail_storage_set_critical(&ctx->mbox->storage->storage,
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen "Mailbox %s: Expunged GUID mismatch for UID %u: %s vs %s",
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainen binary_to_hex(expunged_guid_128, MAIL_GUID_128_SIZE));
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainenstatic int maildir_expunge(struct maildir_mailbox *mbox, const char *path,
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen return maildir_lose_unexpected_dir(box->storage, path);
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen mail_storage_set_critical(&mbox->storage->storage,
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainenstatic int maildir_sync_flags(struct maildir_mailbox *mbox, const char *path,
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen /* get the current flags and keywords */
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen maildir_filename_get_flags(ctx->keywords_sync_ctx,
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen /* apply changes */
1701e3f91107051b1704721bf1dc1e32491faaf9Timo Sirainen index_sync_changes_apply(ctx->sync_changes, NULL,
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen /* and try renaming with the new name */
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen newfname = maildir_filename_set_flags(ctx->keywords_sync_ctx, fname,
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen /* just make sure that the file still exists. avoid rename()
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen here because it's slow on HFS. */
3fe67ec75ccae1230bb9eb9f16affc48377f6441Timo Sirainen "rename(%s, %s) failed: %m",
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainenstatic int maildir_handle_uid_insertion(struct maildir_index_sync_context *ctx,
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen if ((uflags & MAILDIR_UIDLIST_REC_FLAG_NONSYNCED) != 0) {
27586e4785d56aeb76e1fd96af8db799688dc64aTimo Sirainen /* partial syncing */
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen /* most likely a race condition: we read the maildir, then someone else
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen expunged messages and committed changes to index. so, this message
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen shouldn't actually exist. */
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen if ((uflags & MAILDIR_UIDLIST_REC_FLAG_RACING) == 0) {
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen /* mark it racy and check in next sync */
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen maildir_uidlist_add_flags(ctx->mbox->uidlist, filename,
e5acc283bf030b0b5c79ca4e52d315c516a299faPascal Volk ret = maildir_uidlist_sync_init(ctx->mbox->uidlist,
db8b0a3f74a20528d66a3c4be7df920e5c4554c2Timo Sirainen maildir_uidlist_sync_remove(ctx->uidlist_sync_ctx, filename);
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen ret = maildir_uidlist_sync_next(ctx->uidlist_sync_ctx,
1701e3f91107051b1704721bf1dc1e32491faaf9Timo Sirainen /* give the new UID to it immediately */
b365bd121cdc87f63e1dd47c5085a27091118e00Timo Sirainen maildir_uidlist_sync_finish(ctx->uidlist_sync_ctx);
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen i_warning("Maildir %s: Expunged message reappeared, giving a new UID "
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen "(old uid=%u, file=%s)%s", ctx->mbox->box.path,
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen uid, filename, strncmp(filename, "msg.", 4) != 0 ? "" :
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen " (Your MDA is saving MH files into Maildir?)");
94b0ff77495c3ed14bdd4b5d7ae1eb37e8c9efb5Timo Sirainenint maildir_sync_index_begin(struct maildir_mailbox *mbox,
94b0ff77495c3ed14bdd4b5d7ae1eb37e8c9efb5Timo Sirainen struct maildir_sync_context *maildir_sync_ctx,
94b0ff77495c3ed14bdd4b5d7ae1eb37e8c9efb5Timo Sirainen sync_flags = index_storage_get_sync_flags(&mbox->box);
94b0ff77495c3ed14bdd4b5d7ae1eb37e8c9efb5Timo Sirainen /* don't drop recent messages if we're saving messages */
02e61e13a8360a9d3ec92c5fa5ae60c0f0181b71Timo Sirainen sync_flags &= ~MAIL_INDEX_SYNC_FLAG_DROP_RECENT;
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen if (mail_index_sync_begin(_box->index, &sync_ctx, &view,
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen ctx = i_new(struct maildir_index_sync_context, 1);
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen maildir_keywords_sync_init(mbox->keywords, _box->index);
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen index_sync_changes_init(ctx->sync_ctx, ctx->view, ctx->trans,
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainenmaildir_index_header_has_changed(const struct maildir_index_header *old_hdr,
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen if (old_hdr->new_mtime != new_hdr->new_mtime ||
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen old_hdr->new_mtime_nsecs != new_hdr->new_mtime_nsecs ||
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen old_hdr->cur_mtime_nsecs != new_hdr->cur_mtime_nsecs ||
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen old_hdr->uidlist_mtime != new_hdr->uidlist_mtime ||
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen old_hdr->uidlist_mtime_nsecs != new_hdr->uidlist_mtime_nsecs ||
b365bd121cdc87f63e1dd47c5085a27091118e00Timo Sirainen old_hdr->uidlist_size != new_hdr->uidlist_size)
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainenmaildir_sync_index_update_ext_header(struct maildir_index_sync_context *ctx)
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen stat(t_strconcat(mbox->box.path, "/cur", NULL), &st) == 0) {
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen if ((time_t)mbox->maildir_hdr.cur_check_time < st.st_mtime)
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen mbox->maildir_hdr.cur_check_time = st.st_mtime;
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen mbox->maildir_hdr.cur_mtime_nsecs = ST_MTIME_NSEC(st);
b365bd121cdc87f63e1dd47c5085a27091118e00Timo Sirainen mail_index_get_header_ext(mbox->box.view, mbox->maildir_ext_id,
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen maildir_index_header_has_changed(data, &mbox->maildir_hdr)) {
b365bd121cdc87f63e1dd47c5085a27091118e00Timo Sirainen mail_index_update_header_ext(ctx->trans, mbox->maildir_ext_id,
b365bd121cdc87f63e1dd47c5085a27091118e00Timo Sirainenstatic int maildir_sync_index_finish(struct maildir_index_sync_context *ctx,
94b0ff77495c3ed14bdd4b5d7ae1eb37e8c9efb5Timo Sirainen if (time_diff >= MAILDIR_SYNC_TIME_WARN_SECS) {
02e61e13a8360a9d3ec92c5fa5ae60c0f0181b71Timo Sirainen i_warning("Maildir %s: Synchronization took %u seconds "
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen "(%u new msgs, %u flag change attempts, "
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen "%u expunge attempts)",
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen /* Set syncing_commit=TRUE so that if any sync callbacks try
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen to access mails which got lost (eg. expunge callback trying
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen to open the file which was just unlinked) we don't try to
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen start a second index sync and crash. */
94d8e51119003d2bc5a100c663f90141f297385dTimo Sirainen if (mail_index_sync_commit(&ctx->sync_ctx) < 0) {
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen maildir_keywords_sync_deinit(&ctx->keywords_sync_ctx);
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen index_sync_changes_deinit(&ctx->sync_changes);
94d8e51119003d2bc5a100c663f90141f297385dTimo Sirainenint maildir_sync_index_commit(struct maildir_index_sync_context **_ctx)
94d8e51119003d2bc5a100c663f90141f297385dTimo Sirainen struct maildir_index_sync_context *ctx = *_ctx;
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainenvoid maildir_sync_index_rollback(struct maildir_index_sync_context **_ctx)
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen struct maildir_index_sync_context *ctx = *_ctx;
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainenstatic int uint_cmp(const void *p1, const void *p2)
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainenmaildir_sync_mail_keywords(struct maildir_index_sync_context *ctx, uint32_t seq)
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen const unsigned int *old_indexes, *new_indexes;
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen mail_index_lookup_keywords(ctx->view, seq, &ctx->idx_keywords);
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen if (index_keyword_array_cmp(&ctx->keywords, &ctx->idx_keywords)) {
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen /* no changes - we should get here usually */
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen /* sort the keywords */
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen /* drop keywords that are in index-only. we don't want to touch them. */
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen old_indexes = array_get(&ctx->idx_keywords, &old_count);
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen for (i = old_count; i > 0; i--) {
636f017be100bce67d66fd3ae1544a47681efd33Timo Sirainen /* no index-only keywords found, so something changed.
636f017be100bce67d66fd3ae1544a47681efd33Timo Sirainen just replace them all. */
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen kw = mail_index_keywords_create_from_indexes(box->index,
494a5de15db3b2806ab31d5ecc3e1c306ae14d06Timo Sirainen mail_index_update_keywords(ctx->trans, seq, MODIFY_REPLACE, kw);
636f017be100bce67d66fd3ae1544a47681efd33Timo Sirainen /* check again if non-index-only keywords changed */
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen if (index_keyword_array_cmp(&ctx->keywords, &ctx->idx_keywords))
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen /* we can't reset all the keywords or we'd drop indexonly keywords too.
08ed4ab71fd2a4e800d9025a736f0f46b771ea90Timo Sirainen so first remove the unwanted keywords and then add back the wanted
08ed4ab71fd2a4e800d9025a736f0f46b771ea90Timo Sirainen ones. we can get these lists easily by removing common elements
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen from old and new keywords. */
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen new_indexes = array_get(&ctx->keywords, &new_count);
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen for (i = j = 0; i < old_count && j < new_count; ) {
636f017be100bce67d66fd3ae1544a47681efd33Timo Sirainen diff = (int)old_indexes[i] - (int)new_indexes[j];
636f017be100bce67d66fd3ae1544a47681efd33Timo Sirainen old_indexes = array_get(&ctx->idx_keywords, &old_count);
636f017be100bce67d66fd3ae1544a47681efd33Timo Sirainen new_indexes = array_get(&ctx->keywords, &new_count);
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen } else if (diff < 0) {
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen kw = mail_index_keywords_create_from_indexes(box->index,
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen mail_index_update_keywords(ctx->trans, seq, MODIFY_REMOVE, kw);
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen kw = mail_index_keywords_create_from_indexes(box->index,
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen mail_index_update_keywords(ctx->trans, seq, MODIFY_ADD, kw);
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainenint maildir_sync_index(struct maildir_index_sync_context *ctx,
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen struct mail_index_transaction *trans = ctx->trans;
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen uint32_t uid_validity, next_uid, hdr_next_uid, first_recent_uid;
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen unsigned int changes = 0;
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen uint8_t expunged_guid_128[MAIL_GUID_128_SIZE];
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen uid_validity = maildir_uidlist_get_uid_validity(mbox->uidlist);
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen uid_validity != 0 && hdr->uid_validity != 0) {
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen /* uidvalidity changed and index isn't being synced for the
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen first time, reset the index so we can add all messages as
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen i_warning("Maildir %s: UIDVALIDITY changed (%u -> %u)",
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen mbox->box.path, hdr->uid_validity, uid_validity);
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen seq = prev_uid = 0; first_recent_uid = I_MAX(hdr->first_recent_uid, 1);
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen i_array_init(&ctx->keywords, MAILDIR_MAX_KEYWORDS);
636f017be100bce67d66fd3ae1544a47681efd33Timo Sirainen i_array_init(&ctx->idx_keywords, MAILDIR_MAX_KEYWORDS);
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen iter = maildir_uidlist_iter_init(mbox->uidlist);
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen while (maildir_uidlist_iter_next(iter, &uid, &uflags, &filename)) {
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen maildir_filename_get_flags(ctx->keywords_sync_ctx, filename,
636f017be100bce67d66fd3ae1544a47681efd33Timo Sirainen /* the private flags are kept only in indexes. don't use them
636f017be100bce67d66fd3ae1544a47681efd33Timo Sirainen at all even for newly seen mails */
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen /* Trust uidlist recent flags only for newly added
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen messages. When saving/copying messages with flags
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen they're stored to cur/ and uidlist treats them
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen as non-recent. */
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen if ((uflags & MAILDIR_UIDLIST_REC_FLAG_RECENT) == 0) {
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen mail_index_update_flags(trans, seq, MODIFY_REPLACE,
cb933f0a570a9cef5c975eadb818aa6b1002a269Timo Sirainen /* already expunged (no point in showing guid in the
37847ec8eaec9ad55c9df10ae109efe7b37ac573Timo Sirainen expunge record anymore) */
c58906589cafc32df4c04ffbef933baadd3f2276Timo Sirainen index_sync_changes_read(ctx->sync_changes, ctx->uid, &expunged,
68a4946b12583b88fa802e52ebee45cd96056772Timo Sirainen if (!maildir_expunge_is_valid_guid(ctx, ctx->uid,
6dd77763f5451269ace733579cf58f2f3b18bca4Timo Sirainen /* successful expunge */
6dd77763f5451269ace733579cf58f2f3b18bca4Timo Sirainen if ((++changes % MAILDIR_SLOW_MOVE_COUNT) == 0)
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen /* the private flags are stored only in indexes, keep them */
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen ctx->flags |= rec->flags & mbox->box.private_flags_mask;
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen if (index_sync_changes_have(ctx->sync_changes)) {
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen /* apply flag changes to maildir */
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen if ((++changes % MAILDIR_SLOW_MOVE_COUNT) == 0)
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen if ((uflags & MAILDIR_UIDLIST_REC_FLAG_NONSYNCED) != 0) {
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen /* partial syncing */
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen if ((uflags & MAILDIR_UIDLIST_REC_FLAG_NEW_DIR) != 0) {
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen /* we last saw this mail in new/, but it's
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen not there anymore. possibly expunged,
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen make sure. */
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen if ((rec->flags & MAIL_INDEX_MAIL_FLAG_DIRTY) != 0) {
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen /* we haven't been able to update maildir with this
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen record's flag changes. don't sync them. */
e5aa8d4c9bdda79c2db03391ec45b37bf774df14Timo Sirainen if (ctx->flags != (rec->flags & MAIL_FLAGS_NONRECENT)) {
490f66d6476d51cc02333d6eb398a5cd94b67f48Timo Sirainen mail_index_update_flags(trans, seq, MODIFY_REPLACE,
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen /* expunge the rest */
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen for (seq++; seq <= hdr->messages_count; seq++)
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen /* add \Recent flags. use updated view so it contains newly
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen appended messages. */
d02d34e138e32b4266f5a403d6c51d7803bf322fTimo Sirainen view2 = mail_index_transaction_open_updated_view(trans);
d02d34e138e32b4266f5a403d6c51d7803bf322fTimo Sirainen if (mail_index_lookup_seq_range(view2, first_recent_uid, (uint32_t)-1,
e5acc283bf030b0b5c79ca4e52d315c516a299faPascal Volk /* UIDVALIDITY changed, skip over the old messages */
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen index_mailbox_set_recent_seq(&mbox->box, view2, seq, seq2);
d06c46087e9e6e66bbbbb9df1d5b33154349515cTimo Sirainen if (maildir_uidlist_sync_deinit(&ctx->uidlist_sync_ctx,
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen /* check cur/ mtime later. if we came here from saving messages they
490f66d6476d51cc02333d6eb398a5cd94b67f48Timo Sirainen could still be moved to cur/ directory. */
0910ea0672c0295c442eb686cc41e98656831f37Timo Sirainen mbox->maildir_hdr.cur_check_time = time_before_sync;
490f66d6476d51cc02333d6eb398a5cd94b67f48Timo Sirainen uid_validity = hdr->uid_validity != 0 ? hdr->uid_validity :
490f66d6476d51cc02333d6eb398a5cd94b67f48Timo Sirainen maildir_uidlist_set_uid_validity(mbox->uidlist, uid_validity);
490f66d6476d51cc02333d6eb398a5cd94b67f48Timo Sirainen maildir_uidlist_set_next_uid(mbox->uidlist, hdr_next_uid, FALSE);
490f66d6476d51cc02333d6eb398a5cd94b67f48Timo Sirainen offsetof(struct mail_index_header, uid_validity),
490f66d6476d51cc02333d6eb398a5cd94b67f48Timo Sirainen next_uid = maildir_uidlist_get_next_uid(mbox->uidlist);
490f66d6476d51cc02333d6eb398a5cd94b67f48Timo Sirainen i_assert(hdr->first_recent_uid <= first_recent_uid);
6dd77763f5451269ace733579cf58f2f3b18bca4Timo Sirainen if (hdr->first_recent_uid < first_recent_uid) {
490f66d6476d51cc02333d6eb398a5cd94b67f48Timo Sirainen offsetof(struct mail_index_header, first_recent_uid),
490f66d6476d51cc02333d6eb398a5cd94b67f48Timo Sirainen &first_recent_uid, sizeof(first_recent_uid), FALSE);
e5acc283bf030b0b5c79ca4e52d315c516a299faPascal Volkstatic unsigned int maildir_list_get_ext_id(struct maildir_storage *storage,
e5acc283bf030b0b5c79ca4e52d315c516a299faPascal Volk if (storage->maildir_list_ext_id == (uint32_t)-1) {
e5acc283bf030b0b5c79ca4e52d315c516a299faPascal Volk mail_index_ext_register(mail_index_view_get_index(view),
c78e7a94528078728cc639b26a1c83e11b4d7e1bTimo Sirainen "maildir", 0,
17cf149e5f47183bfcc1503649dfb92a14f9dcd9Timo Sirainenint maildir_list_index_has_changed(struct mailbox *box,
e156adefc1260d31a145df2f5e9b3c82050d4163Timo Sirainen struct maildir_mailbox *mbox = (struct maildir_mailbox *)box;
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen ext_id = maildir_list_get_ext_id(mbox->storage, list_view);
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen mail_index_lookup_ext(list_view, seq, ext_id, &data, &expunged);
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen /* doesn't exist, not synced or dirty-synced */
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen root_dir = mailbox_list_get_path(box->list, box->name,
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen /* check if new/ changed */
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen new_dir = t_strconcat(root_dir, "/new", NULL);
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen /* check if cur/ changed */
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen cur_dir = t_strconcat(root_dir, "/cur", NULL);
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainenint maildir_list_index_update_sync(struct mailbox *box,
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen struct maildir_mailbox *mbox = (struct maildir_mailbox *)box;
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen const struct maildir_index_header *mhdr = &mbox->maildir_hdr;
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen const struct maildir_list_index_record *old_rec;
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen /* get the current record */
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen list_view = mail_index_transaction_get_view(trans);
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen ext_id = maildir_list_get_ext_id(mbox->storage, list_view);
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen mail_index_lookup_ext(list_view, seq, ext_id, &data, &expunged);
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen if (mhdr->new_check_time <= mhdr->new_mtime + MAILDIR_SYNC_SECS ||
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen mhdr->cur_check_time <= mhdr->cur_mtime + MAILDIR_SYNC_SECS) {
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen /* dirty, we need a refresh next time */
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen memcmp(old_rec, &new_rec, sizeof(old_rec)) != 0) {