1
/* Copyright (c) 2005-2012 Dovecot authors, see the included COPYING file */
1
/* Copyright (c) 2005-2013 Dovecot authors, see the included COPYING file */
8
8
#include "write-full.h"
9
9
#include "eacces-error.h"
10
10
#include "mailbox-list-private.h"
46
47
static int quota_default_test_alloc(struct quota_transaction_context *ctx,
47
48
uoff_t size, bool *too_large_r);
50
quota_root_parse_grace(struct mail_user *user, const char *root_name,
51
struct quota_root_settings *root_set,
52
const char **error_r);
49
54
static const struct quota_backend *quota_backend_find(const char *name)
176
181
if (quota_root_add_warning_rules(user, root_name, root_set, error_r) < 0)
183
if (quota_root_parse_grace(user, root_name, root_set, error_r) < 0)
195
202
quota_set->debug = user->mail_debug;
196
203
quota_set->quota_exceeded_msg =
197
204
mail_user_plugin_getenv(user, "quota_exceeded_message");
198
quota_set->ignore_save_errors =
199
mail_user_plugin_getenv(user, "quota_ignore_save_errors") != NULL;
200
205
if (quota_set->quota_exceeded_msg == NULL)
201
206
quota_set->quota_exceeded_msg = DEFAULT_QUOTA_EXCEEDED_MSG;
203
208
p_array_init("a_set->root_sets, pool, 4);
204
i_strocpy(root_name, "quota", sizeof(root_name));
209
if (i_strocpy(root_name, "quota", sizeof(root_name)) < 0)
205
211
for (i = 2;; i++) {
206
212
env = mail_user_plugin_getenv(user, root_name);
207
213
if (env == NULL || *env == '\0')
214
220
pool_unref(&pool);
217
i_snprintf(root_name, sizeof(root_name), "quota%d", i);
223
if (i_snprintf(root_name, sizeof(root_name), "quota%d", i) < 0)
219
226
if (array_count("a_set->root_sets) == 0) {
220
227
pool_unref(&pool);
231
quota_set->initialized = TRUE;
223
232
*set_r = quota_set;
362
371
int64_t percentage = *limit;
364
if (percentage <= -100 || percentage >= -1U) {
365
*error_r = p_strdup_printf(root_set->set->pool,
366
"Invalid rule percentage: %lld", (long long)percentage);
373
if (percentage <= -100 || percentage >= UINT_MAX) {
374
*error_r = "Invalid percentage";
392
static int quota_limit_parse(struct quota_root_settings *root_set,
393
struct quota_rule *rule, const char *unit,
394
uint64_t multiply, int64_t *limit,
395
const char **error_r)
397
switch (i_toupper(*unit)) {
408
multiply = 1024*1024;
411
multiply = 1024*1024*1024;
414
multiply = 1024ULL*1024*1024*1024;
418
if (quota_rule_parse_percentage(root_set, rule, limit,
423
*error_r = t_strdup_printf("Unknown unit: %s", unit);
385
431
quota_rule_recalculate_relative_rules(struct quota_rule *rule,
386
432
int64_t bytes_limit, int64_t count_limit)
407
453
quota_rule_recalculate_relative_rules(&warning_rule->rule,
408
454
bytes_limit, count_limit);
456
quota_rule_recalculate_relative_rules(&root_set->grace_rule,
458
root_set->last_mail_max_extra_bytes = root_set->grace_rule.bytes_limit;
460
if (root_set->set->debug && root_set->set->initialized) {
461
i_debug("Quota root %s: Recalculated relative rules with "
462
"bytes=%lld count=%lld. Now grace=%llu", root_set->name,
463
(long long)bytes_limit, (long long)count_limit,
464
(unsigned long long)root_set->last_mail_max_extra_bytes);
415
471
const char *full_rule_def,
416
472
bool relative_rule, const char **error_r)
418
const char **args, *key, *value;
474
const char **args, *key, *value, *error;
420
476
uint64_t multiply;
465
switch (i_toupper(*p)) {
476
multiply = 1024*1024;
479
multiply = 1024*1024*1024;
482
multiply = 1024ULL*1024*1024*1024;
486
if (quota_rule_parse_percentage(root_set, rule, limit,
521
if (quota_limit_parse(root_set, rule, p, multiply,
522
limit, &error) < 0) {
491
523
*error_r = p_strdup_printf(root_set->set->pool,
492
"Invalid rule limit value: %s", *args);
524
"Invalid rule limit value '%s': %s",
497
529
if (!relative_rule) {
498
530
if (rule->bytes_limit < 0) {
532
564
root_set->force_default_rule = TRUE;
534
566
rule = array_append_space(&root_set->rules);
567
rule->mailbox_name = strcasecmp(mailbox_name, "INBOX") == 0 ? "INBOX" :
536
568
p_strdup(root_set->set->pool, mailbox_name);
619
quota_root_parse_grace(struct mail_user *user, const char *root_name,
620
struct quota_root_settings *root_set,
621
const char **error_r)
623
const char *set_name, *value, *error;
626
set_name = t_strconcat(root_name, "_grace", NULL);
627
value = mail_user_plugin_getenv(user, set_name);
630
value = QUOTA_DEFAULT_GRACE;
633
root_set->grace_rule.bytes_limit = strtoll(value, &p, 10);
635
if (quota_limit_parse(root_set, &root_set->grace_rule, p, 1,
636
&root_set->grace_rule.bytes_limit, &error) < 0) {
637
*error_r = p_strdup_printf(root_set->set->pool,
638
"Invalid %s value '%s': %s", set_name, value, error);
641
quota_rule_recalculate_relative_rules(&root_set->grace_rule,
642
root_set->default_rule.bytes_limit, 0);
643
root_set->last_mail_max_extra_bytes = root_set->grace_rule.bytes_limit;
644
if (root_set->set->debug) {
645
i_debug("Quota grace: root=%s bytes=%lld%s",
646
root_set->name, (long long)root_set->grace_rule.bytes_limit,
647
root_set->grace_rule.bytes_percent == 0 ? "" :
648
t_strdup_printf(" (%u%%)", root_set->grace_rule.bytes_percent));
586
653
static int quota_root_get_rule_limits(struct quota_root *root,
587
654
const char *mailbox_name,
588
655
uint64_t *bytes_limit_r,
635
702
/* first check if there already exists a namespace with the exact same
636
703
path. we don't want to count them twice. */
637
path = mailbox_list_get_path(ns->list, NULL,
638
MAILBOX_LIST_PATH_TYPE_MAILBOX);
704
if (mailbox_list_get_root_path(ns->list, MAILBOX_LIST_PATH_TYPE_MAILBOX,
640
706
namespaces = array_get("a->namespaces, &count);
641
707
for (i = 0; i < count; i++) {
642
path2 = mailbox_list_get_path(namespaces[i]->list, NULL,
643
MAILBOX_LIST_PATH_TYPE_MAILBOX);
644
if (path2 != NULL && strcmp(path, path2) == 0) {
708
if (mailbox_list_get_root_path(namespaces[i]->list,
709
MAILBOX_LIST_PATH_TYPE_MAILBOX, &path2) &&
710
strcmp(path, path2) == 0) {
930
996
ctx->bytes_ceil = (uint64_t)-1;
997
ctx->bytes_ceil2 = (uint64_t)-1;
931
998
ctx->count_ceil = (uint64_t)-1;
933
if (box->storage->user->admin) {
934
/* ignore quota for admins */
1000
if (box->storage->user->dsyncing) {
1001
/* ignore quota for dsync */
935
1002
ctx->limits_set = TRUE;
943
1010
const char *mailbox_name;
944
1011
unsigned int i, count;
945
1012
uint64_t bytes_limit, count_limit, current, limit, diff;
948
1016
ctx->limits_set = TRUE;
949
1017
mailbox_name = mailbox_get_vname(ctx->box);
1018
/* use last_mail_max_extra_bytes only for LDA/LMTP */
1019
use_grace = (ctx->box->flags & MAILBOX_FLAG_POST_SESSION) != 0;
951
1021
/* find the lowest quota limits from all roots and use them */
952
1022
roots = array_get(&ctx->quota->roots, &count);
966
1036
QUOTA_NAME_STORAGE_BYTES,
967
1037
¤t, &limit);
969
if (limit < current) {
1039
if (limit <= current) {
970
1041
ctx->bytes_ceil = 0;
1042
ctx->bytes_ceil2 = 0;
971
1043
diff = current - limit;
972
1044
if (ctx->bytes_over < diff)
973
1045
ctx->bytes_over = diff;
975
1047
diff = limit - current;
1048
if (ctx->bytes_ceil2 > diff)
1049
ctx->bytes_ceil2 = diff;
1050
diff += !use_grace ? 0 :
1051
roots[i]->set->last_mail_max_extra_bytes;
976
1052
if (ctx->bytes_ceil > diff)
977
1053
ctx->bytes_ceil = diff;
1114
1190
else if (ctx->bytes_used != 0 || ctx->count_used != 0 ||
1115
1191
ctx->recalculate) T_BEGIN {
1116
ARRAY_DEFINE(warn_roots, struct quota_root *);
1192
ARRAY(struct quota_root *) warn_roots;
1118
1194
mailbox_name = mailbox_get_vname(ctx->box);
1119
1195
(void)mail_namespace_find_unalias(
1135
1211
if (roots[i]->backend.v.update(roots[i], ctx) < 0)
1213
else if (!ctx->sync_transaction)
1138
1214
array_append(&warn_roots, &roots[i], 1);
1140
1216
/* execute quota warnings after all updates. this makes it
1141
1217
work correctly regardless of whether backend.get_resource()
1142
returns updated values before backend.update() or not */
1218
returns updated values before backend.update() or not.
1219
warnings aren't executed when dsync bring the user over,
1220
because the user probably already got the warning on the
1143
1222
array_foreach(&warn_roots, roots)
1144
1223
quota_warnings_execute(ctx, *roots);
1238
static bool quota_is_over(struct quota_transaction_context *ctx, uoff_t size)
1240
if ((ctx->count_used < 0 ||
1241
(uint64_t)ctx->count_used + 1 <= ctx->count_ceil) &&
1242
((ctx->bytes_used < 0 && size <= ctx->bytes_ceil) ||
1243
(uint64_t)ctx->bytes_used + size <= ctx->bytes_ceil))
1159
1249
int quota_try_alloc(struct quota_transaction_context *ctx,
1160
1250
struct mail *mail, bool *too_large_r)
1183
1273
if (quota_transaction_set_limits(ctx) < 0)
1276
/* this is a virtual function mainly for trash plugin and similar,
1277
which may automatically delete mails to stay under quota. */
1186
1278
return ctx->quota->set->test_alloc(ctx, size, too_large_r);
1196
1288
*too_large_r = FALSE;
1198
if ((ctx->count_used < 0 ||
1199
(uint64_t)ctx->count_used + 1 <= ctx->count_ceil) &&
1200
((ctx->bytes_used < 0 && size <= ctx->bytes_ceil) ||
1201
(uint64_t)ctx->bytes_used + size <= ctx->bytes_ceil))
1290
if (!quota_is_over(ctx, size))
1204
1293
/* limit reached. only thing left to do now is to set too_large_r. */