dovecot-2.2: lib-fs: fs_init() API changed to allow returning an...

dovecot at dovecot.org dovecot at dovecot.org
Mon Sep 17 18:13:48 EEST 2012


details:   http://hg.dovecot.org/dovecot-2.2/rev/8f4ce0932777
changeset: 15085:8f4ce0932777
user:      Timo Sirainen <tss at iki.fi>
date:      Mon Sep 17 18:13:32 2012 +0300
description:
lib-fs: fs_init() API changed to allow returning an error.

diffstat:

 src/lib-fs/fs-api-private.h                      |   3 +-
 src/lib-fs/fs-api.c                              |  38 +++++++++++++++----
 src/lib-fs/fs-api.h                              |   6 ++-
 src/lib-fs/fs-posix.c                            |  44 +++++++++++++----------
 src/lib-fs/fs-sis-queue.c                        |  30 ++++++++++------
 src/lib-fs/fs-sis.c                              |  33 ++++++++++++------
 src/lib-storage/index/dbox-common/dbox-storage.c |  14 +++++--
 7 files changed, 110 insertions(+), 58 deletions(-)

diffs (truncated from 309 to 300 lines):

diff -r 64f556e62025 -r 8f4ce0932777 src/lib-fs/fs-api-private.h
--- a/src/lib-fs/fs-api-private.h	Mon Sep 17 17:51:03 2012 +0300
+++ b/src/lib-fs/fs-api-private.h	Mon Sep 17 18:13:32 2012 +0300
@@ -4,7 +4,8 @@
 #include "fs-api.h"
 
 struct fs_vfuncs {
-	struct fs *(*init)(const char *args, const struct fs_settings *set);
+	int (*init)(const char *args, const struct fs_settings *set,
+		    struct fs **fs_r, const char **error_r);
 	void (*deinit)(struct fs *fs);
 
 	int (*open)(struct fs *fs, const char *path, enum fs_open_mode mode,
diff -r 64f556e62025 -r 8f4ce0932777 src/lib-fs/fs-api.c
--- a/src/lib-fs/fs-api.c	Mon Sep 17 17:51:03 2012 +0300
+++ b/src/lib-fs/fs-api.c	Mon Sep 17 18:13:32 2012 +0300
@@ -10,27 +10,47 @@
 	&fs_class_sis_queue
 };
 
-static struct fs *
+static int
 fs_alloc(const struct fs *fs_class, const char *args,
-	 const struct fs_settings *set)
+	 const struct fs_settings *set, struct fs **fs_r, const char **error_r)
 {
 	struct fs *fs;
+	char *error_dup = NULL;
+	int ret;
 
-	fs = fs_class->v.init(args, set);
+	T_BEGIN {
+		const char *error;
+
+		ret = fs_class->v.init(args, set, fs_r, &error);
+		if (ret < 0)
+			error_dup = i_strdup(error);
+	} T_END;
+	if (ret < 0) {
+		/* a bit kludgy way to allow data stack frame usage in normal
+		   conditions but still be able to return error message from
+		   data stack. */
+		*error_r = t_strdup_printf("%s: %s", fs_class->name, error_dup);
+		i_free(error_dup);
+		return -1;
+	}
 	fs->last_error = str_new(default_pool, 64);
-	return fs;
+	return 0;
 }
 
-struct fs *fs_init(const char *driver, const char *args,
-		   const struct fs_settings *set)
+int fs_init(const char *driver, const char *args,
+	    const struct fs_settings *set,
+	    struct fs **fs_r, const char **error_r)
 {
 	unsigned int i;
 
 	for (i = 0; i < N_ELEMENTS(fs_classes); i++) {
-		if (strcmp(fs_classes[i]->name, driver) == 0)
-			return fs_alloc(fs_classes[i], args, set);
+		if (strcmp(fs_classes[i]->name, driver) == 0) {
+			return fs_alloc(fs_classes[i], args,
+					set, fs_r, error_r);
+		}
 	}
-	i_fatal("Unknown fs driver: %s", driver);
+	*error_r = t_strdup_printf("Unknown fs driver: %s", driver);
+	return -1;
 }
 
 void fs_deinit(struct fs **_fs)
diff -r 64f556e62025 -r 8f4ce0932777 src/lib-fs/fs-api.h
--- a/src/lib-fs/fs-api.h	Mon Sep 17 17:51:03 2012 +0300
+++ b/src/lib-fs/fs-api.h	Mon Sep 17 18:13:32 2012 +0300
@@ -2,6 +2,7 @@
 #define FS_API_H
 
 struct stat;
+struct fs;
 struct fs_file;
 struct fs_lock;
 
@@ -31,8 +32,9 @@
 	const char *temp_file_prefix;
 };
 
