virtual-storage.c revision f95b3d29bc56f139c18c880aa574a0ca72b0cffb
a1e4113a5388e34c08459c5b69679c82ac2bddc9Pavel Březina/* Copyright (c) 2008 Dovecot authors, see the included COPYING file */
a1e4113a5388e34c08459c5b69679c82ac2bddc9Pavel Březina
a1e4113a5388e34c08459c5b69679c82ac2bddc9Pavel Březina#include "lib.h"
a1e4113a5388e34c08459c5b69679c82ac2bddc9Pavel Březina#include "array.h"
a1e4113a5388e34c08459c5b69679c82ac2bddc9Pavel Březina#include "ioloop.h"
a1e4113a5388e34c08459c5b69679c82ac2bddc9Pavel Březina#include "str.h"
a1e4113a5388e34c08459c5b69679c82ac2bddc9Pavel Březina#include "mkdir-parents.h"
a1e4113a5388e34c08459c5b69679c82ac2bddc9Pavel Březina#include "unlink-directory.h"
a1e4113a5388e34c08459c5b69679c82ac2bddc9Pavel Březina#include "index-mail.h"
a1e4113a5388e34c08459c5b69679c82ac2bddc9Pavel Březina#include "mail-copy.h"
a1e4113a5388e34c08459c5b69679c82ac2bddc9Pavel Březina#include "mail-search.h"
a1e4113a5388e34c08459c5b69679c82ac2bddc9Pavel Březina#include "virtual-plugin.h"
a1e4113a5388e34c08459c5b69679c82ac2bddc9Pavel Březina#include "virtual-storage.h"
a1e4113a5388e34c08459c5b69679c82ac2bddc9Pavel Březina
a1e4113a5388e34c08459c5b69679c82ac2bddc9Pavel Březina#include <stdio.h>
a1e4113a5388e34c08459c5b69679c82ac2bddc9Pavel Březina#include <stdlib.h>
a1e4113a5388e34c08459c5b69679c82ac2bddc9Pavel Březina#include <unistd.h>
a1e4113a5388e34c08459c5b69679c82ac2bddc9Pavel Březina#include <dirent.h>
a1e4113a5388e34c08459c5b69679c82ac2bddc9Pavel Březina#include <sys/stat.h>
a1e4113a5388e34c08459c5b69679c82ac2bddc9Pavel Březina
a1e4113a5388e34c08459c5b69679c82ac2bddc9Pavel Březina#define VIRTUAL_LIST_CONTEXT(obj) \
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina MODULE_CONTEXT(obj, virtual_mailbox_list_module)
a1e4113a5388e34c08459c5b69679c82ac2bddc9Pavel Březina
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březinaextern struct mail_storage virtual_storage;
a1e4113a5388e34c08459c5b69679c82ac2bddc9Pavel Březinaextern struct mailbox virtual_mailbox;
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březinastatic MODULE_CONTEXT_DEFINE_INIT(virtual_mailbox_list_module,
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina &mailbox_list_module_register);
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina
a1e4113a5388e34c08459c5b69679c82ac2bddc9Pavel Březinastatic int
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březinavirtual_list_delete_mailbox(struct mailbox_list *list, const char *name);
d3c82d0170d6d7407549afdadd08aa7e11aeb9a2Pavel Březinastatic int
a1e4113a5388e34c08459c5b69679c82ac2bddc9Pavel Březinavirtual_list_iter_is_mailbox(struct mailbox_list_iterate_context *ctx,
a1e4113a5388e34c08459c5b69679c82ac2bddc9Pavel Březina const char *dir, const char *fname,
a1e4113a5388e34c08459c5b69679c82ac2bddc9Pavel Březina const char *mailbox_name,
a1e4113a5388e34c08459c5b69679c82ac2bddc9Pavel Březina enum mailbox_list_file_type type,
a1e4113a5388e34c08459c5b69679c82ac2bddc9Pavel Březina enum mailbox_info_flags *flags);
a1e4113a5388e34c08459c5b69679c82ac2bddc9Pavel Březina
a1e4113a5388e34c08459c5b69679c82ac2bddc9Pavel Březinastatic int
a1e4113a5388e34c08459c5b69679c82ac2bddc9Pavel Březinavirtual_get_list_settings(struct mailbox_list_settings *list_set,
a1e4113a5388e34c08459c5b69679c82ac2bddc9Pavel Březina const char *data, enum mail_storage_flags flags,
a1e4113a5388e34c08459c5b69679c82ac2bddc9Pavel Březina const char **layout_r, const char **error_r)
a1e4113a5388e34c08459c5b69679c82ac2bddc9Pavel Březina{
a1e4113a5388e34c08459c5b69679c82ac2bddc9Pavel Březina bool debug = (flags & MAIL_STORAGE_FLAG_DEBUG) != 0;
a1e4113a5388e34c08459c5b69679c82ac2bddc9Pavel Březina
a1e4113a5388e34c08459c5b69679c82ac2bddc9Pavel Březina *layout_r = "fs";
a1e4113a5388e34c08459c5b69679c82ac2bddc9Pavel Březina
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina memset(list_set, 0, sizeof(*list_set));
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina list_set->subscription_fname = VIRTUAL_SUBSCRIPTION_FILE_NAME;
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina list_set->maildir_name = "";
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina if (data == NULL || *data == '\0' || *data == ':') {
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina /* we won't do any guessing for this format. */
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina if (debug)
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina i_info("virtual: mailbox location not given");
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina *error_r = "Root mail directory not given";
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina return -1;
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina }
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina if (debug)
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina i_info("virtual: data=%s", data);
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina return mailbox_list_settings_parse(data, list_set, layout_r, NULL,
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina error_r);
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina}
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březinastatic struct mail_storage *virtual_alloc(void)
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina{
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina struct virtual_storage *storage;
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina pool_t pool;
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina
afdc0179af0ad8ddbedd67422193ef02dcd2bf84Lukas Slebodnik pool = pool_alloconly_create("virtual storage", 512+256);
afdc0179af0ad8ddbedd67422193ef02dcd2bf84Lukas Slebodnik storage = p_new(pool, struct virtual_storage, 1);
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina storage->storage = virtual_storage;
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina storage->storage.pool = pool;
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina return &storage->storage;
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina}
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březinastatic int virtual_create(struct mail_storage *_storage, const char *data,
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina const char **error_r)
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina{
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina struct virtual_storage *storage = (struct virtual_storage *)_storage;
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina struct mailbox_list_settings list_set;
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek struct stat st;
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek const char *layout;
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek if (virtual_get_list_settings(&list_set, data, _storage->flags,
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek &layout, error_r) < 0)
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek return -1;
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek list_set.mail_storage_flags = &_storage->flags;
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek list_set.lock_method = &_storage->lock_method;
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek if (stat(list_set.root_dir, &st) < 0) {
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek if (errno == ENOENT) {
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek *error_r = t_strdup_printf(
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek "Root mail directory doesn't exist: %s",
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek list_set.root_dir);
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek } else if (errno == EACCES) {
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek *error_r = mail_storage_eacces_msg("stat",
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek list_set.root_dir);
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek } else {
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek *error_r = t_strdup_printf("stat(%s) failed: %m",
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek list_set.root_dir);
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek }
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina return -1;
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina }
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina if (mailbox_list_alloc(layout, &_storage->list, error_r) < 0)
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina return -1;
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina storage->list_module_ctx.super = _storage->list->v;
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina _storage->list->v.iter_is_mailbox = virtual_list_iter_is_mailbox;
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina _storage->list->v.delete_mailbox = virtual_list_delete_mailbox;
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina MODULE_CONTEXT_SET_FULL(_storage->list, virtual_mailbox_list_module,
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina storage, &storage->list_module_ctx);
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina /* finish list init after we've overridden vfuncs */
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina mailbox_list_init(_storage->list, _storage->ns, &list_set,
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina mail_storage_get_list_flags(_storage->flags));
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina return 0;
11a87c5f091d6c092b5dadd3d67f900213e280daPetr Cech}
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březinastruct virtual_backend_box *
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březinavirtual_backend_box_lookup_name(struct virtual_mailbox *mbox, const char *name)
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina{
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina struct virtual_backend_box *const *bboxes;
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina unsigned int i, count;
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina bboxes = array_get(&mbox->backend_boxes, &count);
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina for (i = 0; i < count; i++) {
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina if (strcmp(bboxes[i]->name, name) == 0)
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina return bboxes[i];
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina }
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina return NULL;
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina}
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březinastruct virtual_backend_box *
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březinavirtual_backend_box_lookup(struct virtual_mailbox *mbox, uint32_t mailbox_id)
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina{
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina struct virtual_backend_box *const *bboxes;
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina unsigned int i, count;
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina if (mailbox_id == 0)
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina return NULL;
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina bboxes = array_get(&mbox->backend_boxes, &count);
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina for (i = 0; i < count; i++) {
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina if (bboxes[i]->mailbox_id == mailbox_id)
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina return bboxes[i];
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina }
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina return NULL;
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina}
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březinastatic int virtual_mailboxes_open(struct virtual_mailbox *mbox,
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina enum mailbox_open_flags open_flags)
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina{
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina struct virtual_backend_box *const *bboxes;
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina struct mail_namespace *ns;
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina unsigned int i, count;
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina enum mail_error error;
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina const char *str, *mailbox;
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina open_flags |= MAILBOX_OPEN_KEEP_RECENT;
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina bboxes = array_get(&mbox->backend_boxes, &count);
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina for (i = 0; i < count; i++) {
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina mailbox = bboxes[i]->name;
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina ns = mail_namespace_find(virtual_all_namespaces, &mailbox);
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina bboxes[i]->box = mailbox_open(ns->storage, mailbox,
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina NULL, open_flags);
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina if (bboxes[i]->box == NULL) {
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina str = mail_storage_get_last_error(ns->storage, &error);
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina mail_storage_set_error(mbox->ibox.box.storage,
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina error, str);
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina break;
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina }
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina i_array_init(&bboxes[i]->uids, 64);
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina i_array_init(&bboxes[i]->sync_pending_removes, 64);
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina }
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina if (i == count)
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina return 0;
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina else {
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina /* failed */
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina for (; i > 0; i--) {
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina mailbox_close(&bboxes[i-1]->box);
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina array_free(&bboxes[i-1]->uids);
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina }
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina return -1;
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina }
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina}
11a87c5f091d6c092b5dadd3d67f900213e280daPetr Cech
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březinastatic struct mailbox *
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březinavirtual_open(struct virtual_storage *storage, const char *name,
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina enum mailbox_open_flags flags)
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina{
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina struct mail_storage *_storage = &storage->storage;
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina struct virtual_mailbox *mbox;
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina struct mail_index *index;
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina const char *path;
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina pool_t pool;
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina path = mailbox_list_get_path(_storage->list, name,
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina MAILBOX_LIST_PATH_TYPE_MAILBOX);
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina index = index_storage_alloc(_storage, name, flags,
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina VIRTUAL_INDEX_PREFIX);
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina mail_index_set_fsync_types(index, MAIL_INDEX_SYNC_TYPE_APPEND |
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina MAIL_INDEX_SYNC_TYPE_EXPUNGE);
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina pool = pool_alloconly_create("virtual mailbox", 1024+512);
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina mbox = p_new(pool, struct virtual_mailbox, 1);
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina mbox->ibox.box = virtual_mailbox;
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina mbox->ibox.box.pool = pool;
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina mbox->ibox.box.storage = &storage->storage;
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina mbox->ibox.storage = &storage->storage;
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina mbox->ibox.mail_vfuncs = &virtual_mail_vfuncs;
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina mbox->ibox.index = index;
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina mbox->storage = storage;
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina mbox->path = p_strdup(pool, path);
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina mbox->virtual_ext_id =
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina mail_index_ext_register(index, "virtual", 0,
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina sizeof(struct virtual_mail_index_record),
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina sizeof(uint32_t));
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina if (virtual_config_read(mbox) < 0 ||
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina virtual_mailboxes_open(mbox, flags) < 0) {
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina virtual_config_free(mbox);
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina pool_unref(&pool);
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina return NULL;
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina }
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina index_storage_mailbox_init(&mbox->ibox, name, flags, FALSE);
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina return &mbox->ibox.box;
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina}
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březinastatic struct mailbox *
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březinavirtual_mailbox_open(struct mail_storage *_storage, const char *name,
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina struct istream *input, enum mailbox_open_flags flags)
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina{
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina struct virtual_storage *storage = (struct virtual_storage *)_storage;
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina const char *path;
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek struct stat st;
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek if (input != NULL) {
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek mail_storage_set_critical(_storage,
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina "virtual doesn't support streamed mailboxes");
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina return NULL;
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina }
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina path = mailbox_list_get_path(_storage->list, name,
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek MAILBOX_LIST_PATH_TYPE_MAILBOX);
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek if (stat(path, &st) == 0)
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek return virtual_open(storage, name, flags);
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek else if (errno == ENOENT) {
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek mail_storage_set_error(_storage, MAIL_ERROR_NOTFOUND,
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek T_MAIL_ERR_MAILBOX_NOT_FOUND(name));
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek } else if (errno == EACCES) {
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek mail_storage_set_critical(_storage, "%s",
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek mail_storage_eacces_msg("stat", path));
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek } else {
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek mail_storage_set_critical(_storage, "stat(%s) failed: %m",
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek path);
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek }
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek return NULL;
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek}
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozekstatic int virtual_storage_mailbox_close(struct mailbox *box)
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek{
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek struct virtual_mailbox *mbox = (struct virtual_mailbox *)box;
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek struct virtual_backend_box **bboxes;
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek unsigned int i, count;
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek int ret = 0;
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek virtual_config_free(mbox);
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek bboxes = array_get_modifiable(&mbox->backend_boxes, &count);
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek for (i = 0; i < count; i++) {
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek mailbox_search_result_free(&bboxes[i]->search_result);
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek if (mailbox_close(&bboxes[i]->box) < 0)
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek ret = -1;
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek array_free(&bboxes[i]->sync_pending_removes);
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek array_free(&bboxes[i]->uids);
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina }
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina array_free(&mbox->backend_boxes);
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek return index_storage_mailbox_close(box) < 0 ? -1 : ret;
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek}
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozekstatic int virtual_mailbox_create(struct mail_storage *_storage,
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek const char *name ATTR_UNUSED,
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek bool directory ATTR_UNUSED)
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek{
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek mail_storage_set_error(_storage, MAIL_ERROR_NOTPOSSIBLE,
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek "Can't create virtual mailboxes");
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek return -1;
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek}
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozekstatic int
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozekvirtual_delete_nonrecursive(struct mailbox_list *list, const char *path,
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek const char *name)
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek{
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek DIR *dir;
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek struct dirent *d;
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek string_t *full_path;
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek unsigned int dir_len;
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek bool unlinked_something = FALSE;
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek dir = opendir(path);
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek if (dir == NULL) {
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek if (!mailbox_list_set_error_from_errno(list)) {
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek mailbox_list_set_critical(list,
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek "opendir(%s) failed: %m", path);
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek }
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek return -1;
877b92e80bde510d5cd9f03dbf01e2bcf73ab072Michal Židek }
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek full_path = t_str_new(256);
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek str_append(full_path, path);
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek str_append_c(full_path, '/');
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek dir_len = str_len(full_path);
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek errno = 0;
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek while ((d = readdir(dir)) != NULL) {
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek if (d->d_name[0] == '.') {
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek /* skip . and .. */
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek if (d->d_name[1] == '\0')
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek continue;
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek if (d->d_name[1] == '.' && d->d_name[2] == '\0')
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek continue;
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek }
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek str_truncate(full_path, dir_len);
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek str_append(full_path, d->d_name);
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek /* trying to unlink() a directory gives either EPERM or EISDIR
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek (non-POSIX). it doesn't really work anywhere in practise,
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek so don't bother stat()ing the file first */
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina if (unlink(str_c(full_path)) == 0)
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina unlinked_something = TRUE;
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina else if (errno != ENOENT && errno != EISDIR && errno != EPERM) {
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina mailbox_list_set_critical(list,
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina "unlink(%s) failed: %m",
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina str_c(full_path));
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek }
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek }
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek if (closedir(dir) < 0) {
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek mailbox_list_set_critical(list, "closedir(%s) failed: %m",
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek path);
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek }
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek if (rmdir(path) == 0)
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek unlinked_something = TRUE;
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek else if (errno != ENOENT && errno != ENOTEMPTY) {
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek mailbox_list_set_critical(list, "rmdir(%s) failed: %m", path);
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek return -1;
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek }
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek if (!unlinked_something) {
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek mailbox_list_set_error(list, MAIL_ERROR_NOTPOSSIBLE,
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek t_strdup_printf("Directory %s isn't empty, "
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek "can't delete it.", name));
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek return -1;
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek }
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek return 0;
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek}
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březinastatic int
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březinavirtual_list_delete_mailbox(struct mailbox_list *list, const char *name)
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek{
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek struct virtual_storage *storage = VIRTUAL_LIST_CONTEXT(list);
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek struct stat st;
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek const char *src;
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek /* Make sure the indexes are closed before trying to delete the
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek directory that contains them. It can still fail with some NFS
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek implementations if indexes are opened by another session, but
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek that can't really be helped. */
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek index_storage_destroy_unrefed();
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek /* delete the index and control directories */
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek if (storage->list_module_ctx.super.delete_mailbox(list, name) < 0)
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek return -1;
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek /* check if the mailbox actually exists */
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek src = mailbox_list_get_path(list, name, MAILBOX_LIST_PATH_TYPE_MAILBOX);
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek if (stat(src, &st) != 0 && errno == ENOENT) {
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek mailbox_list_set_error(list, MAIL_ERROR_NOTFOUND,
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek T_MAIL_ERR_MAILBOX_NOT_FOUND(name));
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek return -1;
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek }
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek return virtual_delete_nonrecursive(list, src, name);
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek}
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozekstatic void virtual_notify_changes(struct mailbox *box)
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek{
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek struct virtual_mailbox *mbox = (struct virtual_mailbox *)box;
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek // FIXME
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek}
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozekstatic int
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozekvirtual_list_iter_is_mailbox(struct mailbox_list_iterate_context *ctx
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek ATTR_UNUSED,
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek const char *dir, const char *fname,
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek const char *mailbox_name ATTR_UNUSED,
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek enum mailbox_list_file_type type,
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek enum mailbox_info_flags *flags)
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek{
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek const char *path, *maildir_path;
bdf32fbb3c947dd1b2c54d1c21d8028a1ddc80e6Jakub Hrozek struct stat st;
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina int ret = 1;
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina /* try to avoid stat() with these checks */
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina if (type != MAILBOX_LIST_FILE_TYPE_DIR &&
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina type != MAILBOX_LIST_FILE_TYPE_SYMLINK &&
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina type != MAILBOX_LIST_FILE_TYPE_UNKNOWN) {
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina /* it's a file */
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina *flags |= MAILBOX_NOSELECT | MAILBOX_NOINFERIORS;
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina return 0;
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina }
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina /* need to stat() then */
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina path = t_strconcat(dir, "/", fname, NULL);
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina if (stat(path, &st) == 0) {
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina if (!S_ISDIR(st.st_mode)) {
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina /* non-directory */
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina *flags |= MAILBOX_NOSELECT | MAILBOX_NOINFERIORS;
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina ret = 0;
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina } else if (st.st_nlink == 2) {
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina /* no subdirectories */
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina *flags |= MAILBOX_NOCHILDREN;
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina } else if (*ctx->list->set.maildir_name != '\0') {
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina /* non-default configuration: we have one directory
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina containing the mailboxes. if there are 3 links,
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina either this is a selectable mailbox without children
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina or non-selectable mailbox with children */
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina if (st.st_nlink > 3)
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina *flags |= MAILBOX_CHILDREN;
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina } else {
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina /* default configuration: all subdirectories are
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina child mailboxes. */
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina if (st.st_nlink > 2)
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina *flags |= MAILBOX_CHILDREN;
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina }
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina } else {
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina /* non-selectable. probably either access denied, or symlink
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina destination not found. don't bother logging errors. */
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina *flags |= MAILBOX_NOSELECT;
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina }
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina if ((*flags & MAILBOX_NOSELECT) == 0) {
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina /* make sure it's a selectable mailbox */
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina maildir_path = t_strconcat(path, "/"VIRTUAL_CONFIG_FNAME, NULL);
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina if (stat(maildir_path, &st) < 0 || !S_ISDIR(st.st_mode))
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina *flags |= MAILBOX_NOSELECT;
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina }
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina return ret;
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina}
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březinastatic int
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březinavirtual_save_init(struct mailbox_transaction_context *_t,
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina enum mail_flags flags ATTR_UNUSED,
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina struct mail_keywords *keywords ATTR_UNUSED,
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina time_t received_date ATTR_UNUSED,
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina int timezone_offset ATTR_UNUSED,
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina const char *from_envelope ATTR_UNUSED,
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina struct istream *input ATTR_UNUSED,
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina struct mail *dest_mail ATTR_UNUSED,
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina struct mail_save_context **ctx_r)
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina{
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina mail_storage_set_error(_t->box->storage, MAIL_ERROR_NOTPOSSIBLE,
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina "Can't save to virtual mailboxes");
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina *ctx_r = NULL;
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina return -1;
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina}
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březinastatic void virtual_class_init(void)
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina{
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina virtual_transaction_class_init();
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina}
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březinastatic void virtual_class_deinit(void)
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina{
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina virtual_transaction_class_deinit();
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina}
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březinastruct mail_storage virtual_storage = {
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina MEMBER(name) VIRTUAL_STORAGE_NAME,
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina MEMBER(mailbox_is_file) FALSE,
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina {
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina virtual_class_init,
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina virtual_class_deinit,
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina virtual_alloc,
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina virtual_create,
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina index_storage_destroy,
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina NULL,
c02b8482375837b57cb618ed56d4bede0e006d9dPavel Březina virtual_mailbox_open,
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina virtual_mailbox_create
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina }
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina};
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březinastruct mailbox virtual_mailbox = {
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina MEMBER(name) NULL,
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina MEMBER(storage) NULL,
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina {
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina index_storage_is_readonly,
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina index_storage_allow_new_keywords,
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina index_storage_mailbox_enable,
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina virtual_storage_mailbox_close,
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina index_storage_get_status,
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina NULL,
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina NULL,
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina virtual_storage_sync_init,
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina index_mailbox_sync_next,
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina index_mailbox_sync_deinit,
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina NULL,
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina virtual_notify_changes,
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina index_transaction_begin,
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina index_transaction_commit,
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina index_transaction_rollback,
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina index_transaction_set_max_modseq,
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina index_keywords_create,
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina index_keywords_free,
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina index_storage_get_seq_range,
11a87c5f091d6c092b5dadd3d67f900213e280daPetr Cech index_storage_get_uid_range,
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina index_storage_get_expunged_uids,
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina virtual_mail_alloc,
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina index_header_lookup_init,
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina index_header_lookup_ref,
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina index_header_lookup_unref,
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina index_storage_search_init,
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina index_storage_search_deinit,
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina index_storage_search_next_nonblock,
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina index_storage_search_next_update_seq,
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina virtual_save_init,
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina NULL,
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina NULL,
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina NULL,
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina mail_storage_copy,
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina index_storage_is_inconsistent
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina }
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina};
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina