From: Timo Sirainen Date: Tue, 13 Aug 2024 11:47:52 +0000 (+0300) Subject: quota: Convert initial set of quota plugin settings to global settings X-Git-Tag: 2.4.0~411 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=261fd5dda4aee02119f55cff777e11e855733cbf;p=thirdparty%2Fdovecot%2Fcore.git quota: Convert initial set of quota plugin settings to global settings --- diff --git a/src/plugins/quota/Makefile.am b/src/plugins/quota/Makefile.am index b739a899d7..9070b824c8 100644 --- a/src/plugins/quota/Makefile.am +++ b/src/plugins/quota/Makefile.am @@ -38,6 +38,7 @@ quota_dist_sources = \ quota-imapc.c \ quota-maildir.c \ quota-plugin.c \ + quota-settings.c \ quota-storage.c \ quota-util.c @@ -48,6 +49,7 @@ quota_common_objects = \ quota-imapc.lo \ quota-maildir.lo \ quota-plugin.lo \ + quota-settings.lo \ quota-storage.lo \ quota-util.lo \ $(RQUOTA_XDR_LO) @@ -116,7 +118,8 @@ pkginc_lib_HEADERS = \ quota.h \ quota-fs.h \ quota-plugin.h \ - quota-private.h + quota-private.h \ + quota-settings.h noinst_HEADERS = \ quota-status-settings.h diff --git a/src/plugins/quota/quota-private.h b/src/plugins/quota/quota-private.h index 0c71081ad0..23f1f85ad0 100644 --- a/src/plugins/quota/quota-private.h +++ b/src/plugins/quota/quota-private.h @@ -4,6 +4,7 @@ #include "mail-storage-private.h" #include "mail-namespace.h" #include "quota.h" +#include "quota-settings.h" /* Modules should use do "my_id = quota_module_id++" and use quota_module_contexts[id] for their own purposes. */ @@ -28,11 +29,6 @@ struct quota_legacy_settings { pool_t pool; ARRAY(struct quota_root_settings *) root_sets; - - unsigned int max_mailbox_count; - uoff_t max_mail_size; - unsigned int max_messages_per_mailbox; - const char *quota_exceeded_msg; }; struct quota_rule { @@ -163,6 +159,8 @@ struct quota_transaction_context { struct quota *quota; struct mailbox *box; + const struct quota_settings *set; + int64_t bytes_used, count_used; /* how many bytes/mails can be saved until limit is reached. (set once, not updated by bytes_used/count_used). diff --git a/src/plugins/quota/quota-settings.c b/src/plugins/quota/quota-settings.c new file mode 100644 index 0000000000..79c7aad3b7 --- /dev/null +++ b/src/plugins/quota/quota-settings.c @@ -0,0 +1,42 @@ +/* Copyright (c) 2024 Dovecot authors, see the included COPYING file */ + +#include "lib.h" +#include "settings-parser.h" +#include "quota-settings.h" + +#undef DEF +#define DEF(type, name) \ + SETTING_DEFINE_STRUCT_##type(#name, name, struct quota_settings) +static const struct setting_define quota_setting_defines[] = { + DEF(UINT, quota_mailbox_count), + DEF(UINT, quota_mailbox_message_count), + DEF(SIZE, quota_mail_size), + DEF(STR, quota_exceeded_message), + + SETTING_DEFINE_LIST_END +}; + +static const struct quota_settings quota_default_settings = { + .quota_mailbox_count = SET_UINT_UNLIMITED, + .quota_mail_size = SET_SIZE_UNLIMITED, + .quota_mailbox_message_count = SET_UINT_UNLIMITED, + .quota_exceeded_message = "Quota exceeded (mailbox for user is full)", +}; + +const struct setting_parser_info quota_setting_parser_info = { + .name = "quota", + .defines = quota_setting_defines, + .defaults = "a_default_settings, + .struct_size = sizeof(struct quota_settings), + .pool_offset1 = 1 + offsetof(struct quota_settings, pool), +}; + +struct quota_settings *quota_get_unlimited_set(void) +{ + static struct quota_settings set; + if (set.pool == NULL) { + set = quota_default_settings; + set.pool = null_pool; + } + return &set; +} diff --git a/src/plugins/quota/quota-settings.h b/src/plugins/quota/quota-settings.h new file mode 100644 index 0000000000..72e66ec273 --- /dev/null +++ b/src/plugins/quota/quota-settings.h @@ -0,0 +1,17 @@ +#ifndef QUOTA_SETTINGS_H +#define QUOTA_SETTINGS_H + +struct quota_settings { + pool_t pool; + + unsigned int quota_mailbox_count; + uoff_t quota_mail_size; + unsigned int quota_mailbox_message_count; + const char *quota_exceeded_message; +}; + +struct quota_settings *quota_get_unlimited_set(void); + +extern const struct setting_parser_info quota_setting_parser_info; + +#endif diff --git a/src/plugins/quota/quota-storage.c b/src/plugins/quota/quota-storage.c index e3ed4f7b4e..f379fc2334 100644 --- a/src/plugins/quota/quota-storage.c +++ b/src/plugins/quota/quota-storage.c @@ -3,6 +3,7 @@ #include "lib.h" #include "array.h" #include "istream.h" +#include "settings.h" #include "mail-search-build.h" #include "mail-storage-private.h" #include "mailbox-list-private.h" @@ -121,12 +122,19 @@ quota_create_box(struct mailbox *box, const struct mailbox_update *update, bool directory) { struct quota_mailbox *qbox = QUOTA_CONTEXT_REQUIRE(box); - struct quota_user *quser = - QUOTA_USER_CONTEXT_REQUIRE(box->storage->user); - struct quota_legacy_settings *quota_set = quser->quota->set; + const struct quota_settings *set; unsigned int mailbox_count; + const char *error; + + if (settings_get(box->event, "a_setting_parser_info, 0, + &set, &error) < 0) { + mailbox_set_critical(box, "%s", error); + return -1; + } + unsigned int quota_mailbox_count = set->quota_mailbox_count; + settings_free(set); - if (quota_set->max_mailbox_count == 0) { + if (quota_mailbox_count == SET_UINT_UNLIMITED) { /* no mailbox count limit */ } else if (mailbox_is_autocreated(box)) { /* Always allow autocreated mailbox to be created. @@ -134,7 +142,7 @@ quota_create_box(struct mailbox *box, const struct mailbox_update *update, } else if (mailbox_list_get_count(box->list, &mailbox_count) < 0) { mail_storage_copy_list_error(box->storage, box->list); return -1; - } else if (mailbox_count >= quota_set->max_mailbox_count) { + } else if (mailbox_count >= quota_mailbox_count) { mail_storage_set_error(box->storage, MAIL_ERROR_LIMIT, "Maximum number of mailboxes reached"); return -1; diff --git a/src/plugins/quota/quota.c b/src/plugins/quota/quota.c index b5a10329d9..9275167e1e 100644 --- a/src/plugins/quota/quota.c +++ b/src/plugins/quota/quota.c @@ -9,6 +9,7 @@ #include "write-full.h" #include "eacces-error.h" #include "wildcard-match.h" +#include "settings.h" #include "mailbox-list-private.h" #include "quota-private.h" #include "quota-fs.h" @@ -18,9 +19,6 @@ #include -#define DEFAULT_QUOTA_EXCEEDED_MSG \ - "Quota exceeded (mailbox for user is full)" - /* How many seconds after the userdb lookup do we still want to execute the quota_over_script. This applies to quota_over_flag_lazy_check=yes and also after unhibernating IMAP connections. */ @@ -264,7 +262,7 @@ const char *quota_alloc_result_errstr(enum quota_alloc_result res, "server configuration"; case QUOTA_ALLOC_RESULT_OVER_QUOTA_LIMIT: case QUOTA_ALLOC_RESULT_OVER_QUOTA: - return qt->quota->set->quota_exceeded_msg; + return qt->set->quota_exceeded_message; case QUOTA_ALLOC_RESULT_OVER_QUOTA_MAILBOX_LIMIT: return "Too many messages in the mailbox"; } @@ -284,46 +282,6 @@ int quota_user_read_settings(struct mail_user *user, pool = pool_alloconly_create("quota settings", 2048); quota_set = p_new(pool, struct quota_legacy_settings, 1); quota_set->pool = pool; - quota_set->quota_exceeded_msg = - mail_user_plugin_getenv(user, "quota_exceeded_message"); - if (quota_set->quota_exceeded_msg == NULL) - quota_set->quota_exceeded_msg = DEFAULT_QUOTA_EXCEEDED_MSG; - - const char *mailbox_count = - mail_user_plugin_getenv(user, "quota_mailbox_count"); - if (mailbox_count != NULL) { - if (str_to_uint(mailbox_count, "a_set->max_mailbox_count) < 0) { - *error_r = "Invalid quota_mailbox_count"; - event_unref("a_set->event); - pool_unref(&pool); - return -1; - } - } - - const char *max_size = mail_user_plugin_getenv(user, "quota_mail_size"); - if (max_size != NULL) { - const char *error = NULL; - if (str_parse_get_size(max_size, "a_set->max_mail_size, - &error) < 0) { - *error_r = t_strdup_printf("quota_max_mail_size: %s", - error); - event_unref("a_set->event); - pool_unref(&pool); - return -1; - } - } - - const char *max_box_count = - mail_user_plugin_getenv(user, "quota_mailbox_message_count"); - if (max_box_count != NULL) { - if (str_to_uint(max_box_count, - "a_set->max_messages_per_mailbox) < 0) { - *error_r = "Invalid quota_mailbox_message_count"; - event_unref("a_set->event); - pool_unref(&pool); - return -1; - } - } p_array_init("a_set->root_sets, pool, 4); if (i_strocpy(root_name, "quota", sizeof(root_name)) < 0) @@ -867,6 +825,7 @@ struct quota_transaction_context *quota_transaction_begin(struct mailbox *box) if (box->storage->user->dsyncing) { /* ignore quota for dsync */ ctx->limits_set = TRUE; + ctx->set = quota_get_unlimited_set(); } return ctx; } @@ -875,7 +834,6 @@ int quota_transaction_set_limits(struct quota_transaction_context *ctx, enum quota_get_result *error_result_r, const char **error_r) { - const struct quota_legacy_settings *set = ctx->quota->set; struct quota_root *const *roots; const char *mailbox_name, *error; unsigned int i, count; @@ -891,6 +849,14 @@ int quota_transaction_set_limits(struct quota_transaction_context *ctx, use_grace = (ctx->box->flags & MAILBOX_FLAG_POST_SESSION) != 0; ctx->no_quota_updates = TRUE; + i_assert(ctx->set == NULL); + if (settings_get(ctx->box->event, "a_setting_parser_info, + 0, &ctx->set, error_r) < 0) { + ctx->failed = TRUE; + *error_result_r = QUOTA_GET_RESULT_INTERNAL_ERROR; + return -1; + } + /* find the lowest quota limits from all roots and use them */ roots = array_get(&ctx->quota->roots, &count); for (i = 0; i < count; i++) { @@ -973,17 +939,17 @@ int quota_transaction_set_limits(struct quota_transaction_context *ctx, } } - if (set->max_messages_per_mailbox != 0) { + if (ctx->set->quota_mailbox_message_count != SET_UINT_UNLIMITED) { struct mailbox_status status; mailbox_get_open_status(ctx->box, STATUS_MESSAGES, &status); - if (status.messages <= set->max_messages_per_mailbox) { - diff = set->max_messages_per_mailbox - status.messages; + if (status.messages <= ctx->set->quota_mailbox_message_count) { + diff = ctx->set->quota_mailbox_message_count - status.messages; if (ctx->count_ceil > diff) ctx->count_ceil = diff; } else { /* over quota */ ctx->count_ceil = 0; - diff = status.messages - set->max_messages_per_mailbox; + diff = status.messages - ctx->set->quota_mailbox_message_count; if (ctx->count_over < diff) ctx->count_over = diff; } @@ -1148,6 +1114,7 @@ int quota_transaction_commit(struct quota_transaction_context **_ctx) quota_warnings_execute(ctx, *roots); } T_END; + settings_free(ctx->set); i_free(ctx); return ret; } @@ -1266,6 +1233,7 @@ void quota_transaction_rollback(struct quota_transaction_context **_ctx) struct quota_transaction_context *ctx = *_ctx; *_ctx = NULL; + settings_free(ctx->set); i_free(ctx); } @@ -1345,7 +1313,7 @@ enum quota_alloc_result quota_test_alloc(struct quota_transaction_context *ctx, return QUOTA_ALLOC_RESULT_TEMPFAIL; } - uoff_t max_size = ctx->quota->set->max_mail_size; + uoff_t max_size = ctx->set->quota_mail_size; if (max_size > 0 && size > max_size) { *error_r = t_strdup_printf( "Requested allocation size %"PRIuUOFF_T" exceeds max " @@ -1372,11 +1340,11 @@ static enum quota_alloc_result quota_default_test_alloc( if (!quota_transaction_is_over(ctx, size)) return QUOTA_ALLOC_RESULT_OK; - if (ctx->quota->set->max_messages_per_mailbox != 0) { + if (ctx->set->quota_mailbox_message_count != SET_UINT_UNLIMITED) { struct mailbox_status status; mailbox_get_open_status(ctx->box, STATUS_MESSAGES, &status); unsigned int new_count = status.messages + ctx->count_used; - if (new_count >= ctx->quota->set->max_messages_per_mailbox) + if (new_count >= ctx->set->quota_mailbox_message_count) return QUOTA_ALLOC_RESULT_OVER_QUOTA_MAILBOX_LIMIT; }