From: Timo Sirainen Date: Wed, 14 Jan 2009 18:56:01 +0000 (-0500) Subject: Cleaned up read-only mailbox handling. Fixes a bug with Maildir syncing. X-Git-Tag: 1.2.beta1~117 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=42456ec33fe65feb411890f99d436071e0185ee3;p=thirdparty%2Fdovecot%2Fcore.git Cleaned up read-only mailbox handling. Fixes a bug with Maildir syncing. If Maildir was opened read-only (STATUS, EXAMINE) then all flag changes were saved to index as dirty. --HG-- branch : HEAD --- diff --git a/src/lib-storage/index/index-storage.c b/src/lib-storage/index/index-storage.c index cabca38be5..5dc73984b1 100644 --- a/src/lib-storage/index/index-storage.c +++ b/src/lib-storage/index/index-storage.c @@ -463,7 +463,6 @@ void index_storage_mailbox_init(struct index_mailbox *ibox, const char *name, array_create(&ibox->box.module_contexts, ibox->box.pool, sizeof(void *), 5); - ibox->readonly = (flags & MAILBOX_OPEN_READONLY) != 0; ibox->keep_recent = (flags & MAILBOX_OPEN_KEEP_RECENT) != 0; ibox->keep_locked = (flags & MAILBOX_OPEN_KEEP_LOCKED) != 0; ibox->move_to_memory = move_to_memory; @@ -514,15 +513,14 @@ bool index_storage_is_readonly(struct mailbox *box) { struct index_mailbox *ibox = (struct index_mailbox *) box; - return ibox->readonly; + return (ibox->box.open_flags & MAILBOX_OPEN_READONLY) != 0 || + ibox->backend_readonly; } bool index_storage_allow_new_keywords(struct mailbox *box) { - struct index_mailbox *ibox = (struct index_mailbox *) box; - /* FIXME: return FALSE if we're full */ - return !ibox->readonly; + return index_storage_is_readonly(box); } bool index_storage_is_inconsistent(struct mailbox *box) diff --git a/src/lib-storage/index/index-storage.h b/src/lib-storage/index/index-storage.h index b0c7e8df20..bde4f9fee1 100644 --- a/src/lib-storage/index/index-storage.h +++ b/src/lib-storage/index/index-storage.h @@ -55,7 +55,8 @@ struct index_mailbox { time_t sync_last_check; - unsigned int readonly:1; + /* we've discovered there aren't enough permissions to modify mailbox */ + unsigned int backend_readonly:1; unsigned int keep_recent:1; unsigned int keep_locked:1; unsigned int sent_diskspace_warning:1; diff --git a/src/lib-storage/index/maildir/maildir-storage.c b/src/lib-storage/index/maildir/maildir-storage.c index 6bfdb818f4..5068bf2089 100644 --- a/src/lib-storage/index/maildir/maildir-storage.c +++ b/src/lib-storage/index/maildir/maildir-storage.c @@ -468,7 +468,7 @@ maildir_open(struct maildir_storage *storage, const char *name, if (access(t_strconcat(path, "/cur", NULL), W_OK) < 0 && errno == EACCES) - mbox->ibox.readonly = TRUE; + mbox->ibox.backend_readonly = TRUE; mbox->keywords = maildir_keywords_init(mbox); return &mbox->ibox.box; diff --git a/src/lib-storage/index/maildir/maildir-sync-index.c b/src/lib-storage/index/maildir/maildir-sync-index.c index 1bf57f10c3..3c03b8c485 100644 --- a/src/lib-storage/index/maildir/maildir-sync-index.c +++ b/src/lib-storage/index/maildir/maildir-sync-index.c @@ -193,10 +193,10 @@ int maildir_sync_index_begin(struct maildir_mailbox *mbox, ctx->trans = trans; ctx->keywords_sync_ctx = maildir_keywords_sync_init(mbox->keywords, mbox->ibox.index); - - ctx->sync_changes = index_sync_changes_init(&mbox->ibox, ctx->sync_ctx, - ctx->view, ctx->trans, - mbox->ibox.readonly); + ctx->sync_changes = + index_sync_changes_init(&mbox->ibox, ctx->sync_ctx, + ctx->view, ctx->trans, + mbox->ibox.backend_readonly); *ctx_r = ctx; return 0; diff --git a/src/lib-storage/index/mbox/mbox-file.c b/src/lib-storage/index/mbox/mbox-file.c index 0c7d02b3dc..ff4361df29 100644 --- a/src/lib-storage/index/mbox/mbox-file.c +++ b/src/lib-storage/index/mbox/mbox-file.c @@ -19,13 +19,13 @@ int mbox_file_open(struct mbox_mailbox *mbox) if (mbox->mbox_file_stream != NULL) { /* read-only mbox stream */ - i_assert(mbox->mbox_readonly); + i_assert(mbox->ibox.backend_readonly); return 0; } - fd = open(mbox->path, mbox->mbox_readonly ? O_RDONLY : O_RDWR); - if (fd == -1 && errno == EACCES && !mbox->mbox_readonly) { - mbox->mbox_readonly = TRUE; + fd = open(mbox->path, mbox->ibox.backend_readonly ? O_RDONLY : O_RDWR); + if (fd == -1 && errno == EACCES && !mbox->ibox.backend_readonly) { + mbox->ibox.backend_readonly = TRUE; fd = open(mbox->path, O_RDONLY); } @@ -65,7 +65,7 @@ int mbox_file_open_stream(struct mbox_mailbox *mbox) if (mbox->mbox_file_stream != NULL) { /* read-only mbox stream */ - i_assert(mbox->mbox_fd == -1 && mbox->mbox_readonly); + i_assert(mbox->mbox_fd == -1 && mbox->ibox.backend_readonly); } else { if (mbox->mbox_fd == -1) { if (mbox_file_open(mbox) < 0) @@ -95,7 +95,7 @@ static void mbox_file_fix_atime(struct mbox_mailbox *mbox) struct stat st; if (mbox->ibox.recent_flags_count > 0 && mbox->ibox.keep_recent && - mbox->mbox_fd != -1 && !mbox->mbox_readonly) { + mbox->mbox_fd != -1 && !mbox->ibox.backend_readonly) { /* we've seen recent messages which we want to keep recent. keep file's atime lower than mtime so \Marked status gets shown while listing */ @@ -124,7 +124,7 @@ void mbox_file_close_stream(struct mbox_mailbox *mbox) if (mbox->mbox_file_stream != NULL) { if (mbox->mbox_fd == -1) { /* read-only mbox stream */ - i_assert(mbox->mbox_readonly); + i_assert(mbox->ibox.backend_readonly); i_stream_seek(mbox->mbox_file_stream, 0); } else { i_stream_destroy(&mbox->mbox_file_stream); diff --git a/src/lib-storage/index/mbox/mbox-lock.c b/src/lib-storage/index/mbox/mbox-lock.c index 030144f35b..50a3eab410 100644 --- a/src/lib-storage/index/mbox/mbox-lock.c +++ b/src/lib-storage/index/mbox/mbox-lock.c @@ -621,7 +621,7 @@ static int mbox_update_locking(struct mbox_mailbox *mbox, int lock_type, if (mbox->mbox_fd == -1 && mbox->mbox_file_stream != NULL) { /* read-only mbox stream. no need to lock. */ - i_assert(mbox->mbox_readonly); + i_assert(mbox->ibox.backend_readonly); mbox->mbox_lock_type = lock_type; return 1; } diff --git a/src/lib-storage/index/mbox/mbox-save.c b/src/lib-storage/index/mbox/mbox-save.c index 226d66f83e..82a3b69ef0 100644 --- a/src/lib-storage/index/mbox/mbox-save.c +++ b/src/lib-storage/index/mbox/mbox-save.c @@ -254,7 +254,7 @@ mbox_save_init_file(struct mbox_save_context *ctx, bool empty = FALSE; int ret; - if (ctx->mbox->mbox_readonly) { + if (ctx->mbox->ibox.backend_readonly) { mail_storage_set_error(storage, MAIL_ERROR_PERM, "Read-only mbox"); return -1; diff --git a/src/lib-storage/index/mbox/mbox-storage.c b/src/lib-storage/index/mbox/mbox-storage.c index f87119f8f8..3324061a7e 100644 --- a/src/lib-storage/index/mbox/mbox-storage.c +++ b/src/lib-storage/index/mbox/mbox-storage.c @@ -615,10 +615,8 @@ mbox_open(struct mbox_storage *storage, const char *name, if (access(path, R_OK|W_OK) < 0) { if (errno < EACCES) mbox_set_syscall_error(mbox, "access()"); - else { - mbox->ibox.readonly = TRUE; - mbox->mbox_readonly = TRUE; - } + else + mbox->ibox.backend_readonly = TRUE; } if (strcmp(name, "INBOX") == 0) { @@ -652,7 +650,7 @@ mbox_mailbox_open_stream(struct mbox_storage *storage, const char *name, i_stream_ref(input); mbox->mbox_file_stream = input; - mbox->mbox_readonly = TRUE; + mbox->ibox.backend_readonly = TRUE; mbox->no_mbox_file = TRUE; mbox->path = "(read-only mbox stream)"; @@ -785,7 +783,7 @@ static int mbox_storage_mailbox_close(struct mailbox *box) if (mbox->ibox.view != NULL) { hdr = mail_index_get_header(mbox->ibox.view); if ((hdr->flags & MAIL_INDEX_HDR_FLAG_HAVE_DIRTY) != 0 && - !mbox->mbox_readonly) { + !mbox->ibox.backend_readonly) { /* we've done changes to mbox which haven't been written yet. do it now. */ sync_flags |= MBOX_SYNC_REWRITE; diff --git a/src/lib-storage/index/mbox/mbox-storage.h b/src/lib-storage/index/mbox/mbox-storage.h index c0cc58979f..e61b95ee1c 100644 --- a/src/lib-storage/index/mbox/mbox-storage.h +++ b/src/lib-storage/index/mbox/mbox-storage.h @@ -41,7 +41,7 @@ struct mbox_mailbox { struct dotlock *mbox_dotlock; unsigned int mbox_lock_id, mbox_global_lock_id; struct timeout *keep_lock_to; - bool mbox_readonly, mbox_writeonly; + bool mbox_writeonly; uint32_t mbox_ext_idx; struct mbox_index_header mbox_hdr; diff --git a/src/lib-storage/index/mbox/mbox-sync.c b/src/lib-storage/index/mbox/mbox-sync.c index e2901045f1..4ae5c99657 100644 --- a/src/lib-storage/index/mbox/mbox-sync.c +++ b/src/lib-storage/index/mbox/mbox-sync.c @@ -173,7 +173,7 @@ static void mbox_sync_read_index_syncs(struct mbox_sync_context *sync_ctx, } index_sync_changes_read(sync_ctx->sync_changes, uid, sync_expunge_r); - if (sync_ctx->mbox->mbox_readonly) { + if (sync_ctx->mbox->ibox.backend_readonly) { /* we can't expunge anything from read-only mboxes */ *sync_expunge_r = FALSE; } @@ -1535,7 +1535,8 @@ static int mbox_sync_do(struct mbox_sync_context *sync_ctx, /* a) partial sync didn't work b) we ran out of UIDs c) syncing had errors */ - if (sync_ctx->delay_writes && !sync_ctx->mbox->mbox_readonly && + if (sync_ctx->delay_writes && + !sync_ctx->mbox->ibox.backend_readonly && (sync_ctx->errors || sync_ctx->renumber_uids)) { /* fixing a broken mbox state, be sure to write the changes. */ @@ -1672,7 +1673,7 @@ static int mbox_sync_int(struct mbox_mailbox *mbox, enum mbox_sync_flags flags, int ret, changed; bool delay_writes; - delay_writes = mbox->mbox_readonly || + delay_writes = mbox->ibox.backend_readonly || ((flags & MBOX_SYNC_REWRITE) == 0 && getenv("MBOX_LAZY_WRITES") != NULL); @@ -1715,7 +1716,7 @@ again: lock it for writing immediately. the mbox must be locked before index syncing is started to avoid deadlocks, so we don't have much choice either (well, easy ones anyway). */ - int lock_type = mbox->mbox_readonly ? F_RDLCK : F_WRLCK; + int lock_type = mbox->ibox.backend_readonly ? F_RDLCK : F_WRLCK; if ((ret = mbox_lock(mbox, lock_type, lock_id)) <= 0) { if (ret == 0 || lock_type == F_RDLCK) @@ -1724,7 +1725,7 @@ again: /* try as read-only */ if (mbox_lock(mbox, F_RDLCK, lock_id) <= 0) return -1; - mbox->mbox_readonly = TRUE; + mbox->ibox.backend_readonly = TRUE; } } @@ -1790,7 +1791,8 @@ again: i_array_init(&sync_ctx.mails, 64); sync_ctx.flags = flags; - sync_ctx.delay_writes = delay_writes || sync_ctx.mbox->mbox_readonly; + sync_ctx.delay_writes = delay_writes || + sync_ctx.mbox->ibox.backend_readonly; sync_ctx.sync_changes = index_sync_changes_init(&mbox->ibox, index_sync_ctx, @@ -1846,7 +1848,7 @@ again: sync_ctx.index_sync_ctx = NULL; if (ret == 0 && mbox->mbox_fd != -1 && mbox->ibox.keep_recent && - !sync_ctx.mbox->mbox_readonly) { + !sync_ctx.mbox->ibox.backend_readonly) { /* try to set atime back to its original value */ struct utimbuf buf; struct stat st;