bcb4e51a409d94ae670de96afb8483a4f7855294Stephan Bosch/* Copyright (c) 2005-2018 Dovecot authors, see the included COPYING file */
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen#include "lib.h"
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen#include "wildcard-match.h"
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen#include "quota-private.h"
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen#include <ctype.h>
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen#define QUOTA_DEFAULT_GRACE "10%"
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen#define RULE_NAME_DEFAULT_FORCE "*"
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen#define RULE_NAME_DEFAULT_NONFORCE "?"
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainenstruct quota_rule *
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainenquota_root_rule_find(struct quota_root_settings *root_set, const char *name)
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen{
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen struct quota_rule *rule;
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen array_foreach_modifiable(&root_set->rules, rule) {
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen if (wildcard_match(name, rule->mailbox_mask))
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen return rule;
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen }
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen return NULL;
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen}
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainenstatic struct quota_rule *
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainenquota_root_rule_find_exact(struct quota_root_settings *root_set,
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen const char *name)
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen{
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen struct quota_rule *rule;
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen array_foreach_modifiable(&root_set->rules, rule) {
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen if (strcmp(rule->mailbox_mask, name) == 0)
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen return rule;
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen }
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen return NULL;
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen}
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainenstatic int
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainenquota_rule_parse_percentage(struct quota_root_settings *root_set,
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen struct quota_rule *rule,
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen int64_t *limit, const char **error_r)
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen{
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen int64_t percentage = *limit;
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen if (percentage <= -100 || percentage >= UINT_MAX) {
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen *error_r = "Invalid percentage";
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen return -1;
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen }
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen if (rule == &root_set->default_rule) {
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen *error_r = "Default rule can't be a percentage";
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen return -1;
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen }
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen if (limit == &rule->bytes_limit)
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen rule->bytes_percent = percentage;
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen else if (limit == &rule->count_limit)
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen rule->count_percent = percentage;
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen else
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen i_unreached();
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen return 0;
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen}
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainenstatic int quota_limit_parse(struct quota_root_settings *root_set,
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen struct quota_rule *rule, const char *unit,
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen uint64_t multiply, int64_t *limit,
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen const char **error_r)
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen{
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen switch (i_toupper(*unit)) {
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen case '\0':
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen /* default */
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen break;
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen case 'B':
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen multiply = 1;
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen break;
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen case 'K':
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen multiply = 1024;
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen break;
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen case 'M':
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen multiply = 1024*1024;
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen break;
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen case 'G':
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen multiply = 1024*1024*1024;
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen break;
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen case 'T':
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen multiply = 1024ULL*1024*1024*1024;
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen break;
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen case '%':
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen multiply = 0;
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen if (quota_rule_parse_percentage(root_set, rule, limit,
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen error_r) < 0)
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen return -1;
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen break;
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen default:
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen *error_r = t_strdup_printf("Unknown unit: %s", unit);
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen return -1;
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen }
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen *limit *= multiply;
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen return 0;
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen}
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainenstatic void
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainenquota_rule_recalculate_relative_rules(struct quota_rule *rule,
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen int64_t bytes_limit, int64_t count_limit)
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen{
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen if (rule->bytes_percent != 0)
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen rule->bytes_limit = bytes_limit * rule->bytes_percent / 100;
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen if (rule->count_percent != 0)
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen rule->count_limit = count_limit * rule->count_percent / 100;
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen}
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainenvoid quota_root_recalculate_relative_rules(struct quota_root_settings *root_set,
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen int64_t bytes_limit,
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen int64_t count_limit)
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen{
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen struct quota_rule *rule;
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen struct quota_warning_rule *warning_rule;
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen array_foreach_modifiable(&root_set->rules, rule) {
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen quota_rule_recalculate_relative_rules(rule, bytes_limit,
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen count_limit);
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen }
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen array_foreach_modifiable(&root_set->warning_rules, warning_rule) {
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen quota_rule_recalculate_relative_rules(&warning_rule->rule,
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen bytes_limit, count_limit);
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen }
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen quota_rule_recalculate_relative_rules(&root_set->grace_rule,
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen bytes_limit, 0);
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen root_set->last_mail_max_extra_bytes = root_set->grace_rule.bytes_limit;
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen if (root_set->set->debug && root_set->set->initialized) {
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen i_debug("Quota root %s: Recalculated relative rules with "
47a5a7e8296f3b8f2fac9a0659d4de3f2723ba4aMartti Rannanjärvi "bytes=%lld count=%lld. Now grace=%"PRIu64, root_set->name,
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen (long long)bytes_limit, (long long)count_limit,
47a5a7e8296f3b8f2fac9a0659d4de3f2723ba4aMartti Rannanjärvi root_set->last_mail_max_extra_bytes);
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen }
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen}
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainenstatic int
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainenquota_rule_parse_limits(struct quota_root_settings *root_set,
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen struct quota_rule *rule, const char *limits,
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen const char *full_rule_def,
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen bool relative_rule, const char **error_r)
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen{
e48f289d2e5b2546a2c5dcc90f7ab624cc58cca2Stephan Bosch const char **args, *key, *value, *error, *p;
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen uint64_t multiply;
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen int64_t *limit;
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen args = t_strsplit(limits, ":");
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen for (; *args != NULL; args++) {
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen multiply = 1;
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen limit = NULL;
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen key = *args;
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen value = strchr(key, '=');
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen if (value == NULL)
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen value = "";
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen else
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen key = t_strdup_until(key, value++);
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen if (*value == '+') {
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen if (!relative_rule) {
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen *error_r = "Rule limit cannot have '+'";
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen return -1;
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen }
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen value++;
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen } else if (*value != '-' && relative_rule) {
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen i_warning("quota root %s rule %s: "
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen "obsolete configuration for rule '%s' "
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen "should be changed to '%s=+%s'",
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen root_set->name, full_rule_def,
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen *args, key, value);
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen }
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen if (strcmp(key, "storage") == 0) {
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen multiply = 1024;
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen limit = &rule->bytes_limit;
e48f289d2e5b2546a2c5dcc90f7ab624cc58cca2Stephan Bosch if (str_parse_int64(value, limit, &p) < 0) {
e48f289d2e5b2546a2c5dcc90f7ab624cc58cca2Stephan Bosch *error_r = p_strdup_printf(root_set->set->pool,
e48f289d2e5b2546a2c5dcc90f7ab624cc58cca2Stephan Bosch "Invalid storage limit: %s", value);
e48f289d2e5b2546a2c5dcc90f7ab624cc58cca2Stephan Bosch return -1;
e48f289d2e5b2546a2c5dcc90f7ab624cc58cca2Stephan Bosch }
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen } else if (strcmp(key, "bytes") == 0) {
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen limit = &rule->bytes_limit;
e48f289d2e5b2546a2c5dcc90f7ab624cc58cca2Stephan Bosch if (str_parse_int64(value, limit, &p) < 0) {
e48f289d2e5b2546a2c5dcc90f7ab624cc58cca2Stephan Bosch *error_r = p_strdup_printf(root_set->set->pool,
e48f289d2e5b2546a2c5dcc90f7ab624cc58cca2Stephan Bosch "Invalid bytes limit: %s", value);
e48f289d2e5b2546a2c5dcc90f7ab624cc58cca2Stephan Bosch return -1;
e48f289d2e5b2546a2c5dcc90f7ab624cc58cca2Stephan Bosch }
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen } else if (strcmp(key, "messages") == 0) {
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen limit = &rule->count_limit;
e48f289d2e5b2546a2c5dcc90f7ab624cc58cca2Stephan Bosch if (str_parse_int64(value, limit, &p) < 0) {
e48f289d2e5b2546a2c5dcc90f7ab624cc58cca2Stephan Bosch *error_r = p_strdup_printf(root_set->set->pool,
e48f289d2e5b2546a2c5dcc90f7ab624cc58cca2Stephan Bosch "Invalid bytes messages: %s", value);
e48f289d2e5b2546a2c5dcc90f7ab624cc58cca2Stephan Bosch return -1;
e48f289d2e5b2546a2c5dcc90f7ab624cc58cca2Stephan Bosch }
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen } else {
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen *error_r = p_strdup_printf(root_set->set->pool,
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen "Unknown rule limit name: %s", key);
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen return -1;
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen }
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen if (quota_limit_parse(root_set, rule, p, multiply,
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen limit, &error) < 0) {
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen *error_r = p_strdup_printf(root_set->set->pool,
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen "Invalid rule limit value '%s': %s",
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen *args, error);
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen return -1;
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen }
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen }
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen if (!relative_rule) {
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen if (rule->bytes_limit < 0) {
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen *error_r = "Bytes limit can't be negative";
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen return -1;
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen }
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen if (rule->count_limit < 0) {
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen *error_r = "Count limit can't be negative";
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen return -1;
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen }
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen }
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen return 0;
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen}
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainenint quota_root_add_rule(struct quota_root_settings *root_set,
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen const char *rule_def, const char **error_r)
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen{
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen struct quota_rule *rule;
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen const char *p, *mailbox_mask;
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen int ret = 0;
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen p = strchr(rule_def, ':');
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen if (p == NULL) {
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen *error_r = "Invalid rule";
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen return -1;
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen }
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen /* <mailbox mask>:<quota limits> */
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen mailbox_mask = t_strdup_until(rule_def, p++);
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen rule = quota_root_rule_find_exact(root_set, mailbox_mask);
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen if (rule == NULL) {
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen if (strcmp(mailbox_mask, RULE_NAME_DEFAULT_NONFORCE) == 0)
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen rule = &root_set->default_rule;
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen else if (strcmp(mailbox_mask, RULE_NAME_DEFAULT_FORCE) == 0) {
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen rule = &root_set->default_rule;
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen root_set->force_default_rule = TRUE;
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen } else {
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen rule = array_append_space(&root_set->rules);
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen rule->mailbox_mask = strcasecmp(mailbox_mask, "INBOX") == 0 ? "INBOX" :
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen p_strdup(root_set->set->pool, mailbox_mask);
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen }
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen }
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen if (strcmp(p, "ignore") == 0) {
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen rule->ignore = TRUE;
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen if (root_set->set->debug) {
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen i_debug("Quota rule: root=%s mailbox=%s ignored",
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen root_set->name, mailbox_mask);
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen }
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen return 0;
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen }
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen if (strncmp(p, "backend=", 8) == 0) {
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen if (root_set->backend->v.parse_rule == NULL) {
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen *error_r = "backend rule not supported";
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen ret = -1;
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen } else if (!root_set->backend->v.parse_rule(root_set, rule,
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen p + 8, error_r))
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen ret = -1;
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen } else {
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen bool relative_rule = rule != &root_set->default_rule;
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen if (quota_rule_parse_limits(root_set, rule, p, rule_def,
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen relative_rule, error_r) < 0)
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen ret = -1;
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen }
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen quota_root_recalculate_relative_rules(root_set,
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen root_set->default_rule.bytes_limit,
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen root_set->default_rule.count_limit);
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen if (root_set->set->debug) {
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen const char *rule_plus =
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen rule == &root_set->default_rule ? "" : "+";
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen i_debug("Quota rule: root=%s mailbox=%s "
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen "bytes=%s%lld%s messages=%s%lld%s",
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen root_set->name, mailbox_mask,
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen rule->bytes_limit > 0 ? rule_plus : "",
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen (long long)rule->bytes_limit,
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen rule->bytes_percent == 0 ? "" :
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen t_strdup_printf(" (%u%%)", rule->bytes_percent),
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen rule->count_limit > 0 ? rule_plus : "",
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen (long long)rule->count_limit,
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen rule->count_percent == 0 ? "" :
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen t_strdup_printf(" (%u%%)", rule->count_percent));
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen }
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen return ret;
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen}
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainenint quota_root_add_warning_rule(struct quota_root_settings *root_set,
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen const char *rule_def, const char **error_r)
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen{
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen struct quota_warning_rule *warning;
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen struct quota_rule rule;
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen const char *p, *q;
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen int ret;
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen bool reverse = FALSE;
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen p = strchr(rule_def, ' ');
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen if (p == NULL || p[1] == '\0') {
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen *error_r = "No command specified";
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen return -1;
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen }
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen if (*rule_def == '+') {
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen /* warn when exceeding quota */
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen q = rule_def+1;
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen } else if (*rule_def == '-') {
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen /* warn when going below quota */
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen q = rule_def+1;
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen reverse = TRUE;
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen } else {
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen /* default: same as '+' */
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen q = rule_def;
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen }
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen
efe78d3ba24fc866af1c79b9223dc0809ba26cadStephan Bosch i_zero(&rule);
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen ret = quota_rule_parse_limits(root_set, &rule, t_strdup_until(q, p),
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen rule_def, FALSE, error_r);
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen if (ret < 0)
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen return -1;
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen warning = array_append_space(&root_set->warning_rules);
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen warning->command = p_strdup(root_set->set->pool, p+1);
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen warning->rule = rule;
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen warning->reverse = reverse;
10207755f33a4cf1a1e901968137ae4f2bc93bbfTimo Sirainen if (reverse)
10207755f33a4cf1a1e901968137ae4f2bc93bbfTimo Sirainen root_set->have_reverse_warnings = TRUE;
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen quota_root_recalculate_relative_rules(root_set,
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen root_set->default_rule.bytes_limit,
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen root_set->default_rule.count_limit);
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen if (root_set->set->debug) {
47a5a7e8296f3b8f2fac9a0659d4de3f2723ba4aMartti Rannanjärvi i_debug("Quota warning: bytes=%"PRId64"%s "
47a5a7e8296f3b8f2fac9a0659d4de3f2723ba4aMartti Rannanjärvi "messages=%"PRId64"%s reverse=%s command=%s",
47a5a7e8296f3b8f2fac9a0659d4de3f2723ba4aMartti Rannanjärvi warning->rule.bytes_limit,
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen warning->rule.bytes_percent == 0 ? "" :
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen t_strdup_printf(" (%u%%)", warning->rule.bytes_percent),
47a5a7e8296f3b8f2fac9a0659d4de3f2723ba4aMartti Rannanjärvi warning->rule.count_limit,
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen warning->rule.count_percent == 0 ? "" :
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen t_strdup_printf(" (%u%%)", warning->rule.count_percent),
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen warning->reverse ? "yes" : "no",
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen warning->command);
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen }
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen return 0;
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen}
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainenint quota_root_parse_grace(struct quota_root_settings *root_set,
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen const char *value, const char **error_r)
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen{
e48f289d2e5b2546a2c5dcc90f7ab624cc58cca2Stephan Bosch const char *p;
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen if (value == NULL) {
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen /* default */
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen value = QUOTA_DEFAULT_GRACE;
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen }
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen
e48f289d2e5b2546a2c5dcc90f7ab624cc58cca2Stephan Bosch if (str_parse_int64(value, &root_set->grace_rule.bytes_limit, &p) < 0)
e48f289d2e5b2546a2c5dcc90f7ab624cc58cca2Stephan Bosch return -1;
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen if (quota_limit_parse(root_set, &root_set->grace_rule, p, 1,
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen &root_set->grace_rule.bytes_limit, error_r) < 0)
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen return -1;
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen quota_rule_recalculate_relative_rules(&root_set->grace_rule,
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen root_set->default_rule.bytes_limit, 0);
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen root_set->last_mail_max_extra_bytes = root_set->grace_rule.bytes_limit;
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen if (root_set->set->debug) {
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen i_debug("Quota grace: root=%s bytes=%lld%s",
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen root_set->name, (long long)root_set->grace_rule.bytes_limit,
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen root_set->grace_rule.bytes_percent == 0 ? "" :
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen t_strdup_printf(" (%u%%)", root_set->grace_rule.bytes_percent));
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen }
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen return 0;
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen}
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainenbool quota_warning_match(const struct quota_warning_rule *w,
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen uint64_t bytes_before, uint64_t bytes_current,
f97866381675fe12cdab0f2d56a059fe7b88457aTimo Sirainen uint64_t count_before, uint64_t count_current,
f97866381675fe12cdab0f2d56a059fe7b88457aTimo Sirainen const char **reason_r)
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen{
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen#define QUOTA_EXCEEDED(before, current, limit) \
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen ((before) < (uint64_t)(limit) && (current) >= (uint64_t)(limit))
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen if (!w->reverse) {
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen /* over quota (default) */
f97866381675fe12cdab0f2d56a059fe7b88457aTimo Sirainen if (QUOTA_EXCEEDED(bytes_before, bytes_current, w->rule.bytes_limit)) {
47a5a7e8296f3b8f2fac9a0659d4de3f2723ba4aMartti Rannanjärvi *reason_r = t_strdup_printf("bytes=%"PRIu64" -> %"PRIu64" over limit %"PRId64,
47a5a7e8296f3b8f2fac9a0659d4de3f2723ba4aMartti Rannanjärvi bytes_before, bytes_current, w->rule.bytes_limit);
f97866381675fe12cdab0f2d56a059fe7b88457aTimo Sirainen return TRUE;
f97866381675fe12cdab0f2d56a059fe7b88457aTimo Sirainen }
f97866381675fe12cdab0f2d56a059fe7b88457aTimo Sirainen if (QUOTA_EXCEEDED(count_before, count_current, w->rule.count_limit)) {
47a5a7e8296f3b8f2fac9a0659d4de3f2723ba4aMartti Rannanjärvi *reason_r = t_strdup_printf("count=%"PRIu64" -> %"PRIu64" over limit %"PRId64,
47a5a7e8296f3b8f2fac9a0659d4de3f2723ba4aMartti Rannanjärvi count_before, count_current, w->rule.count_limit);
f97866381675fe12cdab0f2d56a059fe7b88457aTimo Sirainen return TRUE;
f97866381675fe12cdab0f2d56a059fe7b88457aTimo Sirainen }
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen } else {
f97866381675fe12cdab0f2d56a059fe7b88457aTimo Sirainen if (QUOTA_EXCEEDED(bytes_current, bytes_before, w->rule.bytes_limit)) {
47a5a7e8296f3b8f2fac9a0659d4de3f2723ba4aMartti Rannanjärvi *reason_r = t_strdup_printf("bytes=%"PRIu64" -> %"PRIu64" below limit %"PRId64,
47a5a7e8296f3b8f2fac9a0659d4de3f2723ba4aMartti Rannanjärvi bytes_before, bytes_current, w->rule.bytes_limit);
f97866381675fe12cdab0f2d56a059fe7b88457aTimo Sirainen return TRUE;
f97866381675fe12cdab0f2d56a059fe7b88457aTimo Sirainen }
f97866381675fe12cdab0f2d56a059fe7b88457aTimo Sirainen if (QUOTA_EXCEEDED(count_current, count_before, w->rule.count_limit)) {
47a5a7e8296f3b8f2fac9a0659d4de3f2723ba4aMartti Rannanjärvi *reason_r = t_strdup_printf("count=%"PRIu64" -> %"PRIu64" below limit %"PRId64,
47a5a7e8296f3b8f2fac9a0659d4de3f2723ba4aMartti Rannanjärvi count_before, count_current, w->rule.count_limit);
f97866381675fe12cdab0f2d56a059fe7b88457aTimo Sirainen return TRUE;
f97866381675fe12cdab0f2d56a059fe7b88457aTimo Sirainen }
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen }
f97866381675fe12cdab0f2d56a059fe7b88457aTimo Sirainen return FALSE;
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen}
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainenbool quota_transaction_is_over(struct quota_transaction_context *ctx,
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen uoff_t size)
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen{
de02255bbe97d5d5c54ca1054bb7c9304ee025a1Timo Sirainen if (ctx->count_used < 0) {
de02255bbe97d5d5c54ca1054bb7c9304ee025a1Timo Sirainen /* we've deleted some messages. we should be ok, unless we
de02255bbe97d5d5c54ca1054bb7c9304ee025a1Timo Sirainen were already over quota and still are after these
de02255bbe97d5d5c54ca1054bb7c9304ee025a1Timo Sirainen deletions. */
1774ab4b71e7fcec670e7bae24a4a5b95738f560Timo Sirainen const uint64_t count_deleted = (uint64_t)-ctx->count_used;
1774ab4b71e7fcec670e7bae24a4a5b95738f560Timo Sirainen
de02255bbe97d5d5c54ca1054bb7c9304ee025a1Timo Sirainen if (ctx->count_over > 0) {
1774ab4b71e7fcec670e7bae24a4a5b95738f560Timo Sirainen if (count_deleted - 1 < ctx->count_over)
de02255bbe97d5d5c54ca1054bb7c9304ee025a1Timo Sirainen return TRUE;
de02255bbe97d5d5c54ca1054bb7c9304ee025a1Timo Sirainen }
de02255bbe97d5d5c54ca1054bb7c9304ee025a1Timo Sirainen } else {
de02255bbe97d5d5c54ca1054bb7c9304ee025a1Timo Sirainen if (ctx->count_ceil < 1 ||
de02255bbe97d5d5c54ca1054bb7c9304ee025a1Timo Sirainen ctx->count_ceil - 1 < (uint64_t)ctx->count_used) {
de02255bbe97d5d5c54ca1054bb7c9304ee025a1Timo Sirainen /* count limit reached */
de02255bbe97d5d5c54ca1054bb7c9304ee025a1Timo Sirainen return TRUE;
de02255bbe97d5d5c54ca1054bb7c9304ee025a1Timo Sirainen }
de02255bbe97d5d5c54ca1054bb7c9304ee025a1Timo Sirainen }
de02255bbe97d5d5c54ca1054bb7c9304ee025a1Timo Sirainen
de02255bbe97d5d5c54ca1054bb7c9304ee025a1Timo Sirainen if (ctx->bytes_used < 0) {
de02255bbe97d5d5c54ca1054bb7c9304ee025a1Timo Sirainen const uint64_t bytes_deleted = (uint64_t)-ctx->bytes_used;
de02255bbe97d5d5c54ca1054bb7c9304ee025a1Timo Sirainen
de02255bbe97d5d5c54ca1054bb7c9304ee025a1Timo Sirainen /* we've deleted some messages. same logic as above. */
de02255bbe97d5d5c54ca1054bb7c9304ee025a1Timo Sirainen if (ctx->bytes_over > 0) {
de02255bbe97d5d5c54ca1054bb7c9304ee025a1Timo Sirainen if (ctx->bytes_over > bytes_deleted) {
de02255bbe97d5d5c54ca1054bb7c9304ee025a1Timo Sirainen /* even after deletions we're over quota */
de02255bbe97d5d5c54ca1054bb7c9304ee025a1Timo Sirainen return TRUE;
de02255bbe97d5d5c54ca1054bb7c9304ee025a1Timo Sirainen }
de02255bbe97d5d5c54ca1054bb7c9304ee025a1Timo Sirainen if (size > bytes_deleted - ctx->bytes_over)
de02255bbe97d5d5c54ca1054bb7c9304ee025a1Timo Sirainen return TRUE;
de02255bbe97d5d5c54ca1054bb7c9304ee025a1Timo Sirainen } else {
de02255bbe97d5d5c54ca1054bb7c9304ee025a1Timo Sirainen if (size > bytes_deleted &&
de02255bbe97d5d5c54ca1054bb7c9304ee025a1Timo Sirainen size - bytes_deleted < ctx->bytes_ceil)
de02255bbe97d5d5c54ca1054bb7c9304ee025a1Timo Sirainen return TRUE;
de02255bbe97d5d5c54ca1054bb7c9304ee025a1Timo Sirainen }
de02255bbe97d5d5c54ca1054bb7c9304ee025a1Timo Sirainen } else if (size == 0) {
de02255bbe97d5d5c54ca1054bb7c9304ee025a1Timo Sirainen /* we need to explicitly test this case, since the generic
de02255bbe97d5d5c54ca1054bb7c9304ee025a1Timo Sirainen check would fail if user is already over quota */
de02255bbe97d5d5c54ca1054bb7c9304ee025a1Timo Sirainen if (ctx->bytes_over > 0)
de02255bbe97d5d5c54ca1054bb7c9304ee025a1Timo Sirainen return TRUE;
de02255bbe97d5d5c54ca1054bb7c9304ee025a1Timo Sirainen } else {
de02255bbe97d5d5c54ca1054bb7c9304ee025a1Timo Sirainen if (ctx->bytes_ceil < size ||
de02255bbe97d5d5c54ca1054bb7c9304ee025a1Timo Sirainen ctx->bytes_ceil - size < (uint64_t)ctx->bytes_used) {
de02255bbe97d5d5c54ca1054bb7c9304ee025a1Timo Sirainen /* bytes limit reached */
de02255bbe97d5d5c54ca1054bb7c9304ee025a1Timo Sirainen return TRUE;
de02255bbe97d5d5c54ca1054bb7c9304ee025a1Timo Sirainen }
de02255bbe97d5d5c54ca1054bb7c9304ee025a1Timo Sirainen }
de02255bbe97d5d5c54ca1054bb7c9304ee025a1Timo Sirainen return FALSE;
b863b7e3fccf75f90f613b875f02fd1781e14e5eTimo Sirainen}