dovecot/dovecot-1.0.rc27-quota-warning.patch
2007-09-25 13:05:58 +00:00

264 lines
7.7 KiB
Diff

http://dovecot.org/list/dovecot/2007-April/021429.html
diff -ru dovecot-1.0.rc27.orig/src/plugins/quota/quota-plugin.c dovecot-1.0.rc27/src/plugins/quota/quota-plugin.c
--- dovecot-1.0.rc27.orig/src/plugins/quota/quota-plugin.c 2007-03-06 17:34:47.000000000 +0100
+++ dovecot-1.0.rc27/src/plugins/quota/quota-plugin.c 2007-03-31 22:18:55.000000000 +0200
@@ -21,9 +21,24 @@
env = getenv("QUOTA");
if (env != NULL) {
+ struct quota_setup *setup;
+ const char *name;
+ unsigned int i;
quota_set = quota_init();
/* Currently we support only one quota setup */
- (void)quota_setup_init(quota_set, env, TRUE);
+ setup = quota_setup_init(quota_set, env, TRUE);
+
+ name = "QUOTA_WARNING";
+ env = getenv(name);
+ i = 1;
+ t_push();
+ while (env != NULL) {
+ (void)quota_warning_init(setup, env);
+
+ name = t_strdup_printf("QUOTA_WARNING%u", ++i);
+ env = getenv(name);
+ }
+ t_pop();
quota_next_hook_mail_storage_created =
hook_mail_storage_created;
diff -ru dovecot-1.0.rc27.orig/src/plugins/quota/quota-private.h dovecot-1.0.rc27/src/plugins/quota/quota-private.h
--- dovecot-1.0.rc27.orig/src/plugins/quota/quota-private.h 2007-03-12 21:34:50.000000000 +0100
+++ dovecot-1.0.rc27/src/plugins/quota/quota-private.h 2007-03-17 00:06:23.000000000 +0100
@@ -22,6 +22,9 @@
/* List of quota roots. It's array because there shouldn't be many. */
array_t ARRAY_DEFINE(roots, struct quota_root *);
+ /* List of quota warnings. There should probably be few. */
+ array_t ARRAY_DEFINE(warnings, struct quota_warning *);
+
unsigned int user_root:1;
};
@@ -86,6 +89,21 @@
unsigned int idx;
};
+enum quota_warning_limit_kind {
+ QUOTA_WARNING_NO_LIMIT,
+ QUOTA_WARNING_PERCENT_LIMIT,
+ QUOTA_WARNING_ABSOLUTE_LIMIT
+};
+
+struct quota_warning {
+ struct quota_setup *setup;
+ uint64_t storage_limit;
+ unsigned int count_limit;
+ enum quota_warning_limit_kind storage_limit_kind:2;
+ enum quota_warning_limit_kind count_limit_kind:2;
+ char *command;
+};
+
struct quota_transaction_context {
array_t ARRAY_DEFINE(root_transactions,
struct quota_root_transaction_context *);
diff -ru dovecot-1.0.rc27.orig/src/plugins/quota/quota.c dovecot-1.0.rc27/src/plugins/quota/quota.c
--- dovecot-1.0.rc27.orig/src/plugins/quota/quota.c 2007-03-06 17:34:47.000000000 +0100
+++ dovecot-1.0.rc27/src/plugins/quota/quota.c 2007-03-31 22:35:22.000000000 +0200
@@ -6,6 +6,8 @@
#include "quota-private.h"
#include "quota-fs.h"
+#include <stdlib.h>
+
unsigned int quota_module_id = 0;
extern struct quota_backend quota_backend_dict;
@@ -59,6 +61,7 @@
setup->data = i_strdup(data);
setup->user_root = user_root;
ARRAY_CREATE(&setup->roots, default_pool, struct quota_root *, 4);
+ ARRAY_CREATE(&setup->warnings, default_pool, struct quota_warning *, 4);
t_push();
p = strchr(setup->data, ':');
@@ -107,6 +110,16 @@
}
array_free(&setup->roots);
+
+ while (array_count(&setup->warnings) > 0) {
+ struct quota_warning *const *warning;
+
+ warning = array_idx(&setup->warnings, 0);
+ quota_warning_deinit(*warning);
+ }
+
+ array_free(&setup->warnings);
+
i_free(setup->data);
i_free(setup);
}
@@ -157,6 +170,82 @@
array_free(&module_contexts);
}
+struct quota_warning *
+quota_warning_init(struct quota_setup *setup, const char *data)
+{
+ const char *p;
+ char *q;
+ const char *const *args;
+ unsigned long long val;
+ struct quota_warning *warning;
+
+ warning = i_new(struct quota_warning, 1);
+ warning->setup = setup;
+
+ p = strchr(data, ' ');
+ if (p == NULL)
+ i_fatal("quota warning: No command specified: %s", data);
+ warning->command = i_strdup(p+1);
+
+ t_push();
+
+ args = t_strsplit(t_strdup_until(data, p), ":");
+ for (; *args != '\0'; args++) {
+ if (strncmp(*args, "storage=", 8) == 0) {
+ val = strtoull(*args + 8, &q, 10);
+ if (q && (strcmp(q, "%") == 0)) {
+ warning->storage_limit = val;
+ warning->storage_limit_kind =
+ QUOTA_WARNING_PERCENT_LIMIT;
+ } else if (q && (strcmp(q, "k") == 0)) {
+ warning->storage_limit = val * 1024;
+ warning->storage_limit_kind =
+ QUOTA_WARNING_ABSOLUTE_LIMIT;
+ } else
+ i_error("quota warning: Malformed setting: %s", *args);
+ } else if (strncmp(*args, "messages=", 9) == 0) {
+ val = strtoull(*args + 8, &q, 10);
+ if (q && (strcmp(q, "%") == 0)) {
+ warning->count_limit = val;
+ warning->count_limit_kind =
+ QUOTA_WARNING_PERCENT_LIMIT;
+ } else if (q && (strcmp(q, "") == 0)) {
+ warning->count_limit = val;
+ warning->count_limit_kind =
+ QUOTA_WARNING_ABSOLUTE_LIMIT;
+ } else
+ i_error("quota warning: Malformed setting: %s", *args);
+ } else {
+ i_error("quota warning: Unknown setting: %s", *args);
+ }
+ }
+
+ t_pop();
+
+ array_append(&setup->warnings, &warning, 1);
+
+ return warning;
+}
+
+void quota_warning_deinit(struct quota_warning *warning)
+{
+ struct quota_warning *const *warnings;
+ unsigned int i, count;
+
+ /* remove from setup */
+ warnings = array_get(&warning->setup->warnings, &count);
+ for (i = 0; i < count; i++) {
+ if (warnings[i] == warning) {
+ array_delete(&warning->setup->warnings, i, 1);
+ break;
+ }
+ }
+ i_assert(i != count);
+
+ i_free(warning->command);
+ i_free(warning);
+}
+
void quota_add_user_storage(struct quota *quota, struct mail_storage *storage)
{
struct quota_setup *const *setups;
@@ -388,15 +477,62 @@
i_free(ctx);
}
+#define CHECK_PERCENT(val, cur, diff, limit) \
+ (100 * ((limit) - (cur) - (diff)) > (val) * (limit))
+#define CHECK_ABSOLUTE(val, cur, diff, limit) \
+ ((limit) - (cur) - (diff) > (val))
+
+#define CHECK2_PERCENT(val, cur, diff, size, limit) \
+ (CHECK_PERCENT(val, cur, diff, limit) \
+ && !CHECK_PERCENT(val, cur, (diff)+(size), limit))
+#define CHECK2_ABSOLUTE(val, cur, diff, size, limit) \
+ (CHECK_ABSOLUTE(val, cur, diff, limit) \
+ && !CHECK_ABSOLUTE(val, cur, (diff)+(size), limit))
+
+#define CHECK(kind, val, cur, diff, size, limit) \
+ ((((kind) == QUOTA_WARNING_PERCENT_LIMIT) \
+ && (CHECK2_PERCENT(val, cur, diff, size, limit))) \
+ || (((kind) == QUOTA_WARNING_ABSOLUTE_LIMIT) \
+ && (CHECK2_ABSOLUTE(val, cur, diff, size, limit))))
+
int quota_default_try_alloc_bytes(struct quota_root_transaction_context *ctx,
uoff_t size, bool *too_large_r)
{
+ struct quota_warning *const * warnings;
+ unsigned int i, count;
int ret;
ret = quota_default_test_alloc_bytes(ctx, size, too_large_r);
if (ret <= 0 || ctx->disabled)
return ret;
+ warnings = array_get(&ctx->root->setup->warnings, &count);
+
+ for (i = 0; i < count; i++) {
+ struct quota_warning *warning = warnings[i];
+ bool run_command = FALSE;
+
+ if (CHECK(warning->storage_limit_kind,
+ warning->storage_limit,
+ ctx->bytes_current,
+ ctx->bytes_diff,
+ size,
+ ctx->bytes_limit))
+ run_command = TRUE;
+
+ if (CHECK(warning->count_limit_kind,
+ warning->count_limit,
+ ctx->count_current,
+ ctx->count_diff,
+ 1,
+ ctx->count_limit))
+ run_command = TRUE;
+
+ if (run_command)
+ system(warning->command);
+
+ }
+
ctx->count_diff++;
ctx->bytes_diff += size;
return 1;
diff -ru dovecot-1.0.rc27.orig/src/plugins/quota/quota.h dovecot-1.0.rc27/src/plugins/quota/quota.h
--- dovecot-1.0.rc27.orig/src/plugins/quota/quota.h 2007-03-06 17:34:47.000000000 +0100
+++ dovecot-1.0.rc27/src/plugins/quota/quota.h 2007-03-16 23:21:33.000000000 +0100
@@ -31,6 +31,10 @@
quota_root_init(struct quota_setup *setup, const char *name);
void quota_root_deinit(struct quota_root *root);
+struct quota_warning *
+quota_warning_init(struct quota_setup *setup, const char *data);
+void quota_warning_deinit(struct quota_warning *warning);
+
/* List all quota roots. Returned quota roots are freed by quota_deinit(). */
struct quota_root_iter *quota_root_iter_init(struct mailbox *box);
struct quota_root *quota_root_iter_next(struct quota_root_iter *iter);