Mercurial > dovecot > core-2.2
changeset 22919:2b16e07f8312
lib-storage: Add mail_user_home_mkdir()
author | Timo Sirainen <timo.sirainen@dovecot.fi> |
---|---|
date | Tue, 24 Apr 2018 18:47:28 +0300 |
parents | 6ca30380a3f5 |
children | 02aed723d139 |
files | src/lib-storage/mail-user.c src/lib-storage/mail-user.h |
diffstat | 2 files changed, 65 insertions(+), 0 deletions(-) [+] |
line wrap: on
line diff
--- a/src/lib-storage/mail-user.c Wed Apr 25 17:45:39 2018 +0300 +++ b/src/lib-storage/mail-user.c Tue Apr 24 18:47:28 2018 +0300 @@ -8,6 +8,7 @@ #include "module-dir.h" #include "home-expand.h" #include "file-create-locked.h" +#include "mkdir-parents.h" #include "safe-mkstemp.h" #include "str.h" #include "strescape.h" @@ -654,6 +655,65 @@ user->v.stats_fill(user, stats); } +static int +mail_user_home_mkdir_try_ns(struct mail_namespace *ns, const char *home) +{ + const enum mailbox_list_path_type types[] = { + MAILBOX_LIST_PATH_TYPE_DIR, + MAILBOX_LIST_PATH_TYPE_ALT_DIR, + MAILBOX_LIST_PATH_TYPE_CONTROL, + MAILBOX_LIST_PATH_TYPE_INDEX, + MAILBOX_LIST_PATH_TYPE_INDEX_PRIVATE, + MAILBOX_LIST_PATH_TYPE_LIST_INDEX, + }; + size_t home_len = strlen(home); + const char *path; + + for (unsigned int i = 0; i < N_ELEMENTS(types); i++) { + if (!mailbox_list_get_root_path(ns->list, types[i], &path)) + continue; + if (strncmp(path, home, home_len) == 0 && + (path[home_len] == '\0' || path[home_len] == '/')) { + return mailbox_list_mkdir_root(ns->list, path, + types[i]) < 0 ? -1 : 1; + } + } + return 0; +} + +int mail_user_home_mkdir(struct mail_user *user) +{ + struct mail_namespace *ns; + const char *home; + int ret; + + if (mail_user_get_home(user, &home) < 0) + return -1; + + /* Try to create the home directory by creating the root directory for + a namespace that exists under the home. This way we end up in the + special mkdir() code in mailbox_list_try_mkdir_root_parent(). + Start from INBOX, since that's usually the correct place. */ + ns = mail_namespace_find_inbox(user->namespaces); + if ((ret = mail_user_home_mkdir_try_ns(ns, home)) != 0) + return ret < 0 ? -1 : 0; + /* try other namespaces */ + for (ns = user->namespaces; ns != NULL; ns = ns->next) { + if ((ns->flags & NAMESPACE_FLAG_INBOX_USER) != 0) { + /* already tried the INBOX namespace */ + continue; + } + if ((ret = mail_user_home_mkdir_try_ns(ns, home)) != 0) + return ret < 0 ? -1 : 0; + } + /* fallback to a safe mkdir() with 0700 mode */ + if (mkdir_parents(home, 0700) < 0 && errno != EEXIST) { + i_error("mkdir_parents(%s) failed: %m", home); + return -1; + } + return 0; +} + static const struct var_expand_func_table mail_user_var_expand_func_table_arr[] = { { "userdb", mail_user_var_expand_func_userdb }, { NULL, NULL }
--- a/src/lib-storage/mail-user.h Wed Apr 25 17:45:39 2018 +0300 +++ b/src/lib-storage/mail-user.h Tue Apr 24 18:47:28 2018 +0300 @@ -196,4 +196,9 @@ plugin must be loaded to have anything filled. */ void mail_user_stats_fill(struct mail_user *user, struct stats *stats); +/* Try to mkdir() user's home directory. Ideally this should be called only + after the caller tries to create a file to the home directory, but it fails + with ENOENT. This way it avoids unnecessary disk IO to the home. */ +int mail_user_home_mkdir(struct mail_user *user); + #endif