shared-storage.c revision bcb4e51a409d94ae670de96afb8483a4f7855294
b9f30617c2c96d54acbc4f85ed17b939c4f28916Timo Sirainen/* Copyright (c) 2008-2018 Dovecot authors, see the included COPYING file */
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen#include "lib.h"
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen#include "array.h"
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen#include "str.h"
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen#include "ioloop.h"
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen#include "var-expand.h"
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen#include "index-storage.h"
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen#include "mail-storage-service.h"
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen#include "mailbox-list-private.h"
d63b4241643b6014d49ff356f14e0f3ee43068a8Timo Sirainen#include "fail-mail-storage.h"
b215a8a123623782554a83f3025ef4e771bd8f01Timo Sirainen#include "shared-storage.h"
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen#include <ctype.h>
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainenextern struct mail_storage shared_storage;
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainenstatic struct mail_storage *shared_storage_alloc(void)
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen{
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen struct shared_storage *storage;
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen pool_t pool;
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen pool = pool_alloconly_create("shared storage", 1024);
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen storage = p_new(pool, struct shared_storage, 1);
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen storage->storage = shared_storage;
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen storage->storage.pool = pool;
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen return &storage->storage;
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen}
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainenstatic int
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainenshared_storage_create(struct mail_storage *_storage, struct mail_namespace *ns,
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen const char **error_r)
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen{
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen struct shared_storage *storage = SHARED_STORAGE(_storage);
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen struct mail_storage *storage_class;
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen const char *driver, *p;
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen char *wildcardp, key;
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen bool have_username;
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen /* location must begin with the actual mailbox driver */
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen p = strchr(ns->set->location, ':');
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen if (p == NULL) {
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen *error_r = "Shared mailbox location not prefixed with driver";
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen return -1;
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen }
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen driver = t_strdup_until(ns->set->location, p);
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen storage->location = p_strdup(_storage->pool, ns->set->location);
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen storage->unexpanded_location =
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen p_strdup(_storage->pool, ns->unexpanded_set->location);
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen storage->storage_class_name = p_strdup(_storage->pool, driver);
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen storage_class = mail_user_get_storage_class(_storage->user, driver);
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen if (storage_class != NULL)
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen _storage->class_flags = storage_class->class_flags;
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen else if (strcmp(driver, "auto") != 0) {
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen *error_r = t_strconcat("Unknown shared storage driver: ",
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen driver, NULL);
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen return -1;
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen }
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen wildcardp = strchr(ns->prefix, '%');
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen if (wildcardp == NULL) {
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen *error_r = "Shared namespace prefix doesn't contain %";
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen return -1;
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen }
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen storage->ns_prefix_pattern = p_strdup(_storage->pool, wildcardp);
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen have_username = FALSE;
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen for (p = storage->ns_prefix_pattern; *p != '\0'; p++) {
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen if (*p != '%')
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen continue;
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen key = p[1];
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen if (key == 'u' || key == 'n')
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen have_username = TRUE;
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen else if (key != '%' && key != 'd')
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen break;
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen }
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen if (*p != '\0') {
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen *error_r = "Shared namespace prefix contains unknown variables";
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen return -1;
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen }
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen if (!have_username) {
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen *error_r = "Shared namespace prefix doesn't contain %u or %n";
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen return -1;
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen }
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen if (p[-1] != mail_namespace_get_sep(ns) &&
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen (ns->flags & (NAMESPACE_FLAG_LIST_PREFIX |
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen NAMESPACE_FLAG_LIST_CHILDREN)) != 0) {
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen *error_r = "Shared namespace prefix doesn't end with hierarchy separator";
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen return -1;
b215a8a123623782554a83f3025ef4e771bd8f01Timo Sirainen }
b215a8a123623782554a83f3025ef4e771bd8f01Timo Sirainen
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen /* truncate prefix after the above checks are done, so they can log
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen the full prefix in error conditions */
b215a8a123623782554a83f3025ef4e771bd8f01Timo Sirainen *wildcardp = '\0';
b215a8a123623782554a83f3025ef4e771bd8f01Timo Sirainen ns->prefix_len = strlen(ns->prefix);
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen return 0;
b215a8a123623782554a83f3025ef4e771bd8f01Timo Sirainen}
b215a8a123623782554a83f3025ef4e771bd8f01Timo Sirainen
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainenstatic void
ce8a6f53ea3ce91b759a54b771e1779564de19a1Timo Sirainenshared_storage_get_list_settings(const struct mail_namespace *ns ATTR_UNUSED,
ce8a6f53ea3ce91b759a54b771e1779564de19a1Timo Sirainen struct mailbox_list_settings *set)
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen{
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen set->layout = "shared";
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen}
b215a8a123623782554a83f3025ef4e771bd8f01Timo Sirainen
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainenstatic void
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainenget_nonexistent_user_location(struct shared_storage *storage,
1cbc0c6372d24168962698c5f4d3e15df8943ebfTimo Sirainen const char *username, string_t *location)
1cbc0c6372d24168962698c5f4d3e15df8943ebfTimo Sirainen{
1cbc0c6372d24168962698c5f4d3e15df8943ebfTimo Sirainen /* user wasn't found. we'll still need to create the storage
1cbc0c6372d24168962698c5f4d3e15df8943ebfTimo Sirainen to avoid exposing which users exist and which don't. */
1cbc0c6372d24168962698c5f4d3e15df8943ebfTimo Sirainen str_append(location, storage->storage_class_name);
1cbc0c6372d24168962698c5f4d3e15df8943ebfTimo Sirainen str_append_c(location, ':');
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen /* use a reachable but nonexistent path as the mail root directory */
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen str_append(location, storage->storage.user->set->base_dir);
1cbc0c6372d24168962698c5f4d3e15df8943ebfTimo Sirainen str_append(location, "/user-not-found/");
1cbc0c6372d24168962698c5f4d3e15df8943ebfTimo Sirainen str_append(location, username);
1cbc0c6372d24168962698c5f4d3e15df8943ebfTimo Sirainen}
1cbc0c6372d24168962698c5f4d3e15df8943ebfTimo Sirainen
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainenstatic bool shared_namespace_exists(struct mail_namespace *ns)
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen{
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen const char *path;
b215a8a123623782554a83f3025ef4e771bd8f01Timo Sirainen struct stat st;
b215a8a123623782554a83f3025ef4e771bd8f01Timo Sirainen
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen path = mailbox_list_get_root_forced(ns->list, MAILBOX_LIST_PATH_TYPE_DIR);
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen if (path == NULL) {
b215a8a123623782554a83f3025ef4e771bd8f01Timo Sirainen /* we can't know if this exists */
b215a8a123623782554a83f3025ef4e771bd8f01Timo Sirainen return TRUE;
b215a8a123623782554a83f3025ef4e771bd8f01Timo Sirainen }
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen return stat(path, &st) == 0;
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen}
1cbc0c6372d24168962698c5f4d3e15df8943ebfTimo Sirainen
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainenint shared_storage_get_namespace(struct mail_namespace **_ns,
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen const char **_name)
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen{
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen struct mail_storage *_storage = (*_ns)->storage;
d63b4241643b6014d49ff356f14e0f3ee43068a8Timo Sirainen struct mailbox_list *list = (*_ns)->list;
d63b4241643b6014d49ff356f14e0f3ee43068a8Timo Sirainen struct shared_storage *storage = SHARED_STORAGE(_storage);
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen struct mail_user *user = _storage->user;
b215a8a123623782554a83f3025ef4e771bd8f01Timo Sirainen struct mail_namespace *new_ns, *ns = *_ns;
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen struct mail_namespace_settings *ns_set, *unexpanded_ns_set;
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen struct mail_user *owner;
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen const char *domain = NULL, *username = NULL, *userdomain = NULL;
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen const char *name, *p, *next, **dest, *error;
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen string_t *prefix, *location;
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen char ns_sep = mail_namespace_get_sep(ns);
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen int ret;
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen
b215a8a123623782554a83f3025ef4e771bd8f01Timo Sirainen p = storage->ns_prefix_pattern;
b215a8a123623782554a83f3025ef4e771bd8f01Timo Sirainen for (name = *_name; *p != '\0';) {
b215a8a123623782554a83f3025ef4e771bd8f01Timo Sirainen if (*p != '%') {
b215a8a123623782554a83f3025ef4e771bd8f01Timo Sirainen if (*p != *name)
b215a8a123623782554a83f3025ef4e771bd8f01Timo Sirainen break;
b215a8a123623782554a83f3025ef4e771bd8f01Timo Sirainen p++; name++;
b215a8a123623782554a83f3025ef4e771bd8f01Timo Sirainen continue;
b215a8a123623782554a83f3025ef4e771bd8f01Timo Sirainen }
b215a8a123623782554a83f3025ef4e771bd8f01Timo Sirainen switch (*++p) {
b215a8a123623782554a83f3025ef4e771bd8f01Timo Sirainen case 'd':
b215a8a123623782554a83f3025ef4e771bd8f01Timo Sirainen dest = &domain;
b215a8a123623782554a83f3025ef4e771bd8f01Timo Sirainen break;
b215a8a123623782554a83f3025ef4e771bd8f01Timo Sirainen case 'n':
b215a8a123623782554a83f3025ef4e771bd8f01Timo Sirainen dest = &username;
b215a8a123623782554a83f3025ef4e771bd8f01Timo Sirainen break;
b215a8a123623782554a83f3025ef4e771bd8f01Timo Sirainen case 'u':
b215a8a123623782554a83f3025ef4e771bd8f01Timo Sirainen dest = &userdomain;
b215a8a123623782554a83f3025ef4e771bd8f01Timo Sirainen break;
b215a8a123623782554a83f3025ef4e771bd8f01Timo Sirainen default:
b215a8a123623782554a83f3025ef4e771bd8f01Timo Sirainen /* we checked this already above */
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen i_unreached();
b215a8a123623782554a83f3025ef4e771bd8f01Timo Sirainen }
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen p++;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen next = strchr(name, *p != '\0' ? *p : ns_sep);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if (next == NULL) {
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen *dest = name;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen name = "";
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen break;
b215a8a123623782554a83f3025ef4e771bd8f01Timo Sirainen }
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen *dest = t_strdup_until(name, next);
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen name = next;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen }
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if (*p != '\0') {
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if (*name == '\0' ||
b215a8a123623782554a83f3025ef4e771bd8f01Timo Sirainen (name[1] == '\0' && *name == ns_sep)) {
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen /* trying to open <prefix>/<user> mailbox */
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen name = "INBOX";
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen } else {
mailbox_list_set_critical(list,
"Invalid namespace prefix %s vs %s",
storage->ns_prefix_pattern, *_name);
return -1;
}
}
/* successfully matched the name. */
if (userdomain != NULL) {
/* user@domain given */
domain = strchr(userdomain, '@');
if (domain == NULL)
username = userdomain;
else {
username = t_strdup_until(userdomain, domain);
domain++;
}
} else if (username == NULL) {
/* trying to open namespace "shared/domain"
namespace prefix. */
mailbox_list_set_error(list, MAIL_ERROR_NOTFOUND,
T_MAIL_ERR_MAILBOX_NOT_FOUND(*_name));
return -1;
} else {
if (domain == NULL) {
/* no domain given, use ours (if we have one) */
domain = i_strchr_to_next(user->username, '@');
}
userdomain = domain == NULL ? username :
t_strconcat(username, "@", domain, NULL);
}
if (*userdomain == '\0') {
mailbox_list_set_error(list, MAIL_ERROR_PARAMS,
"Empty username doesn't exist");
return -1;
}
/* expand the namespace prefix and see if it already exists.
this should normally happen only when the mailbox is being opened */
struct var_expand_table tab[] = {
{ 'u', userdomain, "user" },
{ 'n', username, "username" },
{ 'd', domain, "domain" },
{ 'h', NULL, "home" },
{ '\0', NULL, NULL }
};
prefix = t_str_new(128);
str_append(prefix, ns->prefix);
if (var_expand(prefix, storage->ns_prefix_pattern, tab, &error) <= 0) {
mailbox_list_set_critical(list,
"Failed to expand namespace prefix '%s': %s",
storage->ns_prefix_pattern, error);
return -1;
}
*_ns = mail_namespace_find_prefix(user->namespaces, str_c(prefix));
if (*_ns != NULL) {
*_name = mailbox_list_get_storage_name(ns->list,
t_strconcat(ns->prefix, name, NULL));
return 0;
}
owner = mail_user_alloc(event_get_parent(user->event), userdomain,
user->set_info, user->unexpanded_set);
owner->_service_user = user->_service_user;
mail_storage_service_user_ref(owner->_service_user);
owner->creator = user;
owner->autocreated = TRUE;
owner->session_id = p_strdup(owner->pool, user->session_id);
if (mail_user_init(owner, &error) < 0) {
if (!owner->nonexistent) {
mailbox_list_set_critical(list,
"Couldn't create namespace '%s' for user %s: %s",
ns->prefix, userdomain, error);
mail_user_unref(&owner);
return -1;
}
ret = 0;
} else if (!var_has_key(storage->location, 'h', "home")) {
ret = 1;
} else {
/* we'll need to look up the user's home directory */
if ((ret = mail_user_get_home(owner, &tab[3].value)) < 0) {
mailbox_list_set_critical(list, "Namespace '%s': "
"Could not lookup home for user %s",
ns->prefix, userdomain);
mail_user_unref(&owner);
return -1;
}
}
location = t_str_new(256);
if (ret > 0 &&
var_expand(location, storage->location, tab, &error) <= 0) {
mailbox_list_set_critical(list,
"Failed to expand namespace location '%s': %s",
storage->location, error);
return -1;
}
/* create the new namespace */
new_ns = i_new(struct mail_namespace, 1);
new_ns->refcount = 1;
new_ns->type = MAIL_NAMESPACE_TYPE_SHARED;
new_ns->user = user;
new_ns->prefix = i_strdup(str_c(prefix));
new_ns->owner = owner;
new_ns->flags = (NAMESPACE_FLAG_SUBSCRIPTIONS & ns->flags) |
NAMESPACE_FLAG_LIST_PREFIX | NAMESPACE_FLAG_HIDDEN |
NAMESPACE_FLAG_AUTOCREATED | NAMESPACE_FLAG_INBOX_ANY;
new_ns->user_set = user->set;
new_ns->mail_set = _storage->set;
i_array_init(&new_ns->all_storages, 2);
if (ret <= 0) {
get_nonexistent_user_location(storage, userdomain, location);
new_ns->flags |= NAMESPACE_FLAG_UNUSABLE;
if (ns->user->mail_debug) {
i_debug("shared: Tried to access mails of "
"nonexistent user %s", userdomain);
}
}
ns_set = p_new(user->pool, struct mail_namespace_settings, 1);
ns_set->type = "shared";
ns_set->separator = p_strdup_printf(user->pool, "%c", ns_sep);
ns_set->prefix = new_ns->prefix;
ns_set->location = p_strdup(user->pool, str_c(location));
ns_set->hidden = TRUE;
ns_set->list = "yes";
new_ns->set = ns_set;
unexpanded_ns_set =
p_new(user->pool, struct mail_namespace_settings, 1);
*unexpanded_ns_set = *ns_set;
unexpanded_ns_set->location =
p_strdup(user->pool, storage->unexpanded_location);
new_ns->unexpanded_set = unexpanded_ns_set;
/* We need to create a prefix="" namespace for the owner */
if (mail_namespaces_init_location(owner, str_c(location), &error) < 0) {
/* owner gets freed by namespace deinit */
mail_namespace_destroy(new_ns);
return -1;
}
if (mail_storage_create(new_ns, NULL, _storage->flags |
MAIL_STORAGE_FLAG_NO_AUTOVERIFY, &error) < 0) {
mailbox_list_set_critical(list, "Namespace '%s': %s",
new_ns->prefix, error);
/* owner gets freed by namespace deinit */
mail_namespace_destroy(new_ns);
return -1;
}
if ((new_ns->flags & NAMESPACE_FLAG_UNUSABLE) == 0 &&
!shared_namespace_exists(new_ns)) {
/* this user doesn't have a usable storage */
new_ns->flags |= NAMESPACE_FLAG_UNUSABLE;
}
/* mark the shared namespace root as usable, since it now has
child namespaces */
ns->flags |= NAMESPACE_FLAG_USABLE;
*_name = mailbox_list_get_storage_name(new_ns->list,
t_strconcat(new_ns->prefix, name, NULL));
*_ns = new_ns;
if (_storage->class_flags == 0) {
/* flags are unset if we were using "auto" storage */
_storage->class_flags =
mail_namespace_get_default_storage(new_ns)->class_flags;
}
mail_user_add_namespace(user, &new_ns);
return 0;
}
struct mail_storage shared_storage = {
.name = MAIL_SHARED_STORAGE_NAME,
.class_flags = 0, /* unknown at this point */
.v = {
NULL,
shared_storage_alloc,
shared_storage_create,
index_storage_destroy,
NULL,
shared_storage_get_list_settings,
NULL,
fail_mailbox_alloc,
NULL,
NULL,
}
};