dovecot-1.2: shared mailboxes: Cleanups, fixes and optimizations.
dovecot at dovecot.org
dovecot at dovecot.org
Sat Nov 1 16:05:26 EET 2008
details: http://hg.dovecot.org/dovecot-1.2/rev/4aafdbe62680
changeset: 8375:4aafdbe62680
user: Timo Sirainen <tss at iki.fi>
date: Sat Nov 01 16:05:19 2008 +0200
description:
shared mailboxes: Cleanups, fixes and optimizations.
diffstat:
5 files changed, 103 insertions(+), 51 deletions(-)
src/lib-storage/index/dbox/dbox-storage.c | 9 +
src/lib-storage/index/maildir/maildir-storage.c | 5
src/lib-storage/index/mbox/mbox-storage.c | 4
src/lib-storage/index/shared/shared-storage.c | 133 ++++++++++++++---------
src/lib-storage/index/shared/shared-storage.h | 3
diffs (279 lines):
diff -r 9d7c0ff9c2a0 -r 4aafdbe62680 src/lib-storage/index/dbox/dbox-storage.c
--- a/src/lib-storage/index/dbox/dbox-storage.c Sat Nov 01 16:04:24 2008 +0200
+++ b/src/lib-storage/index/dbox/dbox-storage.c Sat Nov 01 16:05:19 2008 +0200
@@ -119,8 +119,13 @@ static int dbox_create(struct mail_stora
} else if (mkdir_parents(list_set.root_dir,
CREATE_MODE) == 0 || errno == EEXIST) {
} else if (errno == EACCES) {
- *error_r = mail_storage_eacces_msg("mkdir", list_set.root_dir);
- return -1;
+ if (_storage->ns->type != NAMESPACE_SHARED) {
+ *error_r = mail_storage_eacces_msg("mkdir",
+ list_set.root_dir);
+ return -1;
+ }
+ /* can't create a new user, but we don't want to fail
+ the storage creation. */
} else {
*error_r = t_strdup_printf("mkdir(%s) failed: %m",
list_set.root_dir);
diff -r 9d7c0ff9c2a0 -r 4aafdbe62680 src/lib-storage/index/maildir/maildir-storage.c
--- a/src/lib-storage/index/maildir/maildir-storage.c Sat Nov 01 16:04:24 2008 +0200
+++ b/src/lib-storage/index/maildir/maildir-storage.c Sat Nov 01 16:05:19 2008 +0200
@@ -317,6 +317,11 @@ static int mkdir_verify(struct mail_stor
} else if (errno == ENOENT) {
mail_storage_set_error(storage, MAIL_ERROR_NOTFOUND,
"Mailbox was deleted while it was being created");
+ } else if (errno == EACCES && storage->ns->type == NAMESPACE_SHARED) {
+ /* shared namespace, don't log permission errors */
+ mail_storage_set_error(storage, MAIL_ERROR_PERM,
+ MAIL_ERRSTR_NO_PERMISSION);
+ return -1;
} else {
mail_storage_set_critical(storage,
"mkdir(%s) failed: %m", dir);
diff -r 9d7c0ff9c2a0 -r 4aafdbe62680 src/lib-storage/index/mbox/mbox-storage.c
--- a/src/lib-storage/index/mbox/mbox-storage.c Sat Nov 01 16:04:24 2008 +0200
+++ b/src/lib-storage/index/mbox/mbox-storage.c Sat Nov 01 16:05:19 2008 +0200
@@ -353,6 +353,10 @@ mbox_get_list_settings(struct mailbox_li
*error_r = t_strdup_printf("lstat(%s) failed: %m",
list_set->root_dir);
return -1;
+ } else if (errno == ENOENT &&
+ storage->ns->type == NAMESPACE_SHARED) {
+ /* can't create a new user, but we don't want to fail
+ the storage creation. */
} else if ((flags & MAIL_STORAGE_FLAG_NO_AUTOCREATE) != 0) {
*error_r = t_strdup_printf(
"Root mail directory doesn't exist: %s",
diff -r 9d7c0ff9c2a0 -r 4aafdbe62680 src/lib-storage/index/shared/shared-storage.c
--- a/src/lib-storage/index/shared/shared-storage.c Sat Nov 01 16:04:24 2008 +0200
+++ b/src/lib-storage/index/shared/shared-storage.c Sat Nov 01 16:05:19 2008 +0200
@@ -9,6 +9,7 @@
#include "shared-storage.h"
#include <stdlib.h>
+#include <ctype.h>
#define SHARED_LIST_CONTEXT(obj) \
MODULE_CONTEXT(obj, shared_mailbox_list_module)
@@ -29,6 +30,10 @@ static struct mail_storage *shared_alloc
storage->storage = shared_storage;
storage->storage.pool = pool;
storage->storage.storage_class = &shared_storage;
+
+ storage->base_dir = p_strdup(pool, getenv("BASE_DIR"));
+ if (storage->base_dir == NULL)
+ storage->base_dir = PKG_RUNDIR;
return &storage->storage;
}
@@ -99,47 +104,62 @@ static int shared_create(struct mail_sto
return 0;
}
-static const char *lookup_home(const char *user)
-{
- const char *auth_socket;
- const char *home = NULL;
- struct auth_connection *conn;
- struct auth_user_reply *reply;
+static void shared_storage_destroy(struct mail_storage *_storage)
+{
+ struct shared_storage *storage = (struct shared_storage *)_storage;
+
+ if (storage->auth_master_conn != NULL)
+ auth_master_deinit(&storage->auth_master_conn);
+ index_storage_destroy(_storage);
+}
+
+static void shared_storage_auth_master_init(struct shared_storage *storage)
+{
+ const char *auth_socket_path;
+ bool debug;
+
+ auth_socket_path = getenv("AUTH_SOCKET_PATH");
+ if (auth_socket_path == NULL) {
+ auth_socket_path = t_strconcat(storage->base_dir,
+ "/auth-master", NULL);
+ }
+
+ debug = (storage->storage.flags & MAIL_STORAGE_FLAG_DEBUG) != 0;
+ storage->auth_master_conn = auth_master_init(auth_socket_path, debug);
+}
+
+static int
+shared_storage_lookup_home(struct shared_storage *storage,
+ const char *user, const char **home_r)
+{
+ struct auth_user_reply reply;
pool_t userdb_pool;
- struct ioloop *userdb_ioloop;
-
- auth_socket = getenv("AUTH_SOCKET_PATH");
- if (auth_socket == NULL) {
- const char *base_dir = getenv("BASE_DIR");
- if (base_dir == NULL)
- base_dir = PKG_RUNDIR;
- auth_socket = t_strconcat(base_dir, "/auth-master",
- NULL);
- }
-
- userdb_pool = pool_alloconly_create("userdb lookup replys", 512);
- userdb_ioloop = io_loop_create();
- conn = auth_master_init(auth_socket, getenv("DEBUG") != NULL);
- reply = i_new(struct auth_user_reply, 1);
-
- switch (auth_master_user_lookup(conn, user, "shared-storage", userdb_pool, reply)) {
- case -1:
- /* Some error during lookup... */
- case 0:
- /* User not found
- FIXME: It might be a good idea to handle this special case... */
- break;
- case 1:
- home = i_strdup(reply->home);
- }
-
- i_free(reply);
- if (conn != NULL)
- auth_master_deinit(conn);
- io_loop_destroy(&userdb_ioloop);
+ int ret;
+
+ if (storage->auth_master_conn == NULL)
+ shared_storage_auth_master_init(storage);
+
+ userdb_pool = pool_alloconly_create("userdb lookup", 512);
+ ret = auth_master_user_lookup(storage->auth_master_conn, user,
+ AUTH_SERVICE_INTERNAL,
+ userdb_pool, &reply);
+ if (ret > 0)
+ *home_r = t_strdup(reply.home);
pool_unref(&userdb_pool);
-
- return home;
+ return ret;
+}
+
+static void get_nonexisting_user_location(struct shared_storage *storage,
+ string_t *location)
+{
+ /* user wasn't found. we'll still need to create the storage
+ to avoid exposing which users exist and which don't. */
+ str_append(location, storage->storage_class->name);
+ str_append_c(location, ':');
+
+ /* use a reachable but non-existing path as the mail root directory */
+ str_append(location, storage->base_dir);
+ str_append(location, PKG_RUNDIR"/user-not-found");
}
int shared_storage_get_namespace(struct mail_storage *_storage,
@@ -157,9 +177,12 @@ int shared_storage_get_namespace(struct
};
struct var_expand_table *tab;
struct mail_namespace *ns;
- const char *domain = NULL, *username = NULL, *userdomain = NULL, *userhome = NULL;
+ const char *domain = NULL, *username = NULL, *userdomain = NULL;
const char *name, *p, *next, **dest, *error;
string_t *prefix, *location;
+ int ret;
+
+ *ns_r = NULL;
p = storage->ns_prefix_pattern;
for (name = *_name; *p != '\0';) {
@@ -207,12 +230,6 @@ int shared_storage_get_namespace(struct
}
}
- userhome = lookup_home(userdomain);
- if (userhome == NULL) {
- i_error("Namespace '%s': could not lookup home for user %s", _storage->ns->prefix, userdomain);
- return -1;
- }
-
/* expand the namespace prefix and see if it already exists.
this should normally happen only when the mailbox is being opened */
tab = t_malloc(sizeof(static_tab));
@@ -220,7 +237,7 @@ int shared_storage_get_namespace(struct
tab[0].value = userdomain;
tab[1].value = username;
tab[2].value = domain;
- tab[3].value = userhome;
+
prefix = t_str_new(128);
str_append(prefix, _storage->ns->prefix);
var_expand(prefix, storage->ns_prefix_pattern, tab);
@@ -230,6 +247,20 @@ int shared_storage_get_namespace(struct
*_name = mail_namespace_fix_sep(ns, name);
*ns_r = ns;
return 0;
+ }
+
+ if (!var_has_key(storage->location, 'h'))
+ ret = 1;
+ else {
+ /* we'll need to look up the user's home directory */
+ ret = shared_storage_lookup_home(storage, userdomain,
+ &tab[3].value);
+ if (ret < 0) {
+ mail_storage_set_critical(_storage, "Namespace '%s': "
+ "Could not lookup home for user %s",
+ _storage->ns->prefix, userdomain);
+ return -1;
+ }
}
/* create the new namespace */
@@ -242,7 +273,10 @@ int shared_storage_get_namespace(struct
ns->sep = _storage->ns->sep;
location = t_str_new(256);
- var_expand(location, storage->location, tab);
+ if (ret > 0)
+ var_expand(location, storage->location, tab);
+ else
+ get_nonexisting_user_location(storage, location);
if (mail_storage_create(ns, NULL, str_c(location), _storage->flags,
_storage->lock_method, &error) < 0) {
mail_storage_set_critical(_storage, "Namespace '%s': %s",
@@ -301,6 +335,7 @@ static int shared_mailbox_create(struct
if (shared_storage_get_namespace(storage, &name, &ns) < 0)
return -1;
+
ret = mail_storage_mailbox_create(ns->storage, name, directory);
if (ret < 0)
shared_mailbox_copy_error(storage, ns);
@@ -316,7 +351,7 @@ struct mail_storage shared_storage = {
NULL,
shared_alloc,
shared_create,
- index_storage_destroy,
+ shared_storage_destroy,
NULL,
shared_mailbox_open,
shared_mailbox_create
diff -r 9d7c0ff9c2a0 -r 4aafdbe62680 src/lib-storage/index/shared/shared-storage.h
--- a/src/lib-storage/index/shared/shared-storage.h Sat Nov 01 16:04:24 2008 +0200
+++ b/src/lib-storage/index/shared/shared-storage.h Sat Nov 01 16:05:19 2008 +0200
@@ -10,14 +10,17 @@ struct shared_storage {
struct mail_storage storage;
union mailbox_list_module_context list_module_ctx;
+ const char *base_dir;
const char *ns_prefix_pattern;
const char *location;
+ struct auth_master_connection *auth_master_conn;
struct mail_storage *storage_class;
};
struct mailbox_list *shared_mailbox_list_alloc(void);
+/* Returns -1 = error, 0 = user doesn't exist, 1 = ok */
int shared_storage_get_namespace(struct mail_storage *storage,
const char **name,
struct mail_namespace **ns_r);
More information about the dovecot-cvs
mailing list