From: Timo Sirainen Date: Mon, 15 Feb 2010 01:07:19 +0000 (+0200) Subject: lib-storage: Removed INBOX auto-creating from backend code. Added bool box->inbox. X-Git-Tag: 2.0.beta3~78 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=029c8542982001bf1386aee0ea9cb9843e5ab62d;p=thirdparty%2Fdovecot%2Fcore.git lib-storage: Removed INBOX auto-creating from backend code. Added bool box->inbox. --HG-- branch : HEAD --- diff --git a/src/lib-storage/index/cydir/cydir-storage.c b/src/lib-storage/index/cydir/cydir-storage.c index e2a94c5af1..0b04be426b 100644 --- a/src/lib-storage/index/cydir/cydir-storage.c +++ b/src/lib-storage/index/cydir/cydir-storage.c @@ -73,11 +73,6 @@ static int cydir_mailbox_open(struct mailbox *box) if (stat(box->path, &st) == 0) { /* exists, open it */ - } else if (errno == ENOENT && strcmp(box->name, "INBOX") == 0) { - /* INBOX always exists, create it */ - if (box->list->v.create_mailbox_dir(box->list, - box->name, FALSE) < 0) - return -1; } else if (errno == ENOENT) { mail_storage_set_error(box->storage, MAIL_ERROR_NOTFOUND, T_MAIL_ERR_MAILBOX_NOT_FOUND(box->name)); diff --git a/src/lib-storage/index/dbox-common/dbox-storage.c b/src/lib-storage/index/dbox-common/dbox-storage.c index 1b10d48c98..8905bf984c 100644 --- a/src/lib-storage/index/dbox-common/dbox-storage.c +++ b/src/lib-storage/index/dbox-common/dbox-storage.c @@ -71,45 +71,11 @@ dbox_cleanup_if_exists(struct mailbox_list *list, const char *path) return TRUE; } -static int dbox_mailbox_create_indexes(struct mailbox *box, - const struct mailbox_update *update) -{ - struct dbox_storage *storage = (struct dbox_storage *)box->storage; - const char *origin; - mode_t mode; - gid_t gid; - - mailbox_list_get_dir_permissions(box->list, NULL, &mode, &gid, &origin); - if (mkdir_parents_chgrp(box->path, mode, gid, origin) == 0) { - /* create indexes immediately with the dbox header */ - if (index_storage_mailbox_open(box, FALSE) < 0) - return -1; - if (storage->v.mailbox_create_indexes(box, update) < 0) - return -1; - } else if (errno != EEXIST) { - if (!mail_storage_set_error_from_errno(box->storage)) { - mail_storage_set_critical(box->storage, - "mkdir(%s) failed: %m", box->path); - } - return -1; - } - return 0; -} - int dbox_mailbox_open(struct mailbox *box) { if (dbox_cleanup_if_exists(box->list, box->path)) { return index_storage_mailbox_open(box, FALSE); } else if (errno == ENOENT) { - if (strcmp(box->name, "INBOX") == 0 && - (box->list->ns->flags & NAMESPACE_FLAG_INBOX) != 0) { - /* INBOX always exists, create it */ - if (dbox_mailbox_create_indexes(box, NULL) < 0) - return -1; - return box->opened ? 0 : - index_storage_mailbox_open(box, FALSE); - } - mail_storage_set_error(box->storage, MAIL_ERROR_NOTFOUND, T_MAIL_ERR_MAILBOX_NOT_FOUND(box->name)); return -1; diff --git a/src/lib-storage/index/index-storage.c b/src/lib-storage/index/index-storage.c index 016465f669..f06f997644 100644 --- a/src/lib-storage/index/index-storage.c +++ b/src/lib-storage/index/index-storage.c @@ -285,6 +285,8 @@ void index_storage_mailbox_alloc(struct mailbox *box, const char *name, MAILBOX_LIST_PATH_TYPE_MAILBOX); box->path = p_strdup(box->pool, path); box->index = index_storage_alloc(box->list, name, flags, index_prefix); + box->inbox = strcmp(name, "INBOX") == 0 && + (box->list->ns->flags & NAMESPACE_FLAG_INBOX) != 0; if (box->file_create_mode == 0) mailbox_refresh_permissions(box); mail_index_set_permissions(box->index, box->file_create_mode, diff --git a/src/lib-storage/index/maildir/maildir-storage.c b/src/lib-storage/index/maildir/maildir-storage.c index d3692a45df..de127ec75c 100644 --- a/src/lib-storage/index/maildir/maildir-storage.c +++ b/src/lib-storage/index/maildir/maildir-storage.c @@ -322,12 +322,9 @@ static int maildir_mailbox_open_existing(struct mailbox *box) static int maildir_mailbox_open(struct mailbox *box) { + const char *root_dir; struct stat st; int ret; - bool inbox; - - inbox = strcmp(box->name, "INBOX") == 0 && - (box->list->ns->flags & NAMESPACE_FLAG_INBOX) != 0; /* begin by checking if tmp/ directory exists and if it should be cleaned up. */ @@ -340,13 +337,20 @@ static int maildir_mailbox_open(struct mailbox *box) return -1; /* tmp/ directory doesn't exist. does the maildir? */ - if (inbox || (*box->name != '\0' && stat(box->path, &st) == 0)) { + root_dir = mailbox_list_get_path(box->list, NULL, + MAILBOX_LIST_PATH_TYPE_MAILBOX); + if (strcmp(box->path, root_dir) == 0) { + /* root directory. either INBOX or some other namespace root */ + errno = ENOENT; + } else if (stat(box->path, &st) == 0) { /* yes, we'll need to create the missing dirs */ if (create_maildir(box, TRUE) < 0) return -1; return maildir_mailbox_open_existing(box); - } else if (*box->name == '\0' || errno == ENOENT) { + } + + if (errno == ENOENT) { mail_storage_set_error(box->storage, MAIL_ERROR_NOTFOUND, T_MAIL_ERR_MAILBOX_NOT_FOUND(box->name)); return -1; diff --git a/src/lib-storage/index/mbox/mbox-lock.c b/src/lib-storage/index/mbox/mbox-lock.c index 899dd02d1f..3adf0bffca 100644 --- a/src/lib-storage/index/mbox/mbox-lock.c +++ b/src/lib-storage/index/mbox/mbox-lock.c @@ -348,7 +348,7 @@ mbox_dotlock_log_eacces_error(struct mbox_mailbox *mbox, const char *path) errmsg = eacces_error_get_creating("file_dotlock_create", path); dir = strrchr(path, '/'); dir = dir == NULL ? "." : t_strdup_until(path, dir); - if (strcmp(mbox->box.name, "INBOX") != 0) { + if (!mbox->box.inbox) { mail_storage_set_critical(&mbox->storage->storage, "%s (not INBOX -> no privileged locking)", errmsg); } else if (!mbox->mbox_privileged_locking) { diff --git a/src/lib-storage/index/mbox/mbox-storage.c b/src/lib-storage/index/mbox/mbox-storage.c index 3bd6e5da28..f22f2db62c 100644 --- a/src/lib-storage/index/mbox/mbox-storage.c +++ b/src/lib-storage/index/mbox/mbox-storage.c @@ -364,44 +364,42 @@ mbox_mailbox_alloc(struct mail_storage *storage, struct mailbox_list *list, return &mbox->box; } -static int verify_inbox(struct mailbox_list *list) +static int create_inbox(struct mailbox *box) { const char *inbox_path, *rootdir; int fd; - inbox_path = mailbox_list_get_path(list, "INBOX", + inbox_path = mailbox_list_get_path(box->list, "INBOX", MAILBOX_LIST_PATH_TYPE_MAILBOX); - rootdir = mailbox_list_get_path(list, NULL, + rootdir = mailbox_list_get_path(box->list, NULL, MAILBOX_LIST_PATH_TYPE_DIR); - /* make sure inbox file itself exists */ - fd = open(inbox_path, O_RDWR | O_CREAT | O_EXCL, 0660); + fd = open(inbox_path, O_RDWR | O_CREAT, 0660); if (fd == -1 && errno == EACCES) { /* try again with increased privileges */ (void)restrict_access_use_priv_gid(); fd = open(inbox_path, O_RDWR | O_CREAT | O_EXCL, 0660); restrict_access_drop_priv_gid(); } - if (fd != -1) + if (fd != -1) { (void)close(fd); - else if (errno == ENOTDIR && + return 0; + } else if (errno == ENOTDIR && strncmp(inbox_path, rootdir, strlen(rootdir)) == 0) { - mailbox_list_set_critical(list, + mail_storage_set_critical(box->storage, "mbox root directory can't be a file: %s " "(http://wiki.dovecot.org/MailLocation/Mbox)", rootdir); return -1; } else if (errno == EACCES) { - mailbox_list_set_critical(list, "%s", + mail_storage_set_critical(box->storage,"%s", mail_error_create_eacces_msg("open", inbox_path)); return -1; - } else if (errno != EEXIST) { - mailbox_list_set_critical(list, + } else { + mail_storage_set_critical(box->storage, "open(%s, O_CREAT) failed: %m", inbox_path); return -1; } - - return 0; } static void mbox_lock_touch_timeout(struct mbox_mailbox *mbox) @@ -424,7 +422,7 @@ static int mbox_mailbox_open_existing(struct mbox_mailbox *mbox) } move_to_memory = want_memory_indexes(mbox->storage, box->path); - if (strcmp(box->name, "INBOX") == 0) { + if (box->inbox) { /* if INBOX isn't under the root directory, it's probably in /var/mail and we want to allow privileged dotlocking */ rootdir = mailbox_list_get_path(box->list, NULL, @@ -459,14 +457,6 @@ static int mbox_mailbox_open(struct mailbox *box) return index_storage_mailbox_open(box, FALSE); } - if (strcmp(box->name, "INBOX") == 0 && - (box->list->ns->flags & NAMESPACE_FLAG_INBOX) != 0) { - /* make sure INBOX exists */ - if (verify_inbox(box->list) < 0) - return -1; - return mbox_mailbox_open_existing(mbox); - } - if ((ret = stat(box->path, &st)) == 0 && !S_ISDIR(st.st_mode)) return mbox_mailbox_open_existing(mbox); else if (ret == 0) { @@ -514,16 +504,22 @@ mbox_mailbox_create(struct mailbox *box, const struct mailbox_update *update, (box->list->props & MAILBOX_LIST_PROP_NO_NOSELECT) == 0) return 0; - /* create the mbox file */ - ret = mailbox_create_fd(box, box->path, O_RDWR | O_CREAT | O_EXCL, &fd); - if (ret <= 0) { + if (box->inbox) { + if (create_inbox(box) < 0) + return -1; + } else { + /* create the mbox file */ + ret = mailbox_create_fd(box, box->path, + O_RDWR | O_CREAT | O_EXCL, &fd); + if (ret < 0) + return -1; if (ret == 0) { mail_storage_set_error(box->storage, MAIL_ERROR_EXISTS, "Mailbox already exists"); + return -1; } - return -1; + (void)close(fd); } - (void)close(fd); return update == NULL ? 0 : mbox_mailbox_update(box, update); } diff --git a/src/lib-storage/list/mailbox-list-maildir.c b/src/lib-storage/list/mailbox-list-maildir.c index 3744cd6147..8f3b6cacbd 100644 --- a/src/lib-storage/list/mailbox-list-maildir.c +++ b/src/lib-storage/list/mailbox-list-maildir.c @@ -338,7 +338,7 @@ static int maildir_list_create_mailbox_dir(struct mailbox_list *list, const char *name, bool directory ATTR_UNUSED) { - const char *path, *gid_origin, *p; + const char *path, *root_dir, *gid_origin, *p; mode_t mode; gid_t gid; bool create_parent_dir; @@ -355,23 +355,33 @@ maildir_list_create_mailbox_dir(struct mailbox_list *list, const char *name, path = t_strdup_until(path, p); } + root_dir = mailbox_list_get_path(list, NULL, + MAILBOX_LIST_PATH_TYPE_MAILBOX); mailbox_list_get_dir_permissions(list, NULL, &mode, &gid, &gid_origin); if (mkdir_parents_chgrp(path, mode, gid, gid_origin) == 0) { /* ok */ } else if (errno == EEXIST) { - if (!create_parent_dir) { - mailbox_list_set_error(list, MAIL_ERROR_EXISTS, - "Mailbox already exists"); - return -1; + if (create_parent_dir) + return 0; + if (!directory) { + if (strcmp(path, root_dir) == 0) { + /* even though the root directory exists, + the mailbox might not */ + return 0; + } } + + mailbox_list_set_error(list, MAIL_ERROR_EXISTS, + "Mailbox already exists"); + return -1; } else if (mailbox_list_set_error_from_errno(list)) { return -1; } else { mailbox_list_set_critical(list, "mkdir(%s) failed: %m", path); return -1; } - return create_parent_dir ? 0 : + return create_parent_dir || strcmp(path, root_dir) == 0 ? 0 : maildir_list_create_maildirfolder_file(list, path); } diff --git a/src/lib-storage/mail-storage-private.h b/src/lib-storage/mail-storage-private.h index 112c968565..5ed1cc0584 100644 --- a/src/lib-storage/mail-storage-private.h +++ b/src/lib-storage/mail-storage-private.h @@ -263,6 +263,8 @@ struct mailbox { unsigned int backend_readonly:1; /* Mailbox is being deleted */ unsigned int deleting:1; + /* TRUE if this is the INBOX */ + unsigned int inbox:1; }; struct mail_vfuncs { diff --git a/src/lib-storage/mail-storage.c b/src/lib-storage/mail-storage.c index c6618b2f98..f589551221 100644 --- a/src/lib-storage/mail-storage.c +++ b/src/lib-storage/mail-storage.c @@ -526,6 +526,14 @@ static int mailbox_open_full(struct mailbox *box, struct istream *input) ret = box->v.open(box); } T_END; + if (ret < 0 && box->storage->error == MAIL_ERROR_NOTFOUND && + box->input == NULL && box->inbox) T_BEGIN { + /* INBOX should always exist. try to create it and retry. */ + (void)mailbox_create(box, NULL, FALSE); + mailbox_close(box); + ret = box->v.open(box); + } T_END; + if (ret < 0) { if (box->input != NULL) i_stream_unref(&box->input); @@ -635,8 +643,7 @@ int mailbox_delete(struct mailbox *box) "Storage root can't be deleted"); return -1; } - if (strcmp(box->name, "INBOX") == 0 && - (box->list->ns->flags & NAMESPACE_FLAG_INBOX) != 0) { + if (box->inbox) { mail_storage_set_error(box->storage, MAIL_ERROR_NOTPOSSIBLE, "INBOX can't be deleted."); return -1;