cydir-storage.c revision 1108376e39a19912e8394e64e19b1bc6f6691cf6
5f5870385cff47efd2f58e7892f251cf13761528Timo Sirainen/* Copyright (C) 2007 Timo Sirainen */
bbadd5331f534017cf62d5183003b3d9fdad079eTimo Sirainen#define CREATE_MODE 0770 /* umask() should limit it more */
9f0f2de10e4ea0c99052bf4b2bef8179f2536228Timo Sirainen MODULE_CONTEXT(obj, cydir_mailbox_list_module)
373492be949e159fda651807b3acda2c5c077027Timo Sirainenstatic MODULE_CONTEXT_DEFINE_INIT(cydir_mailbox_list_module,
9f0f2de10e4ea0c99052bf4b2bef8179f2536228Timo Sirainencydir_list_delete_mailbox(struct mailbox_list *list, const char *name);
9f0f2de10e4ea0c99052bf4b2bef8179f2536228Timo Sirainenstatic int cydir_list_iter_is_mailbox(struct mailbox_list_iterate_context *ctx,
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainencydir_get_list_settings(struct mailbox_list_settings *list_set,
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen const char *data, enum mail_storage_flags flags)
635df5b4cbcd7b24c825e01d9dd66d3a4274c4c7Timo Sirainen bool debug = (flags & MAIL_STORAGE_FLAG_DEBUG) != 0;
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen const char *p;
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen list_set->subscription_fname = CYDIR_SUBSCRIPTION_FILE_NAME;
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen /* we won't do any guessing for this format. */
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen /* <root dir> [:INDEX=<dir>] */
9f0f2de10e4ea0c99052bf4b2bef8179f2536228Timo Sirainen } while (p != NULL);
9f0f2de10e4ea0c99052bf4b2bef8179f2536228Timo Sirainen /* strip trailing '/' */
9f0f2de10e4ea0c99052bf4b2bef8179f2536228Timo Sirainen list_set->root_dir = t_strndup(list_set->root_dir, len-1);
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen pool = pool_alloconly_create("cydir storage", 512+256);
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen storage = p_new(pool, struct cydir_storage, 1);
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainenstatic int cydir_create(struct mail_storage *_storage, const char *data)
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen struct cydir_storage *storage = (struct cydir_storage *)_storage;
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen if (cydir_get_list_settings(&list_set, data, _storage->flags) < 0)
7744586e3e0fd60158abfbb03a233d3bd8d6c48bTimo Sirainen list_set.mail_storage_flags = &_storage->flags;
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen list_set.lock_method = &_storage->lock_method;
04052d7cacaa866a3f00afb4e104fa46c04c1dd7Timo Sirainen if ((_storage->flags & MAIL_STORAGE_FLAG_NO_AUTOCREATE) != 0) {
3cf67672fdc87583cb23ce088c95bb5dee60e74dTimo Sirainen if (mkdir_parents(list_set.root_dir, CREATE_MODE) < 0 &&
04052d7cacaa866a3f00afb4e104fa46c04c1dd7Timo Sirainen i_error("mkdir_parents(%s) failed: %m", list_set.root_dir);
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen storage->list_module_ctx.super = _storage->list->v;
9dd1c256910f1fb42823116a641e7edb3ad11970Timo Sirainen _storage->list->v.iter_is_mailbox = cydir_list_iter_is_mailbox;
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen _storage->list->v.delete_mailbox = cydir_list_delete_mailbox;
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen MODULE_CONTEXT_SET_FULL(_storage->list, cydir_mailbox_list_module,
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainenstatic int create_cydir(struct mail_storage *storage, const char *path)
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen if (mkdir_parents(path, CREATE_MODE) < 0 && errno != EEXIST) {
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen mail_storage_set_critical(storage, "mkdir(%s) failed: %m",
04052d7cacaa866a3f00afb4e104fa46c04c1dd7Timo Sirainenstatic int create_index_dir(struct mail_storage *storage, const char *name)
7744586e3e0fd60158abfbb03a233d3bd8d6c48bTimo Sirainen root_dir = mailbox_list_get_path(storage->list, name,
1b823b2b7790a1e1b7974fcf11a4c48a28e70f37Timo Sirainen index_dir = mailbox_list_get_path(storage->list, name,
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen if (mkdir_parents(index_dir, CREATE_MODE) < 0 && errno != EEXIST) {
9dd1c256910f1fb42823116a641e7edb3ad11970Timo Sirainen mail_storage_set_critical(storage, "mkdir(%s) failed: %m",
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainenstatic bool cydir_is_recent(struct index_mailbox *ibox __attr_unused__,
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainenstatic struct mailbox *
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainencydir_open(struct cydir_storage *storage, const char *name,
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen struct mail_storage *_storage = &storage->storage;
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen path = mailbox_list_get_path(_storage->list, name,
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen index_dir = mailbox_list_get_path(_storage->list, name,
a7f5035eebbd138a5436a2eb2ce1fa5fd3d269fbTimo Sirainen index = index_storage_alloc(index_dir, path, CYDIR_INDEX_PREFIX);
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen pool = pool_alloconly_create("cydir mailbox", 1024+512);
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen index_storage_mailbox_init(&mbox->ibox, name, flags, FALSE);
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainenstatic struct mailbox *
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainencydir_mailbox_open(struct mail_storage *_storage, const char *name,
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen struct istream *input, enum mailbox_open_flags flags)
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen struct cydir_storage *storage = (struct cydir_storage *)_storage;
062ea54b7775d0c92ed67b9b1f4d93fa8ec80c84Timo Sirainen "cydir doesn't support streamed mailboxes");
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen if (!mailbox_list_is_valid_existing_name(_storage->list, name)) {
a7f5035eebbd138a5436a2eb2ce1fa5fd3d269fbTimo Sirainen mail_storage_set_error(_storage, "Invalid mailbox name");
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen path = mailbox_list_get_path(_storage->list, name,
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen mail_storage_set_critical(_storage, "stat(%s) failed: %m",
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainenstatic int cydir_mailbox_create(struct mail_storage *_storage,
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen if (!mailbox_list_is_valid_create_name(_storage->list, name)) {
383d0e8c24451468d6bea17e4b55d74de744abe6Timo Sirainen mail_storage_set_error(_storage, "Invalid mailbox name");
d477acb83e14a776ece4ca94dcd1869e75d0c6eeTimo Sirainen path = mailbox_list_get_path(_storage->list, name,
738cfeb96c4b9cd92aa3c791d77734c2745cdd1aTimo Sirainen mail_storage_set_error(_storage, "Mailbox already exists");
738cfeb96c4b9cd92aa3c791d77734c2745cdd1aTimo Sirainencydir_delete_nonrecursive(struct mailbox_list *list, const char *path,
738cfeb96c4b9cd92aa3c791d77734c2745cdd1aTimo Sirainen unsigned int dir_len;
15f526e5ac611b4532568d131fcd0abf664abe41Timo Sirainen /* skip . and .. */
f93c833d644ecff0b0f80bee4f1cdde3e697b5c8Timo Sirainen if (d->d_name[1] == '.' && d->d_name[2] == '\0')
4fc74bba3548987b7e8597491cd9fafc1f701be6Timo Sirainen /* trying to unlink() a directory gives either EPERM or EISDIR
4fc74bba3548987b7e8597491cd9fafc1f701be6Timo Sirainen (non-POSIX). it doesn't really work anywhere in practise,
4fc74bba3548987b7e8597491cd9fafc1f701be6Timo Sirainen so don't bother stat()ing the file first */
4fc74bba3548987b7e8597491cd9fafc1f701be6Timo Sirainen else if (errno != ENOENT && errno != EISDIR && errno != EPERM) {
7289c5600711b45f30fe289ab5b0293b51d87041Timo Sirainen "unlink_directory(%s) failed: %m",
7289c5600711b45f30fe289ab5b0293b51d87041Timo Sirainen mailbox_list_set_critical(list, "closedir(%s) failed: %m",
7289c5600711b45f30fe289ab5b0293b51d87041Timo Sirainen else if (errno != ENOENT && errno != ENOTEMPTY) {
7289c5600711b45f30fe289ab5b0293b51d87041Timo Sirainen mailbox_list_set_critical(list, "rmdir(%s) failed: %m", path);
d477acb83e14a776ece4ca94dcd1869e75d0c6eeTimo Sirainen "Directory %s isn't empty, can't delete it.", name));
9dd1c256910f1fb42823116a641e7edb3ad11970Timo Sirainencydir_list_delete_mailbox(struct mailbox_list *list, const char *name)
9dd1c256910f1fb42823116a641e7edb3ad11970Timo Sirainen struct cydir_storage *storage = CYDIR_LIST_CONTEXT(list);
9dd1c256910f1fb42823116a641e7edb3ad11970Timo Sirainen const char *src;
9dd1c256910f1fb42823116a641e7edb3ad11970Timo Sirainen /* Make sure the indexes are closed before trying to delete the
9dd1c256910f1fb42823116a641e7edb3ad11970Timo Sirainen directory that contains them. It can still fail with some NFS
9dd1c256910f1fb42823116a641e7edb3ad11970Timo Sirainen implementations if indexes are opened by another session, but
9dd1c256910f1fb42823116a641e7edb3ad11970Timo Sirainen that can't really be helped. */
9dd1c256910f1fb42823116a641e7edb3ad11970Timo Sirainen /* delete the index and control directories */
9dd1c256910f1fb42823116a641e7edb3ad11970Timo Sirainen if (storage->list_module_ctx.super.delete_mailbox(list, name) < 0)
272aca0a772140d3a45a425a3fd67854ae2ccec2Timo Sirainen /* check if the mailbox actually exists */
9dd1c256910f1fb42823116a641e7edb3ad11970Timo Sirainen src = mailbox_list_get_path(list, name, MAILBOX_LIST_PATH_TYPE_MAILBOX);
1d22eaac93de41319918a1fc6de42bb302e25c1aTimo Sirainen return cydir_delete_nonrecursive(list, src, name);
5d60e31c7b701b606067a20bc88dcc8a6de7bbd6Timo Sirainenstatic int cydir_storage_close(struct mailbox *box)
5d60e31c7b701b606067a20bc88dcc8a6de7bbd6Timo Sirainencydir_notify_changes(struct mailbox *box, unsigned int min_interval,
e9371f899a3d4207a0ffd3923ea5ec7250cf5e75Timo Sirainen mailbox_notify_callback_t *callback, void *context)
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen struct cydir_mailbox *mbox = (struct cydir_mailbox *)box;
9ed2951bd0bb1878a27437d7c00611b2baadd614Timo Sirainen mbox->ibox.min_notify_interval = min_interval;
5d60e31c7b701b606067a20bc88dcc8a6de7bbd6Timo Sirainen index_mailbox_check_add(&mbox->ibox, mbox->path);
e9371f899a3d4207a0ffd3923ea5ec7250cf5e75Timo Sirainenstatic int cydir_list_iter_is_mailbox(struct mailbox_list_iterate_context *ctx,
const char *mail_path;
t_push();
ret = 0;
t_pop();
return ret;
static void cydir_class_init(void)
static void cydir_class_deinit(void)
NULL,
NULL,