static MODULE_CONTEXT_DEFINE_INIT(cydir_mailbox_list_module,
&mailbox_list_module_register);
-static void cydir_list_init(struct mailbox_list *list);
-
static struct mail_storage *cydir_storage_alloc(void)
{
struct cydir_storage *storage;
return &storage->storage;
}
-static int
-cydir_storage_create(struct mail_storage *_storage ATTR_UNUSED,
- struct mail_namespace *ns,
- const char **error_r ATTR_UNUSED)
-{
- cydir_list_init(ns->list);
- return 0;
-}
-
static void
cydir_storage_get_list_settings(const struct mail_namespace *ns ATTR_UNUSED,
struct mailbox_list_settings *set)
cydir_transaction_class_deinit();
}
-static void cydir_list_init(struct mailbox_list *list)
+static void cydir_storage_add_list(struct mail_storage *storage ATTR_UNUSED,
+ struct mailbox_list *list)
{
struct cydir_mailbox_list *mlist;
struct mail_storage cydir_storage = {
MEMBER(name) CYDIR_STORAGE_NAME,
- MEMBER(mailbox_is_file) FALSE,
+ MEMBER(class_flags) 0,
{
NULL,
cydir_class_init,
cydir_class_deinit,
cydir_storage_alloc,
- cydir_storage_create,
+ NULL,
index_storage_destroy,
+ cydir_storage_add_list,
cydir_storage_get_list_settings,
NULL,
cydir_mailbox_open,
{
struct mail_user *user = ctx->storage->storage.user;
struct mail_namespace *ns;
- const char *rebuild_dir, *ns_dir;
- rebuild_dir = ctx->storage->storage_dir;
for (ns = user->namespaces; ns != NULL; ns = ns->next) {
- if (strcmp(ns->storage->name, "dbox") != 0)
- continue;
-
- ns_dir = mailbox_list_get_path(ns->list, NULL,
- MAILBOX_LIST_PATH_TYPE_DIR);
- if (strcmp(ns_dir, rebuild_dir) != 0)
- continue;
-
- if (rebuild_namespace_mailboxes(ctx, ns) < 0)
- return -1;
+ if (ns->storage == &ctx->storage->storage &&
+ ns->alias_for == NULL) {
+ if (rebuild_namespace_mailboxes(ctx, ns) < 0)
+ return -1;
+ }
}
return 0;
}
static MODULE_CONTEXT_DEFINE_INIT(dbox_mailbox_list_module,
&mailbox_list_module_register);
-static void dbox_list_init(struct mailbox_list *list,
- const struct dbox_settings *set);
-
static struct mail_storage *dbox_storage_alloc(void)
{
struct dbox_storage *storage;
return -1;
}
- dbox_list_init(ns->list, storage->set);
+ _storage->unique_root_dir =
+ p_strdup(_storage->pool, ns->list->set.root_dir);
dir = mailbox_list_get_path(ns->list, NULL, MAILBOX_LIST_PATH_TYPE_DIR);
storage->storage_dir = p_strconcat(_storage->pool, dir,
mbox->ibox.box = dbox_mailbox;
mbox->ibox.box.pool = pool;
mbox->ibox.box.storage = _storage;
+ mbox->ibox.box.list = list;
mbox->ibox.mail_vfuncs = &dbox_mail_vfuncs;
mbox->ibox.index = index;
mbox->ibox.keep_index_backups = TRUE;
dbox_transaction_class_deinit();
}
-static void dbox_list_init(struct mailbox_list *list,
- const struct dbox_settings *set)
+static void dbox_storage_add_list(struct mail_storage *storage,
+ struct mailbox_list *list)
{
struct dbox_mailbox_list *mlist;
mlist = p_new(list->pool, struct dbox_mailbox_list, 1);
mlist->module_ctx.super = list->v;
- mlist->set = set;
+ mlist->set = mail_storage_get_driver_settings(storage);
list->v.iter_is_mailbox = dbox_list_iter_is_mailbox;
list->v.delete_mailbox = dbox_list_delete_mailbox;
struct mail_storage dbox_storage = {
MEMBER(name) DBOX_STORAGE_NAME,
- MEMBER(mailbox_is_file) FALSE,
+ MEMBER(class_flags) MAIL_STORAGE_CLASS_FLAG_UNIQUE_ROOT, /* FIXME: for multi-dbox only.. */
{
dbox_get_setting_parser_info,
dbox_storage_alloc,
dbox_storage_create,
dbox_storage_destroy,
+ dbox_storage_add_list,
dbox_storage_get_list_settings,
NULL,
dbox_mailbox_open,
&mailbox_list_module_register);
static const char *maildir_subdirs[] = { "cur", "new", "tmp" };
-static void maildir_list_init(struct mailbox_list *list,
- const struct maildir_settings *set);
-
static bool maildir_is_internal_name(const char *name)
{
return strcmp(name, "cur") == 0 ||
const char *dir;
storage->set = mail_storage_get_driver_settings(_storage);
- maildir_list_init(list, storage->set);
storage->maildir_list_ext_id = (uint32_t)-1;
storage->temp_prefix = mailbox_list_get_temp_prefix(list);
maildir_transaction_class_deinit();
}
-static void maildir_list_init(struct mailbox_list *list,
- const struct maildir_settings *set)
+static void maildir_storage_add_list(struct mail_storage *storage,
+ struct mailbox_list *list)
{
struct maildir_mailbox_list *mlist;
mlist = p_new(list->pool, struct maildir_mailbox_list, 1);
mlist->module_ctx.super = list->v;
- mlist->set = set;
+ mlist->set = mail_storage_get_driver_settings(storage);
if (strcmp(list->name, MAILBOX_LIST_NAME_MAILDIRPLUSPLUS) == 0) {
list->v.iter_is_mailbox = maildirplusplus_iter_is_mailbox;
struct mail_storage maildir_storage = {
MEMBER(name) MAILDIR_STORAGE_NAME,
- MEMBER(mailbox_is_file) FALSE,
+ MEMBER(class_flags) 0,
{
maildir_get_setting_parser_info,
maildir_storage_alloc,
maildir_storage_create,
index_storage_destroy,
+ maildir_storage_add_list,
maildir_storage_get_list_settings,
maildir_storage_autodetect,
maildir_mailbox_open,
static MODULE_CONTEXT_DEFINE_INIT(mbox_mailbox_list_module,
&mailbox_list_module_register);
-static void mbox_list_init(struct mailbox_list *list,
- const struct mbox_settings *set);
-
int mbox_set_syscall_error(struct mbox_mailbox *mbox, const char *function)
{
i_assert(function != NULL);
const char *dir;
storage->set = mail_storage_get_driver_settings(_storage);
- mbox_list_init(ns->list, storage->set);
dir = mailbox_list_get_path(ns->list, NULL,
MAILBOX_LIST_PATH_TYPE_INDEX);
mbox_transaction_class_deinit();
}
-static void mbox_list_init(struct mailbox_list *list,
- const struct mbox_settings *set)
+static void mbox_storage_add_list(struct mail_storage *storage,
+ struct mailbox_list *list)
{
struct mbox_mailbox_list *mlist;
mlist = p_new(list->pool, struct mbox_mailbox_list, 1);
mlist->module_ctx.super = list->v;
- mlist->set = set;
+ mlist->set = mail_storage_get_driver_settings(storage);
if (strcmp(list->name, MAILBOX_LIST_NAME_FS) == 0 &&
*list->set.maildir_name == '\0') {
struct mail_storage mbox_storage = {
MEMBER(name) MBOX_STORAGE_NAME,
- MEMBER(mailbox_is_file) TRUE,
+ MEMBER(class_flags) MAIL_STORAGE_CLASS_FLAG_MAILBOX_IS_FILE,
{
mbox_get_setting_parser_info,
mbox_storage_alloc,
mbox_storage_create,
index_storage_destroy,
+ mbox_storage_add_list,
mbox_storage_get_list_settings,
mbox_storage_autodetect,
mbox_mailbox_open,
extern struct mail_storage raw_storage;
extern struct mailbox raw_mailbox;
-static void raw_list_init(struct mailbox_list *list);
-
static struct mail_storage *raw_storage_alloc(void)
{
struct raw_storage *storage;
return &storage->storage;
}
-static int
-raw_storage_create(struct mail_storage *_storage ATTR_UNUSED,
- struct mail_namespace *ns, const char **error_r ATTR_UNUSED)
-{
- raw_list_init(ns->list);
- return 0;
-}
-
static void
raw_storage_get_list_settings(const struct mail_namespace *ns ATTR_UNUSED,
struct mailbox_list_settings *set)
raw_transaction_class_deinit();
}
-static void raw_list_init(struct mailbox_list *list)
+static void raw_storage_add_list(struct mail_storage *storage ATTR_UNUSED,
+ struct mailbox_list *list)
{
list->v.iter_is_mailbox = raw_list_iter_is_mailbox;
list->v.delete_mailbox = raw_list_delete_mailbox;
struct mail_storage raw_storage = {
MEMBER(name) RAW_STORAGE_NAME,
- MEMBER(mailbox_is_file) TRUE,
+ MEMBER(class_flags) MAIL_STORAGE_CLASS_FLAG_MAILBOX_IS_FILE,
{
NULL,
raw_class_init,
raw_class_deinit,
raw_storage_alloc,
- raw_storage_create,
+ NULL,
index_storage_destroy,
+ raw_storage_add_list,
raw_storage_get_list_settings,
NULL,
raw_mailbox_open,
driver, NULL);
return -1;
}
- _storage->mailbox_is_file = storage->storage_class->mailbox_is_file;
+ _storage->class_flags = storage->storage_class->class_flags;
wildcardp = strchr(ns->prefix, '%');
if (wildcardp == NULL) {
struct mail_storage shared_storage = {
MEMBER(name) SHARED_STORAGE_NAME,
- MEMBER(mailbox_is_file) FALSE, /* unknown at this point */
+ MEMBER(class_flags) 0, /* unknown at this point */
{
NULL,
shared_storage_alloc,
shared_storage_create,
index_storage_destroy,
+ NULL,
shared_storage_get_list_settings,
NULL,
NULL,
#include "array.h"
#include "str.h"
#include "file-lock.h"
-#include "mail-storage.h"
+#include "mail-storage-private.h"
#include "mail-storage-settings.h"
#include "mail-namespace.h"
/* currently we support only a single storage */
i_assert(ns->storage == NULL);
ns->storage = storage;
+
+ if (storage->v.add_list != NULL)
+ storage->v.add_list(storage, ns->list);
}
void mail_namespace_finish_list_init(struct mail_namespace *ns,
static void mail_namespace_free(struct mail_namespace *ns)
{
if (ns->storage != NULL)
- mail_storage_destroy(&ns->storage);
+ mail_storage_unref(&ns->storage);
if (ns->list != NULL)
mailbox_list_destroy(&ns->list);
}
}
- if (ns->storage != NULL)
- mail_storage_destroy(&ns->storage);
mail_namespace_free(ns);
}
int (*create)(struct mail_storage *storage, struct mail_namespace *ns,
const char **error_r);
void (*destroy)(struct mail_storage *storage);
+ void (*add_list)(struct mail_storage *storage,
+ struct mailbox_list *list);
void (*get_list_settings)(const struct mail_namespace *ns,
struct mailbox_list_settings *set);
struct mail_storage_module_register *reg;
};
+enum mail_storage_class_flags {
+ /* mailboxes are files, not directories */
+ MAIL_STORAGE_CLASS_FLAG_MAILBOX_IS_FILE = 0x01,
+ /* root_dir points to a unique directory */
+ MAIL_STORAGE_CLASS_FLAG_UNIQUE_ROOT = 0x02
+};
+
struct mail_storage {
const char *name;
- bool mailbox_is_file;
+ enum mail_storage_class_flags class_flags;
struct mail_storage_vfuncs v;
/* private: */
pool_t pool;
+ struct mail_storage *prev, *next;
+ int refcount;
+ const char *unique_root_dir;
char *error_string;
enum mail_error error;
#include "lib.h"
#include "ioloop.h"
#include "array.h"
+#include "llist.h"
#include "mkdir-parents.h"
#include "var-expand.h"
#include "mail-index-private.h"
}
}
+static struct mail_storage *
+mail_storage_find(struct mail_user *user,
+ const struct mail_storage *storage_class,
+ const struct mailbox_list_settings *set)
+{
+ struct mail_storage *storage = user->storages;
+
+ for (; storage != NULL; storage = storage->next) {
+ if (strcmp(storage->name, storage_class->name) == 0 &&
+ ((storage->class_flags &
+ MAIL_STORAGE_CLASS_FLAG_UNIQUE_ROOT) == 0 ||
+ strcmp(storage->unique_root_dir, set->root_dir) == 0))
+ return storage;
+ }
+ return NULL;
+}
+
int mail_storage_create(struct mail_namespace *ns, const char *driver,
enum mail_storage_flags flags, const char **error_r)
{
return -1;
}
+ storage = mail_storage_find(ns->user, storage_class, &list_set);
+ if (storage != NULL) {
+ /* using an existing storage */
+ storage->refcount++;
+ mail_namespace_add_storage(ns, storage);
+ return 0;
+ }
+
storage = storage_class->v.alloc();
+ storage->refcount = 1;
storage->storage_class = storage_class;
storage->user = ns->user;
storage->set = ns->mail_set;
p_new(storage->pool, struct mail_storage_callbacks, 1);
p_array_init(&storage->module_contexts, storage->pool, 5);
- if (storage->v.create(storage, ns, error_r) < 0) {
+ if (storage->v.create != NULL &&
+ storage->v.create(storage, ns, error_r) < 0) {
*error_r = t_strdup_printf("%s: %s", storage->name, *error_r);
pool_unref(&storage->pool);
return -1;
hook_mail_storage_created(storage);
} T_END;
+ DLLIST_PREPEND(&ns->user->storages, storage);
mail_namespace_add_storage(ns, storage);
return 0;
}
-void mail_storage_destroy(struct mail_storage **_storage)
+void mail_storage_ref(struct mail_storage *storage)
+{
+ storage->refcount++;
+}
+
+void mail_storage_unref(struct mail_storage **_storage)
{
struct mail_storage *storage = *_storage;
- i_assert(storage != NULL);
+ i_assert(storage->refcount > 0);
*_storage = NULL;
+ if (--storage->refcount > 0)
+ return;
+
+ DLLIST_REMOVE(&storage->user->storages, storage);
+
storage->v.destroy(storage);
i_free(storage->error_string);
pool_unref(&storage->pool);
bool mail_storage_is_mailbox_file(struct mail_storage *storage)
{
- return storage->mailbox_is_file;
+ return (storage->class_flags &
+ MAIL_STORAGE_CLASS_FLAG_MAILBOX_IS_FILE) != 0;
}
bool mail_storage_set_error_from_errno(struct mail_storage *storage)
exists. The storage is put into ns->storage. */
int mail_storage_create(struct mail_namespace *ns, const char *driver,
enum mail_storage_flags flags, const char **error_r);
-void mail_storage_destroy(struct mail_storage **storage);
+void mail_storage_ref(struct mail_storage *storage);
+void mail_storage_unref(struct mail_storage **storage);
/* Returns the mail storage settings. */
const struct mail_storage_settings *
const struct mail_user_settings *unexpanded_set;
struct mail_user_settings *set;
struct mail_namespace *namespaces;
+ struct mail_storage *storages;
/* Module-specific contexts. See mail_storage_module_id. */
ARRAY_DEFINE(module_contexts, union mail_user_module_context *);
const char *mailbox_list_get_last_error(struct mailbox_list *list,
enum mail_error *error_r)
{
- *error_r = list->error;
+ if (error_r != NULL)
+ *error_r = list->error;
return list->error_string != NULL ? list->error_string :
"Unknown internal list error";
/* just in case if another process just had converted the mailbox,
reopen the source storage */
- mail_storage_destroy(&source_ns->storage);
+ mail_storage_unref(&source_ns->storage);
if (mail_storage_create(source_ns, NULL,
MAIL_STORAGE_FLAG_NO_AUTOCREATE, &error) < 0) {
/* No need for conversion anymore. */
static MODULE_CONTEXT_DEFINE_INIT(virtual_mailbox_list_module,
&mailbox_list_module_register);
-static void virtual_list_init(struct mailbox_list *list);
-
void virtual_box_copy_error(struct mailbox *dest, struct mailbox *src)
{
const char *str;
return &storage->storage;
}
-static int
-virtual_storage_create(struct mail_storage *_storage ATTR_UNUSED,
- struct mail_namespace *ns,
- const char **error_r ATTR_UNUSED)
-{
- ns->flags |= NAMESPACE_FLAG_NOQUOTA;
- virtual_list_init(ns->list);
- return 0;
-}
-
static void
virtual_storage_get_list_settings(const struct mail_namespace *ns ATTR_UNUSED,
struct mailbox_list_settings *set)
virtual_transaction_class_deinit();
}
-static void virtual_list_init(struct mailbox_list *list)
+static void virtual_storage_add_list(struct mail_storage *storage ATTR_UNUSED,
+ struct mailbox_list *list)
{
struct virtual_mailbox_list *mlist;
mlist = p_new(list->pool, struct virtual_mailbox_list, 1);
mlist->module_ctx.super = list->v;
+ list->ns->flags |= NAMESPACE_FLAG_NOQUOTA;
+
list->v.iter_is_mailbox = virtual_list_iter_is_mailbox;
list->v.delete_mailbox = virtual_list_delete_mailbox;
struct mail_storage virtual_storage = {
MEMBER(name) VIRTUAL_STORAGE_NAME,
- MEMBER(mailbox_is_file) FALSE,
+ MEMBER(class_flags) 0,
{
NULL,
virtual_class_init,
virtual_class_deinit,
virtual_storage_alloc,
- virtual_storage_create,
+ NULL,
index_storage_destroy,
+ virtual_storage_add_list,
virtual_storage_get_list_settings,
NULL,
virtual_mailbox_open,