virtual-storage.c revision c0a87e5f3316a57e6f915882fa1951d0fbb74a61
02c335c23bf5fa225a467c19f2c063fb0dc7b8c3Timo Sirainen/* Copyright (c) 2008-2010 Dovecot authors, see the included COPYING file */
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen#include "lib.h"
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen#include "array.h"
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen#include "ioloop.h"
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen#include "str.h"
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen#include "mkdir-parents.h"
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen#include "unlink-directory.h"
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen#include "index-mail.h"
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen#include "mail-copy.h"
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen#include "mail-search.h"
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen#include "mailbox-list-private.h"
52de839a8249bff5eace53dc1401b28baa0c124bTimo Sirainen#include "virtual-plugin.h"
52de839a8249bff5eace53dc1401b28baa0c124bTimo Sirainen#include "virtual-transaction.h"
52de839a8249bff5eace53dc1401b28baa0c124bTimo Sirainen#include "virtual-storage.h"
338088fe2875e8039d2b3df32cbd7a8396b24ea6Timo Sirainen
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen#include <stdio.h>
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen#include <stdlib.h>
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen#include <unistd.h>
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen#include <dirent.h>
52de839a8249bff5eace53dc1401b28baa0c124bTimo Sirainen#include <sys/stat.h>
52de839a8249bff5eace53dc1401b28baa0c124bTimo Sirainen
52de839a8249bff5eace53dc1401b28baa0c124bTimo Sirainen#define VIRTUAL_LIST_CONTEXT(obj) \
52de839a8249bff5eace53dc1401b28baa0c124bTimo Sirainen MODULE_CONTEXT(obj, virtual_mailbox_list_module)
52de839a8249bff5eace53dc1401b28baa0c124bTimo Sirainen
52de839a8249bff5eace53dc1401b28baa0c124bTimo Sirainenstruct virtual_mailbox_list {
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen union mailbox_list_module_context module_ctx;
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen};
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainenextern struct mail_storage virtual_storage;
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainenextern struct mailbox virtual_mailbox;
338088fe2875e8039d2b3df32cbd7a8396b24ea6Timo Sirainenextern struct virtual_mailbox_vfuncs virtual_mailbox_vfuncs;
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen
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 Sirainen &mailbox_list_module_register);
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainenstatic bool ns_is_visible(struct mail_namespace *ns)
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen{
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen return (ns->flags & NAMESPACE_FLAG_LIST_PREFIX) != 0 ||
338088fe2875e8039d2b3df32cbd7a8396b24ea6Timo Sirainen (ns->flags & NAMESPACE_FLAG_LIST_CHILDREN) != 0 ||
338088fe2875e8039d2b3df32cbd7a8396b24ea6Timo Sirainen (ns->flags & NAMESPACE_FLAG_HIDDEN) == 0;
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen}
338088fe2875e8039d2b3df32cbd7a8396b24ea6Timo Sirainen
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainenstatic const char *get_user_visible_mailbox_name(struct mailbox *box)
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen{
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen if (ns_is_visible(box->list->ns))
338088fe2875e8039d2b3df32cbd7a8396b24ea6Timo Sirainen return box->vname;
338088fe2875e8039d2b3df32cbd7a8396b24ea6Timo Sirainen else {
338088fe2875e8039d2b3df32cbd7a8396b24ea6Timo Sirainen return t_strdup_printf("<hidden>%c%s",
338088fe2875e8039d2b3df32cbd7a8396b24ea6Timo Sirainen mail_namespace_get_sep(box->list->ns),
cf64e39cef453f5a4704ea52b81b188ca411cb15Timo Sirainen box->vname);
cf64e39cef453f5a4704ea52b81b188ca411cb15Timo Sirainen }
cf64e39cef453f5a4704ea52b81b188ca411cb15Timo Sirainen}
cf64e39cef453f5a4704ea52b81b188ca411cb15Timo Sirainen
cf64e39cef453f5a4704ea52b81b188ca411cb15Timo Sirainenvoid virtual_box_copy_error(struct mailbox *dest, struct mailbox *src)
cf64e39cef453f5a4704ea52b81b188ca411cb15Timo Sirainen{
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen const char *name, *str;
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen enum mail_error error;
338088fe2875e8039d2b3df32cbd7a8396b24ea6Timo Sirainen
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen name = get_user_visible_mailbox_name(src);
338088fe2875e8039d2b3df32cbd7a8396b24ea6Timo Sirainen str = mailbox_get_last_error(src, &error);
338088fe2875e8039d2b3df32cbd7a8396b24ea6Timo Sirainen
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen str = t_strdup_printf("%s (for backend mailbox %s)", str, name);
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen mail_storage_set_error(dest->storage, error, str);
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen}
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainenstatic struct mail_storage *virtual_storage_alloc(void)
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen{
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen struct virtual_storage *storage;
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen pool_t pool;
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen pool = pool_alloconly_create("virtual storage", 1024);
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen storage = p_new(pool, struct virtual_storage, 1);
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen storage->storage = virtual_storage;
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen storage->storage.pool = pool;
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen p_array_init(&storage->open_stack, pool, 8);
4307c886579381dbb1897ea1388ae6978c96f560Timo Sirainen return &storage->storage;
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen}
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainenstatic void
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainenvirtual_storage_get_list_settings(const struct mail_namespace *ns ATTR_UNUSED,
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen struct mailbox_list_settings *set)
338088fe2875e8039d2b3df32cbd7a8396b24ea6Timo Sirainen{
338088fe2875e8039d2b3df32cbd7a8396b24ea6Timo Sirainen if (set->layout == NULL)
0482d891a6669537e10a1abc9866b45f2fc55fccTimo Sirainen set->layout = MAILBOX_LIST_NAME_FS;
0482d891a6669537e10a1abc9866b45f2fc55fccTimo Sirainen if (set->subscription_fname == NULL)
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen set->subscription_fname = VIRTUAL_SUBSCRIPTION_FILE_NAME;
338088fe2875e8039d2b3df32cbd7a8396b24ea6Timo Sirainen}
99695d99930b35c2bac85d52e976b44cf8485d83Timo Sirainen
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainenstruct virtual_backend_box *
338088fe2875e8039d2b3df32cbd7a8396b24ea6Timo Sirainenvirtual_backend_box_lookup_name(struct virtual_mailbox *mbox, const char *name)
c59b9c273b41f7bcf51f6803110b67813879ff05Timo Sirainen{
338088fe2875e8039d2b3df32cbd7a8396b24ea6Timo Sirainen struct virtual_backend_box *const *bboxes;
338088fe2875e8039d2b3df32cbd7a8396b24ea6Timo Sirainen unsigned int i, count;
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen
99695d99930b35c2bac85d52e976b44cf8485d83Timo Sirainen bboxes = array_get(&mbox->backend_boxes, &count);
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen for (i = 0; i < count; i++) {
d11111fc5356108b6408a58b4ff1811d5b5678edTimo Sirainen if (strcmp(bboxes[i]->name, name) == 0)
d11111fc5356108b6408a58b4ff1811d5b5678edTimo Sirainen return bboxes[i];
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen }
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen return NULL;
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen}
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainenstruct virtual_backend_box *
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainenvirtual_backend_box_lookup(struct virtual_mailbox *mbox, uint32_t mailbox_id)
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen{
de62ce819d59a529530da4b57be1b8d6dad13d6bTimo Sirainen struct virtual_backend_box *const *bboxes;
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen unsigned int i, count;
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen if (mailbox_id == 0)
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen return NULL;
de62ce819d59a529530da4b57be1b8d6dad13d6bTimo Sirainen
c59b9c273b41f7bcf51f6803110b67813879ff05Timo Sirainen bboxes = array_get(&mbox->backend_boxes, &count);
52de839a8249bff5eace53dc1401b28baa0c124bTimo Sirainen for (i = 0; i < count; i++) {
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen if (bboxes[i]->mailbox_id == mailbox_id)
99695d99930b35c2bac85d52e976b44cf8485d83Timo Sirainen return bboxes[i];
338088fe2875e8039d2b3df32cbd7a8396b24ea6Timo Sirainen }
338088fe2875e8039d2b3df32cbd7a8396b24ea6Timo Sirainen return NULL;
99695d99930b35c2bac85d52e976b44cf8485d83Timo Sirainen}
338088fe2875e8039d2b3df32cbd7a8396b24ea6Timo Sirainen
338088fe2875e8039d2b3df32cbd7a8396b24ea6Timo Sirainenstatic bool virtual_mailbox_is_in_open_stack(struct virtual_storage *storage,
338088fe2875e8039d2b3df32cbd7a8396b24ea6Timo Sirainen const char *name)
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen{
99695d99930b35c2bac85d52e976b44cf8485d83Timo Sirainen const char *const *names;
338088fe2875e8039d2b3df32cbd7a8396b24ea6Timo Sirainen unsigned int i, count;
338088fe2875e8039d2b3df32cbd7a8396b24ea6Timo Sirainen
338088fe2875e8039d2b3df32cbd7a8396b24ea6Timo Sirainen names = array_get(&storage->open_stack, &count);
338088fe2875e8039d2b3df32cbd7a8396b24ea6Timo Sirainen for (i = 0; i < count; i++) {
0482d891a6669537e10a1abc9866b45f2fc55fccTimo Sirainen if (strcmp(names[i], name) == 0)
0482d891a6669537e10a1abc9866b45f2fc55fccTimo Sirainen return TRUE;
338088fe2875e8039d2b3df32cbd7a8396b24ea6Timo Sirainen }
338088fe2875e8039d2b3df32cbd7a8396b24ea6Timo Sirainen return FALSE;
99695d99930b35c2bac85d52e976b44cf8485d83Timo Sirainen}
338088fe2875e8039d2b3df32cbd7a8396b24ea6Timo Sirainen
338088fe2875e8039d2b3df32cbd7a8396b24ea6Timo Sirainenstatic int virtual_backend_box_open_failed(struct virtual_mailbox *mbox,
99695d99930b35c2bac85d52e976b44cf8485d83Timo Sirainen struct virtual_backend_box *bbox)
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen{
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen enum mail_error error;
99695d99930b35c2bac85d52e976b44cf8485d83Timo Sirainen const char *str, *name;
99695d99930b35c2bac85d52e976b44cf8485d83Timo Sirainen
9ba3ecf529e681688bbf728fc3cb5101bd68d671Timo Sirainen str = mailbox_get_last_error(bbox->box, &error);
9ba3ecf529e681688bbf728fc3cb5101bd68d671Timo Sirainen name = t_strdup(get_user_visible_mailbox_name(bbox->box));
9ba3ecf529e681688bbf728fc3cb5101bd68d671Timo Sirainen mailbox_free(&bbox->box);
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen if (error == MAIL_ERROR_NOTFOUND) {
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen /* ignore this. it could be intentional. */
c59b9c273b41f7bcf51f6803110b67813879ff05Timo Sirainen if (mbox->storage->storage.user->mail_debug) {
338088fe2875e8039d2b3df32cbd7a8396b24ea6Timo Sirainen i_debug("virtual mailbox %s: "
338088fe2875e8039d2b3df32cbd7a8396b24ea6Timo Sirainen "Skipping non-existing mailbox %s",
99695d99930b35c2bac85d52e976b44cf8485d83Timo Sirainen mbox->box.vname, name);
99695d99930b35c2bac85d52e976b44cf8485d83Timo Sirainen }
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen return 0;
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen }
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen if (error == MAIL_ERROR_PERM && bbox->wildcard) {
338088fe2875e8039d2b3df32cbd7a8396b24ea6Timo Sirainen /* this mailbox wasn't explicitly specified. just skip it. */
338088fe2875e8039d2b3df32cbd7a8396b24ea6Timo Sirainen return 0;
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen }
338088fe2875e8039d2b3df32cbd7a8396b24ea6Timo Sirainen str = t_strdup_printf(
99695d99930b35c2bac85d52e976b44cf8485d83Timo Sirainen "Virtual mailbox open failed because of mailbox %s: %s",
338088fe2875e8039d2b3df32cbd7a8396b24ea6Timo Sirainen name, str);
338088fe2875e8039d2b3df32cbd7a8396b24ea6Timo Sirainen mail_storage_set_error(mbox->box.storage, error, str);
338088fe2875e8039d2b3df32cbd7a8396b24ea6Timo Sirainen return -1;
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen}
99695d99930b35c2bac85d52e976b44cf8485d83Timo Sirainen
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainenstatic int virtual_backend_box_open(struct virtual_mailbox *mbox,
338088fe2875e8039d2b3df32cbd7a8396b24ea6Timo Sirainen struct virtual_backend_box *bbox,
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen enum mailbox_flags flags)
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen{
338088fe2875e8039d2b3df32cbd7a8396b24ea6Timo Sirainen struct mail_user *user = mbox->storage->storage.user;
338088fe2875e8039d2b3df32cbd7a8396b24ea6Timo Sirainen struct mail_namespace *ns;
338088fe2875e8039d2b3df32cbd7a8396b24ea6Timo Sirainen const char *mailbox;
338088fe2875e8039d2b3df32cbd7a8396b24ea6Timo Sirainen
338088fe2875e8039d2b3df32cbd7a8396b24ea6Timo Sirainen i_assert(bbox->box == NULL);
338088fe2875e8039d2b3df32cbd7a8396b24ea6Timo Sirainen
338088fe2875e8039d2b3df32cbd7a8396b24ea6Timo Sirainen flags |= MAILBOX_FLAG_KEEP_RECENT;
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen
338088fe2875e8039d2b3df32cbd7a8396b24ea6Timo Sirainen mailbox = bbox->name;
338088fe2875e8039d2b3df32cbd7a8396b24ea6Timo Sirainen ns = mail_namespace_find(user->namespaces, mailbox);
338088fe2875e8039d2b3df32cbd7a8396b24ea6Timo Sirainen bbox->box = mailbox_alloc(ns->list, mailbox, flags);
338088fe2875e8039d2b3df32cbd7a8396b24ea6Timo Sirainen
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen if (mailbox_open(bbox->box) < 0)
338088fe2875e8039d2b3df32cbd7a8396b24ea6Timo Sirainen return virtual_backend_box_open_failed(mbox, bbox);
99695d99930b35c2bac85d52e976b44cf8485d83Timo Sirainen i_array_init(&bbox->uids, 64);
99695d99930b35c2bac85d52e976b44cf8485d83Timo Sirainen i_array_init(&bbox->sync_pending_removes, 64);
99695d99930b35c2bac85d52e976b44cf8485d83Timo Sirainen mail_search_args_init(bbox->search_args, bbox->box, FALSE, NULL);
99695d99930b35c2bac85d52e976b44cf8485d83Timo Sirainen return 1;
99695d99930b35c2bac85d52e976b44cf8485d83Timo Sirainen}
99695d99930b35c2bac85d52e976b44cf8485d83Timo Sirainen
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainenstatic int virtual_mailboxes_open(struct virtual_mailbox *mbox,
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen enum mailbox_flags flags)
338088fe2875e8039d2b3df32cbd7a8396b24ea6Timo Sirainen{
338088fe2875e8039d2b3df32cbd7a8396b24ea6Timo Sirainen struct virtual_backend_box *const *bboxes;
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen unsigned int i, count;
338088fe2875e8039d2b3df32cbd7a8396b24ea6Timo Sirainen int ret;
338088fe2875e8039d2b3df32cbd7a8396b24ea6Timo Sirainen
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);
0f3d4fbcf88e2ffd674893aed8cc1288fe17d290Timo Sirainen if (ret <= 0) {
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen if (ret < 0)
338088fe2875e8039d2b3df32cbd7a8396b24ea6Timo Sirainen break;
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen mail_search_args_unref(&bboxes[i]->search_args);
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen array_delete(&mbox->backend_boxes, i, 1);
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen bboxes = array_get(&mbox->backend_boxes, &count);
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen } else {
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen i++;
99695d99930b35c2bac85d52e976b44cf8485d83Timo Sirainen }
338088fe2875e8039d2b3df32cbd7a8396b24ea6Timo Sirainen }
338088fe2875e8039d2b3df32cbd7a8396b24ea6Timo Sirainen if (i == count)
338088fe2875e8039d2b3df32cbd7a8396b24ea6Timo Sirainen return 0;
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen else {
0482d891a6669537e10a1abc9866b45f2fc55fccTimo Sirainen /* failed */
0482d891a6669537e10a1abc9866b45f2fc55fccTimo Sirainen for (; i > 0; i--) {
0482d891a6669537e10a1abc9866b45f2fc55fccTimo Sirainen mailbox_free(&bboxes[i-1]->box);
338088fe2875e8039d2b3df32cbd7a8396b24ea6Timo Sirainen array_free(&bboxes[i-1]->uids);
99695d99930b35c2bac85d52e976b44cf8485d83Timo Sirainen }
338088fe2875e8039d2b3df32cbd7a8396b24ea6Timo Sirainen return -1;
99695d99930b35c2bac85d52e976b44cf8485d83Timo Sirainen }
99695d99930b35c2bac85d52e976b44cf8485d83Timo Sirainen}
99695d99930b35c2bac85d52e976b44cf8485d83Timo Sirainen
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainenstatic struct mailbox *
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainenvirtual_mailbox_alloc(struct mail_storage *_storage, struct mailbox_list *list,
99695d99930b35c2bac85d52e976b44cf8485d83Timo Sirainen const char *vname, enum mailbox_flags flags)
338088fe2875e8039d2b3df32cbd7a8396b24ea6Timo Sirainen{
338088fe2875e8039d2b3df32cbd7a8396b24ea6Timo Sirainen struct virtual_storage *storage = (struct virtual_storage *)_storage;
338088fe2875e8039d2b3df32cbd7a8396b24ea6Timo Sirainen struct virtual_mailbox *mbox;
338088fe2875e8039d2b3df32cbd7a8396b24ea6Timo Sirainen pool_t pool;
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen
0482d891a6669537e10a1abc9866b45f2fc55fccTimo Sirainen pool = pool_alloconly_create("virtual mailbox", 1024+512);
0482d891a6669537e10a1abc9866b45f2fc55fccTimo Sirainen mbox = p_new(pool, struct virtual_mailbox, 1);
0482d891a6669537e10a1abc9866b45f2fc55fccTimo Sirainen mbox->box = virtual_mailbox;
0482d891a6669537e10a1abc9866b45f2fc55fccTimo Sirainen mbox->box.pool = pool;
0482d891a6669537e10a1abc9866b45f2fc55fccTimo Sirainen mbox->box.storage = _storage;
0482d891a6669537e10a1abc9866b45f2fc55fccTimo Sirainen mbox->box.list = list;
99695d99930b35c2bac85d52e976b44cf8485d83Timo Sirainen mbox->box.mail_vfuncs = &virtual_mail_vfuncs;
99695d99930b35c2bac85d52e976b44cf8485d83Timo Sirainen mbox->vfuncs = virtual_mailbox_vfuncs;
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen index_storage_mailbox_alloc(&mbox->box, vname, flags,
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen VIRTUAL_INDEX_PREFIX);
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen mbox->storage = storage;
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen mbox->vseq_lookup_prev_mailbox = i_strdup("");
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen
99695d99930b35c2bac85d52e976b44cf8485d83Timo Sirainen mbox->virtual_ext_id =
99695d99930b35c2bac85d52e976b44cf8485d83Timo Sirainen mail_index_ext_register(mbox->box.index, "virtual", 0,
99695d99930b35c2bac85d52e976b44cf8485d83Timo Sirainen sizeof(struct virtual_mail_index_record),
99695d99930b35c2bac85d52e976b44cf8485d83Timo Sirainen sizeof(uint32_t));
0482d891a6669537e10a1abc9866b45f2fc55fccTimo Sirainen return &mbox->box;
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen}
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainenstatic void virtual_mailbox_close_internal(struct virtual_mailbox *mbox)
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen{
99695d99930b35c2bac85d52e976b44cf8485d83Timo Sirainen struct virtual_backend_box **bboxes;
99695d99930b35c2bac85d52e976b44cf8485d83Timo Sirainen unsigned int i, count;
99695d99930b35c2bac85d52e976b44cf8485d83Timo Sirainen
99695d99930b35c2bac85d52e976b44cf8485d83Timo Sirainen bboxes = array_get_modifiable(&mbox->backend_boxes, &count);
99695d99930b35c2bac85d52e976b44cf8485d83Timo Sirainen for (i = 0; i < count; i++) {
99695d99930b35c2bac85d52e976b44cf8485d83Timo Sirainen if (bboxes[i]->search_result != NULL)
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen mailbox_search_result_free(&bboxes[i]->search_result);
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen if (bboxes[i]->box == NULL)
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen continue;
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen mail_search_args_deinit(bboxes[i]->search_args);
99695d99930b35c2bac85d52e976b44cf8485d83Timo Sirainen mailbox_free(&bboxes[i]->box);
99695d99930b35c2bac85d52e976b44cf8485d83Timo Sirainen if (array_is_created(&bboxes[i]->sync_outside_expunges))
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen array_free(&bboxes[i]->sync_outside_expunges);
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen array_free(&bboxes[i]->sync_pending_removes);
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen array_free(&bboxes[i]->uids);
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen }
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen i_free_and_null(mbox->vseq_lookup_prev_mailbox);
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen}
c59b9c273b41f7bcf51f6803110b67813879ff05Timo Sirainen
c59b9c273b41f7bcf51f6803110b67813879ff05Timo Sirainenstatic int virtual_mailbox_open(struct mailbox *box)
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen{
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen struct virtual_mailbox *mbox = (struct virtual_mailbox *)box;
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen int ret = 0;
c59b9c273b41f7bcf51f6803110b67813879ff05Timo Sirainen
c59b9c273b41f7bcf51f6803110b67813879ff05Timo Sirainen if (virtual_mailbox_is_in_open_stack(mbox->storage, box->name)) {
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen mail_storage_set_critical(box->storage,
c59b9c273b41f7bcf51f6803110b67813879ff05Timo Sirainen "Virtual mailbox loops: %s", box->name);
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen return -1;
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen }
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen if (!array_is_created(&mbox->backend_boxes))
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen ret = virtual_config_read(mbox);
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen if (ret == 0) {
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen array_append(&mbox->storage->open_stack, &box->name, 1);
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen ret = virtual_mailboxes_open(mbox, box->flags);
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen array_delete(&mbox->storage->open_stack,
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen array_count(&mbox->storage->open_stack)-1, 1);
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen }
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen if (ret < 0) {
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen virtual_mailbox_close_internal(mbox);
52de839a8249bff5eace53dc1401b28baa0c124bTimo Sirainen return -1;
52de839a8249bff5eace53dc1401b28baa0c124bTimo Sirainen }
52de839a8249bff5eace53dc1401b28baa0c124bTimo Sirainen return index_storage_mailbox_open(box, FALSE);
52de839a8249bff5eace53dc1401b28baa0c124bTimo Sirainen}
52de839a8249bff5eace53dc1401b28baa0c124bTimo Sirainen
52de839a8249bff5eace53dc1401b28baa0c124bTimo Sirainenstatic void virtual_mailbox_close(struct mailbox *box)
52de839a8249bff5eace53dc1401b28baa0c124bTimo Sirainen{
52de839a8249bff5eace53dc1401b28baa0c124bTimo Sirainen struct virtual_mailbox *mbox = (struct virtual_mailbox *)box;
52de839a8249bff5eace53dc1401b28baa0c124bTimo Sirainen
52de839a8249bff5eace53dc1401b28baa0c124bTimo Sirainen virtual_mailbox_close_internal(mbox);
52de839a8249bff5eace53dc1401b28baa0c124bTimo Sirainen index_storage_mailbox_close(box);
52de839a8249bff5eace53dc1401b28baa0c124bTimo Sirainen}
52de839a8249bff5eace53dc1401b28baa0c124bTimo Sirainen
52de839a8249bff5eace53dc1401b28baa0c124bTimo Sirainenstatic void virtual_mailbox_free(struct mailbox *box)
52de839a8249bff5eace53dc1401b28baa0c124bTimo Sirainen{
52de839a8249bff5eace53dc1401b28baa0c124bTimo Sirainen struct virtual_mailbox *mbox = (struct virtual_mailbox *)box;
52de839a8249bff5eace53dc1401b28baa0c124bTimo Sirainen
52de839a8249bff5eace53dc1401b28baa0c124bTimo Sirainen virtual_config_free(mbox);
52de839a8249bff5eace53dc1401b28baa0c124bTimo Sirainen index_storage_mailbox_free(box);
52de839a8249bff5eace53dc1401b28baa0c124bTimo Sirainen}
52de839a8249bff5eace53dc1401b28baa0c124bTimo Sirainen
52de839a8249bff5eace53dc1401b28baa0c124bTimo Sirainenstatic int
52de839a8249bff5eace53dc1401b28baa0c124bTimo Sirainenvirtual_mailbox_create(struct mailbox *box,
52de839a8249bff5eace53dc1401b28baa0c124bTimo Sirainen const struct mailbox_update *update ATTR_UNUSED,
52de839a8249bff5eace53dc1401b28baa0c124bTimo Sirainen bool directory ATTR_UNUSED)
52de839a8249bff5eace53dc1401b28baa0c124bTimo Sirainen{
52de839a8249bff5eace53dc1401b28baa0c124bTimo Sirainen mail_storage_set_error(box->storage, MAIL_ERROR_NOTPOSSIBLE,
52de839a8249bff5eace53dc1401b28baa0c124bTimo Sirainen "Can't create virtual mailboxes");
52de839a8249bff5eace53dc1401b28baa0c124bTimo Sirainen return -1;
52de839a8249bff5eace53dc1401b28baa0c124bTimo Sirainen}
52de839a8249bff5eace53dc1401b28baa0c124bTimo Sirainen
52de839a8249bff5eace53dc1401b28baa0c124bTimo Sirainenstatic int
52de839a8249bff5eace53dc1401b28baa0c124bTimo Sirainenvirtual_mailbox_update(struct mailbox *box,
52de839a8249bff5eace53dc1401b28baa0c124bTimo Sirainen const struct mailbox_update *update ATTR_UNUSED)
52de839a8249bff5eace53dc1401b28baa0c124bTimo Sirainen{
52de839a8249bff5eace53dc1401b28baa0c124bTimo Sirainen mail_storage_set_error(box->storage, MAIL_ERROR_NOTPOSSIBLE,
52de839a8249bff5eace53dc1401b28baa0c124bTimo Sirainen "Can't update virtual mailboxes");
52de839a8249bff5eace53dc1401b28baa0c124bTimo Sirainen return -1;
52de839a8249bff5eace53dc1401b28baa0c124bTimo Sirainen}
52de839a8249bff5eace53dc1401b28baa0c124bTimo Sirainen
52de839a8249bff5eace53dc1401b28baa0c124bTimo Sirainenstatic int
52de839a8249bff5eace53dc1401b28baa0c124bTimo Sirainenvirtual_mailbox_get_metadata(struct mailbox *box,
52de839a8249bff5eace53dc1401b28baa0c124bTimo Sirainen enum mailbox_metadata_items items,
52de839a8249bff5eace53dc1401b28baa0c124bTimo Sirainen struct mailbox_metadata *metadata_r)
52de839a8249bff5eace53dc1401b28baa0c124bTimo Sirainen{
52de839a8249bff5eace53dc1401b28baa0c124bTimo Sirainen if ((items & MAILBOX_METADATA_GUID) != 0) {
52de839a8249bff5eace53dc1401b28baa0c124bTimo Sirainen mail_storage_set_error(box->storage, MAIL_ERROR_NOTPOSSIBLE,
52de839a8249bff5eace53dc1401b28baa0c124bTimo Sirainen "Virtual mailboxes have no GUIDs");
52de839a8249bff5eace53dc1401b28baa0c124bTimo Sirainen return -1;
52de839a8249bff5eace53dc1401b28baa0c124bTimo Sirainen }
52de839a8249bff5eace53dc1401b28baa0c124bTimo Sirainen return index_mailbox_get_metadata(box, items, metadata_r);
52de839a8249bff5eace53dc1401b28baa0c124bTimo Sirainen}
52de839a8249bff5eace53dc1401b28baa0c124bTimo Sirainen
52de839a8249bff5eace53dc1401b28baa0c124bTimo Sirainenstatic void
52de839a8249bff5eace53dc1401b28baa0c124bTimo Sirainenvirtual_notify_callback(struct mailbox *bbox ATTR_UNUSED, struct mailbox *box)
52de839a8249bff5eace53dc1401b28baa0c124bTimo Sirainen{
52de839a8249bff5eace53dc1401b28baa0c124bTimo Sirainen box->notify_callback(box, box->notify_context);
52de839a8249bff5eace53dc1401b28baa0c124bTimo Sirainen}
52de839a8249bff5eace53dc1401b28baa0c124bTimo Sirainen
52de839a8249bff5eace53dc1401b28baa0c124bTimo Sirainenstatic void virtual_notify_changes(struct mailbox *box)
52de839a8249bff5eace53dc1401b28baa0c124bTimo Sirainen{
52de839a8249bff5eace53dc1401b28baa0c124bTimo Sirainen struct virtual_mailbox *mbox = (struct virtual_mailbox *)box;
52de839a8249bff5eace53dc1401b28baa0c124bTimo Sirainen struct virtual_backend_box *const *bboxes;
52de839a8249bff5eace53dc1401b28baa0c124bTimo Sirainen unsigned int i, count;
52de839a8249bff5eace53dc1401b28baa0c124bTimo Sirainen
52de839a8249bff5eace53dc1401b28baa0c124bTimo Sirainen bboxes = array_get(&mbox->backend_boxes, &count);
52de839a8249bff5eace53dc1401b28baa0c124bTimo Sirainen for (i = 0; i < count; i++) {
52de839a8249bff5eace53dc1401b28baa0c124bTimo Sirainen struct mailbox *bbox = bboxes[i]->box;
52de839a8249bff5eace53dc1401b28baa0c124bTimo Sirainen
52de839a8249bff5eace53dc1401b28baa0c124bTimo Sirainen if (box->notify_callback == NULL)
52de839a8249bff5eace53dc1401b28baa0c124bTimo Sirainen mailbox_notify_changes_stop(bbox);
52de839a8249bff5eace53dc1401b28baa0c124bTimo Sirainen else {
52de839a8249bff5eace53dc1401b28baa0c124bTimo Sirainen mailbox_notify_changes(bbox, box->notify_min_interval,
52de839a8249bff5eace53dc1401b28baa0c124bTimo Sirainen virtual_notify_callback, box);
52de839a8249bff5eace53dc1401b28baa0c124bTimo Sirainen }
52de839a8249bff5eace53dc1401b28baa0c124bTimo Sirainen }
52de839a8249bff5eace53dc1401b28baa0c124bTimo Sirainen}
52de839a8249bff5eace53dc1401b28baa0c124bTimo Sirainen
52de839a8249bff5eace53dc1401b28baa0c124bTimo Sirainenstatic int
52de839a8249bff5eace53dc1401b28baa0c124bTimo Sirainenvirtual_list_get_mailbox_flags(struct mailbox_list *list,
52de839a8249bff5eace53dc1401b28baa0c124bTimo Sirainen const char *dir, const char *fname,
52de839a8249bff5eace53dc1401b28baa0c124bTimo Sirainen enum mailbox_list_file_type type,
52de839a8249bff5eace53dc1401b28baa0c124bTimo Sirainen struct stat *st_r,
52de839a8249bff5eace53dc1401b28baa0c124bTimo Sirainen enum mailbox_info_flags *flags)
52de839a8249bff5eace53dc1401b28baa0c124bTimo Sirainen{
52de839a8249bff5eace53dc1401b28baa0c124bTimo Sirainen struct virtual_mailbox_list *mlist = VIRTUAL_LIST_CONTEXT(list);
52de839a8249bff5eace53dc1401b28baa0c124bTimo Sirainen struct stat st2;
52de839a8249bff5eace53dc1401b28baa0c124bTimo Sirainen const char *virtual_path;
52de839a8249bff5eace53dc1401b28baa0c124bTimo Sirainen int ret;
52de839a8249bff5eace53dc1401b28baa0c124bTimo Sirainen
52de839a8249bff5eace53dc1401b28baa0c124bTimo Sirainen ret = mlist->module_ctx.super.
52de839a8249bff5eace53dc1401b28baa0c124bTimo Sirainen get_mailbox_flags(list, dir, fname, type, st_r, flags);
52de839a8249bff5eace53dc1401b28baa0c124bTimo Sirainen if (ret <= 0 || MAILBOX_INFO_FLAGS_FINISHED(*flags))
52de839a8249bff5eace53dc1401b28baa0c124bTimo Sirainen return ret;
52de839a8249bff5eace53dc1401b28baa0c124bTimo Sirainen
52de839a8249bff5eace53dc1401b28baa0c124bTimo Sirainen /* see if it's a selectable mailbox */
52de839a8249bff5eace53dc1401b28baa0c124bTimo Sirainen virtual_path = t_strconcat(dir, "/", fname, "/"VIRTUAL_CONFIG_FNAME,
52de839a8249bff5eace53dc1401b28baa0c124bTimo Sirainen NULL);
52de839a8249bff5eace53dc1401b28baa0c124bTimo Sirainen if (stat(virtual_path, &st2) < 0)
52de839a8249bff5eace53dc1401b28baa0c124bTimo Sirainen *flags |= MAILBOX_NOSELECT;
52de839a8249bff5eace53dc1401b28baa0c124bTimo Sirainen return ret;
52de839a8249bff5eace53dc1401b28baa0c124bTimo Sirainen}
52de839a8249bff5eace53dc1401b28baa0c124bTimo Sirainen
52de839a8249bff5eace53dc1401b28baa0c124bTimo Sirainenstatic void virtual_storage_add_list(struct mail_storage *storage ATTR_UNUSED,
52de839a8249bff5eace53dc1401b28baa0c124bTimo Sirainen struct mailbox_list *list)
52de839a8249bff5eace53dc1401b28baa0c124bTimo Sirainen{
52de839a8249bff5eace53dc1401b28baa0c124bTimo Sirainen struct mailbox_list_vfuncs *v = list->vlast;
52de839a8249bff5eace53dc1401b28baa0c124bTimo Sirainen struct virtual_mailbox_list *mlist;
52de839a8249bff5eace53dc1401b28baa0c124bTimo Sirainen
52de839a8249bff5eace53dc1401b28baa0c124bTimo Sirainen mlist = p_new(list->pool, struct virtual_mailbox_list, 1);
52de839a8249bff5eace53dc1401b28baa0c124bTimo Sirainen mlist->module_ctx.super = *v;
52de839a8249bff5eace53dc1401b28baa0c124bTimo Sirainen list->vlast = &mlist->module_ctx.super;
52de839a8249bff5eace53dc1401b28baa0c124bTimo Sirainen
52de839a8249bff5eace53dc1401b28baa0c124bTimo Sirainen v->get_mailbox_flags = virtual_list_get_mailbox_flags;
52de839a8249bff5eace53dc1401b28baa0c124bTimo Sirainen
52de839a8249bff5eace53dc1401b28baa0c124bTimo Sirainen MODULE_CONTEXT_SET(list, virtual_mailbox_list_module, mlist);
52de839a8249bff5eace53dc1401b28baa0c124bTimo Sirainen}
52de839a8249bff5eace53dc1401b28baa0c124bTimo Sirainen
52de839a8249bff5eace53dc1401b28baa0c124bTimo Sirainenstatic int virtual_backend_uidmap_cmp(const uint32_t *uid,
52de839a8249bff5eace53dc1401b28baa0c124bTimo Sirainen const struct virtual_backend_uidmap *map)
52de839a8249bff5eace53dc1401b28baa0c124bTimo Sirainen{
52de839a8249bff5eace53dc1401b28baa0c124bTimo Sirainen return *uid < map->real_uid ? -1 :
52de839a8249bff5eace53dc1401b28baa0c124bTimo Sirainen *uid > map->real_uid ? 1 : 0;
52de839a8249bff5eace53dc1401b28baa0c124bTimo Sirainen}
52de839a8249bff5eace53dc1401b28baa0c124bTimo Sirainen
52de839a8249bff5eace53dc1401b28baa0c124bTimo Sirainenstatic bool
52de839a8249bff5eace53dc1401b28baa0c124bTimo Sirainenvirtual_get_virtual_uid(struct mailbox *box, const char *backend_mailbox,
52de839a8249bff5eace53dc1401b28baa0c124bTimo Sirainen uint32_t backend_uidvalidity,
fffb5431af081379c169d0d96aafe2a9a7352be2Timo Sirainen uint32_t backend_uid, uint32_t *uid_r)
fffb5431af081379c169d0d96aafe2a9a7352be2Timo Sirainen{
52de839a8249bff5eace53dc1401b28baa0c124bTimo Sirainen struct virtual_mailbox *mbox = (struct virtual_mailbox *)box;
52de839a8249bff5eace53dc1401b28baa0c124bTimo Sirainen struct virtual_backend_box *bbox;
52de839a8249bff5eace53dc1401b28baa0c124bTimo Sirainen struct mailbox_status status;
52de839a8249bff5eace53dc1401b28baa0c124bTimo Sirainen const struct virtual_backend_uidmap *uids;
52de839a8249bff5eace53dc1401b28baa0c124bTimo Sirainen
52de839a8249bff5eace53dc1401b28baa0c124bTimo Sirainen if (strcmp(mbox->vseq_lookup_prev_mailbox, backend_mailbox) == 0)
52de839a8249bff5eace53dc1401b28baa0c124bTimo Sirainen bbox = mbox->vseq_lookup_prev_bbox;
52de839a8249bff5eace53dc1401b28baa0c124bTimo Sirainen else {
52de839a8249bff5eace53dc1401b28baa0c124bTimo Sirainen i_free(mbox->vseq_lookup_prev_mailbox);
52de839a8249bff5eace53dc1401b28baa0c124bTimo Sirainen mbox->vseq_lookup_prev_mailbox = i_strdup(backend_mailbox);
52de839a8249bff5eace53dc1401b28baa0c124bTimo Sirainen
52de839a8249bff5eace53dc1401b28baa0c124bTimo Sirainen bbox = virtual_backend_box_lookup_name(mbox, backend_mailbox);
52de839a8249bff5eace53dc1401b28baa0c124bTimo Sirainen mbox->vseq_lookup_prev_bbox = bbox;
52de839a8249bff5eace53dc1401b28baa0c124bTimo Sirainen }
08a4f9396a805b2ac70d55fd494637321ada6516Timo Sirainen if (bbox == NULL)
08a4f9396a805b2ac70d55fd494637321ada6516Timo Sirainen return FALSE;
52de839a8249bff5eace53dc1401b28baa0c124bTimo Sirainen
52de839a8249bff5eace53dc1401b28baa0c124bTimo Sirainen mailbox_get_open_status(bbox->box, STATUS_UIDVALIDITY, &status);
52de839a8249bff5eace53dc1401b28baa0c124bTimo Sirainen if (status.uidvalidity != backend_uidvalidity)
52de839a8249bff5eace53dc1401b28baa0c124bTimo Sirainen return FALSE;
uids = array_bsearch(&bbox->uids, &backend_uid,
virtual_backend_uidmap_cmp);
if (uids == NULL)
return FALSE;
*uid_r = uids->virtual_uid;
return TRUE;
}
static void
virtual_get_virtual_backend_boxes(struct mailbox *box,
ARRAY_TYPE(mailboxes) *mailboxes,
bool only_with_msgs)
{
struct virtual_mailbox *mbox = (struct virtual_mailbox *)box;
struct virtual_backend_box *const *bboxes;
unsigned int i, count;
bboxes = array_get(&mbox->backend_boxes, &count);
for (i = 0; i < count; i++) {
if (!only_with_msgs || array_count(&bboxes[i]->uids) > 0)
array_append(mailboxes, &bboxes[i]->box, 1);
}
}
static void
virtual_get_virtual_box_patterns(struct mailbox *box,
ARRAY_TYPE(mailbox_virtual_patterns) *includes,
ARRAY_TYPE(mailbox_virtual_patterns) *excludes)
{
struct virtual_mailbox *mbox = (struct virtual_mailbox *)box;
array_append_array(includes, &mbox->list_include_patterns);
array_append_array(excludes, &mbox->list_exclude_patterns);
}
static bool virtual_is_inconsistent(struct mailbox *box)
{
struct virtual_mailbox *mbox = (struct virtual_mailbox *)box;
if (mbox->inconsistent)
return TRUE;
return index_storage_is_inconsistent(box);
}
struct mail_storage virtual_storage = {
.name = VIRTUAL_STORAGE_NAME,
.class_flags = MAIL_STORAGE_CLASS_FLAG_NOQUOTA,
.v = {
NULL,
virtual_storage_alloc,
NULL,
NULL,
virtual_storage_add_list,
virtual_storage_get_list_settings,
NULL,
virtual_mailbox_alloc,
NULL
}
};
struct mailbox virtual_mailbox = {
.v = {
index_storage_is_readonly,
index_storage_allow_new_keywords,
index_storage_mailbox_enable,
index_storage_mailbox_exists,
virtual_mailbox_open,
virtual_mailbox_close,
virtual_mailbox_free,
virtual_mailbox_create,
virtual_mailbox_update,
index_storage_mailbox_delete,
index_storage_mailbox_rename,
index_storage_get_status,
virtual_mailbox_get_metadata,
NULL,
NULL,
virtual_storage_sync_init,
index_mailbox_sync_next,
index_mailbox_sync_deinit,
NULL,
virtual_notify_changes,
virtual_transaction_begin,
virtual_transaction_commit,
virtual_transaction_rollback,
NULL,
virtual_mail_alloc,
virtual_search_init,
virtual_search_deinit,
virtual_search_next_nonblock,
virtual_search_next_update_seq,
virtual_save_alloc,
virtual_save_begin,
virtual_save_continue,
virtual_save_finish,
virtual_save_cancel,
mail_storage_copy,
virtual_is_inconsistent
}
};
struct virtual_mailbox_vfuncs virtual_mailbox_vfuncs = {
virtual_get_virtual_uid,
virtual_get_virtual_backend_boxes,
virtual_get_virtual_box_patterns
};