const char *auth_socket;
const char *home, *destaddr, *user, *value, *errstr, *path;
ARRAY_TYPE(string) extra_fields;
- struct mail_namespace *ns, *raw_ns;
+ struct mail_user *mail_user, *raw_mail_user;
+ struct mail_namespace *raw_ns;
struct mail_storage *storage;
struct mailbox *box;
struct raw_mailbox *raw_box;
module_dir_init(modules);
namespace_pool = pool_alloconly_create("namespaces", 1024);
- if (mail_namespaces_init(namespace_pool, user, &ns) < 0)
+ mail_user = mail_user_init(user, home);
+ if (mail_namespaces_init(namespace_pool, mail_user) < 0)
i_fatal("Namespace initialization failed");
- raw_ns = mail_namespaces_init_empty(namespace_pool);
+ /* create a separate mail user for the internal namespace */
+ raw_mail_user = mail_user_init(user, NULL);
+ raw_ns = mail_namespaces_init_empty(namespace_pool, raw_mail_user);
raw_ns->flags |= NAMESPACE_FLAG_INTERNAL;
- if (mail_storage_create(raw_ns, "raw", "/tmp", user,
+
+ if (mail_storage_create(raw_ns, "raw", "/tmp",
MAIL_STORAGE_FLAG_FULL_FS_ACCESS,
FILE_LOCK_METHOD_FCNTL, &errstr) < 0)
i_fatal("Couldn't create internal raw storage: %s", errstr);
if (deliver_mail == NULL)
ret = -1;
else {
- if (deliver_mail(ns, &storage, mail, destaddr, mailbox) <= 0) {
+ if (deliver_mail(mail_user->namespaces, &storage, mail,
+ destaddr, mailbox) <= 0) {
/* if message was saved, don't bounce it even though
the script failed later. */
ret = saved_mail ? 0 : -1;
if (ret < 0 && !tried_default_save) {
/* plugins didn't handle this. save into the default mailbox. */
- ret = deliver_save(ns, &storage, mailbox, mail, 0, NULL);
+ ret = deliver_save(mail_user->namespaces,
+ &storage, mailbox, mail, 0, NULL);
}
if (ret < 0 && strcasecmp(mailbox, "INBOX") != 0) {
/* still didn't work. try once more to save it
to INBOX. */
- ret = deliver_save(ns, &storage, "INBOX", mail, 0, NULL);
+ ret = deliver_save(mail_user->namespaces,
+ &storage, "INBOX", mail, 0, NULL);
}
if (ret < 0 ) {
mailbox_transaction_rollback(&t);
mailbox_close(&box);
- mail_namespaces_deinit(&raw_ns);
- mail_namespaces_deinit(&ns);
+ mail_user_deinit(&mail_user);
+ mail_user_deinit(&raw_mail_user);
module_dir_unload(&modules);
mail_storage_deinit();
client_destroy(client, "Disconnected for inactivity");
}
-struct client *client_create(int fd_in, int fd_out,
- struct mail_namespace *namespaces)
+struct client *client_create(int fd_in, int fd_out, struct mail_user *user)
{
struct client *client;
+ struct mail_namespace *ns;
/* always use nonblocking I/O */
net_set_nonblock(fd_in, TRUE);
client_idle_timeout, client);
client->command_pool = pool_alloconly_create("client command", 1024*12);
- client->namespaces = namespaces;
+ client->user = user;
- while (namespaces != NULL) {
- mail_storage_set_callbacks(namespaces->storage,
+ for (ns = user->namespaces; ns != NULL; ns = ns->next) {
+ mail_storage_set_callbacks(ns->storage,
&mail_storage_callbacks, client);
- namespaces = namespaces->next;
}
i_assert(my_client == NULL);
void client_destroy(struct client *client, const char *reason)
{
struct client_command_context *cmd;
+
i_assert(!client->destroyed);
client->destroyed = TRUE;
client_search_updates_free(client);
mailbox_close(&client->mailbox);
}
- mail_namespaces_deinit(&client->namespaces);
+ mail_user_deinit(&client->user);
if (client->free_parser != NULL)
imap_parser_destroy(&client->free_parser);
struct ostream *output;
struct timeout *to_idle, *to_idle_output;
- struct mail_namespace *namespaces;
+ struct mail_user *user;
struct mailbox *mailbox;
struct mailbox_keywords keywords;
unsigned int select_counter; /* increased when mailbox is changed */
/* Create new client with specified input/output handles. socket specifies
if the handle is a socket. */
-struct client *client_create(int fd_in, int fd_out,
- struct mail_namespace *namespaces);
+struct client *client_create(int fd_in, int fd_out, struct mail_user *user);
void client_destroy(struct client *client, const char *reason);
/* Disconnect client connection */
}
/* find the INBOX flags */
- ns = mail_namespace_find_inbox(ctx->cmd->client->namespaces);
+ ns = mail_namespace_find_inbox(ctx->cmd->client->user->namespaces);
list_iter = mailbox_list_iter_init(ns->list, "INBOX", 0);
info = mailbox_list_iter_next(list_iter);
if (info != NULL) {
/* Special request to return the hierarchy delimiter and mailbox root
name. If namespace has a prefix, it's returned as the mailbox root.
Otherwise we'll emulate UW-IMAP behavior. */
- ns = mail_namespace_find_visible(client->namespaces, &ref);
+ ns = mail_namespace_find_visible(client->user->namespaces, &ref);
if (ns != NULL) {
ns_prefix = ns->prefix;
ns_sep = ns->sep;
} else {
ns_prefix = "";
- ns_sep = mail_namespace_get_root_sep(client->namespaces);
+ ns_sep = mail_namespace_get_root_sep(client->user->namespaces);
}
str = t_str_new(64);
ctx = p_new(cmd->pool, struct cmd_list_context, 1);
ctx->cmd = cmd;
- ctx->ns = client->namespaces;
+ ctx->ns = client->user->namespaces;
ctx->lsub = lsub;
cmd->context = ctx;
str = t_str_new(256);
str_append(str, "* NAMESPACE ");
- list_namespaces(client->namespaces, NAMESPACE_PRIVATE, str);
+ list_namespaces(client->user->namespaces, NAMESPACE_PRIVATE, str);
str_append_c(str, ' ');
- list_namespaces(client->namespaces, NAMESPACE_SHARED, str);
+ list_namespaces(client->user->namespaces, NAMESPACE_SHARED, str);
str_append_c(str, ' ');
- list_namespaces(client->namespaces, NAMESPACE_PUBLIC, str);
+ list_namespaces(client->user->namespaces, NAMESPACE_PUBLIC, str);
client_send_line(client, str_c(str));
client_send_tagline(cmd, "OK Namespace completed.");
return FALSE;
verify_name = mailbox;
- ns = mail_namespace_find_subscribable(cmd->client->namespaces,
+ ns = mail_namespace_find_subscribable(cmd->client->user->namespaces,
&mailbox);
if (ns == NULL) {
client_send_tagline(cmd, "NO Unknown namespace.");
verify_name = t_strndup(verify_name, strlen(verify_name)-1);
}
- if (have_listable_namespace_prefix(cmd->client->namespaces,
+ if (have_listable_namespace_prefix(cmd->client->user->namespaces,
verify_name)) {
/* subscribing to a listable namespace prefix, allow it. */
} else {
{
struct mail_namespace *ns;
- ns = mail_namespace_find(cmd->client->namespaces, mailbox);
+ ns = mail_namespace_find(cmd->client->user->namespaces, mailbox);
if (ns != NULL)
return ns;
{
struct client *client;
struct ostream *output;
- struct mail_namespace *ns;
- const char *user, *str, *tag;
+ struct mail_user *user;
+ const char *username, *home, *str, *tag;
lib_signals_init();
lib_signals_set_handler(SIGINT, TRUE, sig_die, NULL);
lib_signals_ignore(SIGPIPE, TRUE);
lib_signals_ignore(SIGALRM, FALSE);
- user = getenv("USER");
- if (user == NULL) {
+ username = getenv("USER");
+ if (username == NULL) {
if (IS_STANDALONE())
- user = getlogin();
- if (user == NULL)
+ username = getlogin();
+ if (username == NULL)
i_fatal("USER environment missing");
}
+ home = getenv("HOME");
if (getenv("DEBUG") != NULL) {
- const char *home;
-
- home = getenv("HOME");
i_info("Effective uid=%s, gid=%s, home=%s",
dec2str(geteuid()), dec2str(getegid()),
home != NULL ? home : "(none)");
parse_workarounds();
namespace_pool = pool_alloconly_create("namespaces", 1024);
- if (mail_namespaces_init(namespace_pool, user, &ns) < 0)
+ user = mail_user_init(username, home);
+ if (mail_namespaces_init(namespace_pool, user) < 0)
i_fatal("Namespace initialization failed");
- client = client_create(0, 1, ns);
+ client = client_create(0, 1, user);
output = client->output;
o_stream_ref(output);
client_send_line(client, t_strconcat(
"* PREAUTH [CAPABILITY ",
str_c(capability_string), "] "
- "Logged in as ", user, NULL));
+ "Logged in as ", user->username, NULL));
} else {
client_send_line(client, t_strconcat(
tag, " OK [CAPABILITY ",
mail-search.c \
mail-search-build.c \
mail-storage.c \
+ mail-user.c \
mailbox-list.c \
mailbox-search-result.c \
mailbox-tree.c
mail-thread.h \
mail-storage.h \
mail-storage-private.h \
+ mail-user.h \
mailbox-list.h \
mailbox-list-private.h \
mailbox-search-result-private.h \
static int
maildir_get_list_settings(struct mailbox_list_settings *list_set,
- const char *data, enum mail_storage_flags flags,
+ const char *data, struct mail_storage *storage,
const char **layout_r, const char **error_r)
{
+ enum mail_storage_flags flags = storage->flags;
+ struct mail_user *user = storage->ns->user;
bool debug = (flags & MAIL_STORAGE_FLAG_DEBUG) != 0;
- const char *home, *path;
+ const char *path;
*layout_r = MAILDIR_PLUSPLUS_DRIVER_NAME;
}
/* we'll need to figure out the maildir location ourself.
- It's $HOME/Maildir unless we are chrooted. */
- if ((home = getenv("HOME")) != NULL) {
- path = t_strconcat(home, "/Maildir", NULL);
+ It's ~/Maildir unless we are chrooted. */
+ if (user->home != NULL) {
+ path = t_strconcat(user->home, "/Maildir", NULL);
if (access(path, R_OK|W_OK|X_OK) == 0) {
if (debug) {
i_info("maildir: root exists (%s)",
}
} else {
if (debug)
- i_info("maildir: HOME not set");
+ i_info("maildir: Home directory not set");
}
if (access("/cur", R_OK|W_OK|X_OK) == 0) {
const char *layout;
struct stat st;
- if (maildir_get_list_settings(&list_set, data, flags, &layout,
+ if (maildir_get_list_settings(&list_set, data, _storage, &layout,
error_r) < 0)
return -1;
list_set.mail_storage_flags = &_storage->flags;
const char *line;
if (from_envelope == NULL) {
- from_envelope =
- t_strconcat(ctx->mbox->storage->storage.user,
- "@", my_hostdomain, NULL);
+ struct mail_storage *storage =
+ &ctx->mbox->storage->storage;
+
+ from_envelope = t_strconcat(storage->ns->user->username,
+ "@", my_hostdomain, NULL);
}
/* save in local timezone, no matter what it was given with */
return FALSE;
}
-static const char *get_root_dir(enum mail_storage_flags flags)
+static const char *get_root_dir(struct mail_storage *storage)
{
const char *home, *path;
- bool debug = (flags & MAIL_STORAGE_FLAG_DEBUG) != 0;
+ bool debug = (storage->flags & MAIL_STORAGE_FLAG_DEBUG) != 0;
- home = getenv("HOME");
+ home = storage->ns->user->home;
if (home != NULL) {
path = t_strconcat(home, "/mail", NULL);
if (access(path, R_OK|W_OK|X_OK) == 0) {
if (debug)
i_info("mbox: checking if we are chrooted:");
- if (mbox_autodetect("", flags))
+ if (mbox_autodetect("", storage->flags))
return "/";
if (debug)
}
static const char *
-get_inbox_file(const char *root_dir, bool only_root, bool debug)
+get_inbox_file(const char *user, const char *root_dir,
+ bool only_root, bool debug)
{
- const char *user, *path;
+ const char *path;
- if (!only_root && (user = getenv("USER")) != NULL) {
+ if (!only_root) {
path = t_strconcat("/var/mail/", user, NULL);
if (access(path, R_OK|W_OK) == 0) {
if (debug)
return path;
}
-static const char *create_root_dir(bool debug, const char **error_r)
+static const char *create_root_dir(struct mail_storage *storage,
+ const char **error_r)
{
const char *home, *path;
- home = getenv("HOME");
+ home = storage->ns->user->home;
if (home == NULL) {
*error_r = "Root mail directory not set and "
"home directory is missing";
return NULL;
}
- if (debug)
+ if ((storage->flags & MAIL_STORAGE_FLAG_DEBUG) != 0)
i_info("mbox: root directory created: %s", path);
return path;
}
static int
mbox_get_list_settings(struct mailbox_list_settings *list_set,
- const char *data, enum mail_storage_flags flags,
+ const char *data, struct mail_storage *storage,
const char **layout_r, const char **error_r)
{
+ enum mail_storage_flags flags = storage->flags;
bool debug = (flags & MAIL_STORAGE_FLAG_DEBUG) != 0;
const char *p;
struct stat st;
/* we'll need to figure out the mail location ourself.
it's root dir if we've already chroot()ed, otherwise
- either $HOME/mail or $HOME/Mail */
- list_set->root_dir = get_root_dir(flags);
+ either ~/mail or ~/Mail */
+ list_set->root_dir = get_root_dir(storage);
} else {
if (debug)
i_info("mbox: data=%s", data);
if (stat(data, &st) < 0 || S_ISDIR(st.st_mode))
list_set->root_dir = data;
else {
- list_set->root_dir = get_root_dir(flags);
+ list_set->root_dir = get_root_dir(storage);
list_set->inbox_path = data;
}
} else {
return -1;
}
- list_set->root_dir = create_root_dir(debug, error_r);
+ list_set->root_dir = create_root_dir(storage, error_r);
if (list_set->root_dir == NULL)
return -1;
} else {
if (list_set->inbox_path == NULL) {
list_set->inbox_path =
- get_inbox_file(list_set->root_dir, !autodetect, debug);
+ get_inbox_file(storage->ns->user->username,
+ list_set->root_dir, !autodetect, debug);
}
return 0;
}
struct mailbox_list_settings list_set;
const char *layout;
- if (mbox_get_list_settings(&list_set, data,
- _storage->flags, &layout, error_r) < 0)
+ if (mbox_get_list_settings(&list_set, data, _storage,
+ &layout, error_r) < 0)
return -1;
list_set.mail_storage_flags = &_storage->flags;
list_set.lock_method = &_storage->lock_method;
static struct mail_namespace *
namespace_add_env(pool_t pool, const char *data, unsigned int num,
- const char *user, enum mail_storage_flags flags,
+ struct mail_user *user, enum mail_storage_flags flags,
enum file_lock_method lock_method)
{
struct mail_namespace *ns;
if (sep != NULL)
ns->sep = *sep;
ns->prefix = p_strdup(pool, prefix);
+ ns->user = user;
- if (mail_storage_create(ns, NULL, data, user, flags, lock_method,
+ if (mail_storage_create(ns, NULL, data, flags, lock_method,
&error) < 0) {
i_error("Namespace '%s': %s", ns->prefix, error);
return NULL;
return dest;
}
-int mail_namespaces_init(pool_t pool, const char *user,
- struct mail_namespace **namespaces_r)
+int mail_namespaces_init(pool_t pool, struct mail_user *user)
{
struct mail_namespace *namespaces, *ns, **ns_p;
enum mail_storage_flags flags;
if (!namespaces_check(namespaces))
return -1;
namespaces = namespaces_sort(namespaces);
- *namespaces_r = namespaces;
+ user->namespaces = namespaces;
if (hook_mail_namespaces_created != NULL) {
T_BEGIN {
ns->flags = NAMESPACE_FLAG_INBOX | NAMESPACE_FLAG_LIST |
NAMESPACE_FLAG_SUBSCRIPTIONS;
ns->prefix = "";
+ ns->user = user;
- if (mail_storage_create(ns, NULL, mail, user, flags, lock_method,
+ if (mail_storage_create(ns, NULL, mail, flags, lock_method,
&error) < 0) {
if (mail != NULL && *mail != '\0')
i_error("mail_location: %s", error);
}
return -1;
}
- *namespaces_r = ns;
+ user->namespaces = ns;
if (hook_mail_namespaces_created != NULL) {
T_BEGIN {
return 0;
}
-struct mail_namespace *mail_namespaces_init_empty(pool_t pool)
+struct mail_namespace *
+mail_namespaces_init_empty(pool_t pool, struct mail_user *user)
{
struct mail_namespace *ns;
ns = p_new(pool, struct mail_namespace, 1);
+ ns->user = user;
ns->prefix = "";
ns->flags = NAMESPACE_FLAG_INBOX | NAMESPACE_FLAG_LIST |
NAMESPACE_FLAG_SUBSCRIPTIONS;
+ user->namespaces = ns;
return ns;
}
#ifndef MAIL_NAMESPACE_H
#define MAIL_NAMESPACE_H
+#include "mail-user.h"
+
enum namespace_type {
NAMESPACE_PRIVATE,
NAMESPACE_SHARED,
const char *prefix;
size_t prefix_len;
+ struct mail_user *user;
struct mailbox_list *list;
/* FIXME: we should support multiple storages in one namespace */
struct mail_storage *storage;
/* Called after namespaces has been created */
extern void (*hook_mail_namespaces_created)(struct mail_namespace *namespaces);
-int mail_namespaces_init(pool_t pool, const char *user,
- struct mail_namespace **namespaces_r);
-struct mail_namespace *mail_namespaces_init_empty(pool_t pool);
+int mail_namespaces_init(pool_t pool, struct mail_user *user);
+struct mail_namespace *
+mail_namespaces_init_empty(pool_t pool, struct mail_user *user);
void mail_namespaces_deinit(struct mail_namespace **namespaces);
/* Update hierarchy separators in given name to real_sep characters. */
struct mail_namespace *ns;
struct mailbox_list *list;
- const char *user; /* name of user accessing the storage */
enum mail_storage_flags flags;
enum file_lock_method lock_method;
unsigned int keyword_max_len;
}
int mail_storage_create(struct mail_namespace *ns, const char *driver,
- const char *data, const char *user,
- enum mail_storage_flags flags,
+ const char *data, enum mail_storage_flags flags,
enum file_lock_method lock_method,
const char **error_r)
{
storage = classes[i]->v.alloc();
storage->flags = flags;
storage->lock_method = lock_method;
- storage->user = p_strdup(storage->pool, user);
storage->ns = ns;
storage->callbacks =
return -1;
}
- home = getenv("HOME");
+ home = ns->user->home;
if (home == NULL || *home == '\0') home = "(not set)";
*error_r = t_strdup_printf(
from data. If data is NULL, it uses the first storage that exists.
The storage is put into ns->storage. */
int mail_storage_create(struct mail_namespace *ns, const char *driver,
- const char *data, const char *user,
- enum mail_storage_flags flags,
+ const char *data, enum mail_storage_flags flags,
enum file_lock_method lock_method,
const char **error_r);
void mail_storage_destroy(struct mail_storage **storage);
acl_env = getenv("ACL");
i_assert(acl_env != NULL);
- owner_username = getenv("USER");
- if (owner_username == NULL)
- i_fatal("ACL: USER environment not set");
-
+ owner_username = list->ns->user->username;
current_username = getenv("MASTER_USER");
if (current_username == NULL)
current_username = owner_username;
if (ns->type != NAMESPACE_PRIVATE)
owner = FALSE;
- /* FIXME: set groups */
backend = acl_backend_init(acl_env, list, current_username,
getenv("ACL_GROUPS") == NULL ? NULL :
t_strsplit(getenv("ACL_GROUPS"), ","),
struct convert_settings set;
memset(&set, 0, sizeof(set));
- set.user = getenv("USER");
- if (set.user == NULL)
- i_fatal("convert plugin: USER unset");
- set.home = getenv("HOME");
- if (set.home == NULL)
+ if (namespaces->user->home == NULL)
i_fatal("convert plugin: HOME unset");
set.skip_broken_mailboxes =
struct mail_namespace *dest_namespaces,
const struct convert_settings *set)
{
+ struct mail_user *user = dest_namespaces->user;
struct mail_namespace *source_ns, *dest_inbox_ns;
struct dotlock *dotlock;
enum mail_storage_flags src_flags;
const char *path, *error;
int ret;
- source_ns = mail_namespaces_init_empty(pool_datastack_create());
+ source_ns = mail_namespaces_init_empty(pool_datastack_create(), user);
dest_inbox_ns = mail_namespace_find_inbox(dest_namespaces);
src_flags = dest_inbox_ns->storage->flags;
lock_method = dest_inbox_ns->storage->lock_method;
src_flags |= MAIL_STORAGE_FLAG_NO_AUTOCREATE;
- if (mail_storage_create(source_ns, NULL, source_data, set->user,
+ if (mail_storage_create(source_ns, NULL, source_data,
src_flags, lock_method, &error) < 0) {
/* No need for conversion. */
return 0;
}
- path = t_strconcat(set->home, "/"CONVERT_LOCK_FILENAME, NULL);
+ path = t_strconcat(user->home, "/"CONVERT_LOCK_FILENAME, NULL);
dotlock_settings.use_excl_lock =
(source_ns->storage->flags &
MAIL_STORAGE_FLAG_DOTLOCK_USE_EXCL) != 0;
/* just in case if another process just had converted the mailbox,
reopen the source storage */
mail_storage_destroy(&source_ns->storage);
- if (mail_storage_create(source_ns, NULL, source_data, set->user,
+ if (mail_storage_create(source_ns, NULL, source_data,
src_flags, lock_method, &error) < 0) {
/* No need for conversion anymore. */
file_dotlock_delete(&dotlock);
struct mail_namespace;
struct convert_settings {
- const char *user;
- const char *home;
bool skip_broken_mailboxes;
bool skip_dotdirs;
char alt_hierarchy_char;
{
struct ioloop *ioloop;
struct convert_settings set;
+ struct mail_user *user;
struct mail_namespace *dest_ns;
enum mail_storage_flags dest_flags;
enum file_lock_method lock_method;
ioloop = io_loop_create();
memset(&set, 0, sizeof(set));
- set.user = argv[1];
- set.home = argv[2];
-
for (i = 5; i < argc; i++) {
if (strcmp(argv[i], "skip_broken_mailboxes") != 0)
set.skip_broken_mailboxes = TRUE;
}
mail_storage_parse_env(&dest_flags, &lock_method);
- dest_ns = mail_namespaces_init_empty(pool_datastack_create());
- if (mail_storage_create(dest_ns, NULL, argv[4], set.user,
+ user = mail_user_init(argv[1], argv[2]);
+ dest_ns = mail_namespaces_init_empty(pool_datastack_create(), user);
+
+ if (mail_storage_create(dest_ns, NULL, argv[4],
dest_flags, lock_method, &error) < 0) {
i_fatal("Failed to create destination "
"mail storage with data '%s': %s", argv[4], error);
i_error("Source storage not found");
else
i_error("Internal failure");
- mail_namespaces_deinit(&dest_ns);
+ mail_user_deinit(&user);
io_loop_destroy(&ioloop);
mail_storage_deinit();
if (dict_uri == NULL)
i_fatal("expire plugin: expire_dict setting missing");
+ // FIXME: user should be per-mail_user?...
expire.username = getenv("USER");
expire.env = expire_env_init(expunge_env, altmove_env);
expire.db = dict_init(dict_uri, DICT_DATA_TYPE_UINT32, expire.username);
#include "lib.h"
#include "ioloop.h"
+#include "env-util.h"
#include "file-lock.h"
#include "randgen.h"
#include "lib-signals.h"
struct auth_connection *auth_conn;
char *user;
+ struct mail_user *mail_user;
pool_t namespace_pool;
- struct mail_namespace *ns;
bool testrun;
};
{
int ret;
+ env_clean();
if ((ret = auth_client_put_user_env(ctx->auth_conn, user)) <= 0) {
if (ret < 0)
return ret;
return 0;
}
- if (mail_namespaces_init(ctx->namespace_pool, user, &ctx->ns) < 0)
+ ctx->mail_user = mail_user_init(user, getenv("HOME"));
+ if (mail_namespaces_init(ctx->namespace_pool, ctx->mail_user) < 0)
return -1;
return 1;
}
static void user_deinit(struct expire_context *ctx)
{
- mail_namespaces_deinit(&ctx->ns);
+ mail_user_deinit(&ctx->mail_user);
i_free_and_null(ctx->user);
p_clear(ctx->namespace_pool);
}
}
ns_mailbox = mailbox;
- ns = mail_namespace_find(ctx->ns, &ns_mailbox);
+ ns = mail_namespace_find(ctx->mail_user->namespaces, &ns_mailbox);
if (ns == NULL) {
/* entire namespace no longer exists, remove the entry */
if (ctx->testrun)
str_append(str, "* QUOTAROOT ");
imap_quote_append_string(str, orig_mailbox, FALSE);
- iter = quota_root_iter_init(quota_set, box);
+ iter = quota_root_iter_init(box);
while ((root = quota_root_iter_next(iter)) != NULL) {
str_append_c(str, ' ');
imap_quote_append_string(str, quota_root_get_name(root), FALSE);
client_send_line(cmd->client, str_c(str));
/* send QUOTA reply for each quotaroot */
- iter = quota_root_iter_init(quota_set, box);
+ iter = quota_root_iter_init(box);
while ((root = quota_root_iter_next(iter)) != NULL)
quota_send(cmd, root);
quota_root_iter_deinit(&iter);
return TRUE;
}
- root = quota_root_lookup(quota_set, root_name);
+ root = quota_root_lookup(cmd->client->user, root_name);
if (root == NULL) {
client_send_tagline(cmd, "NO Quota root doesn't exist.");
return TRUE;
return TRUE;
}
- root = quota_root_lookup(quota_set, root_name);
+ root = quota_root_lookup(cmd->client->user, root_name);
if (root == NULL) {
client_send_tagline(cmd, "NO Quota root doesn't exist.");
return TRUE;
MODULE_CONTEXT(obj, lazy_expunge_mail_storage_module)
#define LAZY_EXPUNGE_LIST_CONTEXT(obj) \
MODULE_CONTEXT(obj, lazy_expunge_mailbox_list_module)
+#define LAZY_EXPUNGE_USER_CONTEXT(obj) \
+ MODULE_CONTEXT(obj, lazy_expunge_mail_user_module)
enum lazy_namespace {
LAZY_NAMESPACE_EXPUNGE,
LAZY_NAMESPACE_COUNT
};
+struct lazy_expunge_mail_user {
+ union mail_user_module_context module_ctx;
+
+ struct mail_namespace *lazy_ns[LAZY_NAMESPACE_COUNT];
+};
+
struct lazy_expunge_mailbox_list {
union mailbox_list_module_context module_ctx;
(struct mail_storage *storage);
static void (*lazy_expunge_next_hook_mailbox_list_created)
(struct mailbox_list *list);
+static void (*lazy_expunge_next_hook_mail_user_created)(struct mail_user *user);
static MODULE_CONTEXT_DEFINE_INIT(lazy_expunge_mail_storage_module,
&mail_storage_module_register);
&mail_module_register);
static MODULE_CONTEXT_DEFINE_INIT(lazy_expunge_mailbox_list_module,
&mailbox_list_module_register);
-
-static struct mail_namespace *lazy_namespaces[LAZY_NAMESPACE_COUNT];
+static MODULE_CONTEXT_DEFINE_INIT(lazy_expunge_mail_user_module,
+ &mail_user_module_register);
static struct mailbox *
mailbox_open_or_create(struct mail_storage *storage, const char *name)
static void lazy_expunge_mail_expunge(struct mail *_mail)
{
+ struct lazy_expunge_mail_user *luser =
+ LAZY_EXPUNGE_USER_CONTEXT(_mail->box->storage->ns->user);
struct lazy_expunge_transaction *lt =
LAZY_EXPUNGE_CONTEXT(_mail->transaction);
struct mail_storage *deststorage;
if (lt->expunge_box == NULL) {
- deststorage = lazy_namespaces[LAZY_NAMESPACE_EXPUNGE]->storage;
+ deststorage = luser->lazy_ns[LAZY_NAMESPACE_EXPUNGE]->storage;
lt->expunge_box = mailbox_open_or_create(deststorage,
_mail->box->name);
if (lt->expunge_box == NULL) {
static int
lazy_expunge_mailbox_list_delete(struct mailbox_list *list, const char *name)
{
+ struct lazy_expunge_mail_user *luser =
+ LAZY_EXPUNGE_USER_CONTEXT(list->ns->user);
struct lazy_expunge_mailbox_list *llist =
LAZY_EXPUNGE_LIST_CONTEXT(list);
struct lazy_expunge_mail_storage *lstorage;
destname = t_strconcat(name, "-", timestamp, NULL);
/* first move the actual mailbox */
- dest_list = lazy_namespaces[LAZY_NAMESPACE_DELETE]->storage->list;
+ dest_list = luser->lazy_ns[LAZY_NAMESPACE_DELETE]->storage->list;
if ((ret = mailbox_move(list, name, dest_list, &destname)) < 0)
return -1;
if (ret == 0) {
}
/* next move the expunged messages mailbox, if it exists */
- list = lazy_namespaces[LAZY_NAMESPACE_EXPUNGE]->storage->list;
+ list = luser->lazy_ns[LAZY_NAMESPACE_EXPUNGE]->storage->list;
dest_list =
- lazy_namespaces[LAZY_NAMESPACE_DELETE_EXPUNGE]->storage->list;
+ luser->lazy_ns[LAZY_NAMESPACE_DELETE_EXPUNGE]->storage->list;
(void)mailbox_move(list, name, dest_list, &destname);
return 0;
}
static void
lazy_expunge_hook_mail_namespaces_created(struct mail_namespace *namespaces)
{
+ struct lazy_expunge_mail_user *luser =
+ LAZY_EXPUNGE_USER_CONTEXT(namespaces->user);
struct lazy_expunge_mail_storage *lstorage;
const char *const *p;
int i;
- if (lazy_expunge_next_hook_mail_namespaces_created != NULL)
- lazy_expunge_next_hook_mail_namespaces_created(namespaces);
-
p = t_strsplit_spaces(getenv("LAZY_EXPUNGE"), " ");
for (i = 0; i < LAZY_NAMESPACE_COUNT; i++, p++) {
const char *name = *p;
if (name == NULL)
i_fatal("lazy_expunge: Missing namespace #%d", i + 1);
- lazy_namespaces[i] =
+ luser->lazy_ns[i] =
mail_namespace_find_prefix(namespaces, name);
- if (lazy_namespaces[i] == NULL)
+ if (luser->lazy_ns[i] == NULL)
i_fatal("lazy_expunge: Unknown namespace: '%s'", name);
- if (strcmp(lazy_namespaces[i]->storage->name, "maildir") != 0) {
+ if (strcmp(luser->lazy_ns[i]->storage->name, "maildir") != 0) {
i_fatal("lazy_expunge: Namespace must be in maildir "
"format: %s", name);
}
/* we don't want to override these namespaces' expunge/delete
operations. */
- lstorage = LAZY_EXPUNGE_CONTEXT(lazy_namespaces[i]->storage);
+ lstorage = LAZY_EXPUNGE_CONTEXT(luser->lazy_ns[i]->storage);
lstorage->internal_namespace = TRUE;
}
+
+ if (lazy_expunge_next_hook_mail_namespaces_created != NULL)
+ lazy_expunge_next_hook_mail_namespaces_created(namespaces);
+}
+
+static void lazy_expunge_mail_user_created(struct mail_user *user)
+{
+ struct lazy_expunge_mail_user *luser;
+
+ luser = p_new(user->pool, struct lazy_expunge_mail_user, 1);
+ luser->module_ctx.super = user->v;
+
+ MODULE_CONTEXT_SET(user, lazy_expunge_mail_user_module, luser);
+
+ if (lazy_expunge_next_hook_mail_user_created != NULL)
+ lazy_expunge_next_hook_mail_user_created(user);
}
void lazy_expunge_plugin_init(void)
lazy_expunge_next_hook_mailbox_list_created = hook_mailbox_list_created;
hook_mailbox_list_created = lazy_expunge_mailbox_list_created;
+
+ lazy_expunge_next_hook_mail_user_created = hook_mail_user_created;
+ hook_mail_user_created = lazy_expunge_mail_user_created;
}
void lazy_expunge_plugin_deinit(void)
lazy_expunge_hook_mail_namespaces_created;
hook_mail_storage_created = lazy_expunge_next_hook_mail_storage_created;
hook_mailbox_list_created = lazy_expunge_next_hook_mailbox_list_created;
+ hook_mail_user_created = lazy_expunge_next_hook_mail_user_created;
}
uoff_t size;
int ret = 0;
- rule = quota_root_rule_find(root, name);
+ rule = quota_root_rule_find(root->set, name);
if (rule != NULL && rule->ignore) {
/* mailbox not included in quota */
return 0;
#include "lib.h"
#include "str.h"
#include "dict.h"
+#include "mail-user.h"
#include "quota-private.h"
#include <stdlib.h>
}
if (*username == '\0')
- username = getenv("USER");
+ username = _root->quota->user->username;
- if (_root->quota->debug) {
+ if (_root->quota->set->debug) {
i_info("dict quota: user=%s, uri=%s, enforcing=%d",
username, args, _root->no_enforcing);
}
}
static int
-dict_quota_get_resource(struct quota_root *_root, const char *name,
- uint64_t *value_r)
+dict_quota_get_resource(struct quota_root *_root,
+ const char *name, uint64_t *value_r)
{
struct dict_quota_root *root = (struct dict_quota_root *)_root;
bool want_bytes;
if (ctx->info == NULL)
return NULL;
- rule = quota_root_rule_find(&ctx->root->root,
+ rule = quota_root_rule_find(ctx->root->root.set,
ctx->info->name);
if (rule != NULL && rule->ignore) {
/* mailbox not included in quota */
static int maildirsize_write(struct maildir_quota_root *root, const char *path)
{
- const struct quota_rule *rule = &root->root.default_rule;
+ const struct quota_rule *rule = &root->root.set->default_rule;
struct mail_storage *const *storages;
unsigned int i, count;
struct dotlock *dotlock;
static void maildirsize_rebuild_later(struct maildir_quota_root *root)
{
- if (!root->root.force_default_rule) {
+ if (!root->root.set->force_default_rule) {
/* FIXME: can't unlink(), because the limits would be lost. */
return;
}
static int maildirsize_parse(struct maildir_quota_root *root,
int fd, const char *const *lines)
{
- struct quota_rule *rule = &root->root.default_rule;
+ struct quota_rule *rule = &root->root.set->default_rule;
uint64_t message_bytes_limit, message_count_limit;
long long bytes_diff, total_bytes;
int count_diff, total_count;
if (rule->bytes_limit == (int64_t)message_bytes_limit &&
rule->count_limit == (int64_t)message_count_limit) {
/* limits haven't changed */
- } else if (root->root.force_default_rule) {
+ } else if (root->root.set->force_default_rule) {
/* we know the limits and they've changed.
the file must be rewritten. */
return 0;
/* we're using limits from the file. */
rule->bytes_limit = message_bytes_limit;
rule->count_limit = message_count_limit;
- quota_root_recalculate_relative_rules(&root->root);
+ quota_root_recalculate_relative_rules(root->root.set);
}
if (*lines == NULL) {
ret = maildirsize_read(root);
} T_END;
if (ret == 0) {
- if (root->root.default_rule.bytes_limit == 0 &&
- root->root.default_rule.count_limit == 0) {
+ if (root->root.set->default_rule.bytes_limit == 0 &&
+ root->root.set->default_rule.count_limit == 0) {
/* no quota */
return 0;
}
}
static bool
-maildir_quota_parse_rule(struct quota_root *root ATTR_UNUSED,
+maildir_quota_parse_rule(struct quota_root_settings *root_set ATTR_UNUSED,
struct quota_rule *rule,
const char *str, const char **error_r)
{
/* defined by imap, pop3, lda */
extern void (*hook_mail_storage_created)(struct mail_storage *storage);
+void (*quota_next_hook_mail_user_created)(struct mail_user *user);
void (*quota_next_hook_mail_storage_created)(struct mail_storage *storage);
void (*quota_next_hook_mailbox_list_created)(struct mailbox_list *list);
const char *quota_plugin_version = PACKAGE_VERSION;
-struct quota *quota_set;
+struct quota_settings *quota_set;
static void quota_root_add_rules(const char *root_name,
- struct quota_root *root)
+ struct quota_root_settings *root_set)
{
const char *rule_name, *rule, *error;
unsigned int i;
if (rule == NULL)
break;
- if (quota_root_add_rule(root, rule, &error) < 0) {
+ if (quota_root_add_rule(root_set, rule, &error) < 0) {
i_fatal("Quota root %s: Invalid rule %s: %s",
root_name, rule, error);
}
}
static void quota_root_add_warning_rules(const char *root_name,
- struct quota_root *root)
+ struct quota_root_settings *root_set)
{
const char *rule_name, *rule, *error;
unsigned int i;
if (rule == NULL)
break;
- if (quota_root_add_warning_rule(root, rule, &error) < 0) {
+ if (quota_root_add_warning_rule(root_set, rule, &error) < 0) {
i_fatal("Quota root %s: Invalid warning rule: %s",
root_name, rule);
}
void quota_plugin_init(void)
{
- struct quota_root *root;
+ struct quota_root_settings *root_set;
unsigned int i;
const char *env;
if (env == NULL)
return;
- quota_set = quota_init();
+ quota_set = quota_settings_init();
- root = quota_root_init(quota_set, env);
- if (root == NULL)
+ root_set = quota_root_settings_init(quota_set, env);
+ if (root_set == NULL)
i_fatal("Couldn't create quota root: %s", env);
- quota_root_add_rules("QUOTA", root);
- quota_root_add_warning_rules("QUOTA", root);
+ quota_root_add_rules("QUOTA", root_set);
+ quota_root_add_warning_rules("QUOTA", root_set);
for (i = 2;; i++) {
const char *root_name;
if (env == NULL)
break;
- root = quota_root_init(quota_set, env);
- if (root == NULL)
+ root_set = quota_root_settings_init(quota_set, env);
+ if (root_set == NULL)
i_fatal("Couldn't create quota root: %s", env);
- quota_root_add_rules(root_name, root);
- quota_root_add_warning_rules(root_name, root);
+ quota_root_add_rules(root_name, root_set);
+ quota_root_add_warning_rules(root_name, root_set);
}
+ quota_next_hook_mail_user_created = hook_mail_user_created;
+ hook_mail_user_created = quota_mail_user_created;
+
quota_next_hook_mail_storage_created = hook_mail_storage_created;
hook_mail_storage_created = quota_mail_storage_created;
void quota_plugin_deinit(void)
{
if (quota_set != NULL) {
+ hook_mail_user_created = quota_next_hook_mail_user_created;
hook_mail_storage_created =
quota_next_hook_mail_storage_created;
hook_mailbox_list_created =
quota_next_hook_mailbox_list_created;
- quota_deinit("a_set);
+ quota_settings_deinit("a_set);
}
}
struct mail_storage;
+extern void (*quota_next_hook_mail_user_created)(struct mail_user *user);
extern void (*quota_next_hook_mail_storage_created)
(struct mail_storage *storage);
extern void (*quota_next_hook_mailbox_list_created)(struct mailbox_list *list);
-/* "quota" symbol already exists in OSX, so we'll use this slightly uglier
- name. */
-extern struct quota *quota_set;
+extern struct quota_settings *quota_set;
+void quota_mail_user_created(struct mail_user *user);
void quota_mail_storage_created(struct mail_storage *storage);
void quota_mailbox_list_created(struct mailbox_list *list);
extern unsigned int quota_module_id;
struct quota {
+ struct mail_user *user;
+ struct quota_settings *set;
+
ARRAY_DEFINE(roots, struct quota_root *);
ARRAY_DEFINE(storages, struct mail_storage *);
+};
+
+struct quota_settings {
+ pool_t pool;
+ ARRAY_DEFINE(root_sets, struct quota_root_settings *);
int (*test_alloc)(struct quota_transaction_context *ctx,
uoff_t size, bool *too_large_r);
};
struct quota_rule {
- char *mailbox_name;
+ const char *mailbox_name;
int64_t bytes_limit, count_limit;
/* relative to default_rule */
struct quota_warning_rule {
struct quota_rule rule;
- char *command;
+ const char *command;
};
struct quota_backend_vfuncs {
int (*init)(struct quota_root *root, const char *args);
void (*deinit)(struct quota_root *root);
- bool (*parse_rule)(struct quota_root *root, struct quota_rule *rule,
+ bool (*parse_rule)(struct quota_root_settings *root_set,
+ struct quota_rule *rule,
const char *str, const char **error_r);
/* called once for each backend */
struct mail_storage *storage);
const char *const *(*get_resources)(struct quota_root *root);
- int (*get_resource)(struct quota_root *root, const char *name,
- uint64_t *value_r);
+ int (*get_resource)(struct quota_root *root,
+ const char *name, uint64_t *value_r);
int (*update)(struct quota_root *root,
struct quota_transaction_context *ctx);
struct quota_backend_vfuncs v;
};
-struct quota_root {
- pool_t pool;
-
+struct quota_root_settings {
/* Unique quota root name. */
const char *name;
- /* pointer to the quota that owns this root */
- struct quota *quota;
+ struct quota_settings *set;
+ const char *args;
- struct quota_backend backend;
+ const struct quota_backend *backend;
struct quota_rule default_rule;
ARRAY_DEFINE(rules, struct quota_rule);
ARRAY_DEFINE(warning_rules, struct quota_warning_rule);
+ /* Limits in default_rule override backend's quota limits */
+ unsigned int force_default_rule:1;
+};
+
+struct quota_root {
+ pool_t pool;
+
+ struct quota_root_settings *set;
+ struct quota *quota;
+ struct quota_backend backend;
+
/* Module-specific contexts. See quota_module_id. */
ARRAY_DEFINE(quota_module_contexts, void);
/* don't enforce quota when saving */
unsigned int no_enforcing:1;
- /* Limits in default_rule override backend's quota limits */
- unsigned int force_default_rule:1;
};
struct quota_transaction_context {
/* Register storage to all user's quota roots. */
void quota_add_user_storage(struct quota *quota, struct mail_storage *storage);
-void quota_remove_user_storage(struct quota *quota,
- struct mail_storage *storage);
+void quota_remove_user_storage(struct mail_storage *storage);
+
+struct quota *quota_get_mail_user_quota(struct mail_user *user);
struct quota_rule *
-quota_root_rule_find(struct quota_root *root, const char *name);
+quota_root_rule_find(struct quota_root_settings *root_set, const char *name);
-void quota_root_recalculate_relative_rules(struct quota_root *root);
+void quota_root_recalculate_relative_rules(struct quota_root_settings *root_set);
int quota_count(struct quota_root *root, uint64_t *bytes_r, uint64_t *count_r);
#endif
MODULE_CONTEXT(obj, quota_mail_module)
#define QUOTA_LIST_CONTEXT(obj) \
MODULE_CONTEXT(obj, quota_mailbox_list_module)
+#define QUOTA_USER_CONTEXT(obj) \
+ MODULE_CONTEXT(obj, quota_user_module)
+
+struct quota_user {
+ union mail_user_module_context module_ctx;
+
+ struct quota *quota;
+};
struct quota_mailbox_list {
union mailbox_list_module_context module_ctx;
static MODULE_CONTEXT_DEFINE_INIT(quota_mail_module, &mail_module_register);
static MODULE_CONTEXT_DEFINE_INIT(quota_mailbox_list_module,
&mailbox_list_module_register);
+static MODULE_CONTEXT_DEFINE_INIT(quota_user_module,
+ &mail_user_module_register);
static void quota_mail_expunge(struct mail *_mail)
{
struct quota_transaction_context *qt;
t = qbox->module_ctx.super.transaction_begin(box, flags);
- qt = quota_transaction_begin(quota_set, box);
+ qt = quota_transaction_begin(box);
MODULE_CONTEXT_SET(t, quota_storage_module, qt);
return t;
return 0;
else if (ret == 0) {
mail_storage_set_error(t->box->storage, MAIL_ERROR_NOSPACE,
- qt->quota->quota_exceeded_msg);
+ qt->quota->set->quota_exceeded_msg);
return -1;
} else {
mail_storage_set_critical(t->box->storage,
if (ret == 0) {
mail_storage_set_error(t->box->storage,
MAIL_ERROR_NOSPACE,
- qt->quota->quota_exceeded_msg);
+ qt->quota->set->quota_exceeded_msg);
return -1;
} else if (ret < 0) {
mail_storage_set_critical(t->box->storage,
}
if (qbox->expunge_qt == NULL)
- qbox->expunge_qt = quota_transaction_begin(quota_set, box);
+ qbox->expunge_qt = quota_transaction_begin(box);
if (i != count) {
/* we already know the size */
{
union mail_storage_module_context *qstorage = QUOTA_CONTEXT(storage);
- quota_remove_user_storage(quota_set, storage);
+ quota_remove_user_storage(storage);
if (qstorage->super.destroy != NULL)
qstorage->super.destroy(storage);
}
+struct quota *quota_get_mail_user_quota(struct mail_user *user)
+{
+ struct quota_user *quser = QUOTA_USER_CONTEXT(user);
+
+ return quser->quota;
+}
+
+static void quota_user_deinit(struct mail_user *user)
+{
+ struct quota_user *quser = QUOTA_USER_CONTEXT(user);
+
+ quota_deinit(&quser->quota);
+ quser->module_ctx.super.deinit(user);
+}
+
+void quota_mail_user_created(struct mail_user *user)
+{
+ struct quota_user *quser;
+
+ quser = p_new(user->pool, struct quota_user, 1);
+ quser->module_ctx.super = user->v;
+ user->v.deinit = quota_user_deinit;
+ quser->quota = quota_init(quota_set, user);
+
+ MODULE_CONTEXT_SET(user, quota_user_module, quser);
+
+ if (quota_next_hook_mail_user_created != NULL)
+ quota_next_hook_mail_user_created(user);
+}
+
void quota_mail_storage_created(struct mail_storage *storage)
{
struct quota_mailbox_list *qlist = QUOTA_LIST_CONTEXT(storage->list);
union mail_storage_module_context *qstorage;
+ struct quota *quota;
qlist->storage = storage;
if (storage->ns->type == NAMESPACE_PRIVATE &&
(storage->ns->flags & NAMESPACE_FLAG_INTERNAL) == 0) {
/* register to user's quota roots */
- quota_add_user_storage(quota_set, storage);
+ quota = quota_get_mail_user_quota(storage->ns->user);
+ quota_add_user_storage(quota, storage);
}
if (quota_next_hook_mail_storage_created != NULL)
static int quota_default_test_alloc(struct quota_transaction_context *ctx,
uoff_t size, bool *too_large_r);
-struct quota *quota_init(void)
+struct quota_settings *quota_settings_init(void)
{
- struct quota *quota;
-
- quota = i_new(struct quota, 1);
- quota->test_alloc = quota_default_test_alloc;
- quota->debug = getenv("DEBUG") != NULL;
- quota->quota_exceeded_msg = getenv("QUOTA_EXCEEDED_MESSAGE");
- if (quota->quota_exceeded_msg == NULL)
- quota->quota_exceeded_msg = DEFAULT_QUOTA_EXCEEDED_MSG;
- i_array_init("a->roots, 4);
- i_array_init("a->storages, 8);
+ struct quota_settings *quota_set;
+ pool_t pool;
- return quota;
+ pool = pool_alloconly_create("quota settings", 256);
+ quota_set = p_new(pool, struct quota_settings, 1);
+ quota_set->pool = pool;
+ quota_set->test_alloc = quota_default_test_alloc;
+ quota_set->debug = getenv("DEBUG") != NULL;
+ quota_set->quota_exceeded_msg = getenv("QUOTA_EXCEEDED_MESSAGE");
+ if (quota_set->quota_exceeded_msg == NULL)
+ quota_set->quota_exceeded_msg = DEFAULT_QUOTA_EXCEEDED_MSG;
+ p_array_init("a_set->root_sets, pool, 4);
+ return quota_set;
}
-void quota_deinit(struct quota **_quota)
+void quota_settings_deinit(struct quota_settings **_quota_set)
{
- struct quota *quota = *_quota;
- struct quota_root **root_p, *root;
+ struct quota_settings *quota_set = *_quota_set;
- *_quota = NULL;
- while (array_count("a->roots) > 0) {
- root_p = array_idx_modifiable("a->roots, 0);
- root = *root_p;
- quota_root_deinit(&root);
- }
+ *_quota_set = NULL;
- array_free("a->roots);
- array_free("a->storages);
- i_free(quota);
+ pool_unref("a_set->pool);
}
static const struct quota_backend *quota_backend_find(const char *name)
return NULL;
}
-struct quota_root *quota_root_init(struct quota *quota, const char *root_def)
+struct quota_root_settings *
+quota_root_settings_init(struct quota_settings *quota_set, const char *root_def)
{
- struct quota_root *root;
+ struct quota_root_settings *root_set;
const struct quota_backend *backend;
- const char *p, *args, *backend_name, *const *tmp;
+ const char *p, *args, *backend_name;
/* <backend>[:<quota root name>[:<backend args>]] */
p = strchr(root_def, ':');
if (backend == NULL)
i_fatal("Unknown quota backend: %s", backend_name);
- root = backend->v.alloc();
- root->quota = quota;
- root->backend = *backend;
- root->pool = pool_alloconly_create("quota root", 512);
+ root_set = p_new(quota_set->pool, struct quota_root_settings, 1);
+ root_set->set = quota_set;
+ root_set->backend = backend;
if (args != NULL) {
/* save root's name */
p = strchr(args, ':');
if (p == NULL) {
- root->name = p_strdup(root->pool, args);
+ root_set->name = p_strdup(quota_set->pool, args);
args = NULL;
} else {
- root->name = p_strdup_until(root->pool, args, p);
+ root_set->name =
+ p_strdup_until(quota_set->pool, args, p);
args = p + 1;
}
} else {
- root->name = "";
+ root_set->name = "";
}
+ root_set->args = p_strdup(quota_set->pool, args);
- if (quota->debug) {
+ if (quota_set->debug) {
i_info("Quota root: name=%s backend=%s args=%s",
- root->name, backend_name, args == NULL ? "" : args);
+ root_set->name, backend_name, args == NULL ? "" : args);
}
- i_array_init(&root->rules, 4);
- i_array_init(&root->warning_rules, 4);
- array_create(&root->quota_module_contexts, default_pool,
- sizeof(void *), 5);
+ p_array_init(&root_set->rules, quota_set->pool, 4);
+ p_array_init(&root_set->warning_rules, quota_set->pool, 4);
+ array_append("a_set->root_sets, &root_set, 1);
+ return root_set;
+}
- array_append("a->roots, &root, 1);
+static struct quota_root *
+quota_root_init(struct quota_root_settings *root_set, struct quota *quota)
+{
+ struct quota_root *root;
+ const char *const *tmp;
- if (backend->v.init != NULL) {
- if (backend->v.init(root, args) < 0) {
- quota_root_deinit(&root);
+ root = root_set->backend->v.alloc();
+ root->pool = pool_alloconly_create("quota root", 512);
+ root->set = root_set;
+ root->quota = quota;
+ root->backend = *root_set->backend;
+
+ array_create(&root->quota_module_contexts, root->pool,
+ sizeof(void *), 10);
+
+ if (root->backend.v.init != NULL) {
+ if (root->backend.v.init(root, root_set->args) < 0)
return NULL;
- }
- } else if (args != NULL) {
- tmp = t_strsplit_spaces(args, " ");
+ } else if (root_set->args != NULL) {
+ tmp = t_strsplit_spaces(root_set->args, " ");
for (; *tmp != NULL; tmp++) {
if (strcmp(*tmp, "noenforcing") == 0)
root->no_enforcing = TRUE;
if (*tmp != NULL) {
i_fatal("Quota root %s backend %s: "
"Unknown parameter: %s",
- root->name, backend_name, *tmp);
+ root_set->name, root->backend.name, *tmp);
}
}
return root;
}
-void quota_root_deinit(struct quota_root **_root)
+static void quota_root_deinit(struct quota_root *root)
{
- struct quota_root *root = *_root;
pool_t pool = root->pool;
- struct quota_root *const *roots;
- struct quota_warning_rule *warnings;
+
+ root->backend.v.deinit(root);
+ pool_unref(&pool);
+}
+
+struct quota *quota_init(struct quota_settings *quota_set,
+ struct mail_user *user)
+{
+ struct quota *quota;
+ struct quota_root *root;
+ struct quota_root_settings *const *root_sets;
unsigned int i, count;
- *_root = NULL;
+ quota = i_new(struct quota, 1);
+ quota->user = user;
+ quota->set = quota_set;
+ i_array_init("a->roots, 8);
- roots = array_get(&root->quota->roots, &count);
+ root_sets = array_get("a_set->root_sets, &count);
+ i_array_init("a->storages, count);
for (i = 0; i < count; i++) {
- if (roots[i] == root) {
- array_delete(&root->quota->roots, i, 1);
- break;
- }
+ root = quota_root_init(root_sets[i], quota);
+ array_append("a->roots, &root, 1);
}
+ return quota;
+}
- warnings = array_get_modifiable(&root->warning_rules, &count);
- for (i = 0; i < count; i++)
- i_free(warnings[i].command);
- array_free(&root->warning_rules);
+void quota_deinit(struct quota **_quota)
+{
+ struct quota *quota = *_quota;
+ struct quota_root *const *roots;
+ unsigned int i, count;
- array_free(&root->rules);
- array_free(&root->quota_module_contexts);
+ *_quota = NULL;
- root->backend.v.deinit(root);
- pool_unref(&pool);
+ roots = array_get("a->roots, &count);
+ for (i = 0; i < count; i++)
+ quota_root_deinit(roots[i]);
+ array_free("a->roots);
+ array_free("a->storages);
+ i_free(quota);
}
struct quota_rule *
-quota_root_rule_find(struct quota_root *root, const char *name)
+quota_root_rule_find(struct quota_root_settings *root_set, const char *name)
{
struct quota_rule *rules;
unsigned int i, count;
- rules = array_get_modifiable(&root->rules, &count);
+ rules = array_get_modifiable(&root_set->rules, &count);
for (i = 0; i < count; i++) {
if (strcmp(rules[i].mailbox_name, name) == 0)
return &rules[i];
}
static int
-quota_rule_parse_percentage(struct quota_root *root, struct quota_rule *rule,
+quota_rule_parse_percentage(struct quota_root_settings *root_set,
+ struct quota_rule *rule,
int64_t *limit, const char **error_r)
{
int64_t percentage = *limit;
if (percentage <= 0 || percentage >= -1U) {
- *error_r = p_strdup_printf(root->pool,
+ *error_r = p_strdup_printf(root_set->set->pool,
"Invalid rule percentage: %lld", (long long)percentage);
return -1;
}
- if (rule == &root->default_rule) {
+ if (rule == &root_set->default_rule) {
*error_r = "Default rule can't be a percentage";
return -1;
}
}
}
-void quota_root_recalculate_relative_rules(struct quota_root *root)
+void quota_root_recalculate_relative_rules(struct quota_root_settings *root_set)
{
struct quota_rule *rules;
struct quota_warning_rule *warning_rules;
unsigned int i, count;
- rules = array_get_modifiable(&root->rules, &count);
+ rules = array_get_modifiable(&root_set->rules, &count);
for (i = 0; i < count; i++) {
quota_rule_recalculate_relative_rules(&rules[i],
- &root->default_rule);
+ &root_set->default_rule);
}
- warning_rules = array_get_modifiable(&root->warning_rules, &count);
+ warning_rules = array_get_modifiable(&root_set->warning_rules, &count);
for (i = 0; i < count; i++) {
quota_rule_recalculate_relative_rules(&warning_rules[i].rule,
- &root->default_rule);
+ &root_set->default_rule);
}
}
static int
-quota_rule_parse_limits(struct quota_root *root, struct quota_rule *rule,
- const char *limits, bool allow_negative,
- const char **error_r)
+quota_rule_parse_limits(struct quota_root_settings *root_set,
+ struct quota_rule *rule, const char *limits,
+ bool allow_negative, const char **error_r)
{
const char **args;
char *p;
limit = &rule->count_limit;
*limit = strtoll(*args + 9, &p, 10);
} else {
- *error_r = p_strdup_printf(root->pool,
+ *error_r = p_strdup_printf(root_set->set->pool,
"Unknown rule limit name: %s", *args);
return -1;
}
break;
case '%':
multiply = 0;
- if (quota_rule_parse_percentage(root, rule, limit,
+ if (quota_rule_parse_percentage(root_set, rule, limit,
error_r) < 0)
return -1;
break;
default:
- *error_r = p_strdup_printf(root->pool,
+ *error_r = p_strdup_printf(root_set->set->pool,
"Invalid rule limit value: %s", *args);
return -1;
}
return 0;
}
-int quota_root_add_rule(struct quota_root *root, const char *rule_def,
- const char **error_r)
+int quota_root_add_rule(struct quota_root_settings *root_set,
+ const char *rule_def, const char **error_r)
{
struct quota_rule *rule;
const char *p, *mailbox_name;
/* <mailbox name>:<quota limits> */
mailbox_name = t_strdup_until(rule_def, p++);
- rule = quota_root_rule_find(root, mailbox_name);
+ rule = quota_root_rule_find(root_set, mailbox_name);
if (rule == NULL) {
if (strcmp(mailbox_name, RULE_NAME_DEFAULT_NONFORCE) == 0)
- rule = &root->default_rule;
+ rule = &root_set->default_rule;
else if (strcmp(mailbox_name, RULE_NAME_DEFAULT_FORCE) == 0) {
- rule = &root->default_rule;
- root->force_default_rule = TRUE;
+ rule = &root_set->default_rule;
+ root_set->force_default_rule = TRUE;
} else {
- rule = array_append_space(&root->rules);
- rule->mailbox_name = p_strdup(root->pool, mailbox_name);
+ rule = array_append_space(&root_set->rules);
+ rule->mailbox_name =
+ p_strdup(root_set->set->pool, mailbox_name);
}
}
if (strcmp(p, "ignore") == 0) {
rule->ignore = TRUE;
- if (root->quota->debug) {
+ if (root_set->set->debug) {
i_info("Quota rule: root=%s mailbox=%s ignored",
- root->name, mailbox_name);
+ root_set->name, mailbox_name);
}
return 0;
}
if (strncmp(p, "backend=", 8) == 0) {
- if (!root->backend.v.parse_rule(root, rule, p + 8, error_r))
+ if (!root_set->backend->v.parse_rule(root_set, rule,
+ p + 8, error_r))
ret = -1;
} else {
- bool allow_negative = rule != &root->default_rule;
+ bool allow_negative = rule != &root_set->default_rule;
- if (quota_rule_parse_limits(root, rule, p,
+ if (quota_rule_parse_limits(root_set, rule, p,
allow_negative, error_r) < 0)
ret = -1;
}
- quota_root_recalculate_relative_rules(root);
- if (root->quota->debug) {
+ quota_root_recalculate_relative_rules(root_set);
+ if (root_set->set->debug) {
i_info("Quota rule: root=%s mailbox=%s "
- "bytes=%lld (%u%%) messages=%lld (%u%%)", root->name,
+ "bytes=%lld (%u%%) messages=%lld (%u%%)", root_set->name,
mailbox_name,
(long long)rule->bytes_limit, rule->bytes_percent,
(long long)rule->count_limit, rule->count_percent);
return ret;
}
-static bool quota_root_get_rule_limits(struct quota_root *root,
+static bool quota_root_get_rule_limits(struct quota_root_settings *root_set,
const char *mailbox_name,
uint64_t *bytes_limit_r,
uint64_t *count_limit_r)
int64_t bytes_limit, count_limit;
bool found;
- bytes_limit = root->default_rule.bytes_limit;
- count_limit = root->default_rule.count_limit;
+ bytes_limit = root_set->default_rule.bytes_limit;
+ count_limit = root_set->default_rule.count_limit;
/* if default rule limits are 0, this rule applies only to specific
mailboxes */
found = bytes_limit != 0 || count_limit != 0;
- rule = quota_root_rule_find(root, mailbox_name);
+ rule = quota_root_rule_find(root_set, mailbox_name);
if (rule != NULL) {
if (!rule->ignore) {
bytes_limit += rule->bytes_limit;
}
}
-void quota_remove_user_storage(struct quota *quota,
- struct mail_storage *storage)
+void quota_remove_user_storage(struct mail_storage *storage)
{
+ struct quota *quota;
struct mail_storage *const *storages;
unsigned int i, count;
-
+
+ quota = quota_get_mail_user_quota(storage->ns->user);
+ if (quota == NULL) {
+ /* no quota for this storage */
+ return;
+ }
+
storages = array_get("a->storages, &count);
for (i = 0; i < count; i++) {
if (storages[i] == storage) {
}
}
-int quota_root_add_warning_rule(struct quota_root *root, const char *rule_def,
- const char **error_r)
+int quota_root_add_warning_rule(struct quota_root_settings *root_set,
+ const char *rule_def, const char **error_r)
{
struct quota_warning_rule *warning;
struct quota_rule rule;
}
memset(&rule, 0, sizeof(rule));
- ret = quota_rule_parse_limits(root, &rule, t_strdup_until(rule_def, p),
+ ret = quota_rule_parse_limits(root_set, &rule,
+ t_strdup_until(rule_def, p),
TRUE, error_r);
if (ret < 0)
return -1;
- warning = array_append_space(&root->warning_rules);
+ warning = array_append_space(&root_set->warning_rules);
warning->command = i_strdup(p+1);
warning->rule = rule;
- quota_root_recalculate_relative_rules(root);
- if (root->quota->debug) {
+ quota_root_recalculate_relative_rules(root_set);
+ if (root_set->set->debug) {
i_info("Quota warning: bytes=%llu (%u%%) "
"messages=%llu (%u%%) command=%s",
(unsigned long long)warning->rule.bytes_limit,
}
struct quota_root_iter *
-quota_root_iter_init(struct quota *quota, struct mailbox *box)
+quota_root_iter_init(struct mailbox *box)
{
+ struct mail_user *user = box->storage->ns->user;
struct quota_root_iter *iter;
iter = i_new(struct quota_root_iter, 1);
- iter->quota = quota;
+ iter->quota = quota_get_mail_user_quota(user);
iter->box = box;
return iter;
}
i_free(iter);
}
-struct quota_root *quota_root_lookup(struct quota *quota, const char *name)
+struct quota_root *quota_root_lookup(struct mail_user *user, const char *name)
{
+ struct quota *quota;
struct quota_root *const *roots;
unsigned int i, count;
+ quota = quota_get_mail_user_quota(user);
roots = array_get("a->roots, &count);
for (i = 0; i < count; i++) {
- if (strcmp(roots[i]->name, name) == 0)
+ if (strcmp(roots[i]->set->name, name) == 0)
return roots[i];
}
return NULL;
const char *quota_root_get_name(struct quota_root *root)
{
- return root->name;
+ return root->set->name;
}
const char *const *quota_root_get_resources(struct quota_root *root)
if (ret <= 0)
return ret;
- (void)quota_root_get_rule_limits(root, mailbox_name,
+ (void)quota_root_get_rule_limits(root->set, mailbox_name,
&bytes_limit, &count_limit);
if (strcmp(name, QUOTA_NAME_STORAGE_BYTES) == 0)
*limit_r = bytes_limit;
return -1;
}
-struct quota_transaction_context *quota_transaction_begin(struct quota *quota,
- struct mailbox *box)
+struct quota_transaction_context *quota_transaction_begin(struct mailbox *box)
{
+ struct mail_user *user = box->storage->ns->user;
struct quota_transaction_context *ctx;
ctx = i_new(struct quota_transaction_context, 1);
- ctx->quota = quota;
+ ctx->quota = quota_get_mail_user_quota(user);
ctx->box = box;
ctx->bytes_left = (uint64_t)-1;
ctx->count_left = (uint64_t)-1;
uint64_t bytes_current, bytes_before, bytes_limit;
uint64_t count_current, count_before, count_limit;
- warnings = array_get_modifiable(&root->warning_rules, &count);
+ warnings = array_get_modifiable(&root->set->warning_rules, &count);
if (count == 0)
return;
if (!quota_root_is_visible(roots[i], ctx->box, TRUE))
continue;
- rule = quota_root_rule_find(roots[i], mailbox_name);
+ rule = quota_root_rule_find(roots[i]->set,
+ mailbox_name);
if (rule != NULL && rule->ignore) {
/* mailbox not included in quota */
continue;
if (quota_transaction_set_limits(ctx) < 0)
return -1;
}
- return ctx->quota->test_alloc(ctx, size, too_large_r);
+ return ctx->quota->set->test_alloc(ctx, size, too_large_r);
}
static int quota_default_test_alloc(struct quota_transaction_context *ctx,
if (!quota_root_is_visible(roots[i], ctx->box, TRUE))
continue;
- if (!quota_root_get_rule_limits(roots[i],
+ if (!quota_root_get_rule_limits(roots[i]->set,
mailbox_get_name(ctx->box),
&bytes_limit, &count_limit))
continue;
struct mail;
struct mailbox;
+struct mail_user;
/* Message storage size kilobytes. */
#define QUOTA_NAME_STORAGE_KILOBYTES "STORAGE"
struct quota_root_iter;
struct quota_transaction_context;
-struct quota *quota_init(void);
-void quota_deinit(struct quota **quota);
+struct quota_settings *quota_settings_init(void);
+void quota_settings_deinit(struct quota_settings **quota_set);
-/* Create a new quota root. */
-struct quota_root *quota_root_init(struct quota *quota, const char *root_def);
-void quota_root_deinit(struct quota_root **root);
+/* Set up a new quota root. */
+struct quota_root_settings *
+quota_root_settings_init(struct quota_settings *quota_set,
+ const char *root_def);
+void quota_root_settings_deinit(struct quota_root_settings **root_set);
/* Add a new rule too the quota root. Returns 0 if ok, -1 if rule is invalid. */
-int quota_root_add_rule(struct quota_root *root, const char *rule_def,
- const char **error_r);
+int quota_root_add_rule(struct quota_root_settings *root_set,
+ const char *rule_def, const char **error_r);
/* Add a new warning rule for the quota root. Returns 0 if ok, -1 if rule is
invalid. */
-int quota_root_add_warning_rule(struct quota_root *root, const char *rule_def,
- const char **error_r);
+int quota_root_add_warning_rule(struct quota_root_settings *root_set,
+ const char *rule_def, const char **error_r);
+
+/* Initialize quota for the given user. */
+struct quota *quota_init(struct quota_settings *quota_set,
+ struct mail_user *user);
+void quota_deinit(struct quota **quota);
/* List all quota roots. Returned quota roots are freed by quota_deinit(). */
-struct quota_root_iter *
-quota_root_iter_init(struct quota *quota, struct mailbox *box);
+struct quota_root_iter *quota_root_iter_init(struct mailbox *box);
struct quota_root *quota_root_iter_next(struct quota_root_iter *iter);
void quota_root_iter_deinit(struct quota_root_iter **iter);
/* Return quota root or NULL. */
-struct quota_root *quota_root_lookup(struct quota *quota, const char *name);
+struct quota_root *quota_root_lookup(struct mail_user *user, const char *name);
/* Returns name of the quota root. */
const char *quota_root_get_name(struct quota_root *root);
uint64_t value, const char **error_r);
/* Start a new quota transaction. */
-struct quota_transaction_context *quota_transaction_begin(struct quota *quota,
- struct mailbox *box);
+struct quota_transaction_context *quota_transaction_begin(struct mailbox *box);
/* Commit quota transaction. Returns 0 if ok, -1 if failed. */
int quota_transaction_commit(struct quota_transaction_context **ctx);
/* Rollback quota transaction changes. */
const char *name;
int priority; /* lower number = higher priority */
- struct mail_storage *storage;
-
/* temporarily set while cleaning: */
+ const char *ns_name;
+ struct mail_storage *storage;
struct mailbox *box;
struct mailbox_transaction_context *trans;
struct mail_search_context *search_ctx;
{
struct mail_search_args *search_args;
- trash->box = mailbox_open(trash->storage, trash->name, NULL,
+ trash->box = mailbox_open(trash->storage, trash->ns_name, NULL,
MAILBOX_OPEN_KEEP_RECENT);
if (trash->box == NULL)
return 0;
return 1;
}
-static void trash_find_storage(struct trash_mailbox *trash)
+static void trash_find_storage(struct quota *quota,
+ struct trash_mailbox *trash)
{
struct mail_storage *const *storages;
unsigned int i, count;
- storages = array_get("a_set->storages, &count);
+ storages = array_get("a->storages, &count);
for (i = 0; i < count; i++) {
- if (mail_namespace_update_name(storages[i]->ns, &trash->name)) {
+ trash->ns_name = trash->name;
+ if (mail_namespace_update_name(storages[i]->ns,
+ &trash->ns_name)) {
trash->storage = storages[i];
return;
}
break;
if (trashes[j].storage == NULL)
- trash_find_storage(&trashes[j]);
+ trash_find_storage(ctx->quota, &trashes[j]);
ret = trash_clean_mailbox_get_next(&trashes[j],
&received);
}
mailbox_close(&trash->box);
+ trash->storage = NULL;
+ trash->ns_name = NULL;
}
if (size_expunged < size_needed) {
virtual_config_parse_line(struct virtual_parse_context *ctx, const char *line,
const char **error_r)
{
+ struct mail_user *user = ctx->mbox->storage->storage.ns->user;
struct virtual_backend_box *bbox;
if (*line == ' ') {
strchr(bbox->name, '%') != NULL) {
bbox->glob = imap_match_init(ctx->pool, bbox->name,
TRUE, ctx->sep);
- bbox->ns = mail_namespace_find(virtual_all_namespaces, &line);
+ bbox->ns = mail_namespace_find(user->namespaces, &line);
ctx->have_wildcards = TRUE;
}
array_append(&ctx->mbox->backend_boxes, &bbox, 1);
static int virtual_config_expand_wildcards(struct virtual_parse_context *ctx)
{
+ struct mail_user *user = ctx->mbox->storage->storage.ns->user;
ARRAY_TYPE(virtual_backend_box) wildcard_boxes;
struct mailbox_list_iterate_context *iter;
struct virtual_backend_box *const *wboxes;
patterns[i] = wboxes[i]->name;
/* match listed mailboxes to wildcards */
- iter = mailbox_list_iter_init_namespaces(
- virtual_all_namespaces, patterns,
+ iter = mailbox_list_iter_init_namespaces(user->namespaces, patterns,
MAILBOX_LIST_ITER_VIRTUAL_NAMES |
MAILBOX_LIST_ITER_RETURN_NO_FLAGS);
while ((info = mailbox_list_iter_next(iter)) != NULL) {
int virtual_config_read(struct virtual_mailbox *mbox)
{
+ struct mail_user *user = mbox->storage->storage.ns->user;
struct virtual_parse_context ctx;
const char *path, *line, *error;
unsigned int linenum = 0;
}
memset(&ctx, 0, sizeof(ctx));
- ctx.sep = mail_namespace_get_root_sep(virtual_all_namespaces);
+ ctx.sep = mail_namespace_get_root_sep(user->namespaces);
ctx.mbox = mbox;
ctx.pool = mbox->ibox.box.pool;
ctx.rule = t_str_new(256);
#include "virtual-storage.h"
#include "virtual-plugin.h"
-static void (*virtual_next_hook_mail_namespaces_created)
- (struct mail_namespace *namespaces);
-
const char *virtual_plugin_version = PACKAGE_VERSION;
-struct mail_namespace *virtual_all_namespaces;
-
-static void
-virtual_hook_mail_namespaces_created(struct mail_namespace *namespaces)
-{
- if (virtual_next_hook_mail_namespaces_created != NULL)
- virtual_next_hook_mail_namespaces_created(namespaces);
-
- /* FIXME: some day we should support multiple clients and this
- global namespaces list doesn't work */
- virtual_all_namespaces = namespaces;
-}
void virtual_plugin_init(void)
{
mail_storage_class_register(&virtual_storage);
-
- virtual_next_hook_mail_namespaces_created =
- hook_mail_namespaces_created;
- hook_mail_namespaces_created = virtual_hook_mail_namespaces_created;
}
void virtual_plugin_deinit(void)
{
mail_storage_class_unregister(&virtual_storage);
-
- hook_mail_namespaces_created =
- virtual_next_hook_mail_namespaces_created;
}
#ifndef VIRTUAL_PLUGIN_H
#define VIRTUAL_PLUGIN_H
-extern struct mail_namespace *virtual_all_namespaces;
-
void virtual_plugin_init(void);
void virtual_plugin_deinit(void);
static int virtual_mailboxes_open(struct virtual_mailbox *mbox,
enum mailbox_open_flags open_flags)
{
+ struct mail_user *user = mbox->storage->storage.ns->user;
struct virtual_backend_box *const *bboxes;
struct mail_namespace *ns;
unsigned int i, count;
bboxes = array_get(&mbox->backend_boxes, &count);
for (i = 0; i < count; i++) {
mailbox = bboxes[i]->name;
- ns = mail_namespace_find(virtual_all_namespaces, &mailbox);
+ ns = mail_namespace_find(user->namespaces, &mailbox);
bboxes[i]->box = mailbox_open(ns->storage, mailbox,
NULL, open_flags);
return FALSE;
}
-struct client *client_create(int fd_in, int fd_out,
- struct mail_namespace *namespaces)
+struct client *client_create(int fd_in, int fd_out, struct mail_user *user)
{
struct mail_storage *storage;
const char *inbox;
client->to_idle = timeout_add(CLIENT_IDLE_TIMEOUT_MSECS,
client_idle_timeout, client);
- client->namespaces = namespaces;
+ client->user = user;
inbox = "INBOX";
- client->inbox_ns = mail_namespace_find(namespaces, &inbox);
+ client->inbox_ns = mail_namespace_find(user->namespaces, &inbox);
if (client->inbox_ns == NULL) {
client_send_line(client, "-ERR No INBOX namespace for user.");
client_destroy(client, "No INBOX namespace for user.");
}
if (client->mailbox != NULL)
mailbox_close(&client->mailbox);
- mail_namespaces_deinit(&client->namespaces);
+ mail_user_deinit(&client->user);
i_free(client->message_sizes);
i_free(client->deleted_bitmask);
command_func_t *cmd;
void *cmd_context;
- struct mail_namespace *namespaces, *inbox_ns;
+ struct mail_user *user;
+ struct mail_namespace *inbox_ns;
struct mailbox *mailbox;
struct mailbox_transaction_context *trans;
/* Create new client with specified input/output handles. socket specifies
if the handle is a socket. */
-struct client *client_create(int fd_in, int fd_out,
- struct mail_namespace *namespaces);
+struct client *client_create(int fd_in, int fd_out, struct mail_user *user);
void client_destroy(struct client *client, const char *reason);
/* Disconnect client connection */
static bool main_init(void)
{
- struct mail_namespace *ns;
+ struct mail_user *user;
struct client *client;
const char *str;
bool ret = TRUE;
"%% variables.");
namespace_pool = pool_alloconly_create("namespaces", 1024);
- if (mail_namespaces_init(namespace_pool, getenv("USER"), &ns) < 0)
+ user = mail_user_init(getenv("USER"), getenv("HOME"));
+ if (mail_namespaces_init(namespace_pool, user) < 0)
i_fatal("Namespace initialization failed");
- client = client_create(0, 1, ns);
+
+ client = client_create(0, 1, user);
if (client == NULL)
return FALSE;