maildir-sync-index.c revision 4a6c27b85b71b535b827ef512ec88416a982dc38
5f5870385cff47efd2f58e7892f251cf13761528Timo Sirainen/* Copyright (c) 2007-2010 Dovecot authors, see the included COPYING file */
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen struct maildir_sync_context *maildir_sync_ctx;
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen struct maildir_keywords_sync_ctx *keywords_sync_ctx;
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen struct maildir_uidlist_sync_ctx *uidlist_sync_ctx;
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen struct index_sync_changes_context *sync_changes;
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen ARRAY_TYPE(keyword_indexes) keywords, idx_keywords;
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainenmaildir_sync_get_keywords_sync_ctx(struct maildir_index_sync_context *ctx)
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainenmaildir_index_expunge(struct maildir_index_sync_context *ctx, uint32_t seq)
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen if (maildir_uidlist_lookup(ctx->mbox->uidlist, uid,
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen mail_generate_guid_128_hash(t_strcut(fname, ':'),
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen mail_index_expunge_guid(ctx->trans, seq, guid_128);
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainenmaildir_expunge_is_valid_guid(struct maildir_index_sync_context *ctx,
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen uint8_t expunged_guid_128[MAIL_GUID_128_SIZE])
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen if (mail_guid_128_is_empty(expunged_guid_128)) {
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen /* no GUID associated with expunge */
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen mail_generate_guid_128_hash(t_strcut(filename, ':'),
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen if (memcmp(guid_128, expunged_guid_128, sizeof(guid_128)) == 0)
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen mail_storage_set_critical(&ctx->mbox->storage->storage,
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen "Mailbox %s: Expunged GUID mismatch for UID %u: %s vs %s",
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen binary_to_hex(expunged_guid_128, MAIL_GUID_128_SIZE));
7d359c1719bf6ff228a96c66d27f5cfa239cb31dTimo Sirainenstatic int maildir_expunge(struct maildir_mailbox *mbox, const char *path,
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen mail_storage_set_critical(&mbox->storage->storage,
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainenstatic int maildir_sync_flags(struct maildir_mailbox *mbox, const char *path,
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen /* get the current flags and keywords */
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen maildir_filename_get_flags(ctx->keywords_sync_ctx,
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen /* apply changes */
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen index_sync_changes_apply(ctx->sync_changes, NULL,
10b8040903b1d1591f1d44552ff466c8789b8814Timo Sirainen /* and try renaming with the new name */
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen newfname = maildir_filename_set_flags(ctx->keywords_sync_ctx, fname,
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen /* just make sure that the file still exists. avoid rename()
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen here because it's slow on HFS. */
67cc1d2d8495c3effad6f639cd8468d0ac7ff198Timo Sirainen "rename(%s, %s) failed: %m",
67cc1d2d8495c3effad6f639cd8468d0ac7ff198Timo Sirainenstatic int maildir_handle_uid_insertion(struct maildir_index_sync_context *ctx,
67cc1d2d8495c3effad6f639cd8468d0ac7ff198Timo Sirainen if ((uflags & MAILDIR_UIDLIST_REC_FLAG_NONSYNCED) != 0) {
67cc1d2d8495c3effad6f639cd8468d0ac7ff198Timo Sirainen /* partial syncing */
67cc1d2d8495c3effad6f639cd8468d0ac7ff198Timo Sirainen /* most likely a race condition: we read the maildir, then someone else
72bc08129fb0aaec8144cc183a998ccc426fef9eTimo Sirainen expunged messages and committed changes to index. so, this message
67cc1d2d8495c3effad6f639cd8468d0ac7ff198Timo Sirainen shouldn't actually exist. */
67cc1d2d8495c3effad6f639cd8468d0ac7ff198Timo Sirainen if ((uflags & MAILDIR_UIDLIST_REC_FLAG_RACING) == 0) {
67cc1d2d8495c3effad6f639cd8468d0ac7ff198Timo Sirainen /* mark it racy and check in next sync */
3a8c3cd1847aea924c6dbf4dee17074ae2039b9dTimo Sirainen maildir_uidlist_add_flags(ctx->mbox->uidlist, filename,
67cc1d2d8495c3effad6f639cd8468d0ac7ff198Timo Sirainen ret = maildir_uidlist_sync_init(ctx->mbox->uidlist,
67cc1d2d8495c3effad6f639cd8468d0ac7ff198Timo Sirainen maildir_uidlist_sync_remove(ctx->uidlist_sync_ctx, filename);
67cc1d2d8495c3effad6f639cd8468d0ac7ff198Timo Sirainen ret = maildir_uidlist_sync_next(ctx->uidlist_sync_ctx,
67cc1d2d8495c3effad6f639cd8468d0ac7ff198Timo Sirainen /* give the new UID to it immediately */
67cc1d2d8495c3effad6f639cd8468d0ac7ff198Timo Sirainen maildir_uidlist_sync_finish(ctx->uidlist_sync_ctx);
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen i_warning("Maildir %s: Expunged message reappeared, giving a new UID "
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainenint maildir_sync_index_begin(struct maildir_mailbox *mbox,
72bc08129fb0aaec8144cc183a998ccc426fef9eTimo Sirainen struct maildir_sync_context *maildir_sync_ctx,
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen sync_flags = index_storage_get_sync_flags(&mbox->box);
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen /* don't drop recent messages if we're saving messages */
67cc1d2d8495c3effad6f639cd8468d0ac7ff198Timo Sirainen sync_flags &= ~MAIL_INDEX_SYNC_FLAG_DROP_RECENT;
67cc1d2d8495c3effad6f639cd8468d0ac7ff198Timo Sirainen if (mail_index_sync_begin(_box->index, &sync_ctx, &view,
db4cad7df8f3a1a584b1f72a06995b188871dc5aTimo Sirainen ctx = i_new(struct maildir_index_sync_context, 1);
72bc08129fb0aaec8144cc183a998ccc426fef9eTimo Sirainen maildir_keywords_sync_init(mbox->keywords, _box->index);
72bc08129fb0aaec8144cc183a998ccc426fef9eTimo Sirainen index_sync_changes_init(ctx->sync_ctx, ctx->view, ctx->trans,
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainenmaildir_index_header_has_changed(const struct maildir_index_header *old_hdr,
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen if (old_hdr->new_mtime != new_hdr->new_mtime ||
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen old_hdr->new_mtime_nsecs != new_hdr->new_mtime_nsecs ||
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen old_hdr->cur_mtime_nsecs != new_hdr->cur_mtime_nsecs ||
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen old_hdr->uidlist_mtime != new_hdr->uidlist_mtime ||
a75d470c9223a75801418fcdda258885c36317e0Timo Sirainen old_hdr->uidlist_mtime_nsecs != new_hdr->uidlist_mtime_nsecs ||
a75d470c9223a75801418fcdda258885c36317e0Timo Sirainen old_hdr->uidlist_size != new_hdr->uidlist_size)
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainenmaildir_sync_index_update_ext_header(struct maildir_index_sync_context *ctx)
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen stat(t_strconcat(mbox->box.path, "/cur", NULL), &st) == 0) {
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen if ((time_t)mbox->maildir_hdr.cur_check_time < st.st_mtime)
a75d470c9223a75801418fcdda258885c36317e0Timo Sirainen mbox->maildir_hdr.cur_check_time = st.st_mtime;
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen mbox->maildir_hdr.cur_mtime_nsecs = ST_MTIME_NSEC(st);
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen mail_index_get_header_ext(mbox->box.view, mbox->maildir_ext_id,
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen maildir_index_header_has_changed(data, &mbox->maildir_hdr)) {
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen mail_index_update_header_ext(ctx->trans, mbox->maildir_ext_id,
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainenstatic int maildir_sync_index_finish(struct maildir_index_sync_context *ctx,
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen /* Set syncing_commit=TRUE so that if any sync callbacks try
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen to access mails which got lost (eg. expunge callback trying
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen to open the file which was just unlinked) we don't try to
5fbccc935e3f7b916aa7c6e302a212821072e83aTimo Sirainen start a second index sync and crash. */
71df09024cea5f2faa93da3bb9513ee96ba6bf22Timo Sirainen if (mail_index_sync_commit(&ctx->sync_ctx) < 0) {
return ret;
bool have_indexonly_keywords;
int diff;
for (i = old_count; i > 0; i--) {
if (!have_indexonly_keywords) {
if (diff == 0) {
} else if (diff < 0) {
bool partial)
const char *filename;
unsigned int changes = 0;
int ret = 0;
seq++;
uid) < 0)
seq--;
goto again;
seq--;
if (expunged) {
if (!partial) {
TRUE) < 0)
if (uid_validity == 0) {
sizeof(struct maildir_list_index_record),
sizeof(uint32_t));
const void *data;
bool expunged;
const void *data;
bool expunged;
if (expunged)