-struct fs *fs_init(const char *driver, const char *args,
-		   const struct fs_settings *set);
+int fs_init(const char *driver, const char *args,
+	    const struct fs_settings *set,
+	    struct fs **fs_r, const char **error_r);
 void fs_deinit(struct fs **fs);
 
 /* Returns 0 if opened, -1 if error (errno is set). */
diff -r 64f556e62025 -r 8f4ce0932777 src/lib-fs/fs-posix.c
--- a/src/lib-fs/fs-posix.c	Mon Sep 17 17:51:03 2012 +0300
+++ b/src/lib-fs/fs-posix.c	Mon Sep 17 18:13:32 2012 +0300
@@ -53,10 +53,12 @@
 	struct dotlock *dotlock;
 };
 
-static struct fs *
-fs_posix_init(const char *args, const struct fs_settings *set)
+static int
+fs_posix_init(const char *args, const struct fs_settings *set,
+	      struct fs **fs_r, const char **error_r)
 {
 	struct posix_fs *fs;
+	const char *const *tmp;
 
 	fs = i_new(struct posix_fs, 1);
 	fs->fs = fs_class_posix;
@@ -66,32 +68,34 @@
 
 	fs->lock_method = FS_POSIX_LOCK_METHOD_FLOCK;
 	fs->mode = FS_DEFAULT_MODE;
-	T_BEGIN {
-		const char *const *tmp = t_strsplit_spaces(args, " ");
 
-		for (; *tmp != NULL; tmp++) {
-			const char *arg = *tmp;
+	tmp = t_strsplit_spaces(args, " ");
+	for (; *tmp != NULL; tmp++) {
+		const char *arg = *tmp;
 
-			if (strcmp(arg, "lock=flock") == 0)
-				fs->lock_method = FS_POSIX_LOCK_METHOD_FLOCK;
-			else if (strcmp(arg, "lock=dotlock") == 0)
-				fs->lock_method = FS_POSIX_LOCK_METHOD_DOTLOCK;
-			else if (strncmp(arg, "mode=", 5) == 0) {
-				fs->mode = strtoul(arg+5, NULL, 8) & 0666;
-				if (fs->mode == 0) {
-					i_fatal("fs-posix: Invalid mode: %s",
-						arg+5);
-				}
-			} else
-				i_fatal("fs-posix: Unknown arg '%s'", arg);
+		if (strcmp(arg, "lock=flock") == 0)
+			fs->lock_method = FS_POSIX_LOCK_METHOD_FLOCK;
+		else if (strcmp(arg, "lock=dotlock") == 0)
+			fs->lock_method = FS_POSIX_LOCK_METHOD_DOTLOCK;
+		else if (strncmp(arg, "mode=", 5) == 0) {
+			fs->mode = strtoul(arg+5, NULL, 8) & 0666;
+			if (fs->mode == 0) {
+				*error_r = t_strdup_printf("Invalid mode: %s",
+							   arg+5);
+				return -1;
+			}
+		} else {
+			*error_r = t_strdup_printf("Unknown arg '%s'", arg);
+			return -1;
 		}
-	} T_END;
+	}
 	fs->dir_mode = fs->mode;
 	if ((fs->dir_mode & 0600) != 0) fs->dir_mode |= 0100;
 	if ((fs->dir_mode & 0060) != 0) fs->dir_mode |= 0010;
 	if ((fs->dir_mode & 0006) != 0) fs->dir_mode |= 0001;
 
-	return &fs->fs;
+	*fs_r = &fs->fs;
+	return 0;
 }
 
 static void fs_posix_deinit(struct fs *_fs)
diff -r 64f556e62025 -r 8f4ce0932777 src/lib-fs/fs-sis-queue.c
--- a/src/lib-fs/fs-sis-queue.c	Mon Sep 17 17:51:03 2012 +0300
+++ b/src/lib-fs/fs-sis-queue.c	Mon Sep 17 18:13:32 2012 +0300
@@ -30,11 +30,12 @@
 	fs_sis_queue_copy_error(fs);
 }
 
