dovecot-2.2: quota: Moved some functions to quota-util.c
dovecot at dovecot.org
dovecot at dovecot.org
Wed Jul 2 17:38:35 UTC 2014
details: http://hg.dovecot.org/dovecot-2.2/rev/0d4de84a54f0
changeset: 17565:0d4de84a54f0
user: Timo Sirainen <tss at iki.fi>
date: Wed Jul 02 20:34:43 2014 +0300
description:
quota: Moved some functions to quota-util.c
diffstat:
src/plugins/quota/Makefile.am | 4 +-
src/plugins/quota/quota-private.h | 12 +-
src/plugins/quota/quota-util.c | 401 ++++++++++++++++++++++++++++++++++++
src/plugins/quota/quota.c | 421 +------------------------------------
4 files changed, 426 insertions(+), 412 deletions(-)
diffs (truncated from 959 to 300 lines):
diff -r d77d880c1385 -r 0d4de84a54f0 src/plugins/quota/Makefile.am
--- a/src/plugins/quota/Makefile.am Wed Jul 02 20:13:35 2014 +0300
+++ b/src/plugins/quota/Makefile.am Wed Jul 02 20:34:43 2014 +0300
@@ -29,7 +29,8 @@
quota-dirsize.c \
quota-maildir.c \
quota-plugin.c \
- quota-storage.c
+ quota-storage.c \
+ quota-util.c
quota_common_objects = \
quota.lo \
@@ -40,6 +41,7 @@
quota-maildir.lo \
quota-plugin.lo \
quota-storage.lo \
+ quota-util.lo \
$(RQUOTA_XDR_LO)
lib10_quota_plugin_la_SOURCES = $(quota_dist_sources)
diff -r d77d880c1385 -r 0d4de84a54f0 src/plugins/quota/quota-private.h
--- a/src/plugins/quota/quota-private.h Wed Jul 02 20:13:35 2014 +0300
+++ b/src/plugins/quota/quota-private.h Wed Jul 02 20:34:43 2014 +0300
@@ -150,8 +150,9 @@
after the first allocation is done, bytes_ceil is set to
bytes_ceil2. */
uint64_t bytes_ceil, bytes_ceil2, count_ceil;
- /* how many bytes/mails we are over quota (either *_ceil or *_over
- is always zero) */
+ /* How many bytes/mails we are over quota. Like *_ceil, these are set
+ only once and not updated by bytes_used/count_used. (Either *_ceil
+ or *_over is always zero.) */
uint64_t bytes_over, count_over;
struct mail *tmp_mail;
@@ -178,4 +179,11 @@
int64_t count_limit);
int quota_count(struct quota_root *root, uint64_t *bytes_r, uint64_t *count_r);
+int quota_root_parse_grace(struct quota_root_settings *root_set,
+ const char *value, const char **error_r);
+bool quota_warning_match(const struct quota_warning_rule *w,
+ uint64_t bytes_before, uint64_t bytes_current,
+ uint64_t count_before, uint64_t count_current);
+bool quota_transaction_is_over(struct quota_transaction_context *ctx, uoff_t size);
+
#endif
diff -r d77d880c1385 -r 0d4de84a54f0 src/plugins/quota/quota-util.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/plugins/quota/quota-util.c Wed Jul 02 20:34:43 2014 +0300
@@ -0,0 +1,401 @@
+/* Copyright (c) 2005-2014 Dovecot authors, see the included COPYING file */
+
+#include "lib.h"
+#include "wildcard-match.h"
+#include "quota-private.h"
+
+#include <ctype.h>
+#include <stdlib.h>
+
+#define QUOTA_DEFAULT_GRACE "10%"
+
+#define RULE_NAME_DEFAULT_FORCE "*"
+#define RULE_NAME_DEFAULT_NONFORCE "?"
+
+struct quota_rule *
+quota_root_rule_find(struct quota_root_settings *root_set, const char *name)
+{
+ struct quota_rule *rule;
+
+ array_foreach_modifiable(&root_set->rules, rule) {
+ if (wildcard_match(name, rule->mailbox_mask))
+ return rule;
+ }
+ return NULL;
+}
+
+static struct quota_rule *
+quota_root_rule_find_exact(struct quota_root_settings *root_set,
+ const char *name)
+{
+ struct quota_rule *rule;
+
+ array_foreach_modifiable(&root_set->rules, rule) {
+ if (strcmp(rule->mailbox_mask, name) == 0)
+ return rule;
+ }
+ return NULL;
+}
+
+static int
+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 <= -100 || percentage >= UINT_MAX) {
+ *error_r = "Invalid percentage";
+ return -1;
+ }
+
+ if (rule == &root_set->default_rule) {
+ *error_r = "Default rule can't be a percentage";
+ return -1;
+ }
+
+ if (limit == &rule->bytes_limit)
+ rule->bytes_percent = percentage;
+ else if (limit == &rule->count_limit)
+ rule->count_percent = percentage;
+ else
+ i_unreached();
+ return 0;
+}
+
+static int quota_limit_parse(struct quota_root_settings *root_set,
+ struct quota_rule *rule, const char *unit,
+ uint64_t multiply, int64_t *limit,
+ const char **error_r)
+{
+ switch (i_toupper(*unit)) {
+ case '\0':
+ /* default */
+ break;
+ case 'B':
+ multiply = 1;
+ break;
+ case 'K':
+ multiply = 1024;
+ break;
+ case 'M':
+ multiply = 1024*1024;
+ break;
+ case 'G':
+ multiply = 1024*1024*1024;
+ break;
+ case 'T':
+ multiply = 1024ULL*1024*1024*1024;
+ break;
+ case '%':
+ multiply = 0;
+ if (quota_rule_parse_percentage(root_set, rule, limit,
+ error_r) < 0)
+ return -1;
+ break;
+ default:
+ *error_r = t_strdup_printf("Unknown unit: %s", unit);
+ return -1;
+ }
+ *limit *= multiply;
+ return 0;
+}
+
+static void
+quota_rule_recalculate_relative_rules(struct quota_rule *rule,
+ int64_t bytes_limit, int64_t count_limit)
+{
+ if (rule->bytes_percent != 0)
+ rule->bytes_limit = bytes_limit * rule->bytes_percent / 100;
+ if (rule->count_percent != 0)
+ rule->count_limit = count_limit * rule->count_percent / 100;
+}
+
+void quota_root_recalculate_relative_rules(struct quota_root_settings *root_set,
+ int64_t bytes_limit,
+ int64_t count_limit)
+{
+ struct quota_rule *rule;
+ struct quota_warning_rule *warning_rule;
+
+ array_foreach_modifiable(&root_set->rules, rule) {
+ quota_rule_recalculate_relative_rules(rule, bytes_limit,
+ count_limit);
+ }
+
+ array_foreach_modifiable(&root_set->warning_rules, warning_rule) {
+ quota_rule_recalculate_relative_rules(&warning_rule->rule,
+ bytes_limit, count_limit);
+ }
+ quota_rule_recalculate_relative_rules(&root_set->grace_rule,
+ bytes_limit, 0);
+ root_set->last_mail_max_extra_bytes = root_set->grace_rule.bytes_limit;
+
+ if (root_set->set->debug && root_set->set->initialized) {
+ i_debug("Quota root %s: Recalculated relative rules with "
+ "bytes=%lld count=%lld. Now grace=%llu", root_set->name,
+ (long long)bytes_limit, (long long)count_limit,
+ (unsigned long long)root_set->last_mail_max_extra_bytes);
+ }
+}
+
+static int
+quota_rule_parse_limits(struct quota_root_settings *root_set,
+ struct quota_rule *rule, const char *limits,
+ const char *full_rule_def,
+ bool relative_rule, const char **error_r)
+{
+ const char **args, *key, *value, *error;
+ char *p;
+ uint64_t multiply;
+ int64_t *limit;
+
+ args = t_strsplit(limits, ":");
+ for (; *args != NULL; args++) {
+ multiply = 1;
+ limit = NULL;
+
+ key = *args;
+ value = strchr(key, '=');
+ if (value == NULL)
+ value = "";
+ else
+ key = t_strdup_until(key, value++);
+
+ if (*value == '+') {
+ if (!relative_rule) {
+ *error_r = "Rule limit cannot have '+'";
+ return -1;
+ }
+ value++;
+ } else if (*value != '-' && relative_rule) {
+ i_warning("quota root %s rule %s: "
+ "obsolete configuration for rule '%s' "
+ "should be changed to '%s=+%s'",
+ root_set->name, full_rule_def,
+ *args, key, value);
+ }
+
+ if (strcmp(key, "storage") == 0) {
+ multiply = 1024;
+ limit = &rule->bytes_limit;
+ *limit = strtoll(value, &p, 10);
+ } else if (strcmp(key, "bytes") == 0) {
+ limit = &rule->bytes_limit;
+ *limit = strtoll(value, &p, 10);
+ } else if (strcmp(key, "messages") == 0) {
+ limit = &rule->count_limit;
+ *limit = strtoll(value, &p, 10);
+ } else {
+ *error_r = p_strdup_printf(root_set->set->pool,
+ "Unknown rule limit name: %s", key);
+ return -1;
+ }
+
+ if (quota_limit_parse(root_set, rule, p, multiply,
+ limit, &error) < 0) {
+ *error_r = p_strdup_printf(root_set->set->pool,
+ "Invalid rule limit value '%s': %s",
+ *args, error);
+ return -1;
+ }
+ }
+ if (!relative_rule) {
+ if (rule->bytes_limit < 0) {
+ *error_r = "Bytes limit can't be negative";
+ return -1;
+ }
+ if (rule->count_limit < 0) {
+ *error_r = "Count limit can't be negative";
+ return -1;
+ }
+ }
+ return 0;
+}
+
+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_mask;
+ int ret = 0;
+
+ p = strchr(rule_def, ':');
+ if (p == NULL) {
+ *error_r = "Invalid rule";
+ return -1;
+ }
+
+ /* <mailbox mask>:<quota limits> */
+ mailbox_mask = t_strdup_until(rule_def, p++);
+
+ rule = quota_root_rule_find_exact(root_set, mailbox_mask);
+ if (rule == NULL) {
+ if (strcmp(mailbox_mask, RULE_NAME_DEFAULT_NONFORCE) == 0)
+ rule = &root_set->default_rule;
+ else if (strcmp(mailbox_mask, RULE_NAME_DEFAULT_FORCE) == 0) {
+ rule = &root_set->default_rule;
+ root_set->force_default_rule = TRUE;
+ } else {
+ rule = array_append_space(&root_set->rules);
+ rule->mailbox_mask = strcasecmp(mailbox_mask, "INBOX") == 0 ? "INBOX" :
+ p_strdup(root_set->set->pool, mailbox_mask);
+ }
+ }
+
+ if (strcmp(p, "ignore") == 0) {
+ rule->ignore = TRUE;
+ if (root_set->set->debug) {
More information about the dovecot-cvs
mailing list