dovecot-2.0: quota: Avoid calling i_fatal() on initialization er...

dovecot at dovecot.org dovecot at dovecot.org
Tue Sep 21 20:05:23 EEST 2010


details:   http://hg.dovecot.org/dovecot-2.0/rev/3780caa2a6f2
changeset: 12150:3780caa2a6f2
user:      Timo Sirainen <tss at iki.fi>
date:      Tue Sep 21 18:05:13 2010 +0100
description:
quota: Avoid calling i_fatal() on initialization errors, plus some other fixes.

diffstat:

 src/plugins/quota/quota-storage.c |   20 ++-
 src/plugins/quota/quota.c         |  288 ++++++++++++++++++++++++-----------------
 src/plugins/quota/quota.h         |   16 +-
 3 files changed, 192 insertions(+), 132 deletions(-)

diffs (truncated from 436 to 300 lines):

diff -r 7dd6ff192718 -r 3780caa2a6f2 src/plugins/quota/quota-storage.c
--- a/src/plugins/quota/quota-storage.c	Tue Sep 21 18:04:30 2010 +0100
+++ b/src/plugins/quota/quota-storage.c	Tue Sep 21 18:05:13 2010 +0100
@@ -454,14 +454,28 @@
 	struct mail_user_vfuncs *v = user->vlast;
 	struct quota_user *quser;
 	struct quota_settings *set;
+	struct quota *quota;
+	const char *error;
+	int ret;
 
