mailbox-list-fs.c revision e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2
e59faf65ce864fe95dc00f5d52b8323cdbd0608aTimo Sirainen/* Copyright (c) 2006-2012 Dovecot authors, see the included COPYING file */
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen#include "lib.h"
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen#include "hostpid.h"
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen#include "mkdir-parents.h"
2f30b72d49fbff0c4096125c139e4bdfef45669cTimo Sirainen#include "mailbox-log.h"
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen#include "subscription-file.h"
91b203fd2132510a47a4b34252c0ae0efd688a19Timo Sirainen#include "mail-storage.h"
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen#include "mailbox-list-subscriptions.h"
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen#include "mailbox-list-delete.h"
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen#include "mailbox-list-fs.h"
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen#include <stdio.h>
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen#include <unistd.h>
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen#include <sys/stat.h>
c040ee67d0ac0fb7375bb543965bf67dcae6affaTimo Sirainen
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen#define GLOBAL_TEMP_PREFIX ".temp."
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainenextern struct mailbox_list fs_mailbox_list;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainenstatic struct mailbox_list *fs_list_alloc(void)
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen{
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen struct fs_mailbox_list *list;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen pool_t pool;
4c1deab456fe8877bf025d11843167ac1f36327aTimo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen pool = pool_alloconly_create("fs list", 2048);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen list = p_new(pool, struct fs_mailbox_list, 1);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen list->list = fs_mailbox_list;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen list->list.pool = pool;
c040ee67d0ac0fb7375bb543965bf67dcae6affaTimo Sirainen
c040ee67d0ac0fb7375bb543965bf67dcae6affaTimo Sirainen list->temp_prefix = p_strconcat(pool, GLOBAL_TEMP_PREFIX,
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen my_hostname, ".", my_pid, ".", NULL);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen return &list->list;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen}
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainenstatic void fs_list_deinit(struct mailbox_list *_list)
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen{
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen struct fs_mailbox_list *list = (struct fs_mailbox_list *)_list;
648d24583c1574441c4fa0331a90bd4d6e7996c5Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen pool_unref(&list->list.pool);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen}
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainenstatic char fs_list_get_hierarchy_sep(struct mailbox_list *list ATTR_UNUSED)
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen{
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen return '/';
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen}
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainenstatic int
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainenfs_list_get_path(struct mailbox_list *_list, const char *name,
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen enum mailbox_list_path_type type, const char **path_r)
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen{
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen const struct mailbox_list_settings *set = &_list->set;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen const char *root_dir, *error;
dca6d617a23e3f93af3b8df59acb46478179fe55Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen if (name == NULL) {
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen /* return root directories */
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen return mailbox_list_set_get_root_path(set, type, path_r) ? 1 : 0;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen }
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen i_assert(mailbox_list_is_valid_name(_list, name, &error));
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen if (mailbox_list_try_get_absolute_path(_list, &name)) {
dca6d617a23e3f93af3b8df59acb46478179fe55Timo Sirainen *path_r = name;
dca6d617a23e3f93af3b8df59acb46478179fe55Timo Sirainen return 1;
dca6d617a23e3f93af3b8df59acb46478179fe55Timo Sirainen }
dca6d617a23e3f93af3b8df59acb46478179fe55Timo Sirainen
dca6d617a23e3f93af3b8df59acb46478179fe55Timo Sirainen root_dir = set->root_dir;
dca6d617a23e3f93af3b8df59acb46478179fe55Timo Sirainen switch (type) {
dca6d617a23e3f93af3b8df59acb46478179fe55Timo Sirainen case MAILBOX_LIST_PATH_TYPE_DIR:
dca6d617a23e3f93af3b8df59acb46478179fe55Timo Sirainen if (*set->maildir_name != '\0') {
dca6d617a23e3f93af3b8df59acb46478179fe55Timo Sirainen *path_r = t_strdup_printf("%s/%s%s", set->root_dir,
dca6d617a23e3f93af3b8df59acb46478179fe55Timo Sirainen set->mailbox_dir_name, name);
dca6d617a23e3f93af3b8df59acb46478179fe55Timo Sirainen return 1;
dca6d617a23e3f93af3b8df59acb46478179fe55Timo Sirainen }
dca6d617a23e3f93af3b8df59acb46478179fe55Timo Sirainen break;
dca6d617a23e3f93af3b8df59acb46478179fe55Timo Sirainen case MAILBOX_LIST_PATH_TYPE_ALT_DIR:
dca6d617a23e3f93af3b8df59acb46478179fe55Timo Sirainen if (set->alt_dir == NULL)
dca6d617a23e3f93af3b8df59acb46478179fe55Timo Sirainen return 0;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen if (*set->maildir_name != '\0') {
dca6d617a23e3f93af3b8df59acb46478179fe55Timo Sirainen *path_r = t_strdup_printf("%s/%s%s", set->alt_dir,
dca6d617a23e3f93af3b8df59acb46478179fe55Timo Sirainen set->mailbox_dir_name, name);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen return 1;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen }
dca6d617a23e3f93af3b8df59acb46478179fe55Timo Sirainen root_dir = set->alt_dir;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen break;
dca6d617a23e3f93af3b8df59acb46478179fe55Timo Sirainen case MAILBOX_LIST_PATH_TYPE_MAILBOX:
dca6d617a23e3f93af3b8df59acb46478179fe55Timo Sirainen break;
dca6d617a23e3f93af3b8df59acb46478179fe55Timo Sirainen case MAILBOX_LIST_PATH_TYPE_ALT_MAILBOX:
dca6d617a23e3f93af3b8df59acb46478179fe55Timo Sirainen if (set->alt_dir == NULL)
dca6d617a23e3f93af3b8df59acb46478179fe55Timo Sirainen return 0;
dca6d617a23e3f93af3b8df59acb46478179fe55Timo Sirainen root_dir = set->alt_dir;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen break;
dca6d617a23e3f93af3b8df59acb46478179fe55Timo Sirainen case MAILBOX_LIST_PATH_TYPE_CONTROL:
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen if (set->control_dir != NULL) {
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen *path_r = t_strdup_printf("%s/%s%s", set->control_dir,
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen set->mailbox_dir_name, name);
533bfba437e4120aa29dd45bca2aa87e30ee28a2Timo Sirainen return 1;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen }
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen break;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen case MAILBOX_LIST_PATH_TYPE_INDEX:
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen if (set->index_dir != NULL) {
533bfba437e4120aa29dd45bca2aa87e30ee28a2Timo Sirainen if (*set->index_dir == '\0')
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen return 0;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen *path_r = t_strdup_printf("%s/%s%s", set->index_dir,
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen set->mailbox_dir_name, name);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen return 1;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen }
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen break;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen case MAILBOX_LIST_PATH_TYPE_INDEX_PRIVATE:
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen if (set->index_pvt_dir == NULL)
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen return 0;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen *path_r = t_strdup_printf("%s/%s%s", set->index_pvt_dir,
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen set->mailbox_dir_name, name);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen return 1;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen }
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen if (type == MAILBOX_LIST_PATH_TYPE_ALT_DIR ||
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen type == MAILBOX_LIST_PATH_TYPE_ALT_MAILBOX) {
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen /* don't use inbox_path */
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen } else if (strcmp(name, "INBOX") == 0 && set->inbox_path != NULL) {
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen /* If INBOX is a file, index and control directories are
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen located in root directory. */
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen if ((_list->flags & MAILBOX_LIST_FLAG_MAILBOX_FILES) == 0 ||
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen type == MAILBOX_LIST_PATH_TYPE_MAILBOX ||
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen type == MAILBOX_LIST_PATH_TYPE_DIR) {
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen *path_r = set->inbox_path;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen return 1;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen }
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen }
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen if (root_dir == NULL)
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen return 0;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen if (*set->maildir_name == '\0') {
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen *path_r = t_strdup_printf("%s/%s%s", root_dir,
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen set->mailbox_dir_name, name);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen } else {
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen *path_r = t_strdup_printf("%s/%s%s/%s", root_dir,
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen set->mailbox_dir_name, name,
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen set->maildir_name);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen }
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen return 1;
e0ca8f2484847b57e20798a9f9c7040708696a90Timo Sirainen}
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainenstatic const char *
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainenfs_list_get_temp_prefix(struct mailbox_list *_list, bool global)
e0ca8f2484847b57e20798a9f9c7040708696a90Timo Sirainen{
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen struct fs_mailbox_list *list = (struct fs_mailbox_list *)_list;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
533bfba437e4120aa29dd45bca2aa87e30ee28a2Timo Sirainen return global ? GLOBAL_TEMP_PREFIX : list->temp_prefix;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen}
96f2533c48ce5def0004931606a2fdf275578880Timo Sirainen
96f2533c48ce5def0004931606a2fdf275578880Timo Sirainenstatic const char *
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainenfs_list_join_refpattern(struct mailbox_list *_list ATTR_UNUSED,
3c493c276f599d9b9cd10764876d648003046954Timo Sirainen const char *ref, const char *pattern)
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen{
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen if (*pattern == '/' || *pattern == '~') {
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen /* pattern overrides reference */
5494a6bc149da8f02fd25c0434a9d612ac33f659Timo Sirainen } else if (*ref != '\0') {
5494a6bc149da8f02fd25c0434a9d612ac33f659Timo Sirainen /* merge reference and pattern */
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen pattern = t_strconcat(ref, pattern, NULL);
3c493c276f599d9b9cd10764876d648003046954Timo Sirainen }
72ba6a8227bfdf02282d7e4f4c49194af5c354ddTimo Sirainen return pattern;
72ba6a8227bfdf02282d7e4f4c49194af5c354ddTimo Sirainen}
3c493c276f599d9b9cd10764876d648003046954Timo Sirainen
3c493c276f599d9b9cd10764876d648003046954Timo Sirainenstatic int fs_list_set_subscribed(struct mailbox_list *_list,
3c493c276f599d9b9cd10764876d648003046954Timo Sirainen const char *name, bool set)
72ba6a8227bfdf02282d7e4f4c49194af5c354ddTimo Sirainen{
3c493c276f599d9b9cd10764876d648003046954Timo Sirainen struct fs_mailbox_list *list = (struct fs_mailbox_list *)_list;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen const char *path;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
3c493c276f599d9b9cd10764876d648003046954Timo Sirainen path = t_strconcat(_list->set.control_dir != NULL ?
3c493c276f599d9b9cd10764876d648003046954Timo Sirainen _list->set.control_dir : _list->set.root_dir,
3c493c276f599d9b9cd10764876d648003046954Timo Sirainen "/", _list->set.subscription_fname, NULL);
3c493c276f599d9b9cd10764876d648003046954Timo Sirainen return subsfile_set_subscribed(_list, path, list->temp_prefix,
3c493c276f599d9b9cd10764876d648003046954Timo Sirainen name, set);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen}
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
5494a6bc149da8f02fd25c0434a9d612ac33f659Timo Sirainen
5494a6bc149da8f02fd25c0434a9d612ac33f659Timo Sirainenstatic const char *mailbox_list_fs_get_trash_dir(struct mailbox_list *list)
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen{
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen const char *root_dir;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen root_dir = mailbox_list_get_root_forced(list, MAILBOX_LIST_PATH_TYPE_DIR);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen return t_strdup_printf("%s/"MAILBOX_LIST_FS_TRASH_DIR_NAME, root_dir);
5494a6bc149da8f02fd25c0434a9d612ac33f659Timo Sirainen}
5494a6bc149da8f02fd25c0434a9d612ac33f659Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainenstatic int
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainenfs_list_delete_maildir(struct mailbox_list *list, const char *name)
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen{
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen const char *path, *trash_dir;
3c493c276f599d9b9cd10764876d648003046954Timo Sirainen bool rmdir_path;
3c493c276f599d9b9cd10764876d648003046954Timo Sirainen int ret;
3c493c276f599d9b9cd10764876d648003046954Timo Sirainen
3c493c276f599d9b9cd10764876d648003046954Timo Sirainen if (*list->set.maildir_name != '\0' &&
3c493c276f599d9b9cd10764876d648003046954Timo Sirainen *list->set.mailbox_dir_name != '\0') {
3c493c276f599d9b9cd10764876d648003046954Timo Sirainen trash_dir = mailbox_list_fs_get_trash_dir(list);
3c493c276f599d9b9cd10764876d648003046954Timo Sirainen ret = mailbox_list_delete_maildir_via_trash(list, name,
3c493c276f599d9b9cd10764876d648003046954Timo Sirainen trash_dir);
3c493c276f599d9b9cd10764876d648003046954Timo Sirainen if (ret < 0)
3c493c276f599d9b9cd10764876d648003046954Timo Sirainen return -1;
3c493c276f599d9b9cd10764876d648003046954Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen if (ret > 0) {
5494a6bc149da8f02fd25c0434a9d612ac33f659Timo Sirainen /* try to delete the parent directory */
3c493c276f599d9b9cd10764876d648003046954Timo Sirainen if (mailbox_list_get_path(list, name,
5494a6bc149da8f02fd25c0434a9d612ac33f659Timo Sirainen MAILBOX_LIST_PATH_TYPE_DIR,
5494a6bc149da8f02fd25c0434a9d612ac33f659Timo Sirainen &path) <= 0)
3c493c276f599d9b9cd10764876d648003046954Timo Sirainen i_unreached();
5494a6bc149da8f02fd25c0434a9d612ac33f659Timo Sirainen if (rmdir(path) < 0 && errno != ENOENT &&
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen errno != ENOTEMPTY && errno != EEXIST) {
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen mailbox_list_set_critical(list,
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen "rmdir(%s) failed: %m", path);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen }
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen return 0;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen }
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen }
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen rmdir_path = *list->set.maildir_name != '\0';
a574952c01611899b8ecf81434dbbb3345f27518Timo Sirainen if (mailbox_list_get_path(list, name, MAILBOX_LIST_PATH_TYPE_MAILBOX,
dca6d617a23e3f93af3b8df59acb46478179fe55Timo Sirainen &path) <= 0)
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen i_unreached();
a3fbf5236d3daec08f191e569cdc4758809cb05fTimo Sirainen return mailbox_list_delete_mailbox_nonrecursive(list, name, path,
eb64c3586d854cddd693f0b811d897399076a441Timo Sirainen rmdir_path);
a3fbf5236d3daec08f191e569cdc4758809cb05fTimo Sirainen}
a3fbf5236d3daec08f191e569cdc4758809cb05fTimo Sirainen
a3fbf5236d3daec08f191e569cdc4758809cb05fTimo Sirainenstatic int fs_list_delete_mailbox(struct mailbox_list *list, const char *name)
a3fbf5236d3daec08f191e569cdc4758809cb05fTimo Sirainen{
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen const char *path;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen int ret;
a3fbf5236d3daec08f191e569cdc4758809cb05fTimo Sirainen
dca6d617a23e3f93af3b8df59acb46478179fe55Timo Sirainen if ((list->flags & MAILBOX_LIST_FLAG_MAILBOX_FILES) != 0) {
dca6d617a23e3f93af3b8df59acb46478179fe55Timo Sirainen ret = mailbox_list_get_path(list, name,
dca6d617a23e3f93af3b8df59acb46478179fe55Timo Sirainen MAILBOX_LIST_PATH_TYPE_MAILBOX,
dca6d617a23e3f93af3b8df59acb46478179fe55Timo Sirainen &path);
dca6d617a23e3f93af3b8df59acb46478179fe55Timo Sirainen if (ret < 0)
dca6d617a23e3f93af3b8df59acb46478179fe55Timo Sirainen return -1;
dca6d617a23e3f93af3b8df59acb46478179fe55Timo Sirainen i_assert(ret > 0);
dca6d617a23e3f93af3b8df59acb46478179fe55Timo Sirainen ret = mailbox_list_delete_mailbox_file(list, name, path);
dca6d617a23e3f93af3b8df59acb46478179fe55Timo Sirainen } else {
dca6d617a23e3f93af3b8df59acb46478179fe55Timo Sirainen ret = fs_list_delete_maildir(list, name);
dca6d617a23e3f93af3b8df59acb46478179fe55Timo Sirainen }
dca6d617a23e3f93af3b8df59acb46478179fe55Timo Sirainen
dca6d617a23e3f93af3b8df59acb46478179fe55Timo Sirainen if (ret == 0 || (list->props & MAILBOX_LIST_PROP_AUTOCREATE_DIRS) != 0)
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen mailbox_list_delete_finish(list, name);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen return ret;
a574952c01611899b8ecf81434dbbb3345f27518Timo Sirainen}
a574952c01611899b8ecf81434dbbb3345f27518Timo Sirainen
a574952c01611899b8ecf81434dbbb3345f27518Timo Sirainenstatic int fs_list_rmdir(struct mailbox_list *list, const char *name,
a574952c01611899b8ecf81434dbbb3345f27518Timo Sirainen const char *path)
a574952c01611899b8ecf81434dbbb3345f27518Timo Sirainen{
a574952c01611899b8ecf81434dbbb3345f27518Timo Sirainen guid_128_t dir_sha128;
a574952c01611899b8ecf81434dbbb3345f27518Timo Sirainen
a574952c01611899b8ecf81434dbbb3345f27518Timo Sirainen if (rmdir(path) < 0)
a574952c01611899b8ecf81434dbbb3345f27518Timo Sirainen return -1;
a574952c01611899b8ecf81434dbbb3345f27518Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen mailbox_name_get_sha128(name, dir_sha128);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen mailbox_list_add_change(list, MAILBOX_LOG_RECORD_DELETE_DIR,
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen dir_sha128);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen return 0;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen}
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainenstatic int fs_list_delete_dir(struct mailbox_list *list, const char *name)
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen{
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen const char *path, *child_name, *child_path, *p;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen char sep;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen if (mailbox_list_get_path(list, name, MAILBOX_LIST_PATH_TYPE_DIR,
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen &path) <= 0)
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen i_unreached();
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen if (fs_list_rmdir(list, name, path) == 0)
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen return 0;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen if (errno == ENOENT || errno == ENOTDIR) {
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen mailbox_list_set_error(list, MAIL_ERROR_NOTFOUND,
c040ee67d0ac0fb7375bb543965bf67dcae6affaTimo Sirainen T_MAIL_ERR_MAILBOX_NOT_FOUND(name));
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen } else if (errno == ENOTEMPTY || errno == EEXIST) {
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen /* mbox workaround: if only .imap/ directory is preventing the
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen deletion, remove it */
c040ee67d0ac0fb7375bb543965bf67dcae6affaTimo Sirainen sep = mailbox_list_get_hierarchy_sep(list);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen child_name = t_strdup_printf("%s%cchild", name, sep);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen if (mailbox_list_get_path(list, child_name,
5fb3bff645380804c9db2510940c41db6b8fdb01Timo Sirainen MAILBOX_LIST_PATH_TYPE_INDEX,
43d32cbe60fdaef2699d99f1ca259053e9350411Timo Sirainen &child_path) > 0 &&
533bfba437e4120aa29dd45bca2aa87e30ee28a2Timo Sirainen strncmp(path, child_path, strlen(path)) == 0) {
5fb3bff645380804c9db2510940c41db6b8fdb01Timo Sirainen /* drop the "/child" part out. */
533bfba437e4120aa29dd45bca2aa87e30ee28a2Timo Sirainen p = strrchr(child_path, '/');
533bfba437e4120aa29dd45bca2aa87e30ee28a2Timo Sirainen if (rmdir(t_strdup_until(child_path, p)) == 0) {
5fb3bff645380804c9db2510940c41db6b8fdb01Timo Sirainen /* try again */
533bfba437e4120aa29dd45bca2aa87e30ee28a2Timo Sirainen if (fs_list_rmdir(list, name, path) == 0)
533bfba437e4120aa29dd45bca2aa87e30ee28a2Timo Sirainen return 0;
5fb3bff645380804c9db2510940c41db6b8fdb01Timo Sirainen }
533bfba437e4120aa29dd45bca2aa87e30ee28a2Timo Sirainen }
5fb3bff645380804c9db2510940c41db6b8fdb01Timo Sirainen
5fb3bff645380804c9db2510940c41db6b8fdb01Timo Sirainen mailbox_list_set_error(list, MAIL_ERROR_EXISTS,
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen "Mailbox has children, delete them first");
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen } else {
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen mailbox_list_set_critical(list, "rmdir(%s) failed: %m", path);
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen }
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen return -1;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen}
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainenstatic int rename_dir(struct mailbox_list *oldlist, const char *oldname,
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen struct mailbox_list *newlist, const char *newname,
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen enum mailbox_list_path_type type, bool rmdir_parent)
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen{
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen struct stat st;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen const char *oldpath, *newpath, *p, *oldparent, *newparent;
c1a6ff4972754448985f179358f236e9032ac8daTimo Sirainen
c1a6ff4972754448985f179358f236e9032ac8daTimo Sirainen if (mailbox_list_get_path(oldlist, oldname, type, &oldpath) <= 0 ||
c1a6ff4972754448985f179358f236e9032ac8daTimo Sirainen mailbox_list_get_path(newlist, newname, type, &newpath) <= 0)
c1a6ff4972754448985f179358f236e9032ac8daTimo Sirainen return 0;
c1a6ff4972754448985f179358f236e9032ac8daTimo Sirainen
c1a6ff4972754448985f179358f236e9032ac8daTimo Sirainen if (strcmp(oldpath, newpath) == 0)
c1a6ff4972754448985f179358f236e9032ac8daTimo Sirainen return 0;
c1a6ff4972754448985f179358f236e9032ac8daTimo Sirainen
c1a6ff4972754448985f179358f236e9032ac8daTimo Sirainen p = strrchr(oldpath, '/');
c1a6ff4972754448985f179358f236e9032ac8daTimo Sirainen oldparent = p == NULL ? "/" : t_strdup_until(oldpath, p);
3c493c276f599d9b9cd10764876d648003046954Timo Sirainen p = strrchr(newpath, '/');
3c493c276f599d9b9cd10764876d648003046954Timo Sirainen newparent = p == NULL ? "/" : t_strdup_until(newpath, p);
3c493c276f599d9b9cd10764876d648003046954Timo Sirainen
3c493c276f599d9b9cd10764876d648003046954Timo Sirainen if (strcmp(oldparent, newparent) != 0 && stat(oldpath, &st) == 0) {
57bf90f66f393c2807b2fc543655013f61d1d9e4Timo Sirainen /* make sure the newparent exists */
3c493c276f599d9b9cd10764876d648003046954Timo Sirainen struct mailbox_permissions perm;
3c493c276f599d9b9cd10764876d648003046954Timo Sirainen
3c493c276f599d9b9cd10764876d648003046954Timo Sirainen mailbox_list_get_root_permissions(newlist, &perm);
c1a6ff4972754448985f179358f236e9032ac8daTimo Sirainen if (mkdir_parents_chgrp(newparent, perm.dir_create_mode,
3c493c276f599d9b9cd10764876d648003046954Timo Sirainen perm.file_create_gid,
3c493c276f599d9b9cd10764876d648003046954Timo Sirainen perm.file_create_gid_origin) < 0 &&
3c493c276f599d9b9cd10764876d648003046954Timo Sirainen errno != EEXIST) {
3c493c276f599d9b9cd10764876d648003046954Timo Sirainen if (mailbox_list_set_error_from_errno(oldlist))
3c493c276f599d9b9cd10764876d648003046954Timo Sirainen return -1;
3c493c276f599d9b9cd10764876d648003046954Timo Sirainen
3c493c276f599d9b9cd10764876d648003046954Timo Sirainen mailbox_list_set_critical(oldlist,
3c493c276f599d9b9cd10764876d648003046954Timo Sirainen "mkdir_parents(%s) failed: %m", newparent);
3c493c276f599d9b9cd10764876d648003046954Timo Sirainen return -1;
3c493c276f599d9b9cd10764876d648003046954Timo Sirainen }
3c493c276f599d9b9cd10764876d648003046954Timo Sirainen }
3c493c276f599d9b9cd10764876d648003046954Timo Sirainen
3c493c276f599d9b9cd10764876d648003046954Timo Sirainen if (rename(oldpath, newpath) < 0 && errno != ENOENT) {
3c493c276f599d9b9cd10764876d648003046954Timo Sirainen mailbox_list_set_critical(oldlist, "rename(%s, %s) failed: %m",
3c493c276f599d9b9cd10764876d648003046954Timo Sirainen oldpath, newpath);
3c493c276f599d9b9cd10764876d648003046954Timo Sirainen return -1;
3c493c276f599d9b9cd10764876d648003046954Timo Sirainen }
3c493c276f599d9b9cd10764876d648003046954Timo Sirainen if (rmdir_parent && (p = strrchr(oldpath, '/')) != NULL) {
3c493c276f599d9b9cd10764876d648003046954Timo Sirainen oldpath = t_strdup_until(oldpath, p);
3c493c276f599d9b9cd10764876d648003046954Timo Sirainen if (rmdir(oldpath) < 0 && errno != ENOENT &&
3c493c276f599d9b9cd10764876d648003046954Timo Sirainen errno != ENOTEMPTY && errno != EEXIST) {
c1a6ff4972754448985f179358f236e9032ac8daTimo Sirainen mailbox_list_set_critical(oldlist,
c1a6ff4972754448985f179358f236e9032ac8daTimo Sirainen "rmdir(%s) failed: %m", oldpath);
c1a6ff4972754448985f179358f236e9032ac8daTimo Sirainen }
c1a6ff4972754448985f179358f236e9032ac8daTimo Sirainen }
3c493c276f599d9b9cd10764876d648003046954Timo Sirainen
3c493c276f599d9b9cd10764876d648003046954Timo Sirainen /* avoid leaving empty directories lying around */
3c493c276f599d9b9cd10764876d648003046954Timo Sirainen mailbox_list_delete_until_root(oldlist, oldpath, type);
3c493c276f599d9b9cd10764876d648003046954Timo Sirainen return 0;
3c493c276f599d9b9cd10764876d648003046954Timo Sirainen}
3c493c276f599d9b9cd10764876d648003046954Timo Sirainen
3c493c276f599d9b9cd10764876d648003046954Timo Sirainenstatic int fs_list_rename_mailbox(struct mailbox_list *oldlist,
3c493c276f599d9b9cd10764876d648003046954Timo Sirainen const char *oldname,
3c493c276f599d9b9cd10764876d648003046954Timo Sirainen struct mailbox_list *newlist,
3c493c276f599d9b9cd10764876d648003046954Timo Sirainen const char *newname)
3c493c276f599d9b9cd10764876d648003046954Timo Sirainen{
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen struct mail_storage *oldstorage;
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen const char *oldvname, *oldpath, *newpath, *alt_newpath, *root_path, *p;
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen struct stat st;
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen struct mailbox_permissions old_perm, new_perm;
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen bool rmdir_parent = FALSE;
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen oldvname = mailbox_list_get_vname(oldlist, oldname);
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen if (mailbox_list_get_storage(&oldlist, oldvname, &oldstorage) < 0)
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen return -1;
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen if (mailbox_list_get_path(oldlist, oldname,
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen MAILBOX_LIST_PATH_TYPE_DIR, &oldpath) <= 0 ||
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen mailbox_list_get_path(newlist, newname,
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen MAILBOX_LIST_PATH_TYPE_DIR, &newpath) <= 0)
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen i_unreached();
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen if (mailbox_list_get_path(newlist, newname, MAILBOX_LIST_PATH_TYPE_ALT_DIR,
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen &alt_newpath) < 0)
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen i_unreached();
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen root_path = mailbox_list_get_root_forced(oldlist, MAILBOX_LIST_PATH_TYPE_MAILBOX);
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen if (strcmp(oldpath, root_path) == 0) {
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen /* most likely INBOX */
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen mailbox_list_set_error(oldlist, MAIL_ERROR_NOTPOSSIBLE,
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen t_strdup_printf("Renaming %s isn't supported.",
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen oldname));
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen return -1;
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen }
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen mailbox_list_get_permissions(oldlist, oldname, &old_perm);
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen mailbox_list_get_permissions(newlist, newname, &new_perm);
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen
10a2e8716e9040908fb60fcda56b5315ea4c1312Timo Sirainen /* if we're renaming under another mailbox, require its permissions
10a2e8716e9040908fb60fcda56b5315ea4c1312Timo Sirainen to be same as ours. */
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen if (strchr(newname, mailbox_list_get_hierarchy_sep(newlist)) != NULL &&
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen (new_perm.file_create_mode != old_perm.file_create_mode ||
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen new_perm.dir_create_mode != old_perm.dir_create_mode ||
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen new_perm.file_create_gid != old_perm.file_create_gid)) {
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen mailbox_list_set_error(oldlist, MAIL_ERROR_NOTPOSSIBLE,
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen "Renaming not supported across conflicting "
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen "directory permissions");
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen return -1;
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen }
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen /* create the hierarchy */
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen p = strrchr(newpath, '/');
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen if (p != NULL) {
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen p = t_strdup_until(newpath, p);
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen if (mkdir_parents_chgrp(p, new_perm.dir_create_mode,
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen new_perm.file_create_gid,
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen new_perm.file_create_gid_origin) < 0 &&
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen errno != EEXIST) {
095c07765b69592c1dd644361f05ee37b1d39bd4Timo Sirainen if (mailbox_list_set_error_from_errno(oldlist))
095c07765b69592c1dd644361f05ee37b1d39bd4Timo Sirainen return -1;
2f30b72d49fbff0c4096125c139e4bdfef45669cTimo Sirainen
2f30b72d49fbff0c4096125c139e4bdfef45669cTimo Sirainen mailbox_list_set_critical(oldlist,
2f30b72d49fbff0c4096125c139e4bdfef45669cTimo Sirainen "mkdir_parents(%s) failed: %m", p);
095c07765b69592c1dd644361f05ee37b1d39bd4Timo Sirainen return -1;
095c07765b69592c1dd644361f05ee37b1d39bd4Timo Sirainen }
095c07765b69592c1dd644361f05ee37b1d39bd4Timo Sirainen }
095c07765b69592c1dd644361f05ee37b1d39bd4Timo Sirainen
095c07765b69592c1dd644361f05ee37b1d39bd4Timo Sirainen /* first check that the destination mailbox doesn't exist.
095c07765b69592c1dd644361f05ee37b1d39bd4Timo Sirainen this is racy, but we need to be atomic and there's hardly any
095c07765b69592c1dd644361f05ee37b1d39bd4Timo Sirainen possibility that someone actually tries to rename two mailboxes
095c07765b69592c1dd644361f05ee37b1d39bd4Timo Sirainen to same new one */
095c07765b69592c1dd644361f05ee37b1d39bd4Timo Sirainen if (lstat(newpath, &st) == 0) {
095c07765b69592c1dd644361f05ee37b1d39bd4Timo Sirainen mailbox_list_set_error(oldlist, MAIL_ERROR_EXISTS,
095c07765b69592c1dd644361f05ee37b1d39bd4Timo Sirainen "Target mailbox already exists");
095c07765b69592c1dd644361f05ee37b1d39bd4Timo Sirainen return -1;
095c07765b69592c1dd644361f05ee37b1d39bd4Timo Sirainen } else if (errno == ENOTDIR) {
2f30b72d49fbff0c4096125c139e4bdfef45669cTimo Sirainen mailbox_list_set_error(oldlist, MAIL_ERROR_NOTPOSSIBLE,
095c07765b69592c1dd644361f05ee37b1d39bd4Timo Sirainen "Target mailbox doesn't allow inferior mailboxes");
2f30b72d49fbff0c4096125c139e4bdfef45669cTimo Sirainen return -1;
2f30b72d49fbff0c4096125c139e4bdfef45669cTimo Sirainen } else if (errno != ENOENT && errno != EACCES) {
2f30b72d49fbff0c4096125c139e4bdfef45669cTimo Sirainen mailbox_list_set_critical(oldlist, "lstat(%s) failed: %m",
2f30b72d49fbff0c4096125c139e4bdfef45669cTimo Sirainen newpath);
2f30b72d49fbff0c4096125c139e4bdfef45669cTimo Sirainen return -1;
10a2e8716e9040908fb60fcda56b5315ea4c1312Timo Sirainen }
095c07765b69592c1dd644361f05ee37b1d39bd4Timo Sirainen
095c07765b69592c1dd644361f05ee37b1d39bd4Timo Sirainen if (alt_newpath != NULL) {
095c07765b69592c1dd644361f05ee37b1d39bd4Timo Sirainen if (stat(alt_newpath, &st) == 0) {
095c07765b69592c1dd644361f05ee37b1d39bd4Timo Sirainen /* race condition or a directory left there lying around?
095c07765b69592c1dd644361f05ee37b1d39bd4Timo Sirainen safest to just report error. */
095c07765b69592c1dd644361f05ee37b1d39bd4Timo Sirainen mailbox_list_set_error(oldlist, MAIL_ERROR_EXISTS,
095c07765b69592c1dd644361f05ee37b1d39bd4Timo Sirainen "Target mailbox already exists");
095c07765b69592c1dd644361f05ee37b1d39bd4Timo Sirainen return -1;
095c07765b69592c1dd644361f05ee37b1d39bd4Timo Sirainen } else if (errno != ENOENT) {
095c07765b69592c1dd644361f05ee37b1d39bd4Timo Sirainen mailbox_list_set_critical(oldlist, "stat(%s) failed: %m",
095c07765b69592c1dd644361f05ee37b1d39bd4Timo Sirainen alt_newpath);
095c07765b69592c1dd644361f05ee37b1d39bd4Timo Sirainen return -1;
095c07765b69592c1dd644361f05ee37b1d39bd4Timo Sirainen }
095c07765b69592c1dd644361f05ee37b1d39bd4Timo Sirainen }
095c07765b69592c1dd644361f05ee37b1d39bd4Timo Sirainen
095c07765b69592c1dd644361f05ee37b1d39bd4Timo Sirainen if (rename(oldpath, newpath) < 0) {
2f30b72d49fbff0c4096125c139e4bdfef45669cTimo Sirainen if (ENOTFOUND(errno)) {
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen mailbox_list_set_error(oldlist, MAIL_ERROR_NOTFOUND,
2f30b72d49fbff0c4096125c139e4bdfef45669cTimo Sirainen T_MAIL_ERR_MAILBOX_NOT_FOUND(oldname));
2f30b72d49fbff0c4096125c139e4bdfef45669cTimo Sirainen } else if (!mailbox_list_set_error_from_errno(oldlist)) {
2f30b72d49fbff0c4096125c139e4bdfef45669cTimo Sirainen mailbox_list_set_critical(oldlist,
2f30b72d49fbff0c4096125c139e4bdfef45669cTimo Sirainen "rename(%s, %s) failed: %m", oldpath, newpath);
2f30b72d49fbff0c4096125c139e4bdfef45669cTimo Sirainen }
2f30b72d49fbff0c4096125c139e4bdfef45669cTimo Sirainen return -1;
91b203fd2132510a47a4b34252c0ae0efd688a19Timo Sirainen }
91b203fd2132510a47a4b34252c0ae0efd688a19Timo Sirainen
91b203fd2132510a47a4b34252c0ae0efd688a19Timo Sirainen if (alt_newpath != NULL) {
f35141938f1ce4fd822a589045c7a01e866922a2Timo Sirainen (void)rename_dir(oldlist, oldname, newlist, newname,
91b203fd2132510a47a4b34252c0ae0efd688a19Timo Sirainen MAILBOX_LIST_PATH_TYPE_ALT_DIR, rmdir_parent);
f35141938f1ce4fd822a589045c7a01e866922a2Timo Sirainen }
91b203fd2132510a47a4b34252c0ae0efd688a19Timo Sirainen (void)rename_dir(oldlist, oldname, newlist, newname,
91b203fd2132510a47a4b34252c0ae0efd688a19Timo Sirainen MAILBOX_LIST_PATH_TYPE_CONTROL, rmdir_parent);
f35141938f1ce4fd822a589045c7a01e866922a2Timo Sirainen (void)rename_dir(oldlist, oldname, newlist, newname,
f35141938f1ce4fd822a589045c7a01e866922a2Timo Sirainen MAILBOX_LIST_PATH_TYPE_INDEX, rmdir_parent);
f35141938f1ce4fd822a589045c7a01e866922a2Timo Sirainen return 0;
f35141938f1ce4fd822a589045c7a01e866922a2Timo Sirainen}
f35141938f1ce4fd822a589045c7a01e866922a2Timo Sirainen
91b203fd2132510a47a4b34252c0ae0efd688a19Timo Sirainenstruct mailbox_list fs_mailbox_list = {
f35141938f1ce4fd822a589045c7a01e866922a2Timo Sirainen .name = MAILBOX_LIST_NAME_FS,
f35141938f1ce4fd822a589045c7a01e866922a2Timo Sirainen .props = 0,
f35141938f1ce4fd822a589045c7a01e866922a2Timo Sirainen .mailbox_name_max_length = MAILBOX_LIST_NAME_MAX_LENGTH,
91b203fd2132510a47a4b34252c0ae0efd688a19Timo Sirainen
91b203fd2132510a47a4b34252c0ae0efd688a19Timo Sirainen {
10a2e8716e9040908fb60fcda56b5315ea4c1312Timo Sirainen fs_list_alloc,
10a2e8716e9040908fb60fcda56b5315ea4c1312Timo Sirainen fs_list_deinit,
91b203fd2132510a47a4b34252c0ae0efd688a19Timo Sirainen NULL,
91b203fd2132510a47a4b34252c0ae0efd688a19Timo Sirainen fs_list_get_hierarchy_sep,
91b203fd2132510a47a4b34252c0ae0efd688a19Timo Sirainen mailbox_list_default_get_vname,
91b203fd2132510a47a4b34252c0ae0efd688a19Timo Sirainen mailbox_list_default_get_storage_name,
ae1a57954535642c09c3b8aee184736ddbb06cdfTimo Sirainen fs_list_get_path,
ae1a57954535642c09c3b8aee184736ddbb06cdfTimo Sirainen fs_list_get_temp_prefix,
ae1a57954535642c09c3b8aee184736ddbb06cdfTimo Sirainen fs_list_join_refpattern,
f35141938f1ce4fd822a589045c7a01e866922a2Timo Sirainen fs_list_iter_init,
f35141938f1ce4fd822a589045c7a01e866922a2Timo Sirainen fs_list_iter_next,
f35141938f1ce4fd822a589045c7a01e866922a2Timo Sirainen fs_list_iter_deinit,
91b203fd2132510a47a4b34252c0ae0efd688a19Timo Sirainen fs_list_get_mailbox_flags,
91b203fd2132510a47a4b34252c0ae0efd688a19Timo Sirainen NULL,
91b203fd2132510a47a4b34252c0ae0efd688a19Timo Sirainen mailbox_list_subscriptions_refresh,
91b203fd2132510a47a4b34252c0ae0efd688a19Timo Sirainen fs_list_set_subscribed,
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen fs_list_delete_mailbox,
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen fs_list_delete_dir,
8bb360f9e5de1c25e4f875205bb06e8bf15dae14Timo Sirainen mailbox_list_delete_symlink_default,
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen fs_list_rename_mailbox,
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen NULL, NULL, NULL, NULL
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen }
fea7b8b3fc182e415b1875d79587c0aa1adb09d7Timo Sirainen};
fea7b8b3fc182e415b1875d79587c0aa1adb09d7Timo Sirainen