-static struct fs *
-fs_sis_queue_init(const char *args, const struct fs_settings *set)
+static int
+fs_sis_queue_init(const char *args, const struct fs_settings *set,
+		  struct fs **fs_r, const char **error_r)
 {
 	struct sis_queue_fs *fs;
-	const char *p, *parent_fs;
+	const char *p, *parent_name, *parent_args, *error;
 
 	fs = i_new(struct sis_queue_fs, 1);
 	fs->fs = fs_class_sis_queue;
@@ -42,18 +43,25 @@
 	/* <queue_dir>:<parent fs>[:<args>] */
 
 	p = strchr(args, ':');
-	if (p == NULL || p[1] == '\0')
-		i_fatal("fs-sis-queue: Parent filesystem not given as parameter");
+	if (p == NULL || p[1] == '\0') {
+		*error_r = "Parent filesystem not given as parameter";
+		return -1;
+	}
 
 	fs->queue_dir = i_strdup_until(args, p);
-	parent_fs = p + 1;
+	parent_name = p + 1;
 
-	p = strchr(parent_fs, ':');
-	if (p == NULL)
-		fs->super = fs_init(parent_fs, "", set);
+	parent_args = strchr(parent_name, ':');
+	if (parent_args == NULL)
+		parent_args = "";
 	else
-		fs->super = fs_init(t_strdup_until(parent_fs, p), p+1, set);
-	return &fs->fs;
+		parent_name = t_strdup_until(parent_name, parent_args++);
+	if (fs_init(parent_name, parent_args, set, &fs->super, &error) < 0) {
+		*error_r = t_strdup_printf("%s: %s", parent_name, error);
+		return -1;
+	}
+	*fs_r = &fs->fs;
+	return 0;
 }
 
 static void fs_sis_queue_deinit(struct fs *_fs)
diff -r 64f556e62025 -r 8f4ce0932777 src/lib-fs/fs-sis.c
--- a/src/lib-fs/fs-sis.c	Mon Sep 17 17:51:03 2012 +0300
+++ b/src/lib-fs/fs-sis.c	Mon Sep 17 18:13:32 2012 +0300
@@ -35,24 +35,35 @@
 	fs_sis_copy_error(fs);
 }
 
-static struct fs *
-fs_sis_init(const char *args, const struct fs_settings *set)
+static int
+fs_sis_init(const char *args, const struct fs_settings *set,
+	    struct fs **fs_r, const char **error_r)
 {
 	struct sis_fs *fs;
-	const char *p;
+	const char *parent_name, *parent_args, *error;
 
 	fs = i_new(struct sis_fs, 1);
 	fs->fs = fs_class_sis;
 
-	if (*args == '\0')
-		i_fatal("fs-sis: Parent filesystem not given as parameter");
+	if (*args == '\0') {
+		*error_r = "Parent filesystem not given as parameter";
+		return -1;
+	}
 
-	p = strchr(args, ':');
-	if (p == NULL)
-		fs->super = fs_init(args, "", set);
-	else
-		fs->super = fs_init(t_strdup_until(args, p), p+1, set);
-	return &fs->fs;
+	parent_args = strchr(args, ':');
+	if (parent_args == NULL) {
+		parent_name = args;
+		parent_args = "";
+	} else {
+		parent_name = t_strdup_until(args, parent_args);
+		parent_args++;
+	}
+	if (fs_init(parent_name, parent_args, set, &fs->super, &error) < 0) {
+		*error_r = t_strdup_printf("%s: %s", parent_name, error);
+		return -1;
+	}
+	*fs_r = &fs->fs;
+	return 0;
 }
 
 static void fs_sis_deinit(struct fs *_fs)
diff -r 64f556e62025 -r 8f4ce0932777 src/lib-storage/index/dbox-common/dbox-storage.c
--- a/src/lib-storage/index/dbox-common/dbox-storage.c	Mon Sep 17 17:51:03 2012 +0300
+++ b/src/lib-storage/index/dbox-common/dbox-storage.c	Mon Sep 17 18:13:32 2012 +0300
@@ -80,16 +80,17 @@
 
 int dbox_storage_create(struct mail_storage *_storage,
 			struct mail_namespace *ns,
-			const char **error_r ATTR_UNUSED)
+			const char **error_r)
 {
 	struct dbox_storage *storage = (struct dbox_storage *)_storage;
 	const struct mail_storage_settings *set = _storage->set;
 	struct fs_settings fs_set;
+	const char *error;
 
 	memset(&fs_set, 0, sizeof(fs_set));
 	fs_set.temp_file_prefix = mailbox_list_get_global_temp_prefix(ns->list);
 
-	if (*set->mail_attachment_fs != '\0') T_BEGIN {
+	if (*set->mail_attachment_fs != '\0') {
 		const char *name, *args, *dir;
 
 		args = strchr(set->mail_attachment_fs, ' ');
@@ -102,8 +103,13 @@
 		dir = mail_user_home_expand(_storage->user,
 					    set->mail_attachment_dir);
 		storage->attachment_dir = p_strdup(_storage->pool, dir);
-		storage->attachment_fs = fs_init(name, args, &fs_set);
-	} T_END;
+		if (fs_init(name, args, &fs_set, &storage->attachment_fs,


More information about the dovecot-cvs mailing list