mailbox-alias-plugin.c revision f67c2a7415cbd1a783920cc84ded731dcafa4ffc
a8c5a86d183db25a57bf193c06b41e092ec2e151Timo Sirainen/* Copyright (c) 2012 Dovecot authors, see the included COPYING file */
02b32cf39a098edf60981fc228e4b034f11f3b90Timo Sirainen
02b32cf39a098edf60981fc228e4b034f11f3b90Timo Sirainen#include "lib.h"
b5ff746939712c6a9bef71405fa786d5471cf177Timo Sirainen#include "str.h"
02b32cf39a098edf60981fc228e4b034f11f3b90Timo Sirainen#include "mail-storage-hooks.h"
02b32cf39a098edf60981fc228e4b034f11f3b90Timo Sirainen#include "mail-storage-private.h"
b5ff746939712c6a9bef71405fa786d5471cf177Timo Sirainen#include "mailbox-list-private.h"
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen#include "mailbox-alias-plugin.h"
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen#define MAILBOX_ALIAS_USER_CONTEXT(obj) \
9e86ad9eb313004cd4c8b5427daeb4c241b57af6Timo Sirainen MODULE_CONTEXT(obj, mailbox_alias_user_module)
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen#define MAILBOX_ALIAS_CONTEXT(obj) \
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen MODULE_CONTEXT(obj, mailbox_alias_storage_module)
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen#define MAILBOX_ALIAS_LIST_CONTEXT(obj) \
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen MODULE_CONTEXT(obj, mailbox_alias_mailbox_list_module)
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainenstruct mailbox_alias {
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen const char *old_vname, *new_vname;
48f78a48f2e1cf299026544444666471ae16ad97Timo Sirainen};
6e77746e501c2b45850b1c530836058ed75e09eeTimo Sirainen
6e77746e501c2b45850b1c530836058ed75e09eeTimo Sirainenstruct mailbox_alias_user {
6e77746e501c2b45850b1c530836058ed75e09eeTimo Sirainen union mail_user_module_context module_ctx;
6e77746e501c2b45850b1c530836058ed75e09eeTimo Sirainen
6e77746e501c2b45850b1c530836058ed75e09eeTimo Sirainen ARRAY_DEFINE(aliases, struct mailbox_alias);
6e77746e501c2b45850b1c530836058ed75e09eeTimo Sirainen};
6e77746e501c2b45850b1c530836058ed75e09eeTimo Sirainen
6e77746e501c2b45850b1c530836058ed75e09eeTimo Sirainenstruct mailbox_alias_mailbox_list {
6e77746e501c2b45850b1c530836058ed75e09eeTimo Sirainen union mailbox_list_module_context module_ctx;
6e77746e501c2b45850b1c530836058ed75e09eeTimo Sirainen};
6e77746e501c2b45850b1c530836058ed75e09eeTimo Sirainen
6e77746e501c2b45850b1c530836058ed75e09eeTimo Sirainenstruct mailbox_alias_mailbox {
6e77746e501c2b45850b1c530836058ed75e09eeTimo Sirainen union mailbox_module_context module_ctx;
8c8f7ac580b661aee3d8b8dd37df4a9b41c77000Timo Sirainen};
8c8f7ac580b661aee3d8b8dd37df4a9b41c77000Timo Sirainen
8c8f7ac580b661aee3d8b8dd37df4a9b41c77000Timo Sirainenenum mailbox_symlink_existence {
8c8f7ac580b661aee3d8b8dd37df4a9b41c77000Timo Sirainen MAILBOX_SYMLINK_EXISTENCE_NONEXISTENT,
8c8f7ac580b661aee3d8b8dd37df4a9b41c77000Timo Sirainen MAILBOX_SYMLINK_EXISTENCE_SYMLINK,
8c8f7ac580b661aee3d8b8dd37df4a9b41c77000Timo Sirainen MAILBOX_SYMLINK_EXISTENCE_NOT_SYMLINK
8c8f7ac580b661aee3d8b8dd37df4a9b41c77000Timo Sirainen};
8c8f7ac580b661aee3d8b8dd37df4a9b41c77000Timo Sirainen
8c8f7ac580b661aee3d8b8dd37df4a9b41c77000Timo Sirainenstatic MODULE_CONTEXT_DEFINE_INIT(mailbox_alias_user_module,
8c8f7ac580b661aee3d8b8dd37df4a9b41c77000Timo Sirainen &mail_user_module_register);
8c8f7ac580b661aee3d8b8dd37df4a9b41c77000Timo Sirainenstatic MODULE_CONTEXT_DEFINE_INIT(mailbox_alias_storage_module,
8c8f7ac580b661aee3d8b8dd37df4a9b41c77000Timo Sirainen &mail_storage_module_register);
8c8f7ac580b661aee3d8b8dd37df4a9b41c77000Timo Sirainenstatic MODULE_CONTEXT_DEFINE_INIT(mailbox_alias_mailbox_list_module,
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen &mailbox_list_module_register);
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainenconst char *mailbox_alias_plugin_version = DOVECOT_VERSION;
48f78a48f2e1cf299026544444666471ae16ad97Timo Sirainen
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainenstatic const char *
48f78a48f2e1cf299026544444666471ae16ad97Timo Sirainenmailbox_alias_find_new(struct mail_user *user, const char *new_vname)
48f78a48f2e1cf299026544444666471ae16ad97Timo Sirainen{
0dc7891233a973829f00371b27810f849b987c66Timo Sirainen struct mailbox_alias_user *auser = MAILBOX_ALIAS_USER_CONTEXT(user);
0dc7891233a973829f00371b27810f849b987c66Timo Sirainen const struct mailbox_alias *alias;
0dc7891233a973829f00371b27810f849b987c66Timo Sirainen
0dc7891233a973829f00371b27810f849b987c66Timo Sirainen array_foreach(&auser->aliases, alias) {
0dc7891233a973829f00371b27810f849b987c66Timo Sirainen if (strcmp(alias->new_vname, new_vname) == 0)
0dc7891233a973829f00371b27810f849b987c66Timo Sirainen return alias->old_vname;
0dc7891233a973829f00371b27810f849b987c66Timo Sirainen }
0dc7891233a973829f00371b27810f849b987c66Timo Sirainen return NULL;
b5ff746939712c6a9bef71405fa786d5471cf177Timo Sirainen}
b5ff746939712c6a9bef71405fa786d5471cf177Timo Sirainen
b5ff746939712c6a9bef71405fa786d5471cf177Timo Sirainenstatic int mailbox_symlink_exists(struct mailbox_list *list, const char *vname,
b5ff746939712c6a9bef71405fa786d5471cf177Timo Sirainen enum mailbox_symlink_existence *existence_r)
b5ff746939712c6a9bef71405fa786d5471cf177Timo Sirainen{
b5ff746939712c6a9bef71405fa786d5471cf177Timo Sirainen struct mailbox_alias_mailbox_list *alist =
b5ff746939712c6a9bef71405fa786d5471cf177Timo Sirainen MAILBOX_ALIAS_LIST_CONTEXT(list);
b5ff746939712c6a9bef71405fa786d5471cf177Timo Sirainen struct stat st;
b5ff746939712c6a9bef71405fa786d5471cf177Timo Sirainen const char *symlink_name, *symlink_path;
b5ff746939712c6a9bef71405fa786d5471cf177Timo Sirainen
b5ff746939712c6a9bef71405fa786d5471cf177Timo Sirainen symlink_name = alist->module_ctx.super.get_storage_name(list, vname);
b5ff746939712c6a9bef71405fa786d5471cf177Timo Sirainen symlink_path = mailbox_list_get_path(list, symlink_name,
b5ff746939712c6a9bef71405fa786d5471cf177Timo Sirainen MAILBOX_LIST_PATH_TYPE_DIR);
b5ff746939712c6a9bef71405fa786d5471cf177Timo Sirainen if (lstat(symlink_path, &st) < 0) {
b5ff746939712c6a9bef71405fa786d5471cf177Timo Sirainen if (errno == ENOENT) {
b5ff746939712c6a9bef71405fa786d5471cf177Timo Sirainen *existence_r = MAILBOX_SYMLINK_EXISTENCE_NONEXISTENT;
b5ff746939712c6a9bef71405fa786d5471cf177Timo Sirainen return 0;
b5ff746939712c6a9bef71405fa786d5471cf177Timo Sirainen }
b5ff746939712c6a9bef71405fa786d5471cf177Timo Sirainen mailbox_list_set_critical(list,
b5ff746939712c6a9bef71405fa786d5471cf177Timo Sirainen "lstat(%s) failed: %m", symlink_path);
b5ff746939712c6a9bef71405fa786d5471cf177Timo Sirainen return -1;
b5ff746939712c6a9bef71405fa786d5471cf177Timo Sirainen }
b5ff746939712c6a9bef71405fa786d5471cf177Timo Sirainen if (S_ISLNK(st.st_mode))
b5ff746939712c6a9bef71405fa786d5471cf177Timo Sirainen *existence_r = MAILBOX_SYMLINK_EXISTENCE_SYMLINK;
b5ff746939712c6a9bef71405fa786d5471cf177Timo Sirainen else
b5ff746939712c6a9bef71405fa786d5471cf177Timo Sirainen *existence_r = MAILBOX_SYMLINK_EXISTENCE_NOT_SYMLINK;
b5ff746939712c6a9bef71405fa786d5471cf177Timo Sirainen return 0;
b5ff746939712c6a9bef71405fa786d5471cf177Timo Sirainen}
b5ff746939712c6a9bef71405fa786d5471cf177Timo Sirainen
b5ff746939712c6a9bef71405fa786d5471cf177Timo Sirainenstatic int mailbox_is_alias_symlink(struct mailbox *box)
b5ff746939712c6a9bef71405fa786d5471cf177Timo Sirainen{
b5ff746939712c6a9bef71405fa786d5471cf177Timo Sirainen enum mailbox_symlink_existence existence;
b5ff746939712c6a9bef71405fa786d5471cf177Timo Sirainen
b5ff746939712c6a9bef71405fa786d5471cf177Timo Sirainen if (mailbox_alias_find_new(box->storage->user, box->vname) == NULL)
b5ff746939712c6a9bef71405fa786d5471cf177Timo Sirainen return 0;
b5ff746939712c6a9bef71405fa786d5471cf177Timo Sirainen if (mailbox_symlink_exists(box->list, box->vname, &existence) < 0) {
b5ff746939712c6a9bef71405fa786d5471cf177Timo Sirainen mail_storage_copy_list_error(box->storage, box->list);
b5ff746939712c6a9bef71405fa786d5471cf177Timo Sirainen return -1;
b5ff746939712c6a9bef71405fa786d5471cf177Timo Sirainen }
b5ff746939712c6a9bef71405fa786d5471cf177Timo Sirainen return existence == MAILBOX_SYMLINK_EXISTENCE_SYMLINK ? 1 : 0;
b5ff746939712c6a9bef71405fa786d5471cf177Timo Sirainen}
b5ff746939712c6a9bef71405fa786d5471cf177Timo Sirainen
b5ff746939712c6a9bef71405fa786d5471cf177Timo Sirainenstatic int
b5ff746939712c6a9bef71405fa786d5471cf177Timo Sirainenmailbox_has_aliases(struct mailbox_list *list, const char *old_vname)
b5ff746939712c6a9bef71405fa786d5471cf177Timo Sirainen{
b5ff746939712c6a9bef71405fa786d5471cf177Timo Sirainen struct mailbox_alias_user *auser =
b5ff746939712c6a9bef71405fa786d5471cf177Timo Sirainen MAILBOX_ALIAS_USER_CONTEXT(list->ns->user);
b5ff746939712c6a9bef71405fa786d5471cf177Timo Sirainen const struct mailbox_alias *alias;
b5ff746939712c6a9bef71405fa786d5471cf177Timo Sirainen enum mailbox_symlink_existence existence;
b5ff746939712c6a9bef71405fa786d5471cf177Timo Sirainen int ret = 0;
b5ff746939712c6a9bef71405fa786d5471cf177Timo Sirainen
b5ff746939712c6a9bef71405fa786d5471cf177Timo Sirainen array_foreach(&auser->aliases, alias) {
b5ff746939712c6a9bef71405fa786d5471cf177Timo Sirainen if (strcmp(alias->old_vname, old_vname) == 0) {
b5ff746939712c6a9bef71405fa786d5471cf177Timo Sirainen if (mailbox_symlink_exists(list, alias->new_vname,
b5ff746939712c6a9bef71405fa786d5471cf177Timo Sirainen &existence) < 0)
b5ff746939712c6a9bef71405fa786d5471cf177Timo Sirainen ret = -1;
b5ff746939712c6a9bef71405fa786d5471cf177Timo Sirainen else if (existence == MAILBOX_SYMLINK_EXISTENCE_SYMLINK)
b5ff746939712c6a9bef71405fa786d5471cf177Timo Sirainen return 1;
b5ff746939712c6a9bef71405fa786d5471cf177Timo Sirainen }
b5ff746939712c6a9bef71405fa786d5471cf177Timo Sirainen }
b5ff746939712c6a9bef71405fa786d5471cf177Timo Sirainen return ret;
b5ff746939712c6a9bef71405fa786d5471cf177Timo Sirainen}
b5ff746939712c6a9bef71405fa786d5471cf177Timo Sirainen
b5ff746939712c6a9bef71405fa786d5471cf177Timo Sirainenstatic int
b5ff746939712c6a9bef71405fa786d5471cf177Timo Sirainenmailbox_alias_create_symlink(struct mailbox *box,
b5ff746939712c6a9bef71405fa786d5471cf177Timo Sirainen const char *old_name, const char *new_name)
b5ff746939712c6a9bef71405fa786d5471cf177Timo Sirainen{
b5ff746939712c6a9bef71405fa786d5471cf177Timo Sirainen const char *old_path, *new_path, *fname;
b5ff746939712c6a9bef71405fa786d5471cf177Timo Sirainen
b5ff746939712c6a9bef71405fa786d5471cf177Timo Sirainen old_path = mailbox_list_get_path(box->list, old_name,
b5ff746939712c6a9bef71405fa786d5471cf177Timo Sirainen MAILBOX_LIST_PATH_TYPE_DIR);
b5ff746939712c6a9bef71405fa786d5471cf177Timo Sirainen new_path = mailbox_list_get_path(box->list, new_name,
b5ff746939712c6a9bef71405fa786d5471cf177Timo Sirainen MAILBOX_LIST_PATH_TYPE_DIR);
b5ff746939712c6a9bef71405fa786d5471cf177Timo Sirainen fname = strrchr(old_path, '/');
b5ff746939712c6a9bef71405fa786d5471cf177Timo Sirainen i_assert(fname != NULL);
b5ff746939712c6a9bef71405fa786d5471cf177Timo Sirainen fname++;
b5ff746939712c6a9bef71405fa786d5471cf177Timo Sirainen i_assert(strncmp(new_path, old_path, fname-old_path) == 0);
b5ff746939712c6a9bef71405fa786d5471cf177Timo Sirainen
b5ff746939712c6a9bef71405fa786d5471cf177Timo Sirainen if (symlink(fname, new_path) < 0) {
b5ff746939712c6a9bef71405fa786d5471cf177Timo Sirainen if (errno == EEXIST) {
b5ff746939712c6a9bef71405fa786d5471cf177Timo Sirainen mail_storage_set_error(box->storage, MAIL_ERROR_EXISTS,
b5ff746939712c6a9bef71405fa786d5471cf177Timo Sirainen "Mailbox already exists");
b5ff746939712c6a9bef71405fa786d5471cf177Timo Sirainen return -1;
b5ff746939712c6a9bef71405fa786d5471cf177Timo Sirainen }
b5ff746939712c6a9bef71405fa786d5471cf177Timo Sirainen mail_storage_set_critical(box->storage,
b5ff746939712c6a9bef71405fa786d5471cf177Timo Sirainen "symlink(%s, %s) failed: %m", fname, new_path);
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen return -1;
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen }
0dc7891233a973829f00371b27810f849b987c66Timo Sirainen return 0;
02b32cf39a098edf60981fc228e4b034f11f3b90Timo Sirainen}
0dc7891233a973829f00371b27810f849b987c66Timo Sirainen
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainenstatic const char *
02b32cf39a098edf60981fc228e4b034f11f3b90Timo Sirainenmailbox_alias_get_storage_name(struct mailbox_list *list, const char *vname)
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen{
02b32cf39a098edf60981fc228e4b034f11f3b90Timo Sirainen struct mailbox_alias_mailbox_list *alist =
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen MAILBOX_ALIAS_LIST_CONTEXT(list);
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen const char *old_vname;
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen enum mailbox_symlink_existence existence;
0dc7891233a973829f00371b27810f849b987c66Timo Sirainen
0dc7891233a973829f00371b27810f849b987c66Timo Sirainen /* access the old mailbox so that e.g. full text search won't
0dc7891233a973829f00371b27810f849b987c66Timo Sirainen index the mailbox twice. this also means that deletion must be
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen careful to delete the symlink, box->name. */
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen old_vname = mailbox_alias_find_new(list->ns->user, vname);
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen if (old_vname != NULL &&
0dc7891233a973829f00371b27810f849b987c66Timo Sirainen mailbox_symlink_exists(list, vname, &existence) == 0 &&
0dc7891233a973829f00371b27810f849b987c66Timo Sirainen existence != MAILBOX_SYMLINK_EXISTENCE_NOT_SYMLINK)
0dc7891233a973829f00371b27810f849b987c66Timo Sirainen vname = old_vname;
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen return alist->module_ctx.super.get_storage_name(list, vname);
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen}
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainenstatic int
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainenmailbox_alias_create(struct mailbox *box, const struct mailbox_update *update,
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen bool directory)
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen{
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen struct mailbox_alias_mailbox *abox = MAILBOX_ALIAS_CONTEXT(box);
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen struct mailbox_alias_mailbox_list *alist =
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen MAILBOX_ALIAS_LIST_CONTEXT(box->list);
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen const char *symlink_name;
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen int ret;
02b32cf39a098edf60981fc228e4b034f11f3b90Timo Sirainen
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen ret = abox->module_ctx.super.create(box, update, directory);
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen if (mailbox_alias_find_new(box->storage->user, box->vname) == NULL)
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen return ret;
0dc7891233a973829f00371b27810f849b987c66Timo Sirainen if (ret < 0 && mailbox_get_last_mail_error(box) != MAIL_ERROR_EXISTS)
0dc7891233a973829f00371b27810f849b987c66Timo Sirainen return ret;
0dc7891233a973829f00371b27810f849b987c66Timo Sirainen
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen /* all the code so far has actually only created the original
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen mailbox. now we'll create the symlink if it's missing. */
9e86ad9eb313004cd4c8b5427daeb4c241b57af6Timo Sirainen symlink_name = alist->module_ctx.super.
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen get_storage_name(box->list, box->vname);
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen return mailbox_alias_create_symlink(box, box->name, symlink_name);
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen}
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen
9e86ad9eb313004cd4c8b5427daeb4c241b57af6Timo Sirainenstatic int mailbox_alias_delete(struct mailbox *box)
0dc7891233a973829f00371b27810f849b987c66Timo Sirainen{
0dc7891233a973829f00371b27810f849b987c66Timo Sirainen struct mailbox_alias_mailbox *abox = MAILBOX_ALIAS_CONTEXT(box);
b5ff746939712c6a9bef71405fa786d5471cf177Timo Sirainen struct mailbox_alias_mailbox_list *alist =
b5ff746939712c6a9bef71405fa786d5471cf177Timo Sirainen MAILBOX_ALIAS_LIST_CONTEXT(box->list);
b5ff746939712c6a9bef71405fa786d5471cf177Timo Sirainen const char *symlink_name;
9e86ad9eb313004cd4c8b5427daeb4c241b57af6Timo Sirainen int ret;
9e86ad9eb313004cd4c8b5427daeb4c241b57af6Timo Sirainen
0dc7891233a973829f00371b27810f849b987c66Timo Sirainen ret = mailbox_has_aliases(box->list, box->vname);
0dc7891233a973829f00371b27810f849b987c66Timo Sirainen if (ret < 0)
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen return -1;
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen if (ret > 0) {
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen mail_storage_set_error(box->storage, MAIL_ERROR_NOTPOSSIBLE,
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen "Can't delete mailbox while it has aliases");
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen return -1;
0dc7891233a973829f00371b27810f849b987c66Timo Sirainen }
0dc7891233a973829f00371b27810f849b987c66Timo Sirainen
0dc7891233a973829f00371b27810f849b987c66Timo Sirainen if (mailbox_is_alias_symlink(box)) {
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen /* we're deleting an alias mailbox. we'll need to handle this
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen explicitly since box->name points to the original mailbox */
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen symlink_name = alist->module_ctx.super.
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen get_storage_name(box->list, box->vname);
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen if (mailbox_list_delete_symlink(box->list, symlink_name) < 0) {
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen mail_storage_copy_list_error(box->storage, box->list);
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen return -1;
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen }
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen return 0;
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen }
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen return abox->module_ctx.super.delete(box);
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen}
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainenstatic int mailbox_alias_rename(struct mailbox *src, struct mailbox *dest,
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen bool rename_children)
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen{
c2bb1764c359ce85a7f7f789ead11dd613ff9769Timo Sirainen struct mailbox_alias_mailbox *abox = MAILBOX_ALIAS_CONTEXT(src);
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen int ret;
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen if (mailbox_is_alias_symlink(src)) {
0dc7891233a973829f00371b27810f849b987c66Timo Sirainen mail_storage_set_error(src->storage, MAIL_ERROR_NOTPOSSIBLE,
0dc7891233a973829f00371b27810f849b987c66Timo Sirainen "Can't rename alias mailboxes");
0dc7891233a973829f00371b27810f849b987c66Timo Sirainen return -1;
0dc7891233a973829f00371b27810f849b987c66Timo Sirainen }
0dc7891233a973829f00371b27810f849b987c66Timo Sirainen if (mailbox_is_alias_symlink(dest)) {
0dc7891233a973829f00371b27810f849b987c66Timo Sirainen mail_storage_set_error(src->storage, MAIL_ERROR_NOTPOSSIBLE,
0dc7891233a973829f00371b27810f849b987c66Timo Sirainen "Can't rename to mailbox alias");
0dc7891233a973829f00371b27810f849b987c66Timo Sirainen return -1;
301b1524a822cec7b79856e8c599112c754bc4c0Timo Sirainen }
0dc7891233a973829f00371b27810f849b987c66Timo Sirainen ret = mailbox_has_aliases(src->list, src->vname);
b5ff746939712c6a9bef71405fa786d5471cf177Timo Sirainen if (ret < 0)
b5ff746939712c6a9bef71405fa786d5471cf177Timo Sirainen return -1;
b5ff746939712c6a9bef71405fa786d5471cf177Timo Sirainen if (ret > 0) {
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen mail_storage_set_error(src->storage, MAIL_ERROR_NOTPOSSIBLE,
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen "Can't rename mailbox while it has aliases");
0dc7891233a973829f00371b27810f849b987c66Timo Sirainen return -1;
0dc7891233a973829f00371b27810f849b987c66Timo Sirainen }
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen return abox->module_ctx.super.rename(src, dest, rename_children);
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen}
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainenstatic void mailbox_alias_mail_user_created(struct mail_user *user)
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen{
02b32cf39a098edf60981fc228e4b034f11f3b90Timo Sirainen struct mail_user_vfuncs *v = user->vlast;
02b32cf39a098edf60981fc228e4b034f11f3b90Timo Sirainen struct mailbox_alias_user *auser;
02b32cf39a098edf60981fc228e4b034f11f3b90Timo Sirainen struct mailbox_alias *alias;
02b32cf39a098edf60981fc228e4b034f11f3b90Timo Sirainen string_t *oldkey, *newkey;
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen const char *old_vname, *new_vname;
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen unsigned int i;
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen auser = p_new(user->pool, struct mailbox_alias_user, 1);
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen auser->module_ctx.super = *v;
0dc7891233a973829f00371b27810f849b987c66Timo Sirainen user->vlast = &auser->module_ctx.super;
0dc7891233a973829f00371b27810f849b987c66Timo Sirainen
0dc7891233a973829f00371b27810f849b987c66Timo Sirainen p_array_init(&auser->aliases, user->pool, 8);
0dc7891233a973829f00371b27810f849b987c66Timo Sirainen
0dc7891233a973829f00371b27810f849b987c66Timo Sirainen oldkey = t_str_new(32);
0dc7891233a973829f00371b27810f849b987c66Timo Sirainen newkey = t_str_new(32);
0dc7891233a973829f00371b27810f849b987c66Timo Sirainen str_append(oldkey, "mailbox_alias_old");
0dc7891233a973829f00371b27810f849b987c66Timo Sirainen str_append(newkey, "mailbox_alias_new");
0dc7891233a973829f00371b27810f849b987c66Timo Sirainen for (i = 2;; i++) {
0dc7891233a973829f00371b27810f849b987c66Timo Sirainen old_vname = mail_user_plugin_getenv(user, str_c(oldkey));
0dc7891233a973829f00371b27810f849b987c66Timo Sirainen new_vname = mail_user_plugin_getenv(user, str_c(newkey));
0dc7891233a973829f00371b27810f849b987c66Timo Sirainen if (old_vname == NULL || new_vname == NULL)
0dc7891233a973829f00371b27810f849b987c66Timo Sirainen break;
0dc7891233a973829f00371b27810f849b987c66Timo Sirainen
0dc7891233a973829f00371b27810f849b987c66Timo Sirainen alias = array_append_space(&auser->aliases);
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen alias->old_vname = old_vname;
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen alias->new_vname = new_vname;
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen str_truncate(oldkey, 0);
0dc7891233a973829f00371b27810f849b987c66Timo Sirainen str_truncate(newkey, 0);
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen str_printfa(oldkey, "mailbox_alias_old%u", i);
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen str_printfa(newkey, "mailbox_alias_new%u", i);
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen }
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen MODULE_CONTEXT_SET(user, mailbox_alias_user_module, auser);
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen}
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainenstatic void mailbox_alias_mailbox_list_created(struct mailbox_list *list)
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen{
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen struct mailbox_list_vfuncs *v = list->vlast;
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen struct mailbox_alias_mailbox_list *alist;
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen alist = p_new(list->pool, struct mailbox_alias_mailbox_list, 1);
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen alist->module_ctx.super = *v;
0dc7891233a973829f00371b27810f849b987c66Timo Sirainen list->vlast = &alist->module_ctx.super;
0dc7891233a973829f00371b27810f849b987c66Timo Sirainen
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen v->get_storage_name = mailbox_alias_get_storage_name;
0dc7891233a973829f00371b27810f849b987c66Timo Sirainen MODULE_CONTEXT_SET(list, mailbox_alias_mailbox_list_module, alist);
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen}
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainenstatic void mailbox_alias_mailbox_allocated(struct mailbox *box)
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen{
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen struct mailbox_vfuncs *v = box->vlast;
0dc7891233a973829f00371b27810f849b987c66Timo Sirainen struct mailbox_alias_mailbox *abox;
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen abox = p_new(box->pool, struct mailbox_alias_mailbox, 1);
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen abox->module_ctx.super = *v;
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen box->vlast = &abox->module_ctx.super;
0dc7891233a973829f00371b27810f849b987c66Timo Sirainen
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen v->create = mailbox_alias_create;
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen v->delete = mailbox_alias_delete;
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen v->rename = mailbox_alias_rename;
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen MODULE_CONTEXT_SET(box, mailbox_alias_storage_module, abox);
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen}
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainenstatic struct mail_storage_hooks mailbox_alias_mail_storage_hooks = {
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen .mail_user_created = mailbox_alias_mail_user_created,
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen .mailbox_list_created = mailbox_alias_mailbox_list_created,
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen .mailbox_allocated = mailbox_alias_mailbox_allocated
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen};
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainenvoid mailbox_alias_plugin_init(struct module *module)
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen{
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen mail_storage_hooks_add(module, &mailbox_alias_mail_storage_hooks);
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen}
void mailbox_alias_plugin_deinit(void)
{
mail_storage_hooks_remove(&mailbox_alias_mail_storage_hooks);
}