Skip to content

Commit

Permalink
lib-storage: Add mail_user_home_mkdir()
Browse files Browse the repository at this point in the history
  • Loading branch information
sirainen committed Apr 26, 2018
1 parent 6b57e4d commit f93e183
Show file tree
Hide file tree
Showing 2 changed files with 65 additions and 0 deletions.
60 changes: 60 additions & 0 deletions src/lib-storage/mail-user.c
Expand Up @@ -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"
Expand Down Expand Up @@ -654,6 +655,65 @@ void mail_user_stats_fill(struct mail_user *user, struct stats *stats)
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 }
Expand Down
5 changes: 5 additions & 0 deletions src/lib-storage/mail-user.h
Expand Up @@ -196,4 +196,9 @@ void mail_user_init_fs_settings(struct mail_user *user,
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

0 comments on commit f93e183

Please sign in to comment.