bcb4e51a409d94ae670de96afb8483a4f7855294Stephan Bosch/* Copyright (c) 2006-2018 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"
b13f738e8eb3f24dc2abf2c804f954b4d864ac6fTimo Sirainen#include "mailbox-list-subscriptions.h"
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen#include "mailbox-list-delete.h"
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen#include "mailbox-list-fs.h"
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen#include <stdio.h>
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen#include <unistd.h>
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen#include <sys/stat.h>
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
c040ee67d0ac0fb7375bb543965bf67dcae6affaTimo Sirainen#define GLOBAL_TEMP_PREFIX ".temp."
b039dabf4c53f72454e795930e7643b6e0e625f9Timo 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;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
4c1deab456fe8877bf025d11843167ac1f36327aTimo 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;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
c040ee67d0ac0fb7375bb543965bf67dcae6affaTimo Sirainen list->temp_prefix = p_strconcat(pool, GLOBAL_TEMP_PREFIX,
c040ee67d0ac0fb7375bb543965bf67dcae6affaTimo 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)
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen{
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen struct fs_mailbox_list *list = (struct fs_mailbox_list *)_list;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
648d24583c1574441c4fa0331a90bd4d6e7996c5Timo Sirainen pool_unref(&list->list.pool);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen}
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainenstatic char fs_list_get_hierarchy_sep(struct mailbox_list *list ATTR_UNUSED)
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen{
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen return '/';
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen}
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen
12b4dbf933ee54f7b96968ba150095baa985fdafTimo Sirainenstatic const char *
12b4dbf933ee54f7b96968ba150095baa985fdafTimo Sirainenfs_list_get_path_to(const struct mailbox_list_settings *set,
12b4dbf933ee54f7b96968ba150095baa985fdafTimo Sirainen const char *root_dir, const char *name)
12b4dbf933ee54f7b96968ba150095baa985fdafTimo Sirainen{
12b4dbf933ee54f7b96968ba150095baa985fdafTimo Sirainen if (*set->maildir_name != '\0' && set->index_control_use_maildir_name) {
12b4dbf933ee54f7b96968ba150095baa985fdafTimo Sirainen return t_strdup_printf("%s/%s%s/%s", root_dir,
12b4dbf933ee54f7b96968ba150095baa985fdafTimo Sirainen set->mailbox_dir_name, name,
12b4dbf933ee54f7b96968ba150095baa985fdafTimo Sirainen set->maildir_name);
12b4dbf933ee54f7b96968ba150095baa985fdafTimo Sirainen } else {
12b4dbf933ee54f7b96968ba150095baa985fdafTimo Sirainen return t_strdup_printf("%s/%s%s", root_dir,
12b4dbf933ee54f7b96968ba150095baa985fdafTimo Sirainen set->mailbox_dir_name, name);
12b4dbf933ee54f7b96968ba150095baa985fdafTimo Sirainen }
12b4dbf933ee54f7b96968ba150095baa985fdafTimo Sirainen}
12b4dbf933ee54f7b96968ba150095baa985fdafTimo Sirainen
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainenstatic int
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainenfs_list_get_path(struct mailbox_list *_list, const char *name,
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen enum mailbox_list_path_type type, const char **path_r)
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen{
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen const struct mailbox_list_settings *set = &_list->set;
e9df0f285429d2b896ecdb4cd873d25e5e895620Timo Sirainen const char *root_dir, *error;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen if (name == NULL) {
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen /* return root directories */
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen return mailbox_list_set_get_root_path(set, type, path_r) ? 1 : 0;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen }
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
e9df0f285429d2b896ecdb4cd873d25e5e895620Timo Sirainen i_assert(mailbox_list_is_valid_name(_list, name, &error));
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen if (mailbox_list_try_get_absolute_path(_list, &name)) {
ad396be1d926e49cd31b0732824362647ecd5fc2Timo Sirainen if (type == MAILBOX_LIST_PATH_TYPE_INDEX &&
ad396be1d926e49cd31b0732824362647ecd5fc2Timo Sirainen *set->index_dir == '\0')
ad396be1d926e49cd31b0732824362647ecd5fc2Timo Sirainen return 0;
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen *path_r = name;
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen return 1;
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen }
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
3c493c276f599d9b9cd10764876d648003046954Timo Sirainen root_dir = set->root_dir;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen switch (type) {
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen case MAILBOX_LIST_PATH_TYPE_DIR:
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen if (*set->maildir_name != '\0') {
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen *path_r = t_strdup_printf("%s/%s%s", set->root_dir,
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen set->mailbox_dir_name, name);
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen return 1;
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen }
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen break;
3c493c276f599d9b9cd10764876d648003046954Timo Sirainen case MAILBOX_LIST_PATH_TYPE_ALT_DIR:
72ba6a8227bfdf02282d7e4f4c49194af5c354ddTimo Sirainen if (set->alt_dir == NULL)
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen return 0;
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen if (*set->maildir_name != '\0') {
12b4dbf933ee54f7b96968ba150095baa985fdafTimo Sirainen /* maildir_name is for the mailbox, caller is asking
12b4dbf933ee54f7b96968ba150095baa985fdafTimo Sirainen for the directory name */
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen *path_r = t_strdup_printf("%s/%s%s", set->alt_dir,
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen set->mailbox_dir_name, name);
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen return 1;
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen }
72ba6a8227bfdf02282d7e4f4c49194af5c354ddTimo Sirainen root_dir = set->alt_dir;
3c493c276f599d9b9cd10764876d648003046954Timo Sirainen break;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen case MAILBOX_LIST_PATH_TYPE_MAILBOX:
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen break;
3c493c276f599d9b9cd10764876d648003046954Timo Sirainen case MAILBOX_LIST_PATH_TYPE_ALT_MAILBOX:
3c493c276f599d9b9cd10764876d648003046954Timo Sirainen if (set->alt_dir == NULL)
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen return 0;
3c493c276f599d9b9cd10764876d648003046954Timo Sirainen root_dir = set->alt_dir;
3c493c276f599d9b9cd10764876d648003046954Timo Sirainen break;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen case MAILBOX_LIST_PATH_TYPE_CONTROL:
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen if (set->control_dir != NULL) {
12b4dbf933ee54f7b96968ba150095baa985fdafTimo Sirainen *path_r = fs_list_get_path_to(set, set->control_dir, name);
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen return 1;
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen }
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen break;
638600575ee95f2513c683ef09cb188f76eacd22Timo Sirainen case MAILBOX_LIST_PATH_TYPE_INDEX_CACHE:
638600575ee95f2513c683ef09cb188f76eacd22Timo Sirainen if (set->index_cache_dir != NULL) {
638600575ee95f2513c683ef09cb188f76eacd22Timo Sirainen *path_r = fs_list_get_path_to(set, set->index_cache_dir, name);
638600575ee95f2513c683ef09cb188f76eacd22Timo Sirainen return 1;
638600575ee95f2513c683ef09cb188f76eacd22Timo Sirainen }
638600575ee95f2513c683ef09cb188f76eacd22Timo Sirainen /* fall through */
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen case MAILBOX_LIST_PATH_TYPE_INDEX:
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen if (set->index_dir != NULL) {
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen if (*set->index_dir == '\0')
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen return 0;
12b4dbf933ee54f7b96968ba150095baa985fdafTimo Sirainen *path_r = fs_list_get_path_to(set, set->index_dir, name);
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen return 1;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen }
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen break;
5da1aa5197a43d83f0fb3eeb83125c7cd73d1b62Timo Sirainen case MAILBOX_LIST_PATH_TYPE_INDEX_PRIVATE:
5da1aa5197a43d83f0fb3eeb83125c7cd73d1b62Timo Sirainen if (set->index_pvt_dir == NULL)
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen return 0;
12b4dbf933ee54f7b96968ba150095baa985fdafTimo Sirainen *path_r = fs_list_get_path_to(set, set->index_pvt_dir, name);
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen return 1;
49c48631cfd07017d5f93d83713fffe4f13730c4Timo Sirainen case MAILBOX_LIST_PATH_TYPE_LIST_INDEX:
49c48631cfd07017d5f93d83713fffe4f13730c4Timo Sirainen i_unreached();
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen }
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
3c493c276f599d9b9cd10764876d648003046954Timo Sirainen if (type == MAILBOX_LIST_PATH_TYPE_ALT_DIR ||
3c493c276f599d9b9cd10764876d648003046954Timo Sirainen type == MAILBOX_LIST_PATH_TYPE_ALT_MAILBOX) {
3c493c276f599d9b9cd10764876d648003046954Timo Sirainen /* don't use inbox_path */
3c493c276f599d9b9cd10764876d648003046954Timo Sirainen } else if (strcmp(name, "INBOX") == 0 && set->inbox_path != NULL) {
3c493c276f599d9b9cd10764876d648003046954Timo Sirainen /* If INBOX is a file, index and control directories are
3c493c276f599d9b9cd10764876d648003046954Timo Sirainen located in root directory. */
3c493c276f599d9b9cd10764876d648003046954Timo Sirainen if ((_list->flags & MAILBOX_LIST_FLAG_MAILBOX_FILES) == 0 ||
3c493c276f599d9b9cd10764876d648003046954Timo Sirainen type == MAILBOX_LIST_PATH_TYPE_MAILBOX ||
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen type == MAILBOX_LIST_PATH_TYPE_DIR) {
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen *path_r = set->inbox_path;
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen return 1;
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen }
3c493c276f599d9b9cd10764876d648003046954Timo Sirainen }
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
7fa561fecd106f0e3f58315db2402f7ba83c4226Timo Sirainen if (root_dir == NULL)
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen return 0;
5494a6bc149da8f02fd25c0434a9d612ac33f659Timo Sirainen if (*set->maildir_name == '\0') {
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen *path_r = t_strdup_printf("%s/%s%s", root_dir,
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen set->mailbox_dir_name, name);
5494a6bc149da8f02fd25c0434a9d612ac33f659Timo Sirainen } else {
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen *path_r = t_strdup_printf("%s/%s%s/%s", root_dir,
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen set->mailbox_dir_name, name,
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen set->maildir_name);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen }
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen return 1;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen}
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainenstatic const char *
c040ee67d0ac0fb7375bb543965bf67dcae6affaTimo Sirainenfs_list_get_temp_prefix(struct mailbox_list *_list, bool global)
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen{
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen struct fs_mailbox_list *list = (struct fs_mailbox_list *)_list;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
c040ee67d0ac0fb7375bb543965bf67dcae6affaTimo Sirainen return global ? GLOBAL_TEMP_PREFIX : list->temp_prefix;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen}
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
5fb3bff645380804c9db2510940c41db6b8fdb01Timo Sirainenstatic const char *
43d32cbe60fdaef2699d99f1ca259053e9350411Timo Sirainenfs_list_join_refpattern(struct mailbox_list *_list ATTR_UNUSED,
533bfba437e4120aa29dd45bca2aa87e30ee28a2Timo Sirainen const char *ref, const char *pattern)
5fb3bff645380804c9db2510940c41db6b8fdb01Timo Sirainen{
533bfba437e4120aa29dd45bca2aa87e30ee28a2Timo Sirainen if (*pattern == '/' || *pattern == '~') {
533bfba437e4120aa29dd45bca2aa87e30ee28a2Timo Sirainen /* pattern overrides reference */
5fb3bff645380804c9db2510940c41db6b8fdb01Timo Sirainen } else if (*ref != '\0') {
533bfba437e4120aa29dd45bca2aa87e30ee28a2Timo Sirainen /* merge reference and pattern */
533bfba437e4120aa29dd45bca2aa87e30ee28a2Timo Sirainen pattern = t_strconcat(ref, pattern, NULL);
5fb3bff645380804c9db2510940c41db6b8fdb01Timo Sirainen }
533bfba437e4120aa29dd45bca2aa87e30ee28a2Timo Sirainen return pattern;
5fb3bff645380804c9db2510940c41db6b8fdb01Timo Sirainen}
5fb3bff645380804c9db2510940c41db6b8fdb01Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainenstatic int fs_list_set_subscribed(struct mailbox_list *_list,
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen const char *name, bool set)
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen{
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen struct fs_mailbox_list *list = (struct fs_mailbox_list *)_list;
177295e3c4000a9ab0ff27ce4e6eba6b96aeac40Timo Sirainen enum mailbox_list_path_type type;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen const char *path;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
3568ea090b5a072e498438e74db23b98103ff2deTimo Sirainen if (_list->set.subscription_fname == NULL) {
3568ea090b5a072e498438e74db23b98103ff2deTimo Sirainen mailbox_list_set_error(_list, MAIL_ERROR_NOTPOSSIBLE,
3568ea090b5a072e498438e74db23b98103ff2deTimo Sirainen "Subscriptions not supported");
3568ea090b5a072e498438e74db23b98103ff2deTimo Sirainen return -1;
3568ea090b5a072e498438e74db23b98103ff2deTimo Sirainen }
3568ea090b5a072e498438e74db23b98103ff2deTimo Sirainen
177295e3c4000a9ab0ff27ce4e6eba6b96aeac40Timo Sirainen type = _list->set.control_dir != NULL ?
177295e3c4000a9ab0ff27ce4e6eba6b96aeac40Timo Sirainen MAILBOX_LIST_PATH_TYPE_CONTROL : MAILBOX_LIST_PATH_TYPE_DIR;
177295e3c4000a9ab0ff27ce4e6eba6b96aeac40Timo Sirainen
177295e3c4000a9ab0ff27ce4e6eba6b96aeac40Timo Sirainen path = t_strconcat(mailbox_list_get_root_forced(_list, type),
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen "/", _list->set.subscription_fname, NULL);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen return subsfile_set_subscribed(_list, path, list->temp_prefix,
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen name, set);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen}
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
3c493c276f599d9b9cd10764876d648003046954Timo Sirainen
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainenstatic const char *mailbox_list_fs_get_trash_dir(struct mailbox_list *list)
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen{
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen const char *root_dir;
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen root_dir = mailbox_list_get_root_forced(list, MAILBOX_LIST_PATH_TYPE_DIR);
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen return t_strdup_printf("%s/"MAILBOX_LIST_FS_TRASH_DIR_NAME, root_dir);
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen}
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen
fd057522c580091ec9803c0dceb4747d8bcaece5Timo Sirainenstatic int
fd057522c580091ec9803c0dceb4747d8bcaece5Timo Sirainenfs_list_delete_maildir(struct mailbox_list *list, const char *name)
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen{
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen const char *path, *trash_dir;
fd057522c580091ec9803c0dceb4747d8bcaece5Timo Sirainen bool rmdir_path;
fd057522c580091ec9803c0dceb4747d8bcaece5Timo Sirainen int ret;
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen if (*list->set.maildir_name != '\0' &&
fd057522c580091ec9803c0dceb4747d8bcaece5Timo Sirainen *list->set.mailbox_dir_name != '\0') {
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen trash_dir = mailbox_list_fs_get_trash_dir(list);
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen ret = mailbox_list_delete_maildir_via_trash(list, name,
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen trash_dir);
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen if (ret < 0)
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen return -1;
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen
fd057522c580091ec9803c0dceb4747d8bcaece5Timo Sirainen if (ret > 0) {
fd057522c580091ec9803c0dceb4747d8bcaece5Timo Sirainen /* try to delete the parent directory */
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen if (mailbox_list_get_path(list, name,
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen MAILBOX_LIST_PATH_TYPE_DIR,
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen &path) <= 0)
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen i_unreached();
fd057522c580091ec9803c0dceb4747d8bcaece5Timo Sirainen if (rmdir(path) < 0 && errno != ENOENT &&
fd057522c580091ec9803c0dceb4747d8bcaece5Timo Sirainen errno != ENOTEMPTY && errno != EEXIST) {
fd057522c580091ec9803c0dceb4747d8bcaece5Timo Sirainen mailbox_list_set_critical(list,
fd057522c580091ec9803c0dceb4747d8bcaece5Timo Sirainen "rmdir(%s) failed: %m", path);
fd057522c580091ec9803c0dceb4747d8bcaece5Timo Sirainen }
fd057522c580091ec9803c0dceb4747d8bcaece5Timo Sirainen return 0;
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen }
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen }
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen
fd057522c580091ec9803c0dceb4747d8bcaece5Timo Sirainen rmdir_path = *list->set.maildir_name != '\0';
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen if (mailbox_list_get_path(list, name, MAILBOX_LIST_PATH_TYPE_MAILBOX,
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen &path) <= 0)
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen i_unreached();
fd057522c580091ec9803c0dceb4747d8bcaece5Timo Sirainen return mailbox_list_delete_mailbox_nonrecursive(list, name, path,
fd057522c580091ec9803c0dceb4747d8bcaece5Timo Sirainen rmdir_path);
fd057522c580091ec9803c0dceb4747d8bcaece5Timo Sirainen}
fd057522c580091ec9803c0dceb4747d8bcaece5Timo Sirainen
fd057522c580091ec9803c0dceb4747d8bcaece5Timo Sirainenstatic int fs_list_delete_mailbox(struct mailbox_list *list, const char *name)
fd057522c580091ec9803c0dceb4747d8bcaece5Timo Sirainen{
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen const char *path;
fd057522c580091ec9803c0dceb4747d8bcaece5Timo Sirainen int ret;
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen
eaa2d473ed2ecdb9856cd98a33f4d3063cfaf2a1Timo Sirainen ret = mailbox_list_get_path(list, name,
eaa2d473ed2ecdb9856cd98a33f4d3063cfaf2a1Timo Sirainen MAILBOX_LIST_PATH_TYPE_MAILBOX, &path);
eaa2d473ed2ecdb9856cd98a33f4d3063cfaf2a1Timo Sirainen if (ret < 0)
eaa2d473ed2ecdb9856cd98a33f4d3063cfaf2a1Timo Sirainen return -1;
eaa2d473ed2ecdb9856cd98a33f4d3063cfaf2a1Timo Sirainen i_assert(ret > 0);
eaa2d473ed2ecdb9856cd98a33f4d3063cfaf2a1Timo Sirainen
fd057522c580091ec9803c0dceb4747d8bcaece5Timo Sirainen if ((list->flags & MAILBOX_LIST_FLAG_MAILBOX_FILES) != 0) {
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen ret = mailbox_list_delete_mailbox_file(list, name, path);
fd057522c580091ec9803c0dceb4747d8bcaece5Timo Sirainen } else {
fd057522c580091ec9803c0dceb4747d8bcaece5Timo Sirainen ret = fs_list_delete_maildir(list, name);
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen }
eaa2d473ed2ecdb9856cd98a33f4d3063cfaf2a1Timo Sirainen if (ret == 0 && list->set.no_noselect)
eaa2d473ed2ecdb9856cd98a33f4d3063cfaf2a1Timo Sirainen mailbox_list_delete_until_root(list, path, MAILBOX_LIST_PATH_TYPE_MAILBOX);
fd057522c580091ec9803c0dceb4747d8bcaece5Timo Sirainen
3fb442057c352645e918314815f8fe2a12b6ee2bTimo Sirainen i_assert(ret <= 0);
3fb442057c352645e918314815f8fe2a12b6ee2bTimo Sirainen return mailbox_list_delete_finish_ret(list, name, ret == 0);
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen}
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen
095c07765b69592c1dd644361f05ee37b1d39bd4Timo Sirainenstatic int fs_list_rmdir(struct mailbox_list *list, const char *name,
095c07765b69592c1dd644361f05ee37b1d39bd4Timo Sirainen const char *path)
2f30b72d49fbff0c4096125c139e4bdfef45669cTimo Sirainen{
de62ce819d59a529530da4b57be1b8d6dad13d6bTimo Sirainen guid_128_t dir_sha128;
2f30b72d49fbff0c4096125c139e4bdfef45669cTimo Sirainen
095c07765b69592c1dd644361f05ee37b1d39bd4Timo Sirainen if (rmdir(path) < 0)
095c07765b69592c1dd644361f05ee37b1d39bd4Timo Sirainen return -1;
095c07765b69592c1dd644361f05ee37b1d39bd4Timo Sirainen
095c07765b69592c1dd644361f05ee37b1d39bd4Timo Sirainen mailbox_name_get_sha128(name, dir_sha128);
095c07765b69592c1dd644361f05ee37b1d39bd4Timo Sirainen mailbox_list_add_change(list, MAILBOX_LOG_RECORD_DELETE_DIR,
095c07765b69592c1dd644361f05ee37b1d39bd4Timo Sirainen dir_sha128);
095c07765b69592c1dd644361f05ee37b1d39bd4Timo Sirainen return 0;
095c07765b69592c1dd644361f05ee37b1d39bd4Timo Sirainen}
095c07765b69592c1dd644361f05ee37b1d39bd4Timo Sirainen
095c07765b69592c1dd644361f05ee37b1d39bd4Timo Sirainenstatic int fs_list_delete_dir(struct mailbox_list *list, const char *name)
095c07765b69592c1dd644361f05ee37b1d39bd4Timo Sirainen{
095c07765b69592c1dd644361f05ee37b1d39bd4Timo Sirainen const char *path, *child_name, *child_path, *p;
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen char sep;
1728ff34ee03de825ad3aeed67d19f8ae140ee2eTimo Sirainen int ret;
095c07765b69592c1dd644361f05ee37b1d39bd4Timo Sirainen
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen if (mailbox_list_get_path(list, name, MAILBOX_LIST_PATH_TYPE_DIR,
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen &path) <= 0)
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen i_unreached();
1728ff34ee03de825ad3aeed67d19f8ae140ee2eTimo Sirainen ret = fs_list_rmdir(list, name, path);
1728ff34ee03de825ad3aeed67d19f8ae140ee2eTimo Sirainen if (!list->set.iter_from_index_dir) {
1728ff34ee03de825ad3aeed67d19f8ae140ee2eTimo Sirainen /* it should exist only in the mail directory */
1728ff34ee03de825ad3aeed67d19f8ae140ee2eTimo Sirainen if (ret == 0)
1728ff34ee03de825ad3aeed67d19f8ae140ee2eTimo Sirainen return 0;
1728ff34ee03de825ad3aeed67d19f8ae140ee2eTimo Sirainen } else if (ret == 0 || errno == ENOENT) {
1728ff34ee03de825ad3aeed67d19f8ae140ee2eTimo Sirainen /* the primary list location is the index directory, but it
1728ff34ee03de825ad3aeed67d19f8ae140ee2eTimo Sirainen exists in both index and mail directories. */
1728ff34ee03de825ad3aeed67d19f8ae140ee2eTimo Sirainen if (mailbox_list_get_path(list, name, MAILBOX_LIST_PATH_TYPE_INDEX,
1728ff34ee03de825ad3aeed67d19f8ae140ee2eTimo Sirainen &path) <= 0)
1728ff34ee03de825ad3aeed67d19f8ae140ee2eTimo Sirainen i_unreached();
1728ff34ee03de825ad3aeed67d19f8ae140ee2eTimo Sirainen if (fs_list_rmdir(list, name, path) == 0)
1728ff34ee03de825ad3aeed67d19f8ae140ee2eTimo Sirainen return 0;
1728ff34ee03de825ad3aeed67d19f8ae140ee2eTimo Sirainen if (ret == 0 && errno == ENOENT) {
1728ff34ee03de825ad3aeed67d19f8ae140ee2eTimo Sirainen /* partial existence: exists in _DIR, but not in
1728ff34ee03de825ad3aeed67d19f8ae140ee2eTimo Sirainen _INDEX. return success anyway. */
1728ff34ee03de825ad3aeed67d19f8ae140ee2eTimo Sirainen return 0;
1728ff34ee03de825ad3aeed67d19f8ae140ee2eTimo Sirainen }
1728ff34ee03de825ad3aeed67d19f8ae140ee2eTimo Sirainen /* a) both directories didn't exist
1728ff34ee03de825ad3aeed67d19f8ae140ee2eTimo Sirainen b) index directory couldn't be rmdir()ed for some reason */
1728ff34ee03de825ad3aeed67d19f8ae140ee2eTimo Sirainen }
2f30b72d49fbff0c4096125c139e4bdfef45669cTimo Sirainen
1e4623e33bc4e37e61fcdc1e24e22327e49e303aTimo Sirainen if (errno == ENOENT || errno == ENOTDIR) {
2f30b72d49fbff0c4096125c139e4bdfef45669cTimo Sirainen mailbox_list_set_error(list, MAIL_ERROR_NOTFOUND,
bdb026e2dc8a7c77585ed5ba489f0056df8074d4Timo Sirainen T_MAILBOX_LIST_ERR_NOT_FOUND(list, name));
10a2e8716e9040908fb60fcda56b5315ea4c1312Timo Sirainen } else if (errno == ENOTEMPTY || errno == EEXIST) {
095c07765b69592c1dd644361f05ee37b1d39bd4Timo Sirainen /* mbox workaround: if only .imap/ directory is preventing the
095c07765b69592c1dd644361f05ee37b1d39bd4Timo Sirainen deletion, remove it */
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen sep = mailbox_list_get_hierarchy_sep(list);
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen child_name = t_strdup_printf("%s%cchild", name, sep);
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen if (mailbox_list_get_path(list, child_name,
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen MAILBOX_LIST_PATH_TYPE_INDEX,
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen &child_path) > 0 &&
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen strncmp(path, child_path, strlen(path)) == 0) {
095c07765b69592c1dd644361f05ee37b1d39bd4Timo Sirainen /* drop the "/child" part out. */
095c07765b69592c1dd644361f05ee37b1d39bd4Timo Sirainen p = strrchr(child_path, '/');
095c07765b69592c1dd644361f05ee37b1d39bd4Timo Sirainen if (rmdir(t_strdup_until(child_path, p)) == 0) {
095c07765b69592c1dd644361f05ee37b1d39bd4Timo Sirainen /* try again */
095c07765b69592c1dd644361f05ee37b1d39bd4Timo Sirainen if (fs_list_rmdir(list, name, path) == 0)
095c07765b69592c1dd644361f05ee37b1d39bd4Timo Sirainen return 0;
095c07765b69592c1dd644361f05ee37b1d39bd4Timo Sirainen }
095c07765b69592c1dd644361f05ee37b1d39bd4Timo Sirainen }
095c07765b69592c1dd644361f05ee37b1d39bd4Timo Sirainen
2f30b72d49fbff0c4096125c139e4bdfef45669cTimo Sirainen mailbox_list_set_error(list, MAIL_ERROR_EXISTS,
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen "Mailbox has children, delete them first");
2f30b72d49fbff0c4096125c139e4bdfef45669cTimo Sirainen } else {
2f30b72d49fbff0c4096125c139e4bdfef45669cTimo Sirainen mailbox_list_set_critical(list, "rmdir(%s) failed: %m", path);
2f30b72d49fbff0c4096125c139e4bdfef45669cTimo Sirainen }
2f30b72d49fbff0c4096125c139e4bdfef45669cTimo Sirainen return -1;
2f30b72d49fbff0c4096125c139e4bdfef45669cTimo Sirainen}
2f30b72d49fbff0c4096125c139e4bdfef45669cTimo Sirainen
91b203fd2132510a47a4b34252c0ae0efd688a19Timo Sirainenstatic int rename_dir(struct mailbox_list *oldlist, const char *oldname,
91b203fd2132510a47a4b34252c0ae0efd688a19Timo Sirainen struct mailbox_list *newlist, const char *newname,
91b203fd2132510a47a4b34252c0ae0efd688a19Timo Sirainen enum mailbox_list_path_type type, bool rmdir_parent)
f35141938f1ce4fd822a589045c7a01e866922a2Timo Sirainen{
253201e2b423d3eceb6a8b41cb3493edeab4d224Timo Sirainen struct stat st;
253201e2b423d3eceb6a8b41cb3493edeab4d224Timo Sirainen const char *oldpath, *newpath, *p, *oldparent, *newparent;
f35141938f1ce4fd822a589045c7a01e866922a2Timo Sirainen
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen if (mailbox_list_get_path(oldlist, oldname, type, &oldpath) <= 0 ||
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen mailbox_list_get_path(newlist, newname, type, &newpath) <= 0)
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen return 0;
f35141938f1ce4fd822a589045c7a01e866922a2Timo Sirainen
f35141938f1ce4fd822a589045c7a01e866922a2Timo Sirainen if (strcmp(oldpath, newpath) == 0)
f35141938f1ce4fd822a589045c7a01e866922a2Timo Sirainen return 0;
f35141938f1ce4fd822a589045c7a01e866922a2Timo Sirainen
253201e2b423d3eceb6a8b41cb3493edeab4d224Timo Sirainen p = strrchr(oldpath, '/');
253201e2b423d3eceb6a8b41cb3493edeab4d224Timo Sirainen oldparent = p == NULL ? "/" : t_strdup_until(oldpath, p);
253201e2b423d3eceb6a8b41cb3493edeab4d224Timo Sirainen p = strrchr(newpath, '/');
253201e2b423d3eceb6a8b41cb3493edeab4d224Timo Sirainen newparent = p == NULL ? "/" : t_strdup_until(newpath, p);
253201e2b423d3eceb6a8b41cb3493edeab4d224Timo Sirainen
253201e2b423d3eceb6a8b41cb3493edeab4d224Timo Sirainen if (strcmp(oldparent, newparent) != 0 && stat(oldpath, &st) == 0) {
253201e2b423d3eceb6a8b41cb3493edeab4d224Timo Sirainen /* make sure the newparent exists */
76b91bac787101e6b0075122ab6478dd98c8a884Timo Sirainen struct mailbox_permissions perm;
253201e2b423d3eceb6a8b41cb3493edeab4d224Timo Sirainen
76b91bac787101e6b0075122ab6478dd98c8a884Timo Sirainen mailbox_list_get_root_permissions(newlist, &perm);
76b91bac787101e6b0075122ab6478dd98c8a884Timo Sirainen if (mkdir_parents_chgrp(newparent, perm.dir_create_mode,
76b91bac787101e6b0075122ab6478dd98c8a884Timo Sirainen perm.file_create_gid,
76b91bac787101e6b0075122ab6478dd98c8a884Timo Sirainen perm.file_create_gid_origin) < 0 &&
253201e2b423d3eceb6a8b41cb3493edeab4d224Timo Sirainen errno != EEXIST) {
253201e2b423d3eceb6a8b41cb3493edeab4d224Timo Sirainen if (mailbox_list_set_error_from_errno(oldlist))
253201e2b423d3eceb6a8b41cb3493edeab4d224Timo Sirainen return -1;
253201e2b423d3eceb6a8b41cb3493edeab4d224Timo Sirainen
253201e2b423d3eceb6a8b41cb3493edeab4d224Timo Sirainen mailbox_list_set_critical(oldlist,
253201e2b423d3eceb6a8b41cb3493edeab4d224Timo Sirainen "mkdir_parents(%s) failed: %m", newparent);
253201e2b423d3eceb6a8b41cb3493edeab4d224Timo Sirainen return -1;
253201e2b423d3eceb6a8b41cb3493edeab4d224Timo Sirainen }
253201e2b423d3eceb6a8b41cb3493edeab4d224Timo Sirainen }
253201e2b423d3eceb6a8b41cb3493edeab4d224Timo Sirainen
f35141938f1ce4fd822a589045c7a01e866922a2Timo Sirainen if (rename(oldpath, newpath) < 0 && errno != ENOENT) {
91b203fd2132510a47a4b34252c0ae0efd688a19Timo Sirainen mailbox_list_set_critical(oldlist, "rename(%s, %s) failed: %m",
f35141938f1ce4fd822a589045c7a01e866922a2Timo Sirainen oldpath, newpath);
f35141938f1ce4fd822a589045c7a01e866922a2Timo Sirainen return -1;
f35141938f1ce4fd822a589045c7a01e866922a2Timo Sirainen }
91b203fd2132510a47a4b34252c0ae0efd688a19Timo Sirainen if (rmdir_parent && (p = strrchr(oldpath, '/')) != NULL) {
91b203fd2132510a47a4b34252c0ae0efd688a19Timo Sirainen oldpath = t_strdup_until(oldpath, p);
10a2e8716e9040908fb60fcda56b5315ea4c1312Timo Sirainen if (rmdir(oldpath) < 0 && errno != ENOENT &&
10a2e8716e9040908fb60fcda56b5315ea4c1312Timo Sirainen errno != ENOTEMPTY && errno != EEXIST) {
91b203fd2132510a47a4b34252c0ae0efd688a19Timo Sirainen mailbox_list_set_critical(oldlist,
91b203fd2132510a47a4b34252c0ae0efd688a19Timo Sirainen "rmdir(%s) failed: %m", oldpath);
91b203fd2132510a47a4b34252c0ae0efd688a19Timo Sirainen }
91b203fd2132510a47a4b34252c0ae0efd688a19Timo Sirainen }
ae1a57954535642c09c3b8aee184736ddbb06cdfTimo Sirainen
ae1a57954535642c09c3b8aee184736ddbb06cdfTimo Sirainen /* avoid leaving empty directories lying around */
ae1a57954535642c09c3b8aee184736ddbb06cdfTimo Sirainen mailbox_list_delete_until_root(oldlist, oldpath, type);
f35141938f1ce4fd822a589045c7a01e866922a2Timo Sirainen return 0;
f35141938f1ce4fd822a589045c7a01e866922a2Timo Sirainen}
f35141938f1ce4fd822a589045c7a01e866922a2Timo Sirainen
91b203fd2132510a47a4b34252c0ae0efd688a19Timo Sirainenstatic int fs_list_rename_mailbox(struct mailbox_list *oldlist,
91b203fd2132510a47a4b34252c0ae0efd688a19Timo Sirainen const char *oldname,
91b203fd2132510a47a4b34252c0ae0efd688a19Timo Sirainen struct mailbox_list *newlist,
71e88fae3be360e9a93b3398e743f99a6f05d2edTimo Sirainen const char *newname)
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen{
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen struct mail_storage *oldstorage;
47d5cc09738defd0020c797866e2a25a344aa65aTimo Sirainen const char *oldvname, *oldpath, *newpath, *alt_newpath, *root_path, *p;
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen struct stat st;
47d5cc09738defd0020c797866e2a25a344aa65aTimo Sirainen struct mailbox_permissions old_perm, new_perm;
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen bool rmdir_parent = FALSE;
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen oldvname = mailbox_list_get_vname(oldlist, oldname);
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen if (mailbox_list_get_storage(&oldlist, oldvname, &oldstorage) < 0)
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen return -1;
91b203fd2132510a47a4b34252c0ae0efd688a19Timo Sirainen
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen if (mailbox_list_get_path(oldlist, oldname,
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen MAILBOX_LIST_PATH_TYPE_DIR, &oldpath) <= 0 ||
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen mailbox_list_get_path(newlist, newname,
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen MAILBOX_LIST_PATH_TYPE_DIR, &newpath) <= 0)
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen i_unreached();
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen if (mailbox_list_get_path(newlist, newname, MAILBOX_LIST_PATH_TYPE_ALT_DIR,
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen &alt_newpath) < 0)
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen i_unreached();
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen root_path = mailbox_list_get_root_forced(oldlist, MAILBOX_LIST_PATH_TYPE_MAILBOX);
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen if (strcmp(oldpath, root_path) == 0) {
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen /* most likely INBOX */
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen mailbox_list_set_error(oldlist, MAIL_ERROR_NOTPOSSIBLE,
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen t_strdup_printf("Renaming %s isn't supported.",
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen oldname));
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen return -1;
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen }
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen
47d5cc09738defd0020c797866e2a25a344aa65aTimo Sirainen mailbox_list_get_permissions(oldlist, oldname, &old_perm);
47d5cc09738defd0020c797866e2a25a344aa65aTimo Sirainen mailbox_list_get_permissions(newlist, newname, &new_perm);
4b2e3b39bc79281211ba9887ab1ebc6fa21da79aTimo Sirainen
4b2e3b39bc79281211ba9887ab1ebc6fa21da79aTimo Sirainen /* if we're renaming under another mailbox, require its permissions
4b2e3b39bc79281211ba9887ab1ebc6fa21da79aTimo Sirainen to be same as ours. */
4b2e3b39bc79281211ba9887ab1ebc6fa21da79aTimo Sirainen if (strchr(newname, mailbox_list_get_hierarchy_sep(newlist)) != NULL &&
47d5cc09738defd0020c797866e2a25a344aa65aTimo Sirainen (new_perm.file_create_mode != old_perm.file_create_mode ||
47d5cc09738defd0020c797866e2a25a344aa65aTimo Sirainen new_perm.dir_create_mode != old_perm.dir_create_mode ||
47d5cc09738defd0020c797866e2a25a344aa65aTimo Sirainen new_perm.file_create_gid != old_perm.file_create_gid)) {
4b2e3b39bc79281211ba9887ab1ebc6fa21da79aTimo Sirainen mailbox_list_set_error(oldlist, MAIL_ERROR_NOTPOSSIBLE,
4b2e3b39bc79281211ba9887ab1ebc6fa21da79aTimo Sirainen "Renaming not supported across conflicting "
4b2e3b39bc79281211ba9887ab1ebc6fa21da79aTimo Sirainen "directory permissions");
4b2e3b39bc79281211ba9887ab1ebc6fa21da79aTimo Sirainen return -1;
4b2e3b39bc79281211ba9887ab1ebc6fa21da79aTimo Sirainen }
4b2e3b39bc79281211ba9887ab1ebc6fa21da79aTimo Sirainen
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen /* create the hierarchy */
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen p = strrchr(newpath, '/');
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen if (p != NULL) {
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen p = t_strdup_until(newpath, p);
47d5cc09738defd0020c797866e2a25a344aa65aTimo Sirainen if (mkdir_parents_chgrp(p, new_perm.dir_create_mode,
47d5cc09738defd0020c797866e2a25a344aa65aTimo Sirainen new_perm.file_create_gid,
47d5cc09738defd0020c797866e2a25a344aa65aTimo Sirainen new_perm.file_create_gid_origin) < 0 &&
fea7b8b3fc182e415b1875d79587c0aa1adb09d7Timo Sirainen errno != EEXIST) {
91b203fd2132510a47a4b34252c0ae0efd688a19Timo Sirainen if (mailbox_list_set_error_from_errno(oldlist))
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen return -1;
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen
91b203fd2132510a47a4b34252c0ae0efd688a19Timo Sirainen mailbox_list_set_critical(oldlist,
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen "mkdir_parents(%s) failed: %m", p);
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen return -1;
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen }
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen }
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen /* first check that the destination mailbox doesn't exist.
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen this is racy, but we need to be atomic and there's hardly any
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen possibility that someone actually tries to rename two mailboxes
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen to same new one */
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen if (lstat(newpath, &st) == 0) {
91b203fd2132510a47a4b34252c0ae0efd688a19Timo Sirainen mailbox_list_set_error(oldlist, MAIL_ERROR_EXISTS,
ff7056842f14fd3b30a2d327dfab165b9d15dd30Timo Sirainen "Target mailbox already exists");
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen return -1;
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen } else if (errno == ENOTDIR) {
91b203fd2132510a47a4b34252c0ae0efd688a19Timo Sirainen mailbox_list_set_error(oldlist, MAIL_ERROR_NOTPOSSIBLE,
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen "Target mailbox doesn't allow inferior mailboxes");
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen return -1;
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen } else if (errno != ENOENT && errno != EACCES) {
91b203fd2132510a47a4b34252c0ae0efd688a19Timo Sirainen mailbox_list_set_critical(oldlist, "lstat(%s) failed: %m",
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen newpath);
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen return -1;
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen }
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen if (alt_newpath != NULL) {
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen if (stat(alt_newpath, &st) == 0) {
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen /* race condition or a directory left there lying around?
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen safest to just report error. */
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen mailbox_list_set_error(oldlist, MAIL_ERROR_EXISTS,
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen "Target mailbox already exists");
0e5f8c4589cfeccb752307c8ac35a2f1633e4ecaTimo Sirainen return -1;
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen } else if (errno != ENOENT) {
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen mailbox_list_set_critical(oldlist, "stat(%s) failed: %m",
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen alt_newpath);
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen return -1;
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen }
0e5f8c4589cfeccb752307c8ac35a2f1633e4ecaTimo Sirainen }
0e5f8c4589cfeccb752307c8ac35a2f1633e4ecaTimo Sirainen
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen if (rename(oldpath, newpath) < 0) {
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen if (ENOTFOUND(errno)) {
91b203fd2132510a47a4b34252c0ae0efd688a19Timo Sirainen mailbox_list_set_error(oldlist, MAIL_ERROR_NOTFOUND,
bdb026e2dc8a7c77585ed5ba489f0056df8074d4Timo Sirainen T_MAILBOX_LIST_ERR_NOT_FOUND(oldlist, oldname));
91b203fd2132510a47a4b34252c0ae0efd688a19Timo Sirainen } else if (!mailbox_list_set_error_from_errno(oldlist)) {
91b203fd2132510a47a4b34252c0ae0efd688a19Timo Sirainen mailbox_list_set_critical(oldlist,
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen "rename(%s, %s) failed: %m", oldpath, newpath);
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen }
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen return -1;
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen }
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen if (alt_newpath != NULL) {
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen (void)rename_dir(oldlist, oldname, newlist, newname,
71e88fae3be360e9a93b3398e743f99a6f05d2edTimo Sirainen MAILBOX_LIST_PATH_TYPE_ALT_DIR, rmdir_parent);
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen }
91b203fd2132510a47a4b34252c0ae0efd688a19Timo Sirainen (void)rename_dir(oldlist, oldname, newlist, newname,
91b203fd2132510a47a4b34252c0ae0efd688a19Timo Sirainen MAILBOX_LIST_PATH_TYPE_CONTROL, rmdir_parent);
91b203fd2132510a47a4b34252c0ae0efd688a19Timo Sirainen (void)rename_dir(oldlist, oldname, newlist, newname,
91b203fd2132510a47a4b34252c0ae0efd688a19Timo Sirainen MAILBOX_LIST_PATH_TYPE_INDEX, rmdir_parent);
638600575ee95f2513c683ef09cb188f76eacd22Timo Sirainen (void)rename_dir(oldlist, oldname, newlist, newname,
638600575ee95f2513c683ef09cb188f76eacd22Timo Sirainen MAILBOX_LIST_PATH_TYPE_INDEX_CACHE, rmdir_parent);
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen return 0;
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen}
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainenstruct mailbox_list fs_mailbox_list = {
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen .name = MAILBOX_LIST_NAME_FS,
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen .props = 0,
48ca4c43ebca6fa3eee217bd4439cba5b5376dd4Timo Sirainen .mailbox_name_max_length = MAILBOX_LIST_NAME_MAX_LENGTH,
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a384b1fccb51884e8afe0f571420961851a2149dTimo Sirainen .v = {
a384b1fccb51884e8afe0f571420961851a2149dTimo Sirainen .alloc = fs_list_alloc,
a384b1fccb51884e8afe0f571420961851a2149dTimo Sirainen .deinit = fs_list_deinit,
a384b1fccb51884e8afe0f571420961851a2149dTimo Sirainen .get_hierarchy_sep = fs_list_get_hierarchy_sep,
a384b1fccb51884e8afe0f571420961851a2149dTimo Sirainen .get_vname = mailbox_list_default_get_vname,
a384b1fccb51884e8afe0f571420961851a2149dTimo Sirainen .get_storage_name = mailbox_list_default_get_storage_name,
a384b1fccb51884e8afe0f571420961851a2149dTimo Sirainen .get_path = fs_list_get_path,
a384b1fccb51884e8afe0f571420961851a2149dTimo Sirainen .get_temp_prefix = fs_list_get_temp_prefix,
a384b1fccb51884e8afe0f571420961851a2149dTimo Sirainen .join_refpattern = fs_list_join_refpattern,
a384b1fccb51884e8afe0f571420961851a2149dTimo Sirainen .iter_init = fs_list_iter_init,
a384b1fccb51884e8afe0f571420961851a2149dTimo Sirainen .iter_next = fs_list_iter_next,
a384b1fccb51884e8afe0f571420961851a2149dTimo Sirainen .iter_deinit = fs_list_iter_deinit,
a384b1fccb51884e8afe0f571420961851a2149dTimo Sirainen .get_mailbox_flags = fs_list_get_mailbox_flags,
a384b1fccb51884e8afe0f571420961851a2149dTimo Sirainen .subscriptions_refresh = mailbox_list_subscriptions_refresh,
a384b1fccb51884e8afe0f571420961851a2149dTimo Sirainen .set_subscribed = fs_list_set_subscribed,
a384b1fccb51884e8afe0f571420961851a2149dTimo Sirainen .delete_mailbox = fs_list_delete_mailbox,
a384b1fccb51884e8afe0f571420961851a2149dTimo Sirainen .delete_dir = fs_list_delete_dir,
a384b1fccb51884e8afe0f571420961851a2149dTimo Sirainen .delete_symlink = mailbox_list_delete_symlink_default,
a384b1fccb51884e8afe0f571420961851a2149dTimo Sirainen .rename_mailbox = fs_list_rename_mailbox,
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen }
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen};