#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"
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 }