virtual-storage.c revision 4ba9a1d3facc515b3feb5238a16bcf91f76fac61
e59faf65ce864fe95dc00f5d52b8323cdbd0608aTimo Sirainen/* Copyright (c) 2008-2010 Dovecot authors, see the included COPYING file */
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen MODULE_CONTEXT(obj, virtual_mailbox_list_module)
f5a7396b31762a1f876517e13ce9065820139f7cTimo Sirainenstruct virtual_storage_module virtual_storage_module =
f5a7396b31762a1f876517e13ce9065820139f7cTimo Sirainen MODULE_CONTEXT_INIT(&mail_storage_module_register);
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainenstatic MODULE_CONTEXT_DEFINE_INIT(virtual_mailbox_list_module,
132487b9a47c2eb6fc80cfa2b0aaf82c6dc3af56Timo Sirainenstatic bool ns_is_visible(struct mail_namespace *ns)
132487b9a47c2eb6fc80cfa2b0aaf82c6dc3af56Timo Sirainen return (ns->flags & NAMESPACE_FLAG_LIST_PREFIX) != 0 ||
132487b9a47c2eb6fc80cfa2b0aaf82c6dc3af56Timo Sirainen (ns->flags & NAMESPACE_FLAG_LIST_CHILDREN) != 0 ||
132487b9a47c2eb6fc80cfa2b0aaf82c6dc3af56Timo Sirainenstatic const char *get_user_visible_mailbox_name(struct mailbox *box)
942302b0247403645394d848b3c620ead262a2a5Timo Sirainenvoid virtual_box_copy_error(struct mailbox *dest, struct mailbox *src)
942302b0247403645394d848b3c620ead262a2a5Timo Sirainen str = mail_storage_get_last_error(src->storage, &error);
132487b9a47c2eb6fc80cfa2b0aaf82c6dc3af56Timo Sirainen str = t_strdup_printf("%s (for backend mailbox %s)", str, name);
942302b0247403645394d848b3c620ead262a2a5Timo Sirainen mail_storage_set_error(dest->storage, error, str);
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainenstatic struct mail_storage *virtual_storage_alloc(void)
cd8507179823de33d6e8242e10dbc15d136245b5Timo Sirainen pool = pool_alloconly_create("virtual storage", 1024);
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen storage = p_new(pool, struct virtual_storage, 1);
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainenvirtual_storage_get_list_settings(const struct mail_namespace *ns ATTR_UNUSED,
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen set->subscription_fname = VIRTUAL_SUBSCRIPTION_FILE_NAME;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainenvirtual_backend_box_lookup_name(struct virtual_mailbox *mbox, const char *name)
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen unsigned int i, count;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen bboxes = array_get(&mbox->backend_boxes, &count);
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen for (i = 0; i < count; i++) {
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainenvirtual_backend_box_lookup(struct virtual_mailbox *mbox, uint32_t mailbox_id)
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen unsigned int i, count;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen bboxes = array_get(&mbox->backend_boxes, &count);
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen for (i = 0; i < count; i++) {
c93ff0433cc3d348116f75a64f9988fedb86fd18Timo Sirainenstatic bool virtual_mailbox_is_in_open_stack(struct virtual_storage *storage,
c93ff0433cc3d348116f75a64f9988fedb86fd18Timo Sirainen const char *const *names;
c93ff0433cc3d348116f75a64f9988fedb86fd18Timo Sirainen unsigned int i, count;
c93ff0433cc3d348116f75a64f9988fedb86fd18Timo Sirainen names = array_get(&storage->open_stack, &count);
c93ff0433cc3d348116f75a64f9988fedb86fd18Timo Sirainen for (i = 0; i < count; i++) {
132487b9a47c2eb6fc80cfa2b0aaf82c6dc3af56Timo Sirainenstatic int virtual_backend_box_open_failed(struct virtual_mailbox *mbox,
132487b9a47c2eb6fc80cfa2b0aaf82c6dc3af56Timo Sirainen str = mail_storage_get_last_error(mailbox_get_storage(bbox->box),
132487b9a47c2eb6fc80cfa2b0aaf82c6dc3af56Timo Sirainen name = t_strdup(get_user_visible_mailbox_name(bbox->box));
755aea84bbe2b15ed7fe991f6462a93333ff571fTimo Sirainen /* ignore this. it could be intentional. */
755aea84bbe2b15ed7fe991f6462a93333ff571fTimo Sirainen if (mbox->storage->storage.user->mail_debug) {
755aea84bbe2b15ed7fe991f6462a93333ff571fTimo Sirainen "Skipping non-existing mailbox %s",
755aea84bbe2b15ed7fe991f6462a93333ff571fTimo Sirainen if (error == MAIL_ERROR_PERM && bbox->wildcard) {
755aea84bbe2b15ed7fe991f6462a93333ff571fTimo Sirainen /* this mailbox wasn't explicitly specified. just skip it. */
132487b9a47c2eb6fc80cfa2b0aaf82c6dc3af56Timo Sirainen "Virtual mailbox open failed because of mailbox %s: %s",
132487b9a47c2eb6fc80cfa2b0aaf82c6dc3af56Timo Sirainen mail_storage_set_error(mbox->box.storage, error, str);
6b399f555c9c5c722d4cd5eab8faa02b2a4731d3Timo Sirainenstatic int virtual_backend_box_open(struct virtual_mailbox *mbox,
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen struct mail_user *user = mbox->storage->storage.user;
6b399f555c9c5c722d4cd5eab8faa02b2a4731d3Timo Sirainen ns = mail_namespace_find(user->namespaces, &mailbox);
e5fd6dfd0a492e4708d4dbb7971d7fc5d7b8fd85Timo Sirainen bbox->box = mailbox_alloc(ns->list, mailbox, flags);
132487b9a47c2eb6fc80cfa2b0aaf82c6dc3af56Timo Sirainen return virtual_backend_box_open_failed(mbox, bbox);
6b399f555c9c5c722d4cd5eab8faa02b2a4731d3Timo Sirainen i_array_init(&bbox->sync_pending_removes, 64);
6b399f555c9c5c722d4cd5eab8faa02b2a4731d3Timo Sirainen mail_search_args_init(bbox->search_args, bbox->box, FALSE, NULL);
6b399f555c9c5c722d4cd5eab8faa02b2a4731d3Timo Sirainenstatic int virtual_mailboxes_open(struct virtual_mailbox *mbox,
6b399f555c9c5c722d4cd5eab8faa02b2a4731d3Timo Sirainen unsigned int i, count;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen bboxes = array_get(&mbox->backend_boxes, &count);
7f3b826a89bcb7a72759912e99f574b28309fe1bTimo Sirainen for (i = 0; i < count; ) {
6b399f555c9c5c722d4cd5eab8faa02b2a4731d3Timo Sirainen ret = virtual_backend_box_open(mbox, bboxes[i], flags);
6b399f555c9c5c722d4cd5eab8faa02b2a4731d3Timo Sirainen mail_search_args_unref(&bboxes[i]->search_args);
6b399f555c9c5c722d4cd5eab8faa02b2a4731d3Timo Sirainen bboxes = array_get(&mbox->backend_boxes, &count);
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen for (; i > 0; i--) {
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainenstatic struct mailbox *
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainenvirtual_mailbox_alloc(struct mail_storage *_storage, struct mailbox_list *list,
18ccd19c244f49665fe03cda785efa066d2c38dfTimo Sirainen struct virtual_storage *storage = (struct virtual_storage *)_storage;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen pool = pool_alloconly_create("virtual mailbox", 1024+512);
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen mbox = p_new(pool, struct virtual_mailbox, 1);
e5fd6dfd0a492e4708d4dbb7971d7fc5d7b8fd85Timo Sirainen index_storage_mailbox_alloc(&mbox->box, name, flags,
ecdce39e5ef4b62eefa9f5818f17d153fd5d710aTimo Sirainen mbox->vseq_lookup_prev_mailbox = i_strdup("");
d22301419109ed4a38351715e6760011421dadecTimo Sirainen mail_index_ext_register(mbox->box.index, "virtual", 0,
eca30f1fe8556c46abc75c94d03f59b2e89d4162Timo Sirainenstatic void virtual_mailbox_close_internal(struct virtual_mailbox *mbox)
eca30f1fe8556c46abc75c94d03f59b2e89d4162Timo Sirainen unsigned int i, count;
eca30f1fe8556c46abc75c94d03f59b2e89d4162Timo Sirainen bboxes = array_get_modifiable(&mbox->backend_boxes, &count);
eca30f1fe8556c46abc75c94d03f59b2e89d4162Timo Sirainen for (i = 0; i < count; i++) {
eca30f1fe8556c46abc75c94d03f59b2e89d4162Timo Sirainen mailbox_search_result_free(&bboxes[i]->search_result);
eca30f1fe8556c46abc75c94d03f59b2e89d4162Timo Sirainen mail_search_args_deinit(bboxes[i]->search_args);
eca30f1fe8556c46abc75c94d03f59b2e89d4162Timo Sirainen if (array_is_created(&bboxes[i]->sync_outside_expunges))
eca30f1fe8556c46abc75c94d03f59b2e89d4162Timo Sirainen array_free(&bboxes[i]->sync_outside_expunges);
eca30f1fe8556c46abc75c94d03f59b2e89d4162Timo Sirainen i_free_and_null(mbox->vseq_lookup_prev_mailbox);
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainenstatic int virtual_mailbox_open(struct mailbox *box)
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen struct virtual_mailbox *mbox = (struct virtual_mailbox *)box;
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen if (virtual_mailbox_is_in_open_stack(mbox->storage, box->name)) {
eca30f1fe8556c46abc75c94d03f59b2e89d4162Timo Sirainen array_append(&mbox->storage->open_stack, &box->name, 1);
eca30f1fe8556c46abc75c94d03f59b2e89d4162Timo Sirainen ret = virtual_mailboxes_open(mbox, box->flags);
eca30f1fe8556c46abc75c94d03f59b2e89d4162Timo Sirainen array_count(&mbox->storage->open_stack)-1, 1);
eca30f1fe8556c46abc75c94d03f59b2e89d4162Timo Sirainen return index_storage_mailbox_open(box, FALSE);
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainenstatic void virtual_mailbox_close(struct mailbox *box)
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen struct virtual_mailbox *mbox = (struct virtual_mailbox *)box;
eca30f1fe8556c46abc75c94d03f59b2e89d4162Timo Sirainenstatic void virtual_mailbox_free(struct mailbox *box)
eca30f1fe8556c46abc75c94d03f59b2e89d4162Timo Sirainen struct virtual_mailbox *mbox = (struct virtual_mailbox *)box;
17ad2164c747cedbf81dae1893063e71a3df0356Timo Sirainen const struct mailbox_update *update ATTR_UNUSED,
17ad2164c747cedbf81dae1893063e71a3df0356Timo Sirainen mail_storage_set_error(box->storage, MAIL_ERROR_NOTPOSSIBLE,
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen "Can't create virtual mailboxes");
17ad2164c747cedbf81dae1893063e71a3df0356Timo Sirainen const struct mailbox_update *update ATTR_UNUSED)
17ad2164c747cedbf81dae1893063e71a3df0356Timo Sirainen mail_storage_set_error(box->storage, MAIL_ERROR_NOTPOSSIBLE,
17ad2164c747cedbf81dae1893063e71a3df0356Timo Sirainen "Can't update virtual mailboxes");
d859478e8b106de6cea54f26861bd4232c92f62cTimo Sirainen mail_storage_set_error(box->storage, MAIL_ERROR_NOTPOSSIBLE,
d859478e8b106de6cea54f26861bd4232c92f62cTimo Sirainen "Virtual mailboxes have no GUIDs");
77d8223da3da23b731257596abefa77e4485b77dTimo Sirainenvirtual_notify_callback(struct mailbox *bbox ATTR_UNUSED, struct mailbox *box)
77d8223da3da23b731257596abefa77e4485b77dTimo Sirainen box->notify_callback(box, box->notify_context);
77d8223da3da23b731257596abefa77e4485b77dTimo Sirainenstatic void virtual_notify_changes(struct mailbox *box)
77d8223da3da23b731257596abefa77e4485b77dTimo Sirainen struct virtual_mailbox *mbox = (struct virtual_mailbox *)box;
77d8223da3da23b731257596abefa77e4485b77dTimo Sirainen unsigned int i, count;
77d8223da3da23b731257596abefa77e4485b77dTimo Sirainen bboxes = array_get(&mbox->backend_boxes, &count);
77d8223da3da23b731257596abefa77e4485b77dTimo Sirainen for (i = 0; i < count; i++) {
77d8223da3da23b731257596abefa77e4485b77dTimo Sirainen mailbox_notify_changes(bbox, box->notify_min_interval,
dca6d617a23e3f93af3b8df59acb46478179fe55Timo Sirainenvirtual_list_get_mailbox_flags(struct mailbox_list *list,
dca6d617a23e3f93af3b8df59acb46478179fe55Timo Sirainen struct virtual_mailbox_list *mlist = VIRTUAL_LIST_CONTEXT(list);
dca6d617a23e3f93af3b8df59acb46478179fe55Timo Sirainen get_mailbox_flags(list, dir, fname, type, st_r, flags);
dca6d617a23e3f93af3b8df59acb46478179fe55Timo Sirainen if (ret <= 0 || MAILBOX_INFO_FLAGS_FINISHED(*flags))
dca6d617a23e3f93af3b8df59acb46478179fe55Timo Sirainen /* see if it's a selectable mailbox */
dca6d617a23e3f93af3b8df59acb46478179fe55Timo Sirainen virtual_path = t_strconcat(dir, "/", fname, "/"VIRTUAL_CONFIG_FNAME,
dca6d617a23e3f93af3b8df59acb46478179fe55Timo Sirainenstatic void virtual_storage_add_list(struct mail_storage *storage ATTR_UNUSED,
dca6d617a23e3f93af3b8df59acb46478179fe55Timo Sirainen mlist = p_new(list->pool, struct virtual_mailbox_list, 1);
539977f9257bd8985be5a8093658da266ae9cd19Timo Sirainen v->get_mailbox_flags = virtual_list_get_mailbox_flags;
dca6d617a23e3f93af3b8df59acb46478179fe55Timo Sirainen MODULE_CONTEXT_SET(list, virtual_mailbox_list_module, mlist);
fde0b1793a2842da00eaa105d5e13fec465f0443Timo Sirainenstatic int virtual_backend_uidmap_cmp(const uint32_t *uid,
ecdce39e5ef4b62eefa9f5818f17d153fd5d710aTimo Sirainenvirtual_get_virtual_uid(struct mailbox *box, const char *backend_mailbox,
ecdce39e5ef4b62eefa9f5818f17d153fd5d710aTimo Sirainen struct virtual_mailbox *mbox = (struct virtual_mailbox *)box;
ecdce39e5ef4b62eefa9f5818f17d153fd5d710aTimo Sirainen if (strcmp(mbox->vseq_lookup_prev_mailbox, backend_mailbox) == 0)
ecdce39e5ef4b62eefa9f5818f17d153fd5d710aTimo Sirainen mbox->vseq_lookup_prev_mailbox = i_strdup(backend_mailbox);
ecdce39e5ef4b62eefa9f5818f17d153fd5d710aTimo Sirainen bbox = virtual_backend_box_lookup_name(mbox, backend_mailbox);
ecdce39e5ef4b62eefa9f5818f17d153fd5d710aTimo Sirainen mailbox_get_status(bbox->box, STATUS_UIDVALIDITY, &status);
ecdce39e5ef4b62eefa9f5818f17d153fd5d710aTimo Sirainen if (status.uidvalidity != backend_uidvalidity)
fde0b1793a2842da00eaa105d5e13fec465f0443Timo Sirainen uids = array_bsearch(&bbox->uids, &backend_uid,
3852872e6954b7132e637294132005e86b8ebd4aTimo Sirainenvirtual_get_virtual_backend_boxes(struct mailbox *box,
3852872e6954b7132e637294132005e86b8ebd4aTimo Sirainen struct virtual_mailbox *mbox = (struct virtual_mailbox *)box;
3852872e6954b7132e637294132005e86b8ebd4aTimo Sirainen unsigned int i, count;
3852872e6954b7132e637294132005e86b8ebd4aTimo Sirainen bboxes = array_get(&mbox->backend_boxes, &count);
3852872e6954b7132e637294132005e86b8ebd4aTimo Sirainen for (i = 0; i < count; i++) {
3852872e6954b7132e637294132005e86b8ebd4aTimo Sirainen if (!only_with_msgs || array_count(&bboxes[i]->uids) > 0)
3852872e6954b7132e637294132005e86b8ebd4aTimo Sirainenvirtual_get_virtual_box_patterns(struct mailbox *box,
b8835b8a21c617ceb82ddc5a176243faf36aa8f7Timo Sirainen ARRAY_TYPE(mailbox_virtual_patterns) *includes,
b8835b8a21c617ceb82ddc5a176243faf36aa8f7Timo Sirainen ARRAY_TYPE(mailbox_virtual_patterns) *excludes)
3852872e6954b7132e637294132005e86b8ebd4aTimo Sirainen struct virtual_mailbox *mbox = (struct virtual_mailbox *)box;
3852872e6954b7132e637294132005e86b8ebd4aTimo Sirainen array_append_array(includes, &mbox->list_include_patterns);
3852872e6954b7132e637294132005e86b8ebd4aTimo Sirainen array_append_array(excludes, &mbox->list_exclude_patterns);
4cf5f0934a25f1fd58f2780108f9d6498c455a1fTimo Sirainenstatic bool virtual_is_inconsistent(struct mailbox *box)
4cf5f0934a25f1fd58f2780108f9d6498c455a1fTimo Sirainen struct virtual_mailbox *mbox = (struct virtual_mailbox *)box;