virtual-storage.c revision c0a87e5f3316a57e6f915882fa1951d0fbb74a61
02c335c23bf5fa225a467c19f2c063fb0dc7b8c3Timo Sirainen/* Copyright (c) 2008-2010 Dovecot authors, see the included COPYING file */
52de839a8249bff5eace53dc1401b28baa0c124bTimo Sirainen MODULE_CONTEXT(obj, virtual_mailbox_list_module)
338088fe2875e8039d2b3df32cbd7a8396b24ea6Timo Sirainenextern struct virtual_mailbox_vfuncs virtual_mailbox_vfuncs;
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainenstruct virtual_storage_module virtual_storage_module =
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen MODULE_CONTEXT_INIT(&mail_storage_module_register);
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainenstatic MODULE_CONTEXT_DEFINE_INIT(virtual_mailbox_list_module,
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainenstatic bool ns_is_visible(struct mail_namespace *ns)
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen return (ns->flags & NAMESPACE_FLAG_LIST_PREFIX) != 0 ||
338088fe2875e8039d2b3df32cbd7a8396b24ea6Timo Sirainen (ns->flags & NAMESPACE_FLAG_LIST_CHILDREN) != 0 ||
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainenstatic const char *get_user_visible_mailbox_name(struct mailbox *box)
cf64e39cef453f5a4704ea52b81b188ca411cb15Timo Sirainenvoid virtual_box_copy_error(struct mailbox *dest, struct mailbox *src)
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen str = t_strdup_printf("%s (for backend mailbox %s)", str, name);
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen mail_storage_set_error(dest->storage, error, str);
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainenstatic struct mail_storage *virtual_storage_alloc(void)
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen pool = pool_alloconly_create("virtual storage", 1024);
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen storage = p_new(pool, struct virtual_storage, 1);
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainenvirtual_storage_get_list_settings(const struct mail_namespace *ns ATTR_UNUSED,
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen set->subscription_fname = VIRTUAL_SUBSCRIPTION_FILE_NAME;
338088fe2875e8039d2b3df32cbd7a8396b24ea6Timo Sirainenvirtual_backend_box_lookup_name(struct virtual_mailbox *mbox, const char *name)
338088fe2875e8039d2b3df32cbd7a8396b24ea6Timo Sirainen unsigned int i, count;
99695d99930b35c2bac85d52e976b44cf8485d83Timo Sirainen bboxes = array_get(&mbox->backend_boxes, &count);
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen for (i = 0; i < count; i++) {
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainenvirtual_backend_box_lookup(struct virtual_mailbox *mbox, uint32_t mailbox_id)
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen unsigned int i, count;
c59b9c273b41f7bcf51f6803110b67813879ff05Timo Sirainen bboxes = array_get(&mbox->backend_boxes, &count);
52de839a8249bff5eace53dc1401b28baa0c124bTimo Sirainen for (i = 0; i < count; i++) {
338088fe2875e8039d2b3df32cbd7a8396b24ea6Timo Sirainenstatic bool virtual_mailbox_is_in_open_stack(struct virtual_storage *storage,
99695d99930b35c2bac85d52e976b44cf8485d83Timo Sirainen const char *const *names;
338088fe2875e8039d2b3df32cbd7a8396b24ea6Timo Sirainen unsigned int i, count;
338088fe2875e8039d2b3df32cbd7a8396b24ea6Timo Sirainen names = array_get(&storage->open_stack, &count);
338088fe2875e8039d2b3df32cbd7a8396b24ea6Timo Sirainen for (i = 0; i < count; i++) {
338088fe2875e8039d2b3df32cbd7a8396b24ea6Timo Sirainenstatic int virtual_backend_box_open_failed(struct virtual_mailbox *mbox,
9ba3ecf529e681688bbf728fc3cb5101bd68d671Timo Sirainen str = mailbox_get_last_error(bbox->box, &error);
9ba3ecf529e681688bbf728fc3cb5101bd68d671Timo Sirainen name = t_strdup(get_user_visible_mailbox_name(bbox->box));
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen /* ignore this. it could be intentional. */
c59b9c273b41f7bcf51f6803110b67813879ff05Timo Sirainen if (mbox->storage->storage.user->mail_debug) {
338088fe2875e8039d2b3df32cbd7a8396b24ea6Timo Sirainen "Skipping non-existing mailbox %s",
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen if (error == MAIL_ERROR_PERM && bbox->wildcard) {
338088fe2875e8039d2b3df32cbd7a8396b24ea6Timo Sirainen /* this mailbox wasn't explicitly specified. just skip it. */
99695d99930b35c2bac85d52e976b44cf8485d83Timo Sirainen "Virtual mailbox open failed because of mailbox %s: %s",
338088fe2875e8039d2b3df32cbd7a8396b24ea6Timo Sirainen mail_storage_set_error(mbox->box.storage, error, str);
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainenstatic int virtual_backend_box_open(struct virtual_mailbox *mbox,
338088fe2875e8039d2b3df32cbd7a8396b24ea6Timo Sirainen struct mail_user *user = mbox->storage->storage.user;
338088fe2875e8039d2b3df32cbd7a8396b24ea6Timo Sirainen ns = mail_namespace_find(user->namespaces, mailbox);
338088fe2875e8039d2b3df32cbd7a8396b24ea6Timo Sirainen bbox->box = mailbox_alloc(ns->list, mailbox, flags);
338088fe2875e8039d2b3df32cbd7a8396b24ea6Timo Sirainen return virtual_backend_box_open_failed(mbox, bbox);
99695d99930b35c2bac85d52e976b44cf8485d83Timo Sirainen i_array_init(&bbox->sync_pending_removes, 64);
99695d99930b35c2bac85d52e976b44cf8485d83Timo Sirainen mail_search_args_init(bbox->search_args, bbox->box, FALSE, NULL);
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainenstatic int virtual_mailboxes_open(struct virtual_mailbox *mbox,
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen unsigned int i, count;
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen bboxes = array_get(&mbox->backend_boxes, &count);
338088fe2875e8039d2b3df32cbd7a8396b24ea6Timo Sirainen for (i = 0; i < count; ) {
0f3d4fbcf88e2ffd674893aed8cc1288fe17d290Timo Sirainen ret = virtual_backend_box_open(mbox, bboxes[i], flags);
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen mail_search_args_unref(&bboxes[i]->search_args);
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen bboxes = array_get(&mbox->backend_boxes, &count);
0482d891a6669537e10a1abc9866b45f2fc55fccTimo Sirainen for (; i > 0; i--) {
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainenstatic struct mailbox *
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainenvirtual_mailbox_alloc(struct mail_storage *_storage, struct mailbox_list *list,
338088fe2875e8039d2b3df32cbd7a8396b24ea6Timo Sirainen struct virtual_storage *storage = (struct virtual_storage *)_storage;
0482d891a6669537e10a1abc9866b45f2fc55fccTimo Sirainen pool = pool_alloconly_create("virtual mailbox", 1024+512);
0482d891a6669537e10a1abc9866b45f2fc55fccTimo Sirainen mbox = p_new(pool, struct virtual_mailbox, 1);
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen index_storage_mailbox_alloc(&mbox->box, vname, flags,
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen mbox->vseq_lookup_prev_mailbox = i_strdup("");
99695d99930b35c2bac85d52e976b44cf8485d83Timo Sirainen mail_index_ext_register(mbox->box.index, "virtual", 0,
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainenstatic void virtual_mailbox_close_internal(struct virtual_mailbox *mbox)
99695d99930b35c2bac85d52e976b44cf8485d83Timo Sirainen unsigned int i, count;
99695d99930b35c2bac85d52e976b44cf8485d83Timo Sirainen bboxes = array_get_modifiable(&mbox->backend_boxes, &count);
99695d99930b35c2bac85d52e976b44cf8485d83Timo Sirainen for (i = 0; i < count; i++) {
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen mailbox_search_result_free(&bboxes[i]->search_result);
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen mail_search_args_deinit(bboxes[i]->search_args);
99695d99930b35c2bac85d52e976b44cf8485d83Timo Sirainen if (array_is_created(&bboxes[i]->sync_outside_expunges))
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen array_free(&bboxes[i]->sync_outside_expunges);
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen i_free_and_null(mbox->vseq_lookup_prev_mailbox);
c59b9c273b41f7bcf51f6803110b67813879ff05Timo Sirainenstatic int virtual_mailbox_open(struct mailbox *box)
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen struct virtual_mailbox *mbox = (struct virtual_mailbox *)box;
c59b9c273b41f7bcf51f6803110b67813879ff05Timo Sirainen if (virtual_mailbox_is_in_open_stack(mbox->storage, box->name)) {
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen array_append(&mbox->storage->open_stack, &box->name, 1);
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen ret = virtual_mailboxes_open(mbox, box->flags);
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen array_count(&mbox->storage->open_stack)-1, 1);
52de839a8249bff5eace53dc1401b28baa0c124bTimo Sirainen return index_storage_mailbox_open(box, FALSE);
52de839a8249bff5eace53dc1401b28baa0c124bTimo Sirainenstatic void virtual_mailbox_close(struct mailbox *box)
52de839a8249bff5eace53dc1401b28baa0c124bTimo Sirainen struct virtual_mailbox *mbox = (struct virtual_mailbox *)box;
52de839a8249bff5eace53dc1401b28baa0c124bTimo Sirainenstatic void virtual_mailbox_free(struct mailbox *box)
52de839a8249bff5eace53dc1401b28baa0c124bTimo Sirainen struct virtual_mailbox *mbox = (struct virtual_mailbox *)box;
52de839a8249bff5eace53dc1401b28baa0c124bTimo Sirainen const struct mailbox_update *update ATTR_UNUSED,
52de839a8249bff5eace53dc1401b28baa0c124bTimo Sirainen mail_storage_set_error(box->storage, MAIL_ERROR_NOTPOSSIBLE,
52de839a8249bff5eace53dc1401b28baa0c124bTimo Sirainen "Can't create virtual mailboxes");
52de839a8249bff5eace53dc1401b28baa0c124bTimo Sirainen const struct mailbox_update *update ATTR_UNUSED)
52de839a8249bff5eace53dc1401b28baa0c124bTimo Sirainen mail_storage_set_error(box->storage, MAIL_ERROR_NOTPOSSIBLE,
52de839a8249bff5eace53dc1401b28baa0c124bTimo Sirainen "Can't update virtual mailboxes");
52de839a8249bff5eace53dc1401b28baa0c124bTimo Sirainenvirtual_mailbox_get_metadata(struct mailbox *box,
52de839a8249bff5eace53dc1401b28baa0c124bTimo Sirainen mail_storage_set_error(box->storage, MAIL_ERROR_NOTPOSSIBLE,
52de839a8249bff5eace53dc1401b28baa0c124bTimo Sirainen "Virtual mailboxes have no GUIDs");
52de839a8249bff5eace53dc1401b28baa0c124bTimo Sirainen return index_mailbox_get_metadata(box, items, metadata_r);
52de839a8249bff5eace53dc1401b28baa0c124bTimo Sirainenvirtual_notify_callback(struct mailbox *bbox ATTR_UNUSED, struct mailbox *box)
52de839a8249bff5eace53dc1401b28baa0c124bTimo Sirainen box->notify_callback(box, box->notify_context);
52de839a8249bff5eace53dc1401b28baa0c124bTimo Sirainenstatic void virtual_notify_changes(struct mailbox *box)
52de839a8249bff5eace53dc1401b28baa0c124bTimo Sirainen struct virtual_mailbox *mbox = (struct virtual_mailbox *)box;
52de839a8249bff5eace53dc1401b28baa0c124bTimo Sirainen unsigned int i, count;
52de839a8249bff5eace53dc1401b28baa0c124bTimo Sirainen bboxes = array_get(&mbox->backend_boxes, &count);
52de839a8249bff5eace53dc1401b28baa0c124bTimo Sirainen for (i = 0; i < count; i++) {
52de839a8249bff5eace53dc1401b28baa0c124bTimo Sirainen mailbox_notify_changes(bbox, box->notify_min_interval,
52de839a8249bff5eace53dc1401b28baa0c124bTimo Sirainenvirtual_list_get_mailbox_flags(struct mailbox_list *list,
52de839a8249bff5eace53dc1401b28baa0c124bTimo Sirainen struct virtual_mailbox_list *mlist = VIRTUAL_LIST_CONTEXT(list);
52de839a8249bff5eace53dc1401b28baa0c124bTimo Sirainen get_mailbox_flags(list, dir, fname, type, st_r, flags);
52de839a8249bff5eace53dc1401b28baa0c124bTimo Sirainen if (ret <= 0 || MAILBOX_INFO_FLAGS_FINISHED(*flags))
52de839a8249bff5eace53dc1401b28baa0c124bTimo Sirainen /* see if it's a selectable mailbox */
52de839a8249bff5eace53dc1401b28baa0c124bTimo Sirainen virtual_path = t_strconcat(dir, "/", fname, "/"VIRTUAL_CONFIG_FNAME,
52de839a8249bff5eace53dc1401b28baa0c124bTimo Sirainenstatic void virtual_storage_add_list(struct mail_storage *storage ATTR_UNUSED,
52de839a8249bff5eace53dc1401b28baa0c124bTimo Sirainen mlist = p_new(list->pool, struct virtual_mailbox_list, 1);
52de839a8249bff5eace53dc1401b28baa0c124bTimo Sirainen v->get_mailbox_flags = virtual_list_get_mailbox_flags;
52de839a8249bff5eace53dc1401b28baa0c124bTimo Sirainen MODULE_CONTEXT_SET(list, virtual_mailbox_list_module, mlist);
52de839a8249bff5eace53dc1401b28baa0c124bTimo Sirainenstatic int virtual_backend_uidmap_cmp(const uint32_t *uid,
52de839a8249bff5eace53dc1401b28baa0c124bTimo Sirainenvirtual_get_virtual_uid(struct mailbox *box, const char *backend_mailbox,
52de839a8249bff5eace53dc1401b28baa0c124bTimo Sirainen struct virtual_mailbox *mbox = (struct virtual_mailbox *)box;
52de839a8249bff5eace53dc1401b28baa0c124bTimo Sirainen if (strcmp(mbox->vseq_lookup_prev_mailbox, backend_mailbox) == 0)
52de839a8249bff5eace53dc1401b28baa0c124bTimo Sirainen mbox->vseq_lookup_prev_mailbox = i_strdup(backend_mailbox);
52de839a8249bff5eace53dc1401b28baa0c124bTimo Sirainen bbox = virtual_backend_box_lookup_name(mbox, backend_mailbox);
52de839a8249bff5eace53dc1401b28baa0c124bTimo Sirainen mailbox_get_open_status(bbox->box, STATUS_UIDVALIDITY, &status);
52de839a8249bff5eace53dc1401b28baa0c124bTimo Sirainen if (status.uidvalidity != backend_uidvalidity)
return FALSE;
return TRUE;
bool only_with_msgs)
unsigned int i, count;
for (i = 0; i < count; i++) {
return TRUE;
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,