]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
Added struct mail_user and fixed the code to support multiple users per process.
authorTimo Sirainen <tss@iki.fi>
Tue, 12 Aug 2008 16:28:42 +0000 (12:28 -0400)
committerTimo Sirainen <tss@iki.fi>
Tue, 12 Aug 2008 16:28:42 +0000 (12:28 -0400)
--HG--
branch : HEAD

43 files changed:
src/deliver/deliver.c
src/imap/client.c
src/imap/client.h
src/imap/cmd-list.c
src/imap/cmd-namespace.c
src/imap/cmd-subscribe.c
src/imap/commands-util.c
src/imap/main.c
src/lib-storage/Makefile.am
src/lib-storage/index/maildir/maildir-storage.c
src/lib-storage/index/mbox/mbox-save.c
src/lib-storage/index/mbox/mbox-storage.c
src/lib-storage/mail-namespace.c
src/lib-storage/mail-namespace.h
src/lib-storage/mail-storage-private.h
src/lib-storage/mail-storage.c
src/lib-storage/mail-storage.h
src/plugins/acl/acl-mailbox-list.c
src/plugins/convert/convert-plugin.c
src/plugins/convert/convert-storage.c
src/plugins/convert/convert-storage.h
src/plugins/convert/convert-tool.c
src/plugins/expire/expire-plugin.c
src/plugins/expire/expire-tool.c
src/plugins/imap-quota/imap-quota-plugin.c
src/plugins/lazy-expunge/lazy-expunge-plugin.c
src/plugins/quota/quota-count.c
src/plugins/quota/quota-dict.c
src/plugins/quota/quota-maildir.c
src/plugins/quota/quota-plugin.c
src/plugins/quota/quota-plugin.h
src/plugins/quota/quota-private.h
src/plugins/quota/quota-storage.c
src/plugins/quota/quota.c
src/plugins/quota/quota.h
src/plugins/trash/trash-plugin.c
src/plugins/virtual/virtual-config.c
src/plugins/virtual/virtual-plugin.c
src/plugins/virtual/virtual-plugin.h
src/plugins/virtual/virtual-storage.c
src/pop3/client.c
src/pop3/client.h
src/pop3/main.c

index 6448e04cfbc1c9dd7672e7ad269dd024dfc95426..f8edc5105384cc6fdcb8a8d66580a396ad0c05fe 100644 (file)
@@ -777,7 +777,8 @@ int main(int argc, char *argv[])
        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;
@@ -1002,12 +1003,16 @@ int main(int argc, char *argv[])
        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);
@@ -1044,7 +1049,8 @@ int main(int argc, char *argv[])
        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;
@@ -1056,12 +1062,14 @@ int main(int argc, char *argv[])
 
        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 ) {
@@ -1108,8 +1116,8 @@ int main(int argc, char *argv[])
        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();
index 3ac47092a17940c47dd62718d12b653776bee722..5b8a762bb691a20d6ecd07522711ead8f33145ea 100644 (file)
@@ -25,10 +25,10 @@ static void client_idle_timeout(struct client *client)
        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);
@@ -48,12 +48,11 @@ struct client *client_create(int fd_in, int fd_out,
                                      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);
@@ -130,6 +129,7 @@ static const char *client_get_disconnect_reason(struct client *client)
 void client_destroy(struct client *client, const char *reason)
 {
        struct client_command_context *cmd;
+
        i_assert(!client->destroyed);
        client->destroyed = TRUE;
 
@@ -161,7 +161,7 @@ void client_destroy(struct client *client, const char *reason)
                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);
