quota-imapc.c revision fde14422caabc3c4ac4a6c5e3e5cf176cedd90a6
bcb4e51a409d94ae670de96afb8483a4f7855294Stephan Bosch/* Copyright (c) 2017 Dovecot authors, see the included COPYING file */
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen#include "lib.h"
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen#include "array.h"
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen#include "ioloop.h"
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen#include "imap-arg.h"
6e2856a5beeeb0edf5d852dde63d99fb9af11151Martti Rannanjärvi#include "imapc-storage.h"
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen#include "mailbox-list-private.h"
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen#include "quota-private.h"
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
39ee82dad4d4fa61e3ed074d191afc6a9b82e249Timo Sirainenstruct imapc_quota_refresh_root {
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen const char *name;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen unsigned int order;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen uint64_t bytes_cur, count_cur;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen uint64_t bytes_limit, count_limit;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen};
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
39ee82dad4d4fa61e3ed074d191afc6a9b82e249Timo Sirainenstruct imapc_quota_refresh {
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen pool_t pool;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen const char *box_name;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen ARRAY(struct imapc_quota_refresh_root) roots;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen};
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainenstruct imapc_quota_root {
ad859755efbf4b0c7787b6868f92ceafffdb368fTimo Sirainen struct quota_root root;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen const char *box_name, *root_name;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen struct mail_namespace *imapc_ns;
39ee82dad4d4fa61e3ed074d191afc6a9b82e249Timo Sirainen struct imapc_storage_client *client;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen bool initialized;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen uint64_t bytes_last, count_last;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen struct timeval last_refresh;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen struct imapc_quota_refresh refresh;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen};
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainenextern struct quota_backend quota_backend_imapc;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
678d0463849ba777106eb7875f27db07a5d8e3dfTimo Sirainenstatic struct quota_root *imapc_quota_alloc(void)
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen{
678d0463849ba777106eb7875f27db07a5d8e3dfTimo Sirainen struct imapc_quota_root *root;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen root = i_new(struct imapc_quota_root, 1);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen return &root->root;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen}
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainenstatic void handle_box_param(struct quota_root *_root, const char *param_value)
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen{
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen ((struct imapc_quota_root *)_root)->box_name = p_strdup(_root->pool, param_value);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen}
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainenstatic void handle_root_param(struct quota_root *_root, const char *param_value)
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen{
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen ((struct imapc_quota_root *)_root)->root_name = p_strdup(_root->pool, param_value);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen}
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainenstatic int imapc_quota_init(struct quota_root *_root, const char *args,
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen const char **error_r)
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen{
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen struct imapc_quota_root *root = (struct imapc_quota_root *)_root;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen const struct quota_param_parser imapc_params[] = {
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen {.param_name = "box=", .param_handler = handle_box_param},
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen {.param_name = "root=", .param_handler = handle_root_param},
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen quota_param_ns,
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen {.param_name = NULL}
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen };
8d35582f2577c64517b2341c5d6477c7010e0a0cPhil Carmody
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen _root->auto_updating = TRUE;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen if (quota_parse_parameters(_root, &args, error_r, imapc_params, TRUE) < 0)
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen return -1;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
39ee82dad4d4fa61e3ed074d191afc6a9b82e249Timo Sirainen if (root->box_name == NULL && root->root_name == NULL)
39ee82dad4d4fa61e3ed074d191afc6a9b82e249Timo Sirainen root->box_name = "INBOX";
39ee82dad4d4fa61e3ed074d191afc6a9b82e249Timo Sirainen /* we'll never try to enforce the quota - it's just a lot of
39ee82dad4d4fa61e3ed074d191afc6a9b82e249Timo Sirainen unnecessary remote GETQUOTA calls. */
39ee82dad4d4fa61e3ed074d191afc6a9b82e249Timo Sirainen _root->no_enforcing = TRUE;
39ee82dad4d4fa61e3ed074d191afc6a9b82e249Timo Sirainen return 0;
39ee82dad4d4fa61e3ed074d191afc6a9b82e249Timo Sirainen}
39ee82dad4d4fa61e3ed074d191afc6a9b82e249Timo Sirainen
39ee82dad4d4fa61e3ed074d191afc6a9b82e249Timo Sirainenstatic void imapc_quota_deinit(struct quota_root *_root)
39ee82dad4d4fa61e3ed074d191afc6a9b82e249Timo Sirainen{
39ee82dad4d4fa61e3ed074d191afc6a9b82e249Timo Sirainen i_free(_root);
39ee82dad4d4fa61e3ed074d191afc6a9b82e249Timo Sirainen}
39ee82dad4d4fa61e3ed074d191afc6a9b82e249Timo Sirainen
39ee82dad4d4fa61e3ed074d191afc6a9b82e249Timo Sirainenstatic void
39ee82dad4d4fa61e3ed074d191afc6a9b82e249Timo Sirainenimapc_quota_root_namespace_added(struct quota_root *_root,
39ee82dad4d4fa61e3ed074d191afc6a9b82e249Timo Sirainen struct mail_namespace *ns)
39ee82dad4d4fa61e3ed074d191afc6a9b82e249Timo Sirainen{
39ee82dad4d4fa61e3ed074d191afc6a9b82e249Timo Sirainen struct imapc_quota_root *root = (struct imapc_quota_root *)_root;
39ee82dad4d4fa61e3ed074d191afc6a9b82e249Timo Sirainen
39ee82dad4d4fa61e3ed074d191afc6a9b82e249Timo Sirainen if (root->imapc_ns == NULL)
39ee82dad4d4fa61e3ed074d191afc6a9b82e249Timo Sirainen root->imapc_ns = ns;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen}
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainenstatic struct imapc_quota_refresh *
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainenimapc_quota_root_refresh_find(struct imapc_storage_client *client)
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen{
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen struct imapc_storage *storage = client->_storage;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen struct quota *quota;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen struct quota_root *const *rootp;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen i_assert(storage != NULL);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen quota = quota_get_mail_user_quota(storage->storage.user);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen i_assert(quota != NULL);
8d35582f2577c64517b2341c5d6477c7010e0a0cPhil Carmody
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen /* find the quota root that is being refreshed */
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen array_foreach(&quota->roots, rootp) {
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen if ((*rootp)->backend.name == quota_backend_imapc.name) {
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen struct imapc_quota_root *root =
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen (struct imapc_quota_root *)*rootp;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
8d35582f2577c64517b2341c5d6477c7010e0a0cPhil Carmody if (root->refresh.pool != NULL)
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen return &root->refresh;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen }
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen }
39ee82dad4d4fa61e3ed074d191afc6a9b82e249Timo Sirainen return NULL;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen}
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainenstatic struct imapc_quota_refresh_root *
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainenimapc_quota_refresh_root_get(struct imapc_quota_refresh *refresh,
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen const char *root_name)
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen{
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen struct imapc_quota_refresh_root *refresh_root;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen array_foreach_modifiable(&refresh->roots, refresh_root) {
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen if (strcmp(refresh_root->name, root_name) == 0)
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen return refresh_root;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen }
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen refresh_root = array_append_space(&refresh->roots);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen refresh_root->order = UINT_MAX;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen refresh_root->name = p_strdup(refresh->pool, root_name);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen refresh_root->bytes_limit = (uint64_t)-1;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen refresh_root->count_limit = (uint64_t)-1;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen return refresh_root;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen}
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
414b2d3b63412c4bef6a4caa7a7222f3abbdbabaTimo Sirainenstatic void imapc_untagged_quotaroot(const struct imapc_untagged_reply *reply,
414b2d3b63412c4bef6a4caa7a7222f3abbdbabaTimo Sirainen struct imapc_storage_client *client)
414b2d3b63412c4bef6a4caa7a7222f3abbdbabaTimo Sirainen{
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen struct imapc_quota_refresh *refresh;
414b2d3b63412c4bef6a4caa7a7222f3abbdbabaTimo Sirainen struct imapc_quota_refresh_root *refresh_root;
414b2d3b63412c4bef6a4caa7a7222f3abbdbabaTimo Sirainen const char *mailbox_name, *root_name;
414b2d3b63412c4bef6a4caa7a7222f3abbdbabaTimo Sirainen unsigned int i;
414b2d3b63412c4bef6a4caa7a7222f3abbdbabaTimo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen if (!imap_arg_get_astring(&reply->args[0], &mailbox_name))
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen return;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen if ((refresh = imapc_quota_root_refresh_find(client)) == NULL ||
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen refresh->box_name == NULL ||
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen strcmp(refresh->box_name, mailbox_name) != 0) {
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen /* unsolicited QUOTAROOT reply - ignore */
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen return;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen }
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen if (array_count(&refresh->roots) > 0) {
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen /* duplicate QUOTAROOT reply - ignore */
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen return;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen }
e83126866761632b437e532dfdc30be01d14039dTimo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen i = 1;
39ee82dad4d4fa61e3ed074d191afc6a9b82e249Timo Sirainen while (imap_arg_get_astring(&reply->args[i], &root_name)) {
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen refresh_root = imapc_quota_refresh_root_get(refresh, root_name);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen refresh_root->order = i;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen i++;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen }
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen}
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainenstatic void imapc_untagged_quota(const struct imapc_untagged_reply *reply,
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen struct imapc_storage_client *client)
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen{
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen const struct imap_arg *list;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen struct imapc_quota_refresh *refresh;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen struct imapc_quota_refresh_root *refresh_root;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen const char *root_name, *resource, *value_str, *limit_str;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen uint64_t value, limit;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen unsigned int i;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen if (!imap_arg_get_astring(&reply->args[0], &root_name) ||
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen !imap_arg_get_list(&reply->args[1], &list))
2ac5f36aa7c2e7a07ba8815d43a6d7483f62e74cTimo Sirainen return;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen if ((refresh = imapc_quota_root_refresh_find(client)) == NULL) {
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen /* unsolicited QUOTA reply - ignore */
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen return;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen }
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen refresh_root = imapc_quota_refresh_root_get(refresh, root_name);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen for (i = 0; list[i].type != IMAP_ARG_EOL; i += 3) {
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen if (!imap_arg_get_atom(&list[i], &resource) ||
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen !imap_arg_get_atom(&list[i+1], &value_str) ||
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen !imap_arg_get_atom(&list[i+2], &limit_str) ||
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen /* RFC2087 uses 32bit number, but be ready for future */
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen str_to_uint64(value_str, &value) < 0 ||
2ac5f36aa7c2e7a07ba8815d43a6d7483f62e74cTimo Sirainen str_to_uint64(limit_str, &limit) < 0)
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen return;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen if (strcasecmp(resource, QUOTA_NAME_STORAGE_KILOBYTES) == 0) {
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen refresh_root->bytes_cur = value * 1024;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen refresh_root->bytes_limit = limit * 1024;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen } else if (strcasecmp(resource, QUOTA_NAME_MESSAGES) == 0) {
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen refresh_root->count_cur = value;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen refresh_root->count_limit = limit;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen }
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen }
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen}
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainenstatic bool imapc_quota_client_init(struct imapc_quota_root *root)
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen{
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen struct mailbox_list *list;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen struct mail_storage *storage;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen if (root->initialized)
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen return root->client != NULL;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen root->initialized = TRUE;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen list = root->imapc_ns->list;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen if (mailbox_list_get_storage(&list, "", &storage) == 0 &&
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen strcmp(storage->name, IMAPC_STORAGE_NAME) != 0) {
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen /* non-imapc namespace, skip */
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen if ((storage->class_flags &
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen MAIL_STORAGE_CLASS_FLAG_NOQUOTA) == 0) {
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen i_warning("quota: Namespace '%s' is not imapc, "
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen "skipping for imapc quota",
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen root->imapc_ns->prefix);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen }
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen return FALSE;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen }
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen root->client = ((struct imapc_storage *)storage)->client;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen imapc_storage_client_register_untagged(root->client, "QUOTAROOT",
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen imapc_untagged_quotaroot);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen imapc_storage_client_register_untagged(root->client, "QUOTA",
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen imapc_untagged_quota);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen return TRUE;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen}
678d0463849ba777106eb7875f27db07a5d8e3dfTimo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainenstatic void imapc_quota_refresh_init(struct imapc_quota_refresh *refresh)
678d0463849ba777106eb7875f27db07a5d8e3dfTimo Sirainen{
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen i_assert(refresh->pool == NULL);
678d0463849ba777106eb7875f27db07a5d8e3dfTimo Sirainen
678d0463849ba777106eb7875f27db07a5d8e3dfTimo Sirainen refresh->pool = pool_alloconly_create("imapc quota refresh", 256);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen p_array_init(&refresh->roots, refresh->pool, 4);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen}
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainenstatic void
678d0463849ba777106eb7875f27db07a5d8e3dfTimo Sirainenimapc_quota_refresh_update(struct quota *quota,
678d0463849ba777106eb7875f27db07a5d8e3dfTimo Sirainen struct imapc_quota_refresh *refresh)
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen{
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen struct quota_root *const *rootp;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen const struct imapc_quota_refresh_root *refresh_root;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen if (array_count(&refresh->roots) == 0) {
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen i_error("quota: imapc didn't return any QUOTA results");
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen return;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen }
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen /* use the first quota root for everything */
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen refresh_root = array_idx(&refresh->roots, 0);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen array_foreach(&quota->roots, rootp) {
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen if ((*rootp)->backend.name == quota_backend_imapc.name) {
39ee82dad4d4fa61e3ed074d191afc6a9b82e249Timo Sirainen struct imapc_quota_root *root =
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen (struct imapc_quota_root *)*rootp;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen root->bytes_last = refresh_root->bytes_cur;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen root->count_last = refresh_root->count_cur;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen root->root.bytes_limit = refresh_root->bytes_limit;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen root->root.count_limit = refresh_root->count_limit;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen }
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen }
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen}
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainenstatic void
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainenimapc_quota_refresh_deinit(struct quota *quota,
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen struct imapc_quota_refresh *refresh, bool success)
678d0463849ba777106eb7875f27db07a5d8e3dfTimo Sirainen{
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen if (success)
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen imapc_quota_refresh_update(quota, refresh);
678d0463849ba777106eb7875f27db07a5d8e3dfTimo Sirainen pool_unref(&refresh->pool);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen i_zero(refresh);
678d0463849ba777106eb7875f27db07a5d8e3dfTimo Sirainen}
678d0463849ba777106eb7875f27db07a5d8e3dfTimo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainenstatic int
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainenimapc_quota_refresh_root_order_cmp(const struct imapc_quota_refresh_root *root1,
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen const struct imapc_quota_refresh_root *root2)
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen{
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen if (root1->order < root2->order)
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen return -1;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen else if (root1->order > root2->order)
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen return 1;
678d0463849ba777106eb7875f27db07a5d8e3dfTimo Sirainen else
678d0463849ba777106eb7875f27db07a5d8e3dfTimo Sirainen return 0;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen}
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainenstatic int imapc_quota_refresh_mailbox(struct imapc_quota_root *root)
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen{
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen struct imapc_simple_context sctx;
e3df4d9063a06e0cd228a1713677ec105b0a4aa2Timo Sirainen struct imapc_command *cmd;
e3df4d9063a06e0cd228a1713677ec105b0a4aa2Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen i_assert(root->box_name != NULL);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
678d0463849ba777106eb7875f27db07a5d8e3dfTimo Sirainen /* ask quotas for the configured mailbox */
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen imapc_quota_refresh_init(&root->refresh);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen root->refresh.box_name = root->box_name;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen imapc_simple_context_init(&sctx, root->client);
e3df4d9063a06e0cd228a1713677ec105b0a4aa2Timo Sirainen cmd = imapc_client_cmd(root->client->client,
1d40278513aafd35dcac239729fd3194833f9674Timo Sirainen imapc_simple_callback, &sctx);
1d40278513aafd35dcac239729fd3194833f9674Timo Sirainen imapc_command_sendf(cmd, "GETQUOTAROOT %s", root->box_name);
e3df4d9063a06e0cd228a1713677ec105b0a4aa2Timo Sirainen imapc_simple_run(&sctx);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen /* if there are multiple quota roots, use the first one returned by
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen the QUOTAROOT */
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen array_sort(&root->refresh.roots, imapc_quota_refresh_root_order_cmp);
e3df4d9063a06e0cd228a1713677ec105b0a4aa2Timo Sirainen imapc_quota_refresh_deinit(root->root.quota, &root->refresh,
e3df4d9063a06e0cd228a1713677ec105b0a4aa2Timo Sirainen sctx.ret == 0);
e3df4d9063a06e0cd228a1713677ec105b0a4aa2Timo Sirainen return sctx.ret;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen}
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
e3df4d9063a06e0cd228a1713677ec105b0a4aa2Timo Sirainenstatic int imapc_quota_refresh_root(struct imapc_quota_root *root)
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen{
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen struct imapc_simple_context sctx;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen struct imapc_command *cmd;
1d40278513aafd35dcac239729fd3194833f9674Timo Sirainen
1d40278513aafd35dcac239729fd3194833f9674Timo Sirainen i_assert(root->root_name != NULL);
1d40278513aafd35dcac239729fd3194833f9674Timo Sirainen
1d40278513aafd35dcac239729fd3194833f9674Timo Sirainen /* ask quotas for the configured quota root */
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen imapc_quota_refresh_init(&root->refresh);
39ee82dad4d4fa61e3ed074d191afc6a9b82e249Timo Sirainen
e3df4d9063a06e0cd228a1713677ec105b0a4aa2Timo Sirainen imapc_simple_context_init(&sctx, root->client);
e3df4d9063a06e0cd228a1713677ec105b0a4aa2Timo Sirainen cmd = imapc_client_cmd(root->client->client,
e3df4d9063a06e0cd228a1713677ec105b0a4aa2Timo Sirainen imapc_simple_callback, &sctx);
39ee82dad4d4fa61e3ed074d191afc6a9b82e249Timo Sirainen imapc_command_sendf(cmd, "GETQUOTA %s", root->root_name);
e3df4d9063a06e0cd228a1713677ec105b0a4aa2Timo Sirainen imapc_simple_run(&sctx);
39ee82dad4d4fa61e3ed074d191afc6a9b82e249Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen /* there shouldn't be more than one QUOTA reply, but ignore anyway
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen anything we didn't expect. */
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen while (array_count(&root->refresh.roots) > 0) {
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen const struct imapc_quota_refresh_root *refresh_root =
c307328f59c963eba21091ecd36c9435d42b47d8Timo Sirainen array_idx(&root->refresh.roots, 0);
c307328f59c963eba21091ecd36c9435d42b47d8Timo Sirainen if (strcmp(refresh_root->name, root->root_name) == 0)
c307328f59c963eba21091ecd36c9435d42b47d8Timo Sirainen break;
c307328f59c963eba21091ecd36c9435d42b47d8Timo Sirainen array_delete(&root->refresh.roots, 0, 1);
c307328f59c963eba21091ecd36c9435d42b47d8Timo Sirainen }
c307328f59c963eba21091ecd36c9435d42b47d8Timo Sirainen imapc_quota_refresh_deinit(root->root.quota, &root->refresh,
c307328f59c963eba21091ecd36c9435d42b47d8Timo Sirainen sctx.ret == 0);
c307328f59c963eba21091ecd36c9435d42b47d8Timo Sirainen return sctx.ret;
c307328f59c963eba21091ecd36c9435d42b47d8Timo Sirainen}
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainenstatic int imapc_quota_refresh(struct imapc_quota_root *root)
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen{
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen enum imapc_capability capa;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen int ret;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen if (root->imapc_ns == NULL) {
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen /* imapc namespace is missing - disable this quota backend */
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen return 0;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen }
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen if (root->last_refresh.tv_sec == ioloop_timeval.tv_sec &&
678d0463849ba777106eb7875f27db07a5d8e3dfTimo Sirainen root->last_refresh.tv_usec == ioloop_timeval.tv_usec)
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen return 0;
678d0463849ba777106eb7875f27db07a5d8e3dfTimo Sirainen if (!imapc_quota_client_init(root))
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen return 0;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
985acc0cfd9184b3f4f4cfd6b9e5686a65226147Timo Sirainen if (imapc_client_get_capabilities(root->client->client, &capa) < 0)
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen return -1;
678d0463849ba777106eb7875f27db07a5d8e3dfTimo Sirainen if ((capa & IMAPC_CAPABILITY_QUOTA) == 0) {
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen /* no QUOTA capability - disable quota */
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen i_warning("quota: Remote IMAP server doesn't support QUOTA - disabling");
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen root->client = NULL;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen return 0;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen }
678d0463849ba777106eb7875f27db07a5d8e3dfTimo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen if (root->root_name == NULL)
678d0463849ba777106eb7875f27db07a5d8e3dfTimo Sirainen ret = imapc_quota_refresh_mailbox(root);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen else
678d0463849ba777106eb7875f27db07a5d8e3dfTimo Sirainen ret = imapc_quota_refresh_root(root);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen /* set the last_refresh only after the refresh, because it changes
678d0463849ba777106eb7875f27db07a5d8e3dfTimo Sirainen ioloop_timeval. */
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen root->last_refresh = ioloop_timeval;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen return ret;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen}
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainenstatic int imapc_quota_init_limits(struct quota_root *_root)
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen{
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen struct imapc_quota_root *root = (struct imapc_quota_root *)_root;
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen return imapc_quota_refresh(root);
7bd5b1c64cc987715bdaf8cc4907c3c37d5d7b29Timo Sirainen}
39ee82dad4d4fa61e3ed074d191afc6a9b82e249Timo Sirainen
39ee82dad4d4fa61e3ed074d191afc6a9b82e249Timo Sirainenstatic void
39ee82dad4d4fa61e3ed074d191afc6a9b82e249Timo Sirainenimapc_quota_namespace_added(struct quota *quota, struct mail_namespace *ns)
39ee82dad4d4fa61e3ed074d191afc6a9b82e249Timo Sirainen{
39ee82dad4d4fa61e3ed074d191afc6a9b82e249Timo Sirainen struct quota_root **roots;
39ee82dad4d4fa61e3ed074d191afc6a9b82e249Timo Sirainen unsigned int i, count;
2ac5f36aa7c2e7a07ba8815d43a6d7483f62e74cTimo Sirainen
39ee82dad4d4fa61e3ed074d191afc6a9b82e249Timo Sirainen roots = array_get_modifiable(&quota->roots, &count);
39ee82dad4d4fa61e3ed074d191afc6a9b82e249Timo Sirainen for (i = 0; i < count; i++) {
39ee82dad4d4fa61e3ed074d191afc6a9b82e249Timo Sirainen if (roots[i]->backend.name == quota_backend_imapc.name &&
39ee82dad4d4fa61e3ed074d191afc6a9b82e249Timo Sirainen ((roots[i]->ns_prefix == NULL &&
39ee82dad4d4fa61e3ed074d191afc6a9b82e249Timo Sirainen ns->type == MAIL_NAMESPACE_TYPE_PRIVATE) ||
39ee82dad4d4fa61e3ed074d191afc6a9b82e249Timo Sirainen roots[i]->ns == ns))
39ee82dad4d4fa61e3ed074d191afc6a9b82e249Timo Sirainen imapc_quota_root_namespace_added(roots[i], ns);
39ee82dad4d4fa61e3ed074d191afc6a9b82e249Timo Sirainen }
39ee82dad4d4fa61e3ed074d191afc6a9b82e249Timo Sirainen}
39ee82dad4d4fa61e3ed074d191afc6a9b82e249Timo Sirainen
39ee82dad4d4fa61e3ed074d191afc6a9b82e249Timo Sirainenstatic const char *const *
39ee82dad4d4fa61e3ed074d191afc6a9b82e249Timo Sirainenimapc_quota_root_get_resources(struct quota_root *root ATTR_UNUSED)
39ee82dad4d4fa61e3ed074d191afc6a9b82e249Timo Sirainen{
39ee82dad4d4fa61e3ed074d191afc6a9b82e249Timo Sirainen static const char *resources_both[] = {
39ee82dad4d4fa61e3ed074d191afc6a9b82e249Timo Sirainen QUOTA_NAME_STORAGE_KILOBYTES,
e83126866761632b437e532dfdc30be01d14039dTimo Sirainen QUOTA_NAME_MESSAGES,
39ee82dad4d4fa61e3ed074d191afc6a9b82e249Timo Sirainen NULL
39ee82dad4d4fa61e3ed074d191afc6a9b82e249Timo Sirainen };
39ee82dad4d4fa61e3ed074d191afc6a9b82e249Timo Sirainen return resources_both;
39ee82dad4d4fa61e3ed074d191afc6a9b82e249Timo Sirainen}
39ee82dad4d4fa61e3ed074d191afc6a9b82e249Timo Sirainen
39ee82dad4d4fa61e3ed074d191afc6a9b82e249Timo Sirainenstatic int
39ee82dad4d4fa61e3ed074d191afc6a9b82e249Timo Sirainenimapc_quota_get_resource(struct quota_root *_root, const char *name,
39ee82dad4d4fa61e3ed074d191afc6a9b82e249Timo Sirainen uint64_t *value_r)
39ee82dad4d4fa61e3ed074d191afc6a9b82e249Timo Sirainen{
39ee82dad4d4fa61e3ed074d191afc6a9b82e249Timo Sirainen struct imapc_quota_root *root = (struct imapc_quota_root *)_root;
39ee82dad4d4fa61e3ed074d191afc6a9b82e249Timo Sirainen
39ee82dad4d4fa61e3ed074d191afc6a9b82e249Timo Sirainen if (imapc_quota_refresh(root) < 0)
39ee82dad4d4fa61e3ed074d191afc6a9b82e249Timo Sirainen return -1;
39ee82dad4d4fa61e3ed074d191afc6a9b82e249Timo Sirainen
39ee82dad4d4fa61e3ed074d191afc6a9b82e249Timo Sirainen if (strcmp(name, QUOTA_NAME_STORAGE_BYTES) == 0)
39ee82dad4d4fa61e3ed074d191afc6a9b82e249Timo Sirainen *value_r = root->bytes_last;
39ee82dad4d4fa61e3ed074d191afc6a9b82e249Timo Sirainen else if (strcmp(name, QUOTA_NAME_MESSAGES) == 0)
39ee82dad4d4fa61e3ed074d191afc6a9b82e249Timo Sirainen *value_r = root->count_last;
39ee82dad4d4fa61e3ed074d191afc6a9b82e249Timo Sirainen else
39ee82dad4d4fa61e3ed074d191afc6a9b82e249Timo Sirainen return 0;
39ee82dad4d4fa61e3ed074d191afc6a9b82e249Timo Sirainen return 1;
39ee82dad4d4fa61e3ed074d191afc6a9b82e249Timo Sirainen}
39ee82dad4d4fa61e3ed074d191afc6a9b82e249Timo Sirainen
39ee82dad4d4fa61e3ed074d191afc6a9b82e249Timo Sirainenstatic int
39ee82dad4d4fa61e3ed074d191afc6a9b82e249Timo Sirainenimapc_quota_update(struct quota_root *root ATTR_UNUSED,
39ee82dad4d4fa61e3ed074d191afc6a9b82e249Timo Sirainen struct quota_transaction_context *ctx ATTR_UNUSED)
39ee82dad4d4fa61e3ed074d191afc6a9b82e249Timo Sirainen{
39ee82dad4d4fa61e3ed074d191afc6a9b82e249Timo Sirainen return 0;
39ee82dad4d4fa61e3ed074d191afc6a9b82e249Timo Sirainen}
39ee82dad4d4fa61e3ed074d191afc6a9b82e249Timo Sirainen
39ee82dad4d4fa61e3ed074d191afc6a9b82e249Timo Sirainenstruct quota_backend quota_backend_imapc = {
39ee82dad4d4fa61e3ed074d191afc6a9b82e249Timo Sirainen "imapc",
39ee82dad4d4fa61e3ed074d191afc6a9b82e249Timo Sirainen
39ee82dad4d4fa61e3ed074d191afc6a9b82e249Timo Sirainen {
39ee82dad4d4fa61e3ed074d191afc6a9b82e249Timo Sirainen imapc_quota_alloc,
39ee82dad4d4fa61e3ed074d191afc6a9b82e249Timo Sirainen imapc_quota_init,
39ee82dad4d4fa61e3ed074d191afc6a9b82e249Timo Sirainen imapc_quota_deinit,
39ee82dad4d4fa61e3ed074d191afc6a9b82e249Timo Sirainen NULL,
39ee82dad4d4fa61e3ed074d191afc6a9b82e249Timo Sirainen imapc_quota_init_limits,
39ee82dad4d4fa61e3ed074d191afc6a9b82e249Timo Sirainen imapc_quota_namespace_added,
39ee82dad4d4fa61e3ed074d191afc6a9b82e249Timo Sirainen imapc_quota_root_get_resources,
39ee82dad4d4fa61e3ed074d191afc6a9b82e249Timo Sirainen imapc_quota_get_resource,
39ee82dad4d4fa61e3ed074d191afc6a9b82e249Timo Sirainen imapc_quota_update,
39ee82dad4d4fa61e3ed074d191afc6a9b82e249Timo Sirainen NULL,
39ee82dad4d4fa61e3ed074d191afc6a9b82e249Timo Sirainen NULL
39ee82dad4d4fa61e3ed074d191afc6a9b82e249Timo Sirainen }
39ee82dad4d4fa61e3ed074d191afc6a9b82e249Timo Sirainen};
39ee82dad4d4fa61e3ed074d191afc6a9b82e249Timo Sirainen