Mercurial > dovecot > original-hg > dovecot-1.2
changeset 8082:db66611fd195 HEAD
Added struct mail_user and fixed the code to support multiple users per process.
line wrap: on
line diff
--- a/src/deliver/deliver.c Fri Aug 08 17:16:07 2008 -0400 +++ b/src/deliver/deliver.c Tue Aug 12 12:28:42 2008 -0400 @@ -777,7 +777,8 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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();
--- a/src/imap/client.c Fri Aug 08 17:16:07 2008 -0400 +++ b/src/imap/client.c Tue Aug 12 12:28:42 2008 -0400 @@ -25,10 +25,10 @@ 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 @@ 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 @@ 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 @@ 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);
--- a/src/imap/client.h Fri Aug 08 17:16:07 2008 -0400 +++ b/src/imap/client.h Tue Aug 12 12:28:42 2008 -0400 @@ -74,7 +74,7 @@ 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 @@ /* 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 */
--- a/src/imap/cmd-list.c Fri Aug 08 17:16:07 2008 -0400 +++ b/src/imap/cmd-list.c Tue Aug 12 12:28:42 2008 -0400 @@ -185,7 +185,7 @@ } /* 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 @@ /* 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 @@ 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;
--- a/src/imap/cmd-namespace.c Fri Aug 08 17:16:07 2008 -0400 +++ b/src/imap/cmd-namespace.c Tue Aug 12 12:28:42 2008 -0400 @@ -42,11 +42,11 @@ 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.");
--- a/src/imap/cmd-subscribe.c Fri Aug 08 17:16:07 2008 -0400 +++ b/src/imap/cmd-subscribe.c Tue Aug 12 12:28:42 2008 -0400 @@ -35,7 +35,7 @@ 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 @@ 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 {
--- a/src/imap/commands-util.c Fri Aug 08 17:16:07 2008 -0400 +++ b/src/imap/commands-util.c Tue Aug 12 12:28:42 2008 -0400 @@ -23,7 +23,7 @@ { 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;
--- a/src/imap/main.c Fri Aug 08 17:16:07 2008 -0400 +++ b/src/imap/main.c Tue Aug 12 12:28:42 2008 -0400 @@ -161,8 +161,8 @@ { 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 @@ 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 @@ 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 @@ 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 ",
--- a/src/lib-storage/Makefile.am Fri Aug 08 17:16:07 2008 -0400 +++ b/src/lib-storage/Makefile.am Tue Aug 12 12:28:42 2008 -0400 @@ -16,6 +16,7 @@ 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 @@ 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 \
--- a/src/lib-storage/index/maildir/maildir-storage.c Fri Aug 08 17:16:07 2008 -0400 +++ b/src/lib-storage/index/maildir/maildir-storage.c Tue Aug 12 12:28:42 2008 -0400 @@ -60,11 +60,13 @@ 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 @@ } /* 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 @@ } } 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 @@ 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;
--- a/src/lib-storage/index/mbox/mbox-save.c Fri Aug 08 17:16:07 2008 -0400 +++ b/src/lib-storage/index/mbox/mbox-save.c Tue Aug 12 12:28:42 2008 -0400 @@ -135,9 +135,11 @@ 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 */
--- a/src/lib-storage/index/mbox/mbox-storage.c Fri Aug 08 17:16:07 2008 -0400 +++ b/src/lib-storage/index/mbox/mbox-storage.c Tue Aug 12 12:28:42 2008 -0400 @@ -185,12 +185,12 @@ 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 @@ 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_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 @@ 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 @@ 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 @@ /* 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 @@ 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 @@ 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 @@ 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 @@ 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;
--- a/src/lib-storage/mail-namespace.c Fri Aug 08 17:16:07 2008 -0400 +++ b/src/lib-storage/mail-namespace.c Tue Aug 12 12:28:42 2008 -0400 @@ -29,7 +29,7 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ } return -1; } - *namespaces_r = ns; + user->namespaces = ns; if (hook_mail_namespaces_created != NULL) { T_BEGIN { @@ -258,14 +259,17 @@ 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; }
--- a/src/lib-storage/mail-namespace.h Fri Aug 08 17:16:07 2008 -0400 +++ b/src/lib-storage/mail-namespace.h Tue Aug 12 12:28:42 2008 -0400 @@ -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 @@ 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 @@ /* 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. */
--- a/src/lib-storage/mail-storage-private.h Fri Aug 08 17:16:07 2008 -0400 +++ b/src/lib-storage/mail-storage-private.h Tue Aug 12 12:28:42 2008 -0400 @@ -61,7 +61,6 @@ 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;
--- a/src/lib-storage/mail-storage.c Fri Aug 08 17:16:07 2008 -0400 +++ b/src/lib-storage/mail-storage.c Tue Aug 12 12:28:42 2008 -0400 @@ -169,8 +169,7 @@ } 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 @@ 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 @@ return -1; } - home = getenv("HOME"); + home = ns->user->home; if (home == NULL || *home == '\0') home = "(not set)"; *error_r = t_strdup_printf(
--- a/src/lib-storage/mail-storage.h Fri Aug 08 17:16:07 2008 -0400 +++ b/src/lib-storage/mail-storage.h Tue Aug 12 12:28:42 2008 -0400 @@ -248,8 +248,7 @@ 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);
--- a/src/plugins/acl/acl-mailbox-list.c Fri Aug 08 17:16:07 2008 -0400 +++ b/src/plugins/acl/acl-mailbox-list.c Tue Aug 12 12:28:42 2008 -0400 @@ -415,10 +415,7 @@ 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 @@ 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"), ","),
--- a/src/plugins/convert/convert-plugin.c Fri Aug 08 17:16:07 2008 -0400 +++ b/src/plugins/convert/convert-plugin.c Tue Aug 12 12:28:42 2008 -0400 @@ -19,11 +19,7 @@ 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 =
--- a/src/plugins/convert/convert-storage.c Fri Aug 08 17:16:07 2008 -0400 +++ b/src/plugins/convert/convert-storage.c Tue Aug 12 12:28:42 2008 -0400 @@ -392,6 +392,7 @@ 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 @@ 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 @@ /* 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);
--- a/src/plugins/convert/convert-storage.h Fri Aug 08 17:16:07 2008 -0400 +++ b/src/plugins/convert/convert-storage.h Tue Aug 12 12:28:42 2008 -0400 @@ -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;
--- a/src/plugins/convert/convert-tool.c Fri Aug 08 17:16:07 2008 -0400 +++ b/src/plugins/convert/convert-tool.c Tue Aug 12 12:28:42 2008 -0400 @@ -18,6 +18,7 @@ { 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 @@ 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 @@ } 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 @@ 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();
--- a/src/plugins/expire/expire-plugin.c Fri Aug 08 17:16:07 2008 -0400 +++ b/src/plugins/expire/expire-plugin.c Tue Aug 12 12:28:42 2008 -0400 @@ -294,6 +294,7 @@ 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);
--- a/src/plugins/expire/expire-tool.c Fri Aug 08 17:16:07 2008 -0400 +++ b/src/plugins/expire/expire-tool.c Tue Aug 12 12:28:42 2008 -0400 @@ -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 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 @@ { 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 @@ 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 @@ } 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)
--- a/src/plugins/imap-quota/imap-quota-plugin.c Fri Aug 08 17:16:07 2008 -0400 +++ b/src/plugins/imap-quota/imap-quota-plugin.c Tue Aug 12 12:28:42 2008 -0400 @@ -82,7 +82,7 @@ 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 @@ 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 @@ 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 @@ 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;
--- a/src/plugins/lazy-expunge/lazy-expunge-plugin.c Fri Aug 08 17:16:07 2008 -0400 +++ b/src/plugins/lazy-expunge/lazy-expunge-plugin.c Tue Aug 12 12:28:42 2008 -0400 @@ -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 @@ 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 @@ (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 @@ &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 @@ 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 @@ 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 @@ 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 @@ } /* 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_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 @@ 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 @@ 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 @@ 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; }
--- a/src/plugins/quota/quota-count.c Fri Aug 08 17:16:07 2008 -0400 +++ b/src/plugins/quota/quota-count.c Tue Aug 12 12:28:42 2008 -0400 @@ -19,7 +19,7 @@ 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;
--- a/src/plugins/quota/quota-dict.c Fri Aug 08 17:16:07 2008 -0400 +++ b/src/plugins/quota/quota-dict.c Tue Aug 12 12:28:42 2008 -0400 @@ -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 @@ } 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 @@ } 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;
--- a/src/plugins/quota/quota-maildir.c Fri Aug 08 17:16:07 2008 -0400 +++ b/src/plugins/quota/quota-maildir.c Tue Aug 12 12:28:42 2008 -0400 @@ -149,7 +149,7 @@ 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 @@ 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 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 @@ 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 @@ 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 @@ /* 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 @@ 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 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) {
--- a/src/plugins/quota/quota-plugin.c Fri Aug 08 17:16:07 2008 -0400 +++ b/src/plugins/quota/quota-plugin.c Tue Aug 12 12:28:42 2008 -0400 @@ -11,14 +11,15 @@ /* 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 @@ 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_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 @@ 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 @@ 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 @@ 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 @@ 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_deinit(void) { if (quota_set != NULL) { + hook_mail_user_created = quota_next_hook_mail_user_created; hook_mail_storage_created = quota_next_hook_mail_storage_created; hook_mailbox_list_created = quota_next_hook_mailbox_list_created; - quota_deinit("a_set); + quota_settings_deinit("a_set); } }
--- a/src/plugins/quota/quota-plugin.h Fri Aug 08 17:16:07 2008 -0400 +++ b/src/plugins/quota/quota-plugin.h Tue Aug 12 12:28:42 2008 -0400 @@ -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);
--- a/src/plugins/quota/quota-private.h Fri Aug 08 17:16:07 2008 -0400 +++ b/src/plugins/quota/quota-private.h Tue Aug 12 12:28:42 2008 -0400 @@ -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_rule { - char *mailbox_name; + const char *mailbox_name; int64_t bytes_limit, count_limit; /* relative to default_rule */ @@ -33,7 +41,7 @@ struct quota_warning_rule { struct quota_rule rule; - char *command; + const char *command; }; struct quota_backend_vfuncs { @@ -41,7 +49,8 @@ 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 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_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 @@ /* 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
--- a/src/plugins/quota/quota-storage.c Fri Aug 08 17:16:07 2008 -0400 +++ b/src/plugins/quota/quota-storage.c Tue Aug 12 12:28:42 2008 -0400 @@ -17,6 +17,14 @@ 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_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 @@ 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 @@ 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 @@ 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 @@ } 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 @@ { 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 @@ 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)
--- a/src/plugins/quota/quota.c Fri Aug 08 17:16:07 2008 -0400 +++ b/src/plugins/quota/quota.c Tue Aug 12 12:28:42 2008 -0400 @@ -42,37 +42,30 @@ 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; + struct quota_settings *quota_set; + pool_t pool; - quota = i_new(struct quota, 1); - quota->test_alloc = quota_default_test_alloc; - quota->debug = getenv("DEBUG") != NULL; - quota->quota_exceeded_msg = getenv("QUOTA_EXCEEDED_MESSAGE"); - if (quota->quota_exceeded_msg == NULL) - quota->quota_exceeded_msg = DEFAULT_QUOTA_EXCEEDED_MSG; - i_array_init("a->roots, 4); - i_array_init("a->storages, 8); - - return quota; + pool = pool_alloconly_create("quota settings", 256); + quota_set = p_new(pool, struct quota_settings, 1); + quota_set->pool = pool; + quota_set->test_alloc = quota_default_test_alloc; + quota_set->debug = getenv("DEBUG") != NULL; + quota_set->quota_exceeded_msg = getenv("QUOTA_EXCEEDED_MESSAGE"); + if (quota_set->quota_exceeded_msg == NULL) + quota_set->quota_exceeded_msg = DEFAULT_QUOTA_EXCEEDED_MSG; + p_array_init("a_set->root_sets, pool, 4); + return quota_set; } -void quota_deinit(struct quota **_quota) +void quota_settings_deinit(struct quota_settings **_quota_set) { - struct quota *quota = *_quota; - struct quota_root **root_p, *root; + struct quota_settings *quota_set = *_quota_set; - *_quota = NULL; - while (array_count("a->roots) > 0) { - root_p = array_idx_modifiable("a->roots, 0); - root = *root_p; - quota_root_deinit(&root); - } + *_quota_set = NULL; - array_free("a->roots); - array_free("a->storages); - i_free(quota); + pool_unref("a_set->pool); } static const struct quota_backend *quota_backend_find(const char *name) @@ -87,11 +80,12 @@ 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 @@ if (backend == NULL) i_fatal("Unknown quota backend: %s", backend_name); - root = backend->v.alloc(); - root->quota = quota; - root->backend = *backend; - root->pool = pool_alloconly_create("quota root", 512); + root_set = p_new(quota_set->pool, struct quota_root_settings, 1); + root_set->set = quota_set; + root_set->backend = backend; if (args != NULL) { /* save root's name */ p = strchr(args, ':'); if (p == NULL) { - root->name = p_strdup(root->pool, args); + root_set->name = p_strdup(quota_set->pool, args); args = NULL; } else { - root->name = p_strdup_until(root->pool, args, p); + root_set->name = + p_strdup_until(quota_set->pool, args, p); args = p + 1; } } else { - root->name = ""; + root_set->name = ""; } + root_set->args = p_strdup(quota_set->pool, args); - if (quota->debug) { + if (quota_set->debug) { i_info("Quota root: name=%s backend=%s args=%s", - root->name, backend_name, args == NULL ? "" : args); + root_set->name, backend_name, args == NULL ? "" : args); } - i_array_init(&root->rules, 4); - i_array_init(&root->warning_rules, 4); - array_create(&root->quota_module_contexts, default_pool, - sizeof(void *), 5); + p_array_init(&root_set->rules, quota_set->pool, 4); + p_array_init(&root_set->warning_rules, quota_set->pool, 4); + array_append("a_set->root_sets, &root_set, 1); + return root_set; +} - array_append("a->roots, &root, 1); +static struct quota_root * +quota_root_init(struct quota_root_settings *root_set, struct quota *quota) +{ + struct quota_root *root; + const char *const *tmp; - if (backend->v.init != NULL) { - if (backend->v.init(root, args) < 0) { - quota_root_deinit(&root); + root = root_set->backend->v.alloc(); + root->pool = pool_alloconly_create("quota root", 512); + root->set = root_set; + root->quota = quota; + root->backend = *root_set->backend; + + array_create(&root->quota_module_contexts, root->pool, + sizeof(void *), 10); + + if (root->backend.v.init != NULL) { + if (root->backend.v.init(root, root_set->args) < 0) return NULL; - } - } else if (args != NULL) { - tmp = t_strsplit_spaces(args, " "); + } else if (root_set->args != NULL) { + tmp = t_strsplit_spaces(root_set->args, " "); for (; *tmp != NULL; tmp++) { if (strcmp(*tmp, "noenforcing") == 0) root->no_enforcing = TRUE; @@ -154,49 +161,65 @@ 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; - unsigned int i, count; - - *_root = NULL; - - roots = array_get(&root->quota->roots, &count); - for (i = 0; i < count; i++) { - if (roots[i] == root) { - array_delete(&root->quota->roots, i, 1); - break; - } - } - - warnings = array_get_modifiable(&root->warning_rules, &count); - for (i = 0; i < count; i++) - i_free(warnings[i].command); - array_free(&root->warning_rules); - - array_free(&root->rules); - array_free(&root->quota_module_contexts); 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; + + quota = i_new(struct quota, 1); + quota->user = user; + quota->set = quota_set; + i_array_init("a->roots, 8); + + root_sets = array_get("a_set->root_sets, &count); + i_array_init("a->storages, count); + for (i = 0; i < count; i++) { + root = quota_root_init(root_sets[i], quota); + array_append("a->roots, &root, 1); + } + return quota; +} + +void quota_deinit(struct quota **_quota) +{ + struct quota *quota = *_quota; + struct quota_root *const *roots; + unsigned int i, count; + + *_quota = NULL; + + roots = array_get("a->roots, &count); + for (i = 0; i < count; i++) + quota_root_deinit(roots[i]); + array_free("a->roots); + array_free("a->storages); + i_free(quota); +} + struct quota_rule * -quota_root_rule_find(struct quota_root *root, const char *name) +quota_root_rule_find(struct quota_root_settings *root_set, const char *name) { struct quota_rule *rules; unsigned int i, count; - rules = array_get_modifiable(&root->rules, &count); + rules = array_get_modifiable(&root_set->rules, &count); for (i = 0; i < count; i++) { if (strcmp(rules[i].mailbox_name, name) == 0) return &rules[i]; @@ -205,18 +228,19 @@ } 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 @@ } } -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 @@ 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 @@ 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 @@ 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 @@ /* <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 @@ 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 @@ 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_remove_user_storage(struct quota *quota, - struct mail_storage *storage) +void quota_remove_user_storage(struct mail_storage *storage) { + struct quota *quota; struct mail_storage *const *storages; unsigned int i, count; - + + quota = quota_get_mail_user_quota(storage->ns->user); + if (quota == NULL) { + /* no quota for this storage */ + return; + } + storages = array_get("a->storages, &count); for (i = 0; i < count; i++) { if (storages[i] == storage) { @@ -504,8 +536,8 @@ } } -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 @@ } 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 @@ } 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 @@ i_free(iter); } -struct quota_root *quota_root_lookup(struct quota *quota, const char *name) +struct quota_root *quota_root_lookup(struct mail_user *user, const char *name) { + struct quota *quota; struct quota_root *const *roots; unsigned int i, count; + quota = quota_get_mail_user_quota(user); roots = array_get("a->roots, &count); for (i = 0; i < count; i++) { - if (strcmp(roots[i]->name, name) == 0) + if (strcmp(roots[i]->set->name, name) == 0) return roots[i]; } return NULL; @@ -623,7 +659,7 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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 @@ 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;
--- a/src/plugins/quota/quota.h Fri Aug 08 17:16:07 2008 -0400 +++ b/src/plugins/quota/quota.h Tue Aug 12 12:28:42 2008 -0400 @@ -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_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 @@ 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. */
--- a/src/plugins/trash/trash-plugin.c Fri Aug 08 17:16:07 2008 -0400 +++ b/src/plugins/trash/trash-plugin.c Tue Aug 12 12:28:42 2008 -0400 @@ -21,9 +21,9 @@ const char *name; int priority; /* lower number = higher priority */ + /* temporarily set while cleaning: */ + const char *ns_name; struct mail_storage *storage; - - /* temporarily set while cleaning: */ struct mailbox *box; struct mailbox_transaction_context *trans; struct mail_search_context *search_ctx; @@ -45,7 +45,7 @@ { 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 @@ return 1; } -static void trash_find_storage(struct trash_mailbox *trash) +static void trash_find_storage(struct quota *quota, + struct trash_mailbox *trash) { struct mail_storage *const *storages; unsigned int i, count; - storages = array_get("a_set->storages, &count); + storages = array_get("a->storages, &count); for (i = 0; i < count; i++) { - if (mail_namespace_update_name(storages[i]->ns, &trash->name)) { + trash->ns_name = trash->name; + if (mail_namespace_update_name(storages[i]->ns, + &trash->ns_name)) { trash->storage = storages[i]; return; } @@ -124,7 +127,7 @@ 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 @@ } mailbox_close(&trash->box); + trash->storage = NULL; + trash->ns_name = NULL; } if (size_expunged < size_needed) {
--- a/src/plugins/virtual/virtual-config.c Fri Aug 08 17:16:07 2008 -0400 +++ b/src/plugins/virtual/virtual-config.c Tue Aug 12 12:28:42 2008 -0400 @@ -89,6 +89,7 @@ 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 @@ 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 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 @@ 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 @@ 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 @@ } 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);
--- a/src/plugins/virtual/virtual-plugin.c Fri Aug 08 17:16:07 2008 -0400 +++ b/src/plugins/virtual/virtual-plugin.c Tue Aug 12 12:28:42 2008 -0400 @@ -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; }
--- a/src/plugins/virtual/virtual-plugin.h Fri Aug 08 17:16:07 2008 -0400 +++ b/src/plugins/virtual/virtual-plugin.h Tue Aug 12 12:28:42 2008 -0400 @@ -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);
--- a/src/plugins/virtual/virtual-storage.c Fri Aug 08 17:16:07 2008 -0400 +++ b/src/plugins/virtual/virtual-storage.c Tue Aug 12 12:28:42 2008 -0400 @@ -169,6 +169,7 @@ 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 @@ 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);
--- a/src/pop3/client.c Fri Aug 08 17:16:07 2008 -0400 +++ b/src/pop3/client.c Tue Aug 12 12:28:42 2008 -0400 @@ -138,8 +138,7 @@ 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 @@ 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 @@ } 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);
--- a/src/pop3/client.h Fri Aug 08 17:16:07 2008 -0400 +++ b/src/pop3/client.h Tue Aug 12 12:28:42 2008 -0400 @@ -16,7 +16,8 @@ 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 @@ /* 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 */
--- a/src/pop3/main.c Fri Aug 08 17:16:07 2008 -0400 +++ b/src/pop3/main.c Tue Aug 12 12:28:42 2008 -0400 @@ -180,7 +180,7 @@ 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 @@ "%% 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;