Replaced by namespace { mail_location } setting.
e_error(ctx->ctx.cctx->event,
"Both source and destination mail_location "
"points to same directory: %s (namespace %s "
- "{ location } is set explicitly?)",
+ "{ mail_location } is set explicitly?)",
mailbox_list_get_root_forced(user->namespaces->list,
MAILBOX_LIST_PATH_TYPE_MAILBOX),
ns->set->name);
ctx->src_username :
dest_user->username;
+ const char *const code_override_fields[] = {
+ t_strdup_printf("mail_location=%s", ctx->src_location),
+ NULL,
+ };
+ input.code_override_fields = code_override_fields;
+
mail_storage_service_io_deactivate_user(ctx->ctx.cur_service_user);
input.flags_override_add = MAIL_STORAGE_SERVICE_FLAG_NO_NAMESPACES |
MAIL_STORAGE_SERVICE_FLAG_NO_RESTRICT_ACCESS;
if (mail_storage_service_lookup_next(ctx->ctx.storage_service, &input,
&user, &error) < 0)
i_fatal("Import user initialization failed: %s", error);
- if (mail_namespaces_init_location(user, ctx->src_location, &error) < 0)
+ if (mail_namespaces_init_location(user, user->event, &error) < 0)
i_fatal("Import namespace initialization failed: %s", error);
ctx->src_user = user;
if (!dsync_brain_want_namespace(brain, ns))
continue;
e_debug(brain->event, "Namespace %s has location %s",
- ns->set->name, ns->set->location);
+ ns->set->name, ns->list->mail_set->mail_location);
if (dsync_mailbox_tree_fill(brain->local_mailbox_tree, ns,
brain->sync_box,
brain->sync_box_guid,
const struct master_service_settings *service_set =
master_service_get_service_settings(master_service);
const char *const code_override_fields[] = {
+ "mail_location=raw::LAYOUT=none",
/* use unwritable home directory */
t_strdup_printf("mail_home=%s/empty", service_set->base_dir),
/* absolute paths are ok with raw storage */
ns_set = p_new(user->pool, struct mail_namespace_settings, 1);
ns_set->name = "raw-storage";
- ns_set->location = "raw::LAYOUT=none";
ns_set->separator = "/";
ns = mail_namespaces_init_empty(user);
ns->flags |= NAMESPACE_FLAG_NOQUOTA | NAMESPACE_FLAG_NOACL;
ns->set = ns_set;
- if (mail_storage_create(ns, 0, &error) < 0)
+ if (mail_storage_create(ns, user->event, 0, &error) < 0)
i_fatal("Couldn't create internal raw storage: %s", error);
if (mail_namespaces_init_finish(ns, &error) < 0)
i_fatal("Couldn't create internal raw namespace: %s", error);
char *wildcardp, key;
bool have_username;
+ struct mail_storage_settings *set;
+ if (settings_get(ns->list->event, &mail_storage_setting_parser_info, 0,
+ &set, error_r) < 0)
+ return -1;
+
/* location must begin with the actual mailbox driver */
- p = strchr(ns->set->location, ':');
+ p = strchr(set->mail_location, ':');
if (p == NULL) {
- *error_r = "Shared mailbox location not prefixed with driver";
+ *error_r = "Shared mailbox mail_location not prefixed with driver";
+ settings_free(set);
return -1;
}
- driver = t_strdup_until(ns->set->location, p);
- storage->unexpanded_location =
- p_strdup(_storage->pool, ns->set->unexpanded_location);
- storage->unexpanded_location_override =
- ns->set->unexpanded_location_override;
+ driver = t_strdup_until(set->mail_location, p);
storage->storage_class_name = p_strdup(_storage->pool, driver);
+ settings_free(set);
if (mail_user_get_storage_class(_storage->user, driver) == NULL &&
strcmp(driver, "auto") != 0) {
struct mail_namespace *ns = *_ns;
struct shared_storage *storage = SHARED_STORAGE(_storage);
enum mail_storage_flags new_storage_flags = 0;
- const char *location, *error;
+ const char *error;
struct shared_mail_user_var_expand_ctx var_expand_ctx = {
.owner = owner,
event_set_ptr(set_event, SETTINGS_EVENT_VAR_EXPAND_FUNC_CONTEXT,
&var_expand_ctx);
- struct mail_namespace_settings *set;
- if (settings_get(set_event, &mail_namespace_setting_parser_info, 0,
+ /* Expanding mail_location may verify whether the user exists by
+ trying to access %{owner_home}. This sets
+ var_expand_ctx.nonexistent flag. Otherwise we don't need these
+ settings here. */
+ struct mail_storage_settings *set;
+ if (settings_get(set_event, &mail_storage_setting_parser_info, 0,
&set, &error) < 0) {
mailbox_list_set_critical(ns->list, "Namespace %s: %s",
ns->set->name, error);
event_unref(&set_event);
return -1;
}
- event_unref(&set_event);
+ settings_free(set);
/* create the new namespace */
struct mail_namespace *new_ns = i_new(struct mail_namespace, 1);
NAMESPACE_FLAG_AUTOCREATED | NAMESPACE_FLAG_INBOX_ANY;
i_array_init(&new_ns->all_storages, 2);
- if (!var_expand_ctx.nonexistent)
- location = t_strdup(set->location);
- else {
- location = get_nonexistent_user_location(storage, owner->username);
+ if (var_expand_ctx.nonexistent) {
+ struct settings_instance *set_instance =
+ mail_storage_service_user_get_settings_instance(
+ user->service_user);
+ new_ns->_set_instance = settings_instance_dup(set_instance);
+ event_set_ptr(set_event, SETTINGS_EVENT_INSTANCE,
+ new_ns->_set_instance);
+
+ const char *location =
+ get_nonexistent_user_location(storage,
+ owner->username);
+ settings_override(new_ns->_set_instance,
+ "mail_location", location,
+ SETTINGS_OVERRIDE_TYPE_CODE);
+
new_ns->flags |= NAMESPACE_FLAG_UNUSABLE;
e_debug(ns->user->event,
"shared: Tried to access mails of "
"nonexistent user %s", owner->username);
}
- settings_free(set);
struct mail_namespace_settings *ns_set =
p_new(user->pool, struct mail_namespace_settings, 1);
ns_set->separator = p_strdup_printf(user->pool, "%c",
mail_namespace_get_sep(ns));
ns_set->prefix = new_ns->prefix;
- ns_set->location = p_strdup(user->pool, location);
- ns_set->unexpanded_location =
- p_strdup(user->pool, storage->unexpanded_location);
- ns_set->unexpanded_location_override =
- storage->unexpanded_location_override;
ns_set->hidden = TRUE;
ns_set->list = "yes";
new_ns->set = ns_set;
/* We need to create a prefix="" namespace for the owner */
- if (mail_namespaces_init_location(owner, location, &error) < 0) {
+ if (mail_namespaces_init_location(owner, set_event, &error) < 0) {
e_error(ns->user->event,
"Failed to create shared namespace %s: %s",
new_ns->prefix, error);
/* owner gets freed by namespace deinit */
mail_namespace_destroy(new_ns);
+ event_unref(&set_event);
return -1;
}
new_storage_flags = _storage->flags &
ENUM_NEGATE(MAIL_STORAGE_FLAG_SHARED_DYNAMIC);
new_storage_flags |= MAIL_STORAGE_FLAG_NO_AUTOVERIFY;
- if (mail_storage_create(new_ns, new_storage_flags, &error) < 0) {
+ if (mail_storage_create(new_ns, set_event, new_storage_flags, &error) < 0) {
mailbox_list_set_critical(ns->list, "Namespace %s: %s",
new_ns->prefix, error);
/* owner gets freed by namespace deinit */
mail_namespace_destroy(new_ns);
+ event_unref(&set_event);
return -1;
}
if ((new_ns->flags & NAMESPACE_FLAG_UNUSABLE) == 0 &&
_storage->class_flags =
mail_namespace_get_default_storage(new_ns)->class_flags;
}
+ event_unref(&set_event);
*_ns = new_ns;
return 0;
union mailbox_list_module_context list_module_ctx;
const char *ns_prefix_pattern;
- const char *unexpanded_location;
- bool unexpanded_location_override;
-
const char *storage_class_name;
};
#include "settings.h"
#include "mailbox-list-private.h"
#include "mail-storage-private.h"
+#include "mail-storage-service.h"
#include "mail-storage-settings.h"
#include "mail-namespace.h"
.type = "private",
.separator = "",
.prefix = "",
- .location = "fail::LAYOUT=none",
- .unexpanded_location = "0fail::LAYOUT=none",
.alias_for = "",
.inbox = FALSE,
if (ns->list != NULL)
mailbox_list_destroy(&ns->list);
+ settings_instance_free(&ns->_set_instance);
if (ns->owner != ns->user && ns->owner != NULL)
mail_user_unref(&ns->owner);
if (ns->set->pool != NULL)
return 0;
}
-int mail_namespaces_init_add(struct mail_user *user,
+int mail_namespaces_init_add(struct mail_user *user, struct event *set_event,
const struct mail_namespace_settings *ns_set,
struct mail_namespace **ns_p, const char **error_r)
{
- const struct mail_storage_settings *mail_set =
- mail_user_set_get_storage_set(user);
enum mail_storage_flags flags = 0;
struct mail_namespace *ns;
const char *error;
int ret;
- if (*ns_set->location == '\0') {
- struct mail_namespace_settings *ns_set_copy =
- p_new(ns_set->pool, struct mail_namespace_settings, 1);
- *ns_set_copy = *ns_set;
- ns_set_copy->location = mail_set->mail_location;
- ns_set = ns_set_copy;
- }
-
e_debug(user->event, "Namespace %s: type=%s, prefix=%s, sep=%s, "
- "inbox=%s, hidden=%s, list=%s, subscriptions=%s "
- "location=%s",
+ "inbox=%s, hidden=%s, list=%s, subscriptions=%s",
ns_set->name, ns_set->type, ns_set->prefix,
ns_set->separator == NULL ? "" : ns_set->separator,
ns_set->inbox ? "yes" : "no",
ns_set->hidden ? "yes" : "no",
ns_set->list,
- ns_set->subscriptions ? "yes" : "no", ns_set->location);
+ ns_set->subscriptions ? "yes" : "no");
if ((ret = mail_namespace_alloc(user, ns_set, &ns, error_r)) < 0)
return ret;
ns->flags |= NAMESPACE_FLAG_NOQUOTA | NAMESPACE_FLAG_NOACL;
}
- if (mail_storage_create(ns, flags, &error) < 0) {
+ if (mail_storage_create(ns, set_event, flags, &error) < 0) {
*error_r = t_strdup_printf("Namespace %s: %s",
ns->set->name, error);
mail_namespace_free(ns);
prefixless_found = TRUE;
}
if (!prefixless_found) {
- if (mail_namespaces_init_add(user,
+ struct settings_instance *set_instance =
+ mail_storage_service_user_get_settings_instance(
+ user->service_user);
+ set_instance = settings_instance_dup(set_instance);
+ settings_override(set_instance,
+ "mail_location", "fail::LAYOUT=none",
+ SETTINGS_OVERRIDE_TYPE_CODE);
+
+ struct event *set_event = event_create(user->event);
+ event_set_ptr(set_event, SETTINGS_EVENT_INSTANCE, set_instance);
+
+ if (mail_namespaces_init_add(user, set_event,
&prefixless_ns_set,
&ns, error_r) < 0)
i_unreached();
+
+ i_assert(ns->_set_instance == NULL);
+ ns->_set_instance = set_instance;
+
+ event_unref(&set_event);
ns->next = namespaces;
namespaces = ns;
}
continue;
}
- if (mail_namespaces_init_add(user, ns_set,
+ struct event *set_event = event_create(user->event);
+ event_add_str(set_event, "namespace", ns_names[i]);
+
+ if (mail_namespaces_init_add(user, set_event, ns_set,
ns_p, error_r) < 0) {
if (!ns_set->ignore_on_failure) {
mail_namespaces_deinit(&namespaces);
settings_free(ns_set);
+ event_unref(&set_event);
return -1;
}
e_debug(user->event, "Skipping namespace %s: %s",
ns_p = &(*ns_p)->next;
}
settings_free(ns_set);
+ event_unref(&set_event);
}
if (namespaces == NULL) {
}
static int
-mail_namespaces_init_location_full(struct mail_user *user, const char *location,
- bool default_location, const char **error_r)
+mail_namespaces_init_location_full(struct mail_user *user,
+ struct event *set_event,
+ const char *override_location,
+ const char **error_r)
{
struct mail_namespace_settings *inbox_set;
struct mail_namespace *ns;
/* enums must be changed */
inbox_set->type = "private";
inbox_set->list = "yes";
- inbox_set->location = p_strdup(user->pool, location);
-
- if (default_location) {
- /* treat this the same as if a namespace was created with
- default settings. dsync relies on finding a namespace
- without explicit location setting. */
- inbox_set->unexpanded_location = "";
- } else {
- inbox_set->unexpanded_location = inbox_set->location;
- inbox_set->unexpanded_location_override = TRUE;
- }
if ((ret = mail_namespace_alloc(user, inbox_set, &ns, error_r)) < 0)
return ret;
- if (mail_storage_create(ns, 0, error_r) < 0) {
+ if (override_location[0] != '\0') {
+ struct settings_instance *set_instance =
+ mail_storage_service_user_get_settings_instance(
+ user->service_user);
+ i_assert(ns->_set_instance == NULL);
+ ns->_set_instance = settings_instance_dup(set_instance);
+ settings_override(ns->_set_instance,
+ "mail_location", override_location,
+ SETTINGS_OVERRIDE_TYPE_CODE);
+ }
+
+ if (mail_storage_create(ns, set_event, 0, error_r) < 0) {
mail_namespace_free(ns);
return -1;
}
{
const struct mail_storage_settings *mail_set;
const char *location, *location_source, *error;
- bool default_location = FALSE;
+ struct event *set_event = event_create(user->event);
mail_set = mail_user_set_get_storage_set(user);
if (*mail_set->mail_location != '\0') {
location_source = "mail_location setting";
- location = mail_set->mail_location;
- default_location = TRUE;
+ location = "";
} else if ((location = getenv("MAIL")) != NULL) {
location_source = "environment MAIL";
} else if ((location = getenv("MAILDIR")) != NULL) {
location = "";
location_source = "autodetection";
}
- if (mail_namespaces_init_location_full(user, location,
- default_location, &error) == 0)
+ int ret = mail_namespaces_init_location_full(user, set_event,
+ location, &error);
+ event_unref(&set_event);
+
+ if (ret == 0)
return 0;
else if (location[0] != '\0') {
*error_r = t_strdup_printf(
}
}
-int mail_namespaces_init_location(struct mail_user *user, const char *location,
+int mail_namespaces_init_location(struct mail_user *user,
+ struct event *set_event,
const char **error_r)
{
- return mail_namespaces_init_location_full(user, location,
- FALSE, error_r);
+ return mail_namespaces_init_location_full(user, set_event, "", error_r);
}
struct mail_namespace *mail_namespaces_init_empty(struct mail_user *user)
struct mailbox_list *list;
struct mail_storage *storage; /* default storage */
ARRAY(struct mail_storage *) all_storages;
+ /* Instance used for overriding settings - may be NULL */
+ struct settings_instance *_set_instance;
const struct mail_namespace_settings *set;
/* Add and initialize namespaces to user based on namespace settings. */
int mail_namespaces_init(struct mail_user *user, const char **error_r);
-/* Add and initialize INBOX namespace to user based on the given location. */
-int mail_namespaces_init_location(struct mail_user *user, const char *location,
+/* Add and initialize INBOX namespace to user based on the settings event. */
+int mail_namespaces_init_location(struct mail_user *user,
+ struct event *set_event,
const char **error_r);
/* Add an empty namespace to user. */
struct mail_namespace *mail_namespaces_init_empty(struct mail_user *user);
/* Allocate a new namespace and initialize it. This is called automatically by
mail_namespaces_init(). */
-int mail_namespaces_init_add(struct mail_user *user,
+int mail_namespaces_init_add(struct mail_user *user, struct event *set_event,
const struct mail_namespace_settings *ns_set,
struct mail_namespace **ns_p, const char **error_r);
int mail_namespaces_init_finish(struct mail_namespace *namespaces,
static bool mail_storage_settings_apply(struct event *event, void *_set, const char *key, const char *value, bool override, const char **error_r);
static bool mail_storage_settings_ext_check(struct event *event, void *_set, pool_t pool, const char **error_r);
-static bool namespace_settings_apply(struct event *event, void *_set, const char *key, const char *value, bool override, const char **error_r);
static bool namespace_settings_ext_check(struct event *event, void *_set, pool_t pool, const char **error_r);
static bool mailbox_settings_check(void *_set, pool_t pool, const char **error_r);
static bool mail_user_settings_apply(struct event *event, void *_set, const char *key, const char *value, bool override, const char **error_r);
DEF(ENUM, type),
DEF(STR, separator),
DEF(STR, prefix),
- DEF(STR, location),
DEF(STR, alias_for),
DEF(BOOL, inbox),
.type = "private:shared:public",
.separator = "",
.prefix = "",
- .location = "",
.alias_for = "",
.inbox = FALSE,
.struct_size = sizeof(struct mail_namespace_settings),
.pool_offset1 = 1 + offsetof(struct mail_namespace_settings, pool),
- .setting_apply = namespace_settings_apply,
.ext_check_func = namespace_settings_ext_check,
};
return ret;
}
-static bool
-namespace_settings_apply(struct event *event ATTR_UNUSED, void *_set,
- const char *key, const char *value,
- bool override, const char **error_r ATTR_UNUSED)
-{
- struct mail_namespace_settings *set = _set;
-
- if (strcmp(key, "namespace_location") == 0) {
- set->unexpanded_location = value;
- set->unexpanded_location_override = override;
- }
- return TRUE;
-}
-
static bool namespace_settings_ext_check(struct event *event,
void *_set, pool_t pool ATTR_UNUSED,
const char **error_r)
struct mail_namespace_settings *ns = _set;
int ret;
-#ifndef CONFIG_BINARY
- i_assert(ns->unexpanded_location != NULL);
-#endif
-
if (ns->separator[0] != '\0' && ns->separator[1] != '\0') {
*error_r = t_strdup_printf("Namespace %s: "
"Hierarchy separator must be only one character long",
const char *type;
const char *separator;
const char *prefix;
- const char *location;
const char *alias_for;
bool inbox;
unsigned int order;
ARRAY_TYPE(const_string) mailboxes;
- const char *unexpanded_location;
- bool unexpanded_location_override;
bool parsed_have_special_use_mailboxes;
};
static struct mail_storage *
mail_storage_get_class(struct mail_namespace *ns, const char *driver,
+ const struct mail_storage_settings *mail_set,
struct mailbox_list_settings *list_set,
enum mail_storage_flags flags, const char **error_r)
{
(void)mail_user_get_home(ns->user, &home);
if (home == NULL || *home == '\0') home = "(not set)";
- if (ns->set->location == NULL || *ns->set->location == '\0') {
+ if (mail_set->mail_location[0] == '\0') {
*error_r = t_strdup_printf(
"Mail storage autodetection failed with home=%s", home);
- } else if (str_begins_with(ns->set->location, "auto:")) {
+ } else if (str_begins_with(mail_set->mail_location, "auto:")) {
*error_r = t_strdup_printf(
"Autodetection failed for %s (home=%s)",
- ns->set->location, home);
+ mail_set->mail_location, home);
} else {
*error_r = t_strdup_printf(
"Ambiguous mail location setting, "
"don't know what to do with it: %s "
"(try prefixing it with mbox: or maildir:)",
- ns->set->location);
+ mail_set->mail_location);
}
return NULL;
}
}
static int
-mail_storage_create_full_real(struct mail_namespace *ns,
- const char *data, enum mail_storage_flags flags,
- struct mail_storage **storage_r,
- const char **error_r)
+mail_storage_create_real(struct mail_namespace *ns, struct event *set_event,
+ enum mail_storage_flags flags,
+ struct mail_storage **storage_r, const char **error_r)
{
struct mail_storage *storage_class, *storage = NULL;
struct mailbox_list *list;
+ const struct mail_storage_settings *mail_set;
struct mailbox_list_settings list_set;
enum mailbox_list_flags list_flags = 0;
- const char *p, *driver = NULL;
+ const char *p, *data, *driver = NULL;
+
+ if (settings_get(set_event, &mail_storage_setting_parser_info, 0,
+ &mail_set, error_r) < 0)
+ return -1;
+ data = mail_set->mail_location;
mailbox_list_settings_init_defaults(&list_set);
if ((flags & MAIL_STORAGE_FLAG_SHARED_DYNAMIC) != 0) {
} else {
mail_storage_set_autodetection(&data, &driver);
if (mailbox_list_settings_parse(ns->user, data, &list_set,
- error_r) < 0)
+ error_r) < 0) {
+ settings_free(mail_set);
return -1;
+ }
}
- storage_class = mail_storage_get_class(ns, driver, &list_set, flags,
- error_r);
+ storage_class = mail_storage_get_class(ns, driver, mail_set, &list_set,
+ flags, error_r);
+ settings_free(mail_set);
if (storage_class == NULL)
return -1;
i_assert(list_set.layout != NULL);
return 0;
}
-int mail_storage_create(struct mail_namespace *ns,
+int mail_storage_create(struct mail_namespace *ns, struct event *set_event,
enum mail_storage_flags flags, const char **error_r)
{
struct mail_storage *storage;
int ret;
T_BEGIN {
- ret = mail_storage_create_full_real(ns, ns->set->location,
- flags, &storage, error_r);
+ ret = mail_storage_create_real(ns, set_event, flags,
+ &storage, error_r);
} T_END_PASS_STR_IF(ret < 0, error_r);
return ret;
}
struct mail_storage *mail_storage_find_class(const char *name);
/* Create a storage for the namespace. */
-int mail_storage_create(struct mail_namespace *ns,
+int mail_storage_create(struct mail_namespace *ns, struct event *event,
enum mail_storage_flags flags, const char **error_r);
void mail_storage_unref(struct mail_storage **storage);
const char *mailbox_list_get_unexpanded_path(struct mailbox_list *list,
enum mailbox_list_path_type type)
{
- const struct mail_storage_settings *mail_set;
- const char *location = list->ns->set->unexpanded_location;
+ const char *location = list->mail_set->unexpanded_mail_location;
struct mail_user *user = list->ns->user;
struct mailbox_list_settings set;
const char *p, *path, *error;
- if (list->ns->set->unexpanded_location_override) {
+ if (list->mail_set->unexpanded_mail_location_override) {
/* set using -o or userdb lookup. */
return "";
}
- if (*location == '\0') {
- mail_set = mail_user_set_get_storage_set(user);
- if (mail_set->unexpanded_mail_location_override)
- return "";
- location = mail_set->unexpanded_mail_location;
- }
-
/* type:settings */
p = strchr(location, ':');
if (p == NULL)