-	set = quota_user_read_settings(user);
-	if (set != NULL) {
+	if ((ret = quota_user_read_settings(user, &set, &error)) > 0) {
+		if (quota_init(set, user, &quota, &error) < 0) {
+			quota_settings_deinit(&set);
+			ret = -1;
+		}
+	}
+
+	if (ret < 0) {
+		user->error = p_strdup_printf(user->pool,
+			"Failed to initialize quota: %s", error);
+		return;
+	}
+	if (ret > 0) {
 		quser = p_new(user->pool, struct quota_user, 1);
 		quser->module_ctx.super = *v;
 		user->vlast = &quser->module_ctx.super;
 		v->deinit = quota_user_deinit;
-		quser->quota = quota_init(set, user);
+		quser->quota = quota;
 
 		MODULE_CONTEXT_SET(user, quota_user_module, quser);
 	} else if (user->mail_debug) {
diff -r 7dd6ff192718 -r 3780caa2a6f2 src/plugins/quota/quota.c
--- a/src/plugins/quota/quota.c	Tue Sep 21 18:04:30 2010 +0100
+++ b/src/plugins/quota/quota.c	Tue Sep 21 18:05:13 2010 +0100
@@ -45,96 +45,6 @@
 static int quota_default_test_alloc(struct quota_transaction_context *ctx,
 				    uoff_t size, bool *too_large_r);
 
-static void quota_root_add_rules(struct mail_user *user, const char *root_name, 
-				 struct quota_root_settings *root_set)
-{
-	const char *rule_name, *rule, *error;
-	unsigned int i;
-
-	rule_name = t_strconcat(root_name, "_rule", NULL);
-	for (i = 2;; i++) {
-		rule = mail_user_plugin_getenv(user, rule_name);
-		if (rule == NULL)
-			break;
-
-		if (quota_root_add_rule(root_set, rule, &error) < 0) {
-			i_fatal("Quota root %s: Invalid rule %s: %s",
-				root_name, rule, error);
-		}
-		rule_name = t_strdup_printf("%s_rule%d", root_name, i);
-	}
-}
-
-static void
-quota_root_add_warning_rules(struct mail_user *user, const char *root_name,
-			     struct quota_root_settings *root_set)
-{
-	const char *rule_name, *rule, *error;
-	unsigned int i;
-
-	rule_name = t_strconcat(root_name, "_warning", NULL);
-	for (i = 2;; i++) {
-		rule = mail_user_plugin_getenv(user, rule_name);
-		if (rule == NULL)
-			break;
-
-		if (quota_root_add_warning_rule(root_set, rule, &error) < 0) {
-			i_fatal("Quota root %s: Invalid warning rule: %s",
-				root_name, rule);
-		}
-		rule_name = t_strdup_printf("%s_warning%d", root_name, i);
-	}
-}
-
-struct quota_settings *quota_user_read_settings(struct mail_user *user)
-{
-	struct quota_settings *quota_set;
-	struct quota_root_settings *root_set;
-	char root_name[6 + MAX_INT_STRLEN];
-	const char *env;
-	unsigned int i;
-	pool_t pool;
-
-	pool = pool_alloconly_create("quota settings", 2048);
-	quota_set = p_new(pool, struct quota_settings, 1);
-	quota_set->pool = pool;
-	quota_set->test_alloc = quota_default_test_alloc;
-	quota_set->debug = user->mail_debug;
-	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;
-
-	p_array_init(&quota_set->root_sets, pool, 4);
-	i_strocpy(root_name, "quota", sizeof(root_name));
-	for (i = 2;; i++) {
-		env = mail_user_plugin_getenv(user, root_name);
-		if (env == NULL)
-			break;
-
-		root_set = quota_root_settings_init(quota_set, env);
-		if (root_set == NULL) {
-			i_fatal("Couldn't create quota root %s: %s",
-				root_name, env);
-		}
-		quota_root_add_rules(user, root_name, root_set);
-		quota_root_add_warning_rules(user, root_name, root_set);
-
-		i_snprintf(root_name, sizeof(root_name), "quota%d", i);
-	}
-
-	return quota_set;
-}
-
-void quota_settings_deinit(struct quota_settings **_quota_set)
-{
-	struct quota_settings *quota_set = *_quota_set;
-
-	*_quota_set = NULL;
-
-	pool_unref(&quota_set->pool);
-}
-
 static const struct quota_backend *quota_backend_find(const char *name)
 {
 	unsigned int i;
@@ -147,8 +57,57 @@
 	return NULL;
 }
 
-struct quota_root_settings *
-quota_root_settings_init(struct quota_settings *quota_set, const char *root_def)
+static int quota_root_add_rules(struct mail_user *user, const char *root_name,
+				struct quota_root_settings *root_set,
+				const char **error_r)
+{
+	const char *rule_name, *rule, *error;
+	unsigned int i;
+
+	rule_name = t_strconcat(root_name, "_rule", NULL);
+	for (i = 2;; i++) {
+		rule = mail_user_plugin_getenv(user, rule_name);
+		if (rule == NULL)
+			break;
+
+		if (quota_root_add_rule(root_set, rule, &error) < 0) {
+			*error_r = t_strdup_printf("Invalid rule %s: %s",
+						   rule, error);
+			return -1;
+		}
+		rule_name = t_strdup_printf("%s_rule%d", root_name, i);
+	}
+	return 0;
+}
+
+static int
+quota_root_add_warning_rules(struct mail_user *user, const char *root_name,
+			     struct quota_root_settings *root_set,
+			     const char **error_r)
+{
+	const char *rule_name, *rule, *error;
+	unsigned int i;
+
+	rule_name = t_strconcat(root_name, "_warning", NULL);
+	for (i = 2;; i++) {
+		rule = mail_user_plugin_getenv(user, rule_name);
+		if (rule == NULL)
+			break;
+
+		if (quota_root_add_warning_rule(root_set, rule, &error) < 0) {
+			*error_r = t_strdup_printf("Invalid warning rule: %s",
+						   rule);
+			return -1;
+		}
+		rule_name = t_strdup_printf("%s_warning%d", root_name, i);
+	}
+	return 0;
+}
+
+static int
+quota_root_settings_init(struct quota_settings *quota_set, const char *root_def,
+			 struct quota_root_settings **set_r,
+			 const char **error_r)
 {
 	struct quota_root_settings *root_set;
 	const struct quota_backend *backend;
@@ -166,8 +125,9 @@
 
 	backend = quota_backend_find(backend_name);
 	if (backend == NULL) {
-		i_error("Unknown quota backend: %s", backend_name);
-		return NULL;
+		*error_r = t_strdup_printf("Unknown quota backend: %s",
+					   backend_name);
+		return -1;
 	}
 	
 	root_set = p_new(quota_set->pool, struct quota_root_settings, 1);
@@ -198,11 +158,89 @@
 	p_array_init(&root_set->rules, quota_set->pool, 4);
 	p_array_init(&root_set->warning_rules, quota_set->pool, 4);
 	array_append(&quota_set->root_sets, &root_set, 1);
-	return root_set;
+	*set_r = root_set;
+	return 0;
 }
 
-static struct quota_root *
-quota_root_init(struct quota_root_settings *root_set, struct quota *quota)
+static int
+quota_root_add(struct quota_settings *quota_set, struct mail_user *user,
+	       const char *env, const char *root_name, const char **error_r)
+{
+	struct quota_root_settings *root_set;
+
+	if (quota_root_settings_init(quota_set, env, &root_set, error_r) < 0)
+		return -1;
+	if (quota_root_add_rules(user, root_name, root_set, error_r) < 0)
+		return -1;
+	if (quota_root_add_warning_rules(user, root_name, root_set, error_r) < 0)
+		return -1;
+	return 0;
+}
+
+int quota_user_read_settings(struct mail_user *user,
+			     struct quota_settings **set_r,
+			     const char **error_r)
+{
+	struct quota_settings *quota_set;
+	char root_name[6 + MAX_INT_STRLEN];
+	const char *env, *error;
+	unsigned int i;
+	pool_t pool;
+
+	pool = pool_alloconly_create("quota settings", 2048);
+	quota_set = p_new(pool, struct quota_settings, 1);
+	quota_set->pool = pool;
+	quota_set->test_alloc = quota_default_test_alloc;
+	quota_set->debug = user->mail_debug;
+	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;
+
+	p_array_init(&quota_set->root_sets, pool, 4);
+	i_strocpy(root_name, "quota", sizeof(root_name));
+	for (i = 2;; i++) {
+		env = mail_user_plugin_getenv(user, root_name);
+		if (env == NULL)
+			break;
+
+		if (quota_root_add(quota_set, user, env, root_name,
+				   &error) < 0) {
+			*error_r = t_strdup_printf("Invalid quota root %s: %s",
+						   root_name, error);
+			pool_unref(&pool);
+			return -1;
+		}
+		i_snprintf(root_name, sizeof(root_name), "quota%d", i);
+	}
+	if (array_count(&quota_set->root_sets) == 0) {
+		pool_unref(&pool);
+		return 0;
+	}
+	*set_r = quota_set;
+	return 1;
+}
+
+void quota_settings_deinit(struct quota_settings **_quota_set)
+{
+	struct quota_settings *quota_set = *_quota_set;
+
+	*_quota_set = NULL;
+
+	pool_unref(&quota_set->pool);
+}
+
+static void quota_root_deinit(struct quota_root *root)
+{
+	pool_t pool = root->pool;
+
+	root->backend.v.deinit(root);
+	pool_unref(&pool);
+}
+
+static int
+quota_root_init(struct quota_root_settings *root_set, struct quota *quota,
+		struct quota_root **root_r, const char **error_r)
 {
 	struct quota_root *root;
 	const char *const *tmp;


More information about the dovecot-cvs mailing list