virtual-storage.c revision 8b31f966d9688e07672ef1958dcbdb7686523c04
5a580c3a38ced62d4bcc95b8ac7c4f2935b5d294Timo Sirainen/* Copyright (c) 2008-2013 Dovecot authors, see the included COPYING file */
499fec3443374cc89fb8c83b8027c1614097d7a3Timo Sirainenextern struct virtual_mailbox_vfuncs virtual_mailbox_vfuncs;
f5a7396b31762a1f876517e13ce9065820139f7cTimo Sirainenstruct virtual_storage_module virtual_storage_module =
f5a7396b31762a1f876517e13ce9065820139f7cTimo Sirainen MODULE_CONTEXT_INIT(&mail_storage_module_register);
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)
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,
11352dc3e4b29f3d2763c82f8ea4f99e8daf4fa3Timo Sirainen str = mailbox_get_last_error(bbox->box, &error);
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;
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo 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);
8b31f966d9688e07672ef1958dcbdb7686523c04Timo Sirainen mailbox_get_open_status(bbox->box, 0, &status);
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;
c529313e1cbc22244d4528e80aa3e485f8806cd3Timo Sirainen pool = pool_alloconly_create("virtual mailbox", 2048);
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen mbox = p_new(pool, struct virtual_mailbox, 1);
8c909e451d14075c05d90382cf8eebc4e354f569Timo Sirainen index_storage_mailbox_alloc(&mbox->box, vname, flags, MAIL_INDEX_PREFIX);
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);
c4bb0320ab43ea35fa6df88fc745fdad906cee44Timo Sirainenvirtual_mailbox_exists(struct mailbox *box, bool auto_boxes ATTR_UNUSED,
c4bb0320ab43ea35fa6df88fc745fdad906cee44Timo Sirainen return index_storage_mailbox_exists_full(box, VIRTUAL_CONFIG_FNAME,
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);
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen if (index_storage_mailbox_open(box, FALSE) < 0)
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen mail_index_ext_register(mbox->box.index, "virtual", 0,
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");
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainenvirtual_storage_get_status(struct mailbox *box,
8b31f966d9688e07672ef1958dcbdb7686523c04Timo Sirainen struct virtual_mailbox *mbox = (struct virtual_mailbox *)box;
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen if (index_storage_get_status(box, items, status_r) < 0)
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen /* Virtual mailboxes have no cached data of their own, so the
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen current value is always 0. The most important use for this
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen functionality is for "doveadm index" to do FTS indexing and
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen it doesn't really matter there if we set this value
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen correctly or not. So for now just assume that everything is
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen status_r->last_cached_seq = status_r->messages;
51327f2489a4e0e615eb9f7d921473cf8512bb79Timo Sirainenvirtual_mailbox_get_metadata(struct mailbox *box,
206ed2f6fa3a6fb291498627b2da626581c07a18Timo Sirainen if (index_mailbox_get_metadata(box, items, metadata_r) < 0)
51327f2489a4e0e615eb9f7d921473cf8512bb79Timo Sirainen mail_storage_set_error(box->storage, MAIL_ERROR_NOTPOSSIBLE,
51327f2489a4e0e615eb9f7d921473cf8512bb79Timo 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++) {
9438ecaf1caee1bb33c8d7f638742875ac42c4e5Timo Sirainen mailbox_notify_changes(bbox, virtual_notify_callback, box);
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen struct virtual_mailbox *mbox = (struct virtual_mailbox *)box;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen unsigned int n, i, count;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen strcmp(mbox->lookup_prev_bbox->box->vname, backend_mailbox->vname) == 0)
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen bbox = virtual_backend_box_lookup_name(mbox, backend_mailbox->vname);
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen seq_range_array_iter_init(&iter, backend_uids); n = 0;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen while (seq_range_array_iter_nth(&iter, n++, &uid)) {
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen while (i < count && uids[i].real_uid < uid) i++;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainenvirtual_get_virtual_uid_map(struct mailbox *box,
ecdce39e5ef4b62eefa9f5818f17d153fd5d710aTimo Sirainen struct virtual_mailbox *mbox = (struct virtual_mailbox *)box;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen unsigned int n, i, count;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen strcmp(mbox->lookup_prev_bbox->box->vname, backend_mailbox->vname) == 0)
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen bbox = virtual_backend_box_lookup_name(mbox, backend_mailbox->vname);
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen seq_range_array_iter_init(&iter, backend_uids); n = 0;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen while (seq_range_array_iter_nth(&iter, n++, &uid)) {
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen while (i < count && uids[i].real_uid < uid) i++;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen array_append(virtual_uids_r, &uids[i].virtual_uid, 1);
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)
4cf5f0934a25f1fd58f2780108f9d6498c455a1fTimo Sirainenstatic bool virtual_is_inconsistent(struct mailbox *box)
4cf5f0934a25f1fd58f2780108f9d6498c455a1fTimo Sirainen struct virtual_mailbox *mbox = (struct virtual_mailbox *)box;
4ba9a1d3facc515b3feb5238a16bcf91f76fac61Timo Sirainen .class_flags = MAIL_STORAGE_CLASS_FLAG_NOQUOTA,