dovecot-2.1: lib-storage: Abort index/control/alt root dir creat...

dovecot at dovecot.org dovecot at dovecot.org
Wed Feb 1 20:30:32 EET 2012


details:   http://hg.dovecot.org/dovecot-2.1/rev/d01932c7828a
changeset: 14043:d01932c7828a
user:      Timo Sirainen <tss at iki.fi>
date:      Wed Feb 01 20:30:18 2012 +0200
description:
lib-storage: Abort index/control/alt root dir creation if mountpoint isn't mounted.

diffstat:

 src/lib-master/mountpoint-list.c |  41 +++++++++++++++++++++++++++++++++++++--
 src/lib-master/mountpoint-list.h |   5 ++++
 src/lib-storage/mail-user.c      |  35 ++++++++++++++++++++++++++++++++++
 src/lib-storage/mail-user.h      |   8 +++++++
 src/lib-storage/mailbox-list.c   |  14 ++++++++++++-
 5 files changed, 99 insertions(+), 4 deletions(-)

diffs (221 lines):

diff -r cf34d9fc5cec -r d01932c7828a src/lib-master/mountpoint-list.c
--- a/src/lib-master/mountpoint-list.c	Wed Feb 01 20:21:38 2012 +0200
+++ b/src/lib-master/mountpoint-list.c	Wed Feb 01 20:30:18 2012 +0200
@@ -18,6 +18,7 @@
 	pool_t pool;
 	const char *perm_path, *state_path;
 	ARRAY_DEFINE(recs, struct mountpoint_list_rec *);
+	struct stat load_st;
 	bool load_failed;
 };
 
@@ -49,8 +50,6 @@
 	NULL
 };
 
-static int mountpoint_list_load(struct mountpoint_list *list);
-
 struct mountpoint_list *
 mountpoint_list_init(const char *perm_path, const char *state_path)
 {
@@ -64,10 +63,16 @@
 	list->state_path = p_strdup(pool, state_path);
 	p_array_init(&list->recs, pool, 16);
 
-	(void)mountpoint_list_load(list);
+	(void)mountpoint_list_refresh(list);
 	return list;
 }
 
+struct mountpoint_list *
+mountpoint_list_init_readonly(const char *state_path)
+{
+	return mountpoint_list_init(NULL, state_path);
+}
+
 void mountpoint_list_deinit(struct mountpoint_list **_list)
 {
 	struct mountpoint_list *list = *_list;
@@ -92,6 +97,10 @@
 			i_error("open(%s) failed: %m", list->state_path);
 			return -1;
 		}
+		if (list->perm_path == NULL) {
+			/* we're in read-only mode */
+			return 0;
+		}
 		if (file_copy(list->perm_path, list->state_path, FALSE) < 0)
 			return -1;
 		fd = open(list->perm_path, O_RDONLY);
@@ -104,6 +113,8 @@
 			return -1;
 		}
 	}
+	if (fstat(fd, &list->load_st) < 0)
+		i_error("fstat(%s) failed: %m", list->state_path);
 	input = i_stream_create_fd(fd, (size_t)-1, TRUE);
 	while ((line = i_stream_read_next_line(input)) != NULL) {
 		p = strchr(line, ' ');
@@ -131,6 +142,28 @@
 	return ret;
 }
 
+int mountpoint_list_refresh(struct mountpoint_list *list)
+{
+	struct stat st;
+
+	if (list->load_st.st_mtime != 0) {
+		if (stat(list->state_path, &st) < 0) {
+			if (errno == ENOENT)
+				return 0;
+			i_error("stat(%s) failed: %m", list->state_path);
+			return -1;
+		}
+		if (st.st_mtime == list->load_st.st_mtime &&
+		    ST_MTIME_NSEC(st) == ST_MTIME_NSEC(list->load_st) &&
+		    st.st_ino == list->load_st.st_ino) {
+			/* unchanged */
+			return 0;
+		}
+	}
+	array_clear(&list->recs);
+	return mountpoint_list_load(list);
+}
+
 static int
 mountpoint_list_save_to(struct mountpoint_list *list, const char *path)
 {
@@ -175,6 +208,8 @@
 {
 	int ret;
 
+	i_assert(list->perm_path != NULL);
+
 	if (list->load_failed)
 		return -1;
 
diff -r cf34d9fc5cec -r d01932c7828a src/lib-master/mountpoint-list.h
--- a/src/lib-master/mountpoint-list.h	Wed Feb 01 20:21:38 2012 +0200
+++ b/src/lib-master/mountpoint-list.h	Wed Feb 01 20:30:18 2012 +0200
@@ -24,8 +24,13 @@
 
 struct mountpoint_list *
 mountpoint_list_init(const char *perm_path, const char *state_path);
+struct mountpoint_list *
+mountpoint_list_init_readonly(const char *state_path);
 void mountpoint_list_deinit(struct mountpoint_list **list);
 
+/* Reload the mountpoints if they have changed. Returns 0 if ok,
+   -1 if I/O error. */
+int mountpoint_list_refresh(struct mountpoint_list *list);
 /* Save the current list of mountpoints. Returns 0 if successful,
    -1 if I/O error. */
 int mountpoint_list_save(struct mountpoint_list *list);
diff -r cf34d9fc5cec -r d01932c7828a src/lib-storage/mail-user.c
--- a/src/lib-storage/mail-user.c	Wed Feb 01 20:21:38 2012 +0200
+++ b/src/lib-storage/mail-user.c	Wed Feb 01 20:30:18 2012 +0200
@@ -12,6 +12,7 @@
 #include "settings-parser.h"
 #include "auth-master.h"
 #include "master-service.h"
+#include "mountpoint-list.h"
 #include "mail-storage-settings.h"
 #include "mail-storage-private.h"
 #include "mail-namespace.h"
@@ -26,6 +27,8 @@
 static void mail_user_deinit_base(struct mail_user *user)
 {
 	mail_namespaces_deinit(&user->namespaces);
+	if (user->mountpoints != NULL)
+		mountpoint_list_deinit(&user->mountpoints);
 }
 
 struct mail_user *mail_user_alloc(const char *username,
@@ -365,3 +368,35 @@
 	return t_strconcat(net_ip2addr(user->remote_ip), "/",
 			   str_tabescape(user->username), NULL);
 }
+
+bool mail_user_is_path_mounted(struct mail_user *user, const char *path,
+			       const char **error_r)
+{
+	struct mountpoint_list_rec *rec;
+	const char *mounts_path;
+
+	*error_r = NULL;
+
+	if (user->mountpoints == NULL) {
+		mounts_path = t_strdup_printf("%s/"MOUNTPOINT_LIST_FNAME,
+					      user->set->base_dir);
+		user->mountpoints = mountpoint_list_init_readonly(mounts_path);
+	} else {
+		(void)mountpoint_list_refresh(user->mountpoints);
+	}
+	rec = mountpoint_list_find(user->mountpoints, path);
+	if (rec == NULL || strcmp(rec->state, MOUNTPOINT_STATE_IGNORE) == 0) {
+		/* we don't have any knowledge of this path's mountpoint.
+		   assume it's fine. */
+		return TRUE;
+	}
+	/* record exists for this mountpoint. see if it's mounted */
+	if (mountpoint_list_update_mounted(user->mountpoints) == 0 &&
+	    !rec->mounted) {
+		*error_r = t_strdup_printf("Mountpoint %s isn't mounted. "
+			"Mount it or remove it with doveadm mount remove",
+			rec->mount_path);
+		return FALSE;
+	}
+	return TRUE;
+}
diff -r cf34d9fc5cec -r d01932c7828a src/lib-storage/mail-user.h
--- a/src/lib-storage/mail-user.h	Wed Feb 01 20:21:38 2012 +0200
+++ b/src/lib-storage/mail-user.h	Wed Feb 01 20:30:18 2012 +0200
@@ -35,6 +35,8 @@
 	struct mail_storage *storages;
 	ARRAY_DEFINE(hooks, const struct mail_storage_hooks *);
 
+	struct mountpoint_list *mountpoints;
+
 	/* Module-specific contexts. See mail_storage_module_id. */
 	ARRAY_DEFINE(module_contexts, union mail_user_module_context *);
 
@@ -118,5 +120,11 @@
 int mail_user_try_home_expand(struct mail_user *user, const char **path);
 /* Returns unique user+ip identifier for anvil. */
 const char *mail_user_get_anvil_userip_ident(struct mail_user *user);
+/* Returns FALSE if path is in a mountpoint that should be mounted,
+   but isn't mounted. In such a situation it's better to fail than to attempt
+   any kind of automatic file/dir creations. error_r gives an error about which
+   mountpoint should be mounted. */
+bool mail_user_is_path_mounted(struct mail_user *user, const char *path,
+			       const char **error_r);
 
 #endif
diff -r cf34d9fc5cec -r d01932c7828a src/lib-storage/mailbox-list.c
--- a/src/lib-storage/mailbox-list.c	Wed Feb 01 20:21:38 2012 +0200
+++ b/src/lib-storage/mailbox-list.c	Wed Feb 01 20:30:18 2012 +0200
@@ -789,11 +789,23 @@
 			    enum mailbox_list_path_type type,
 			    const char **error_r)
 {
-	const char *expanded, *unexpanded, *root_dir, *p, *origin;
+	const char *expanded, *unexpanded, *root_dir, *p, *origin, *error;
 	struct stat st;
 	mode_t file_mode, dir_mode;
 	gid_t gid;
 
+	if (stat(path, &st) == 0) {
+		/* looks like it already exists, don't bother checking
+		   further. */
+		return 0;
+	}
+
+	if (!mail_user_is_path_mounted(list->ns->user, path, &error)) {
+		*error_r = t_strdup_printf(
+			"Can't create mailbox root dir %s: %s", path, error);
+		return -1;
+	}
+
 	mailbox_list_get_root_permissions(list, &file_mode, &dir_mode,
 					  &gid, &origin);
 


More information about the dovecot-cvs mailing list