index eb236de3d6490175e8bf994ade89aed24b74539c..ab5b245cb7d7dc39206cc183ff72c3ec768e26ae 100644 (file)
@@ -74,7 +74,7 @@ struct client {
        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 */
@@ -124,8 +124,7 @@ struct client {
 
 /* 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 */
index ce9928922c1839892a8f78876747480e6c814734..4e7027c8ccf50ab06835d5ce585279acf3288480 100644 (file)
@@ -185,7 +185,7 @@ list_get_inbox_flags(struct cmd_list_context *ctx)
        }
 
        /* 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) {
@@ -704,13 +704,13 @@ static void cmd_list_ref_root(struct client *client, const char *ref)
        /* 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);
@@ -754,7 +754,7 @@ bool cmd_list_full(struct client_command_context *cmd, bool lsub)
 
        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;
index 000c56fb5959385e612d7cc65319635333de605b..62f86ce233e0c5278d353577fe272be0acd418f1 100644 (file)
@@ -42,11 +42,11 @@ bool cmd_namespace(struct client_command_context *cmd)
        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.");
index 66bb13cd1ff7e832069cec805f8b2fe8facc9a0c..127845dd352ca86b14f45fabf62ba1c3262d5232 100644 (file)
@@ -35,7 +35,7 @@ bool cmd_subscribe_full(struct client_command_context *cmd, bool subscribe)
                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.");
@@ -49,7 +49,7 @@ bool cmd_subscribe_full(struct client_command_context *cmd, bool subscribe)
                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 {
index adc73adc508101541794f2e92a4093a99d88e43a..8413dd7da20a769746c7db8dbd6bf11701f169e7 100644 (file)
@@ -23,7 +23,7 @@ client_find_namespace(struct client_command_context *cmd, const char **mailbox)
 {
        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;
 
index 12a577a6924190c4380123214f5c90b3d34b62c1..df2ca22a2e69db0fcc207bfb617396cf72e06c0a 100644 (file)
@@ -161,8 +161,8 @@ static void main_init(void)
 {
        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);
@@ -170,18 +170,16 @@ static void main_init(void)
         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)");
@@ -232,9 +230,10 @@ static void main_init(void)
         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);
@@ -246,7 +245,7 @@ static void main_init(void)
                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 ",
index 11fd9b2116dd637d63e38964fbea53c07aab6fbd..2eaf0885301d5c1e76a9198516714ed87d4d2f0f 100644 (file)
@@ -16,6 +16,7 @@ libstorage_a_SOURCES = \
        mail-search.c \
        mail-search-build.c \
        mail-storage.c \
+       mail-user.c \
        mailbox-list.c \
        mailbox-search-result.c \
        mailbox-tree.c
@@ -29,6 +30,7 @@ headers = \
        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 \
index 8ce23f7148be385d15be9ce52c462df116911712..c2874d76b862b5e4968c69525c175fd50eb46263 100644 (file)
@@ -60,11 +60,13 @@ maildirplusplus_iter_is_mailbox(struct mailbox_list_iterate_context *ctx,
 
 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;
 
@@ -79,9 +81,9 @@ maildir_get_list_settings(struct mailbox_list_settings *list_set,
                }
 
                /* 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)",
@@ -96,7 +98,7 @@ maildir_get_list_settings(struct mailbox_list_settings *list_set,
                        }
                } 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) {
@@ -191,7 +193,7 @@ maildir_create(struct mail_storage *_storage, const char *data,
        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;
index 3f55bd4a913ef80603f88025f0b1d9e6a12087f6..b897651335de2e3ff347ad5c469011c62d8f967f 100644 (file)
@@ -135,9 +135,11 @@ static int write_from_line(struct mbox_save_context *ctx, time_t received_date,
                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 */
index 15deb252dfbbac30c464c596a29590b50790cbe3..35cf59d9a9b0d6727ed06d668429a09bbface959 100644 (file)
@@ -185,12 +185,12 @@ static bool mbox_autodetect(const char *data, enum mail_storage_flags flags)
        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) {
@@ -213,7 +213,7 @@ static const char *get_root_dir(enum mail_storage_flags flags)
 
        if (debug)
                i_info("mbox: checking if we are chrooted:");
-       if (mbox_autodetect("", flags))
+       if (mbox_autodetect("", storage->flags))
                return "/";
 
        if (debug)
@@ -223,11 +223,12 @@ static const char *get_root_dir(enum mail_storage_flags flags)
 }
 
 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)
