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