virtual-storage.c revision 8305127d1074cf9a1e25dec9be2735276462079d
02c335c23bf5fa225a467c19f2c063fb0dc7b8c3Timo Sirainen/* Copyright (c) 2008-2010 Dovecot authors, see the included COPYING file */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen MODULE_CONTEXT(obj, virtual_mailbox_list_module)
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainenstruct virtual_storage_module virtual_storage_module =
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen MODULE_CONTEXT_INIT(&mail_storage_module_register);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstatic MODULE_CONTEXT_DEFINE_INIT(virtual_mailbox_list_module,
0dffa25d211be541ee3c953b23566a1a990789dfTimo Sirainenstatic bool ns_is_visible(struct mail_namespace *ns)
0dffa25d211be541ee3c953b23566a1a990789dfTimo Sirainen return (ns->flags & NAMESPACE_FLAG_LIST_PREFIX) != 0 ||
0dffa25d211be541ee3c953b23566a1a990789dfTimo Sirainen (ns->flags & NAMESPACE_FLAG_LIST_CHILDREN) != 0 ||
49e9acb52bb5d328f8cf10bce1082c4bc213caeaTimo Sirainenstatic const char *get_user_visible_mailbox_name(struct mailbox *box)
407d64647d77771080eb75f800162014927f10c6Timo Sirainenvoid virtual_box_copy_error(struct mailbox *dest, struct mailbox *src)
1da9587dfb6632ac6446ad12b09fdf77c8542e2cTimo Sirainen str = mail_storage_get_last_error(src->storage, &error);
1da9587dfb6632ac6446ad12b09fdf77c8542e2cTimo Sirainen str = t_strdup_printf("%s (for backend mailbox %s)", str, name);
1da9587dfb6632ac6446ad12b09fdf77c8542e2cTimo Sirainen mail_storage_set_error(dest->storage, error, str);
1da9587dfb6632ac6446ad12b09fdf77c8542e2cTimo Sirainenstatic struct mail_storage *virtual_storage_alloc(void)
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen pool = pool_alloconly_create("virtual storage", 1024);
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen storage = p_new(pool, struct virtual_storage, 1);
49e9acb52bb5d328f8cf10bce1082c4bc213caeaTimo Sirainenvirtual_storage_get_list_settings(const struct mail_namespace *ns ATTR_UNUSED,
ae8817f05005f57bba32479a610b52d083e2b6ebTimo Sirainen set->subscription_fname = VIRTUAL_SUBSCRIPTION_FILE_NAME;
c680a6b35b459045e92814778908da5a93922107Timo Sirainenvirtual_backend_box_lookup_name(struct virtual_mailbox *mbox, const char *name)
a050ca9def13949dbaa67bd6574a41c4f397ae26Timo Sirainen unsigned int i, count;
a050ca9def13949dbaa67bd6574a41c4f397ae26Timo Sirainen bboxes = array_get(&mbox->backend_boxes, &count);
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen for (i = 0; i < count; i++) {
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainenvirtual_backend_box_lookup(struct virtual_mailbox *mbox, uint32_t mailbox_id)
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen unsigned int i, count;
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen bboxes = array_get(&mbox->backend_boxes, &count);
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen for (i = 0; i < count; i++) {
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainenstatic bool virtual_mailbox_is_in_open_stack(struct virtual_storage *storage,
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen const char *const *names;
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen unsigned int i, count;
a050ca9def13949dbaa67bd6574a41c4f397ae26Timo Sirainen names = array_get(&storage->open_stack, &count);
3f99d19bf3361a4b0952e4e3ad64d4d6988de469Timo Sirainen for (i = 0; i < count; i++) {
3f99d19bf3361a4b0952e4e3ad64d4d6988de469Timo Sirainenstatic int virtual_backend_box_open_failed(struct virtual_mailbox *mbox,
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen str = mail_storage_get_last_error(mailbox_get_storage(bbox->box),
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen name = t_strdup(get_user_visible_mailbox_name(bbox->box));
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen (error == MAIL_ERROR_PERM || error == MAIL_ERROR_NOTFOUND)) {
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen /* this mailbox wasn't explicitly specified. just skip it. */
86bde2c1838d1ce967fa2b394bb952004a4adcb7Timo Sirainen /* the virtual mailbox exists, we just can't open it.
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen change the error type. */
687794a61c9e3bf27c712b442b8fc8836c63ae44Timo Sirainen "Virtual mailbox open failed because of mailbox %s: %s",
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen mail_storage_set_error(mbox->box.storage, error, str);
659fe5d24825b160cae512538088020d97a60239Timo Sirainenstatic int virtual_backend_box_open(struct virtual_mailbox *mbox,
3f99d19bf3361a4b0952e4e3ad64d4d6988de469Timo Sirainen struct mail_user *user = mbox->storage->storage.user;
e063aca6bc2f08bec516d4b631052ea9191f011dTimo Sirainen ns = mail_namespace_find(user->namespaces, &mailbox);
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen bbox->box = mailbox_alloc(ns->list, mailbox, flags);
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen return virtual_backend_box_open_failed(mbox, bbox);
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen i_array_init(&bbox->sync_pending_removes, 64);
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen mail_search_args_init(bbox->search_args, bbox->box, FALSE, NULL);
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainenstatic int virtual_mailboxes_open(struct virtual_mailbox *mbox,
88187ee880b4829443e0d55ea7d145d9d5880217Timo Sirainen unsigned int i, count;
ba94d6d7e2f7b07d51f5c27e7532f6502ac9a298Timo Sirainen bboxes = array_get(&mbox->backend_boxes, &count);
ba94d6d7e2f7b07d51f5c27e7532f6502ac9a298Timo Sirainen for (i = 0; i < count; ) {
ba94d6d7e2f7b07d51f5c27e7532f6502ac9a298Timo Sirainen ret = virtual_backend_box_open(mbox, bboxes[i], flags);
3da614c39dd29f536c485089e67839b4cf89fed3Timo Sirainen mail_search_args_unref(&bboxes[i]->search_args);
ba94d6d7e2f7b07d51f5c27e7532f6502ac9a298Timo Sirainen bboxes = array_get(&mbox->backend_boxes, &count);
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen for (; i > 0; i--) {
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainenstatic struct mailbox *
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainenvirtual_mailbox_alloc(struct mail_storage *_storage, struct mailbox_list *list,
ba94d6d7e2f7b07d51f5c27e7532f6502ac9a298Timo Sirainen struct virtual_storage *storage = (struct virtual_storage *)_storage;
88187ee880b4829443e0d55ea7d145d9d5880217Timo Sirainen pool = pool_alloconly_create("virtual mailbox", 1024+512);
ba94d6d7e2f7b07d51f5c27e7532f6502ac9a298Timo Sirainen mbox = p_new(pool, struct virtual_mailbox, 1);
ba94d6d7e2f7b07d51f5c27e7532f6502ac9a298Timo Sirainen index_storage_mailbox_alloc(&mbox->box, name, flags,
220195605754218b4d6e3a51f5a25be9d0e202e0Timo Sirainen mbox->vseq_lookup_prev_mailbox = i_strdup("");
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen mail_index_ext_register(mbox->box.index, "virtual", 0,
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainenstatic void virtual_mailbox_close_internal(struct virtual_mailbox *mbox)
ba94d6d7e2f7b07d51f5c27e7532f6502ac9a298Timo Sirainen unsigned int i, count;
ba94d6d7e2f7b07d51f5c27e7532f6502ac9a298Timo Sirainen bboxes = array_get_modifiable(&mbox->backend_boxes, &count);
ba94d6d7e2f7b07d51f5c27e7532f6502ac9a298Timo Sirainen for (i = 0; i < count; i++) {
88187ee880b4829443e0d55ea7d145d9d5880217Timo Sirainen mailbox_search_result_free(&bboxes[i]->search_result);
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen mail_search_args_deinit(bboxes[i]->search_args);
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen if (array_is_created(&bboxes[i]->sync_outside_expunges))
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen array_free(&bboxes[i]->sync_outside_expunges);
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen i_free_and_null(mbox->vseq_lookup_prev_mailbox);
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainenstatic int virtual_mailbox_open(struct mailbox *box)
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen struct virtual_mailbox *mbox = (struct virtual_mailbox *)box;
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen if (virtual_mailbox_is_in_open_stack(mbox->storage, box->name)) {
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen /* exists, open it */
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen mail_storage_set_error(box->storage, MAIL_ERROR_NOTFOUND,
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen array_append(&mbox->storage->open_stack, &box->name, 1);
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen ret = virtual_mailboxes_open(mbox, box->flags);
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen array_count(&mbox->storage->open_stack)-1, 1);
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen return index_storage_mailbox_open(box, FALSE);
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainenstatic void virtual_mailbox_close(struct mailbox *box)
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen struct virtual_mailbox *mbox = (struct virtual_mailbox *)box;
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainenstatic void virtual_mailbox_free(struct mailbox *box)
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen struct virtual_mailbox *mbox = (struct virtual_mailbox *)box;
919875067c26fb261a15b3f7afdb67d7eeddb226Timo Sirainen const struct mailbox_update *update ATTR_UNUSED,
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen mail_storage_set_error(box->storage, MAIL_ERROR_NOTPOSSIBLE,
1df526903ed039e8ff966a223c43b8d04eddf3c7Phil Carmody "Can't create virtual mailboxes");
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen const struct mailbox_update *update ATTR_UNUSED)
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen mail_storage_set_error(box->storage, MAIL_ERROR_NOTPOSSIBLE,
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen "Can't update virtual mailboxes");
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen mail_storage_set_error(box->storage, MAIL_ERROR_NOTPOSSIBLE,
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen "Virtual mailboxes have no GUIDs");
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainenstatic void virtual_notify_changes(struct mailbox *box ATTR_UNUSED)
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen /* FIXME: maybe some day */
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainenvirtual_list_get_mailbox_flags(struct mailbox_list *list,
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen struct virtual_mailbox_list *mlist = VIRTUAL_LIST_CONTEXT(list);
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen get_mailbox_flags(list, dir, fname, type, st_r, flags);
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen if (ret <= 0 || MAILBOX_INFO_FLAGS_FINISHED(*flags))
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen /* see if it's a selectable mailbox */
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen virtual_path = t_strconcat(dir, "/", fname, "/"VIRTUAL_CONFIG_FNAME,
919875067c26fb261a15b3f7afdb67d7eeddb226Timo Sirainenstatic void virtual_storage_add_list(struct mail_storage *storage ATTR_UNUSED,
b6612c334604eeb27e1ca2bd804ac66dcbc2eaadTimo Sirainen mlist = p_new(list->pool, struct virtual_mailbox_list, 1);
b6612c334604eeb27e1ca2bd804ac66dcbc2eaadTimo Sirainen list->v.get_mailbox_flags = virtual_list_get_mailbox_flags;
919875067c26fb261a15b3f7afdb67d7eeddb226Timo Sirainen MODULE_CONTEXT_SET(list, virtual_mailbox_list_module, mlist);
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainenstatic int virtual_backend_uidmap_cmp(const uint32_t *uid,
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainenvirtual_get_virtual_uid(struct mailbox *box, const char *backend_mailbox,
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen struct virtual_mailbox *mbox = (struct virtual_mailbox *)box;
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen if (strcmp(mbox->vseq_lookup_prev_mailbox, backend_mailbox) == 0)
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen mbox->vseq_lookup_prev_mailbox = i_strdup(backend_mailbox);
919875067c26fb261a15b3f7afdb67d7eeddb226Timo Sirainen bbox = virtual_backend_box_lookup_name(mbox, backend_mailbox);
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen mailbox_get_status(bbox->box, STATUS_UIDVALIDITY, &status);
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen if (status.uidvalidity != backend_uidvalidity)
7604ee75aa54ab2e400de45999e326c358bc2d24Phil Carmody uids = array_bsearch(&bbox->uids, &backend_uid,
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainenvirtual_get_virtual_backend_boxes(struct mailbox *box,
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen struct virtual_mailbox *mbox = (struct virtual_mailbox *)box;
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen unsigned int i, count;
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen bboxes = array_get(&mbox->backend_boxes, &count);
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen for (i = 0; i < count; i++) {
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen if (!only_with_msgs || array_count(&bboxes[i]->uids) > 0)
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainenvirtual_get_virtual_box_patterns(struct mailbox *box,
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen ARRAY_TYPE(mailbox_virtual_patterns) *includes,
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen ARRAY_TYPE(mailbox_virtual_patterns) *excludes)
7604ee75aa54ab2e400de45999e326c358bc2d24Phil Carmody struct virtual_mailbox *mbox = (struct virtual_mailbox *)box;
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen array_append_array(includes, &mbox->list_include_patterns);
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen array_append_array(excludes, &mbox->list_exclude_patterns);
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainenstatic bool virtual_is_inconsistent(struct mailbox *box)
e34d170f8f0e084bd94bfbc1a7085ece67e508dfTimo Sirainen struct virtual_mailbox *mbox = (struct virtual_mailbox *)box;