@@ -253,11 +254,12 @@ get_inbox_file(const char *root_dir, bool only_root, bool 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";
@@ -270,16 +272,17 @@ static const char *create_root_dir(bool debug, const char **error_r)
                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;
@@ -300,8 +303,8 @@ mbox_get_list_settings(struct mailbox_list_settings *list_set,
 
                /* 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);
@@ -313,7 +316,7 @@ mbox_get_list_settings(struct mailbox_list_settings *list_set,
                        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 {
@@ -330,7 +333,7 @@ mbox_get_list_settings(struct mailbox_list_settings *list_set,
                        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 {
@@ -360,7 +363,8 @@ mbox_get_list_settings(struct mailbox_list_settings *list_set,
 
        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;
 }
@@ -432,8 +436,8 @@ static int mbox_create(struct mail_storage *_storage, const char *data,
        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;
index 4f71fd0a8bf91e6ad708637617638e1b463e6ec1..6c66e5d701d48f21656c3b80923da31fe1fadb4c 100644 (file)
@@ -29,7 +29,7 @@ void mail_namespace_init_storage(struct mail_namespace *ns)
 
 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;
@@ -77,8 +77,9 @@ namespace_add_env(pool_t pool, const char *data, unsigned int num,
        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;
@@ -177,8 +178,7 @@ namespaces_sort(struct mail_namespace *src)
        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;
@@ -213,7 +213,7 @@ int mail_namespaces_init(pool_t pool, const char *user,
                if (!namespaces_check(namespaces))
                        return -1;
                namespaces = namespaces_sort(namespaces);
-               *namespaces_r = namespaces;
+               user->namespaces = namespaces;
 
                if (hook_mail_namespaces_created != NULL) {
                        T_BEGIN {
@@ -237,8 +237,9 @@ int mail_namespaces_init(pool_t pool, const char *user,
        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);
@@ -248,7 +249,7 @@ int mail_namespaces_init(pool_t pool, const char *user,
                }
                return -1;
        }
-       *namespaces_r = ns;
+       user->namespaces = ns;
 
        if (hook_mail_namespaces_created != NULL) {
                T_BEGIN {
@@ -258,14 +259,17 @@ int mail_namespaces_init(pool_t pool, const char *user,
        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;
 }
 
index f9c737f15b618311bff739d5546ccd57150a35e8..bcdeae1c6008ff72a7c8e503c93dda8c0420dfa0 100644 (file)
@@ -1,6 +1,8 @@
 #ifndef MAIL_NAMESPACE_H
 #define MAIL_NAMESPACE_H
 
+#include "mail-user.h"
+
 enum namespace_type {
        NAMESPACE_PRIVATE,
        NAMESPACE_SHARED,
@@ -32,6 +34,7 @@ struct mail_namespace {
        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;
@@ -40,9 +43,9 @@ struct mail_namespace {
 /* 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. */
index 70f43ad26a4b09d696d19656611d3b5c5f9b7409..933922bb972f1f6ba0bd5e484004aa0068b9ce8e 100644 (file)
@@ -61,7 +61,6 @@ struct mail_storage {
        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;
index 936ef6395dcb0f7de8df1d44c12dff729b7747d1..41cce6c42e071d4fda2bb688742b272dbe0afee5 100644 (file)
@@ -169,8 +169,7 @@ mail_storage_set_autodetection(const char **data, const char **driver,
 }
 
 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)
 {
@@ -214,7 +213,6 @@ int mail_storage_create(struct mail_namespace *ns, const char *driver,
                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 =
@@ -239,7 +237,7 @@ int mail_storage_create(struct mail_namespace *ns, const char *driver,
                        return -1;
                }
 
-               home = getenv("HOME");
+               home = ns->user->home;
                if (home == NULL || *home == '\0') home = "(not set)";
 
                *error_r = t_strdup_printf(
index 80dd30ef537638081cd68c63905fe63465276458..4e6451cb07bf3bc958ab3927ae05a2ac54ec457a 100644 (file)
@@ -248,8 +248,7 @@ void mail_storage_parse_env(enum mail_storage_flags *flags_r,
    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);
index 53dd11c81a2d7139d7b744f2ef15325f54bb7a55..09a1240eceec0d40af8bb9d8ab99bf593a6098ea 100644 (file)
@@ -415,10 +415,7 @@ void acl_mailbox_list_created(struct mailbox_list *list)
        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;
@@ -432,7 +429,6 @@ void acl_mailbox_list_created(struct mailbox_list *list)
        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"), ","),
index b01006a271578058916797fed7a4624e528ab40c..46d0288661e0e090198b479f1f94dbb52f468019 100644 (file)
@@ -19,11 +19,7 @@ static void convert_mail_storage(struct mail_namespace *namespaces,
        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 =
index d4447bae8b83d05948cf2d9ce16cfbd2932687e4..e7625251ca94f7467feaffa2a26400ccfb1f476f 100644 (file)
@@ -392,6 +392,7 @@ int convert_storage(const char *source_data,
                    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;
@@ -399,19 +400,19 @@ int convert_storage(const char *source_data,
        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;
@@ -430,7 +431,7 @@ int convert_storage(const char *source_data,
        /* 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);
index 04b4f9db699687749146cdea712bc15703648f7b..ab121e8220a7b5a3f92794aaae889a3c4ab98cdf 100644 (file)
@@ -4,8 +4,6 @@
 struct mail_namespace;
 
 struct convert_settings {
-       const char *user;
-       const char *home;
        bool skip_broken_mailboxes;
        bool skip_dotdirs;
        char alt_hierarchy_char;
index df51827f2f99796d94e4abd2fde0dcc825e75db6..ac62cc1658ea1757aeb60d55aef39e5fd0b9e547 100644 (file)
@@ -18,6 +18,7 @@ int main(int argc, const char *argv[])
 {
        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;
@@ -37,9 +38,6 @@ int main(int argc, const char *argv[])
        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;
@@ -50,8 +48,10 @@ int main(int argc, const char *argv[])
        }
 
        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);
@@ -64,7 +64,7 @@ int main(int argc, const char *argv[])
                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();
index 29a0f82673359d89bff111d24bba30f55510ccb7..35ccf20fc38e2184867c850aadc1f47931ce7985 100644 (file)
@@ -294,6 +294,7 @@ void expire_plugin_init(void)
                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);
index d06116d2bedcfc6fab29904343f279a7ac2b319d..6f23d6f1c1c0373aff63252f3d323c6e1c20d43a 100644 (file)
@@ -2,6 +2,7 @@
 
 #include "lib.h"
 #include "ioloop.h"
+#include "env-util.h"
 #include "file-lock.h"
 #include "randgen.h"
 #include "lib-signals.h"
@@ -25,8 +26,8 @@ struct expire_context {
        struct auth_connection *auth_conn;
 
        char *user;
+       struct mail_user *mail_user;
        pool_t namespace_pool;
-       struct mail_namespace *ns;
        bool testrun;
 };
 
@@ -34,6 +35,7 @@ static int user_init(struct expire_context *ctx, const char *user)
 {
        int ret;
 
+       env_clean();
        if ((ret = auth_client_put_user_env(ctx->auth_conn, user)) <= 0) {
                if (ret < 0)
                        return ret;
@@ -42,14 +44,15 @@ static int user_init(struct expire_context *ctx, const char *user)
                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);
 }
@@ -86,7 +89,7 @@ mailbox_delete_old_mails(struct expire_context *ctx, const char *user,
        }
 
        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)
index f2899323900ac94c901b3b75a27cd84f2402d811..edfa43a6ca9e83cfe5dc93ad5cbde4e3e5ecea29 100644 (file)
@@ -82,7 +82,7 @@ static bool cmd_getquotaroot(struct client_command_context *cmd)
        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);
@@ -91,7 +91,7 @@ static bool cmd_getquotaroot(struct client_command_context *cmd)
        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);
@@ -115,7 +115,7 @@ static bool cmd_getquota(struct client_command_context *cmd)
                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;
@@ -148,7 +148,7 @@ static bool cmd_setquota(struct client_command_context *cmd)
                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;
index a8753c0b2b219243fa058c71710407f5025b9330..422f69c6b836657d0b43bc696aaa69d1b43668e3 100644 (file)
@@ -19,6 +19,8 @@
        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,
@@ -28,6 +30,12 @@ enum lazy_namespace {
        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;
 
@@ -57,6 +65,7 @@ static void (*lazy_expunge_next_hook_mail_storage_created)
        (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);
@@ -64,8 +73,8 @@ static MODULE_CONTEXT_DEFINE_INIT(lazy_expunge_mail_module,
                                  &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)
@@ -95,12 +104,14 @@ 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) {
@@ -414,6 +425,8 @@ mailbox_move(struct mailbox_list *src_list, const char *src_name,
 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;
@@ -455,7 +468,7 @@ lazy_expunge_mailbox_list_delete(struct mailbox_list *list, const char *name)
        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) {
@@ -465,9 +478,9 @@ lazy_expunge_mailbox_list_delete(struct mailbox_list *list, const char *name)
        }
 
        /* 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;
 }
@@ -526,13 +539,12 @@ static void lazy_expunge_mailbox_list_created(struct mailbox_list *list)
 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;
@@ -540,20 +552,36 @@ lazy_expunge_hook_mail_namespaces_created(struct mail_namespace *namespaces)
                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)
@@ -571,6 +599,9 @@ 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)
@@ -582,4 +613,5 @@ 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;
 }
index 397aff56af3bfaa9974bfb1079feced06f25c2fd..bf2cdfc43d88d2ab5d738fc5638b93562ac2e3a5 100644 (file)
@@ -19,7 +19,7 @@ quota_count_mailbox(struct quota_root *root, struct mail_storage *storage,
        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;
index ce54cf736d42896ed5dd6f5fc6ff21599e75571c..02c8d7944ee3dc38be1cfef574c8ca56e2b53f5d 100644 (file)
@@ -3,6 +3,7 @@
 #include "lib.h"
 #include "str.h"
 #include "dict.h"
+#include "mail-user.h"
 #include "quota-private.h"
 
 #include <stdlib.h>
@@ -48,9 +49,9 @@ static int dict_quota_init(struct quota_root *_root, const char *args)
        }
 
        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);
        }
@@ -104,8 +105,8 @@ dict_quota_count(struct dict_quota_root *root,
 }
 
 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;
index d73c7f8bc926e78fc77979b26d7e4ed0d93eb0fa..108bc3c2894d487f81a1f79565c62c07524b7d76 100644 (file)
@@ -149,7 +149,7 @@ maildir_list_next(struct maildir_list_context *ctx, time_t *mtime_r)
                        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 */
@@ -217,7 +217,7 @@ maildirs_check_have_changed(struct maildir_quota_root *root,
 
 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;
@@ -319,7 +319,7 @@ static int maildirsize_recalculate_storage(struct maildir_quota_root *root,
 
 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;
        }
@@ -410,7 +410,7 @@ maildir_parse_limit(const char *str, uint64_t *bytes_r, uint64_t *count_r)
 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;
@@ -432,7 +432,7 @@ static int maildirsize_parse(struct maildir_quota_root *root,
        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;
@@ -440,7 +440,7 @@ static int maildirsize_parse(struct maildir_quota_root *root,
                /* 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) {
@@ -603,8 +603,8 @@ static int maildirquota_refresh(struct maildir_quota_root *root)
                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;
                }
@@ -661,7 +661,7 @@ static void maildir_quota_deinit(struct quota_root *_root)
 }
 
 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)
 {
index da5c0112ac805bb43323699a0d91bb113a541d63..52733cdca2ee4d62f8aef8d2a7d02dcec7e33bf4 100644 (file)
 /* 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;
@@ -30,7 +31,7 @@ static void quota_root_add_rules(const char *root_name,
                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);
                }
@@ -39,7 +40,7 @@ static void quota_root_add_rules(const char *root_name,
 }
 
 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;
@@ -51,7 +52,7 @@ static void quota_root_add_warning_rules(const char *root_name,
                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);
                }
@@ -61,7 +62,7 @@ static void quota_root_add_warning_rules(const char *root_name,
 
 void quota_plugin_init(void)
 {
-       struct quota_root *root;
+       struct quota_root_settings *root_set;
        unsigned int i;
        const char *env;
 
@@ -69,13 +70,13 @@ void quota_plugin_init(void)
        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;
@@ -86,13 +87,16 @@ void quota_plugin_init(void)
                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;
 
@@ -103,10 +107,11 @@ void quota_plugin_init(void)
 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(&quota_set);
+               quota_settings_deinit(&quota_set);
        }
 }
index 6567ba8f87305c12e4f59f4df7bb6533f9acaed5..74d9ccd6c956c23e8ccea103ccf7fd4eafb3a91e 100644 (file)
@@ -3,14 +3,14 @@
 
 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);
 
index 8c397539f542c19e57e7aa4d678a63062d85067c..f72535e3d2604c62c0451f511aff74e45e354d47 100644 (file)
@@ -9,9 +9,17 @@
 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);
 
@@ -20,7 +28,7 @@ struct quota {
 };
 
 struct quota_rule {
-       char *mailbox_name;
+       const char *mailbox_name;
 
        int64_t bytes_limit, count_limit;
        /* relative to default_rule */
@@ -33,7 +41,7 @@ struct quota_rule {
 struct quota_warning_rule {
        struct quota_rule rule;
 
-       char *command;
+       const char *command;
 };
 
 struct quota_backend_vfuncs {
@@ -41,7 +49,8 @@ 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 */
@@ -49,8 +58,8 @@ struct quota_backend_vfuncs {
                              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);
@@ -64,27 +73,34 @@ struct quota_backend {
        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 {
@@ -105,13 +121,14 @@ 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
index 7ef5781bc64de12f20403a44efe4e89e167ceb1a..aa2dd537137ed3937e0205c3f1f810234a1fa5ad 100644 (file)
        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;
@@ -41,6 +49,8 @@ static MODULE_CONTEXT_DEFINE_INIT(quota_storage_module,
 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)
 {
@@ -74,7 +84,7 @@ quota_mailbox_transaction_begin(struct mailbox *box,
        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;
@@ -150,7 +160,7 @@ static int quota_check(struct mailbox_transaction_context *t, struct mail *mail)
                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,
@@ -212,7 +222,7 @@ quota_save_begin(struct mail_save_context *ctx, struct istream *input)
                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,
@@ -294,7 +304,7 @@ static void quota_mailbox_sync_notify(struct mailbox *box, uint32_t uid,
        }
 
        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 */
@@ -436,16 +446,47 @@ static void quota_storage_destroy(struct mail_storage *storage)
 {
        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;
 
@@ -459,7 +500,8 @@ void quota_mail_storage_created(struct mail_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)
index 3e74a340b53faf38c38e0237bb39bb7761f40fa3..25c35f4b05c595692916112524cfeb7b6b623241 100644 (file)
@@ -42,37 +42,30 @@ static const struct quota_backend *quota_backends[] = {
 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(&quota->roots, 4);
-       i_array_init(&quota->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(&quota_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(&quota->roots) > 0) {
-               root_p = array_idx_modifiable(&quota->roots, 0);
-               root = *root_p;
-               quota_root_deinit(&root);
-       }
+       *_quota_set = NULL;
 
-       array_free(&quota->roots);
-       array_free(&quota->storages);
-       i_free(quota);
+       pool_unref(&quota_set->pool);
 }
 
 static const struct quota_backend *quota_backend_find(const char *name)
@@ -87,11 +80,12 @@ 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, ':');
@@ -107,44 +101,57 @@ struct quota_root *quota_root_init(struct quota *quota, const char *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(&quota_set->root_sets, &root_set, 1);
+       return root_set;
+}
 
-       array_append(&quota->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;
@@ -154,49 +161,65 @@ struct quota_root *quota_root_init(struct quota *quota, const char *root_def)
                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(&quota->roots, 8);
 
-       roots = array_get(&root->quota->roots, &count);
+       root_sets = array_get(&quota_set->root_sets, &count);
+       i_array_init(&quota->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(&quota->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(&quota->roots, &count);
+       for (i = 0; i < count; i++)
+               quota_root_deinit(roots[i]);
+       array_free(&quota->roots);
+       array_free(&quota->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];
@@ -205,18 +228,19 @@ quota_root_rule_find(struct quota_root *root, const char *name)
 }
 
 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;
        }
@@ -244,29 +268,29 @@ quota_rule_recalculate_relative_rules(struct quota_rule *rule,
        }
 }
 
-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;
@@ -288,7 +312,7 @@ quota_rule_parse_limits(struct quota_root *root, struct quota_rule *rule,
                        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;
                }
@@ -314,12 +338,12 @@ quota_rule_parse_limits(struct quota_root *root, struct quota_rule *rule,
                        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;
                }
@@ -338,8 +362,8 @@ quota_rule_parse_limits(struct quota_root *root, struct quota_rule *rule,
        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;
@@ -354,43 +378,45 @@ int quota_root_add_rule(struct quota_root *root, const char *rule_def,
        /* <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);
@@ -398,7 +424,7 @@ int quota_root_add_rule(struct quota_root *root, const char *rule_def,
        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)
@@ -407,14 +433,14 @@ static bool quota_root_get_rule_limits(struct quota_root *root,
        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;
@@ -489,12 +515,18 @@ 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;
        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(&quota->storages, &count);
        for (i = 0; i < count; i++) {
                if (storages[i] == storage) {
@@ -504,8 +536,8 @@ void quota_remove_user_storage(struct quota *quota,
        }
 }
 
-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;
@@ -519,17 +551,18 @@ int quota_root_add_warning_rule(struct quota_root *root, const char *rule_def,
        }
 
        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,
@@ -541,12 +574,13 @@ int quota_root_add_warning_rule(struct quota_root *root, const char *rule_def,
 }
 
 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;
 }
@@ -608,14 +642,16 @@ void quota_root_iter_deinit(struct quota_root_iter **_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(&quota->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;
@@ -623,7 +659,7 @@ struct quota_root *quota_root_lookup(struct quota *quota, const char *name)
 
 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)
@@ -649,7 +685,7 @@ int quota_get_resource(struct quota_root *root, const char *mailbox_name,
        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;
@@ -676,13 +712,13 @@ int quota_set_resource(struct quota_root *root ATTR_UNUSED,
        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;
@@ -756,7 +792,7 @@ static void quota_warnings_execute(struct quota_transaction_context *ctx,
        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;
 
@@ -801,7 +837,8 @@ int quota_transaction_commit(struct quota_transaction_context **_ctx)
                        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;
@@ -856,7 +893,7 @@ int quota_test_alloc(struct quota_transaction_context *ctx,
                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,
@@ -877,7 +914,7 @@ 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;
index 2f757f71421ffca3e0e4d03850502bedf3e2f23a..0a716a7e00eae4d6769955780b5510d2a4cad3ff 100644 (file)
@@ -3,6 +3,7 @@
 
 struct mail;
 struct mailbox;
+struct mail_user;
 
 /* Message storage size kilobytes. */
 #define QUOTA_NAME_STORAGE_KILOBYTES "STORAGE"
@@ -16,29 +17,35 @@ struct quota_root;
 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);
@@ -53,8 +60,7 @@ int quota_set_resource(struct quota_root *root, const char *name,
                       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. */
index 579d8747f7beb118c687aa9fcd8e23c87350360a..e3e340912bc58289a6bbd39e98ed5e644c8b06cb 100644 (file)
@@ -21,9 +21,9 @@ struct trash_mailbox {
        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;
@@ -45,7 +45,7 @@ static int trash_clean_mailbox_open(struct trash_mailbox *trash)
 {
        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;
@@ -89,14 +89,17 @@ static int trash_clean_mailbox_get_next(struct trash_mailbox *trash,
        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(&quota_set->storages, &count);
+       storages = array_get(&quota->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;
                }
@@ -124,7 +127,7 @@ static int trash_try_clean_mails(struct quota_transaction_context *ctx,
                                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);
@@ -177,6 +180,8 @@ err:
                }
 
                mailbox_close(&trash->box);
+               trash->storage = NULL;
+               trash->ns_name = NULL;
        }
 
        if (size_expunged < size_needed) {
index 2dd6a125e9bf04d13be96d95b723c43e7c86c4e6..bf4792e1c203b92f47ab558aba1861250ecf41b4 100644 (file)
@@ -89,6 +89,7 @@ static int
 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 == ' ') {
@@ -110,7 +111,7 @@ virtual_config_parse_line(struct virtual_parse_context *ctx, const char *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);
@@ -154,6 +155,7 @@ static void virtual_config_copy_expanded(struct virtual_parse_context *ctx,
 
 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;
@@ -170,8 +172,7 @@ static int virtual_config_expand_wildcards(struct virtual_parse_context *ctx)
                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) {
@@ -191,6 +192,7 @@ static int virtual_config_expand_wildcards(struct virtual_parse_context *ctx)
 
 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;
@@ -213,7 +215,7 @@ int virtual_config_read(struct virtual_mailbox *mbox)
        }
 
        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);
index 97faf4ab3f9f75d93e320623c735620d9716fa43..40d02834147b6f3b9182fbe9d197d4b9cb1b65d7 100644 (file)
@@ -5,36 +5,14 @@
 #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;
 }
index cb73a76f8acbb24cf216ae14573f6b4b8cf61e29..59b5c7a2a6f28010a5e03b222c9282771bcae3f5 100644 (file)
@@ -1,8 +1,6 @@
 #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);
 
index d172033cc14165ccc392a68b62a63daed1632ef4..81da117df60b681b7015ee8163657b5d24141134 100644 (file)
@@ -169,6 +169,7 @@ static bool virtual_mailbox_is_in_open_stack(struct virtual_storage *storage,
 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;
@@ -180,7 +181,7 @@ static int virtual_mailboxes_open(struct virtual_mailbox *mbox,
        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);
 
index 40f1fbe745841b68285beb28b7324bfdd724f5d3..4220b157cf820abcb071d7965ac077dde49899e7 100644 (file)
@@ -138,8 +138,7 @@ static bool init_mailbox(struct client *client, const char **error_r)
        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;
@@ -164,10 +163,10 @@ struct client *client_create(int fd_in, int fd_out,
        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.");
@@ -273,7 +272,7 @@ void client_destroy(struct client *client, const char *reason)
        }
        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);
index 35cb285e772783a01d2e21d2f8289fc861e72ce1..4c21cece99e8e64a361db769f71a74e82092d91d 100644 (file)
@@ -16,7 +16,8 @@ struct client {
        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;
 
@@ -49,8 +50,7 @@ struct client {
 
 /* 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 */
index 227d4aec06c88f5496c6444d7a1cc89bd43a6426..e25e13d8d20b77e935687e5b479fe2858f6d8cb3 100644 (file)
@@ -180,7 +180,7 @@ static void drop_privileges(void)
 
 static bool main_init(void)
 {
-       struct mail_namespace *ns;
+       struct mail_user *user;
        struct client *client;
        const char *str;
        bool ret = TRUE;
@@ -231,9 +231,11 @@ static bool main_init(void)
                        "%% 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;