bcb4e51a409d94ae670de96afb8483a4f7855294Stephan Bosch/* Copyright (c) 2006-2018 Dovecot authors, see the included COPYING file */
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen#include "lib.h"
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen#include "array.h"
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen#include "hostpid.h"
3c493c276f599d9b9cd10764876d648003046954Timo Sirainen#include "eacces-error.h"
3c493c276f599d9b9cd10764876d648003046954Timo Sirainen#include "mkdir-parents.h"
c19f0dd4d274c15ef7b592dcc9d8c2c8c1e22abeTimo Sirainen#include "str.h"
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen#include "subscription-file.h"
b13f738e8eb3f24dc2abf2c804f954b4d864ac6fTimo Sirainen#include "mailbox-list-subscriptions.h"
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen#include "mailbox-list-delete.h"
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen#include "mailbox-list-maildir.h"
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen#include <stdio.h>
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen#include <sys/stat.h>
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
c040ee67d0ac0fb7375bb543965bf67dcae6affaTimo Sirainen#define MAILDIR_GLOBAL_TEMP_PREFIX "temp."
c040ee67d0ac0fb7375bb543965bf67dcae6affaTimo Sirainen#define IMAPDIR_GLOBAL_TEMP_PREFIX ".temp."
c040ee67d0ac0fb7375bb543965bf67dcae6affaTimo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainenextern struct mailbox_list maildir_mailbox_list;
63ca9cacc5d2d1b1cebfc430bb89637f8c138e4cTimo Sirainenextern struct mailbox_list imapdir_mailbox_list;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainenstatic struct mailbox_list *maildir_list_alloc(void)
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen{
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen struct maildir_mailbox_list *list;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen pool_t pool;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
14e581093719c4353205bf5ba4743d8575c49d1bTimo Sirainen pool = pool_alloconly_create("maildir++ list", 2048);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen list = p_new(pool, struct maildir_mailbox_list, 1);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen list->list = maildir_mailbox_list;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen list->list.pool = pool;
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen list->sep = '.';
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
c040ee67d0ac0fb7375bb543965bf67dcae6affaTimo Sirainen list->global_temp_prefix = MAILDIR_GLOBAL_TEMP_PREFIX;
c040ee67d0ac0fb7375bb543965bf67dcae6affaTimo Sirainen list->temp_prefix = p_strconcat(pool, list->global_temp_prefix,
c040ee67d0ac0fb7375bb543965bf67dcae6affaTimo Sirainen my_hostname, ".", my_pid, ".", NULL);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen return &list->list;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen}
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
63ca9cacc5d2d1b1cebfc430bb89637f8c138e4cTimo Sirainenstatic struct mailbox_list *imapdir_list_alloc(void)
63ca9cacc5d2d1b1cebfc430bb89637f8c138e4cTimo Sirainen{
63ca9cacc5d2d1b1cebfc430bb89637f8c138e4cTimo Sirainen struct maildir_mailbox_list *list;
63ca9cacc5d2d1b1cebfc430bb89637f8c138e4cTimo Sirainen pool_t pool;
63ca9cacc5d2d1b1cebfc430bb89637f8c138e4cTimo Sirainen
63ca9cacc5d2d1b1cebfc430bb89637f8c138e4cTimo Sirainen pool = pool_alloconly_create("imapdir list", 1024);
63ca9cacc5d2d1b1cebfc430bb89637f8c138e4cTimo Sirainen list = p_new(pool, struct maildir_mailbox_list, 1);
63ca9cacc5d2d1b1cebfc430bb89637f8c138e4cTimo Sirainen list->list = imapdir_mailbox_list;
63ca9cacc5d2d1b1cebfc430bb89637f8c138e4cTimo Sirainen list->list.pool = pool;
441f0e0d84082eb498e620327ebf4de509052d15Timo Sirainen list->sep = '.';
63ca9cacc5d2d1b1cebfc430bb89637f8c138e4cTimo Sirainen
c040ee67d0ac0fb7375bb543965bf67dcae6affaTimo Sirainen list->global_temp_prefix = IMAPDIR_GLOBAL_TEMP_PREFIX;
c040ee67d0ac0fb7375bb543965bf67dcae6affaTimo Sirainen list->temp_prefix = p_strconcat(pool, list->global_temp_prefix,
c040ee67d0ac0fb7375bb543965bf67dcae6affaTimo Sirainen my_hostname, ".", my_pid, ".", NULL);
63ca9cacc5d2d1b1cebfc430bb89637f8c138e4cTimo Sirainen return &list->list;
63ca9cacc5d2d1b1cebfc430bb89637f8c138e4cTimo Sirainen}
63ca9cacc5d2d1b1cebfc430bb89637f8c138e4cTimo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainenstatic void maildir_list_deinit(struct mailbox_list *_list)
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen{
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen struct maildir_mailbox_list *list =
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen (struct maildir_mailbox_list *)_list;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
648d24583c1574441c4fa0331a90bd4d6e7996c5Timo Sirainen pool_unref(&list->list.pool);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen}
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
63ca9cacc5d2d1b1cebfc430bb89637f8c138e4cTimo Sirainenstatic const char *
63ca9cacc5d2d1b1cebfc430bb89637f8c138e4cTimo Sirainenmaildir_list_get_dirname_path(struct mailbox_list *list, const char *dir,
63ca9cacc5d2d1b1cebfc430bb89637f8c138e4cTimo Sirainen const char *name)
63ca9cacc5d2d1b1cebfc430bb89637f8c138e4cTimo Sirainen{
e12d2886114e48ccd871ae73fd0a962375096a8aTimo Sirainen if (*name == '\0')
e12d2886114e48ccd871ae73fd0a962375096a8aTimo Sirainen return dir;
e12d2886114e48ccd871ae73fd0a962375096a8aTimo Sirainen else if (list->name == imapdir_mailbox_list.name)
63ca9cacc5d2d1b1cebfc430bb89637f8c138e4cTimo Sirainen return t_strdup_printf("%s/%s", dir, name);
e12d2886114e48ccd871ae73fd0a962375096a8aTimo Sirainen
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen return t_strdup_printf("%s/%c%s", dir,
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen mailbox_list_get_hierarchy_sep(list), name);
63ca9cacc5d2d1b1cebfc430bb89637f8c138e4cTimo Sirainen}
63ca9cacc5d2d1b1cebfc430bb89637f8c138e4cTimo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainenstatic const char *
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainenmaildir_list_get_absolute_path(struct mailbox_list *list, const char *name)
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen{
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen const char *p;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
96f2533c48ce5def0004931606a2fdf275578880Timo Sirainen if (!mailbox_list_try_get_absolute_path(list, &name)) {
83c21c990eb2a370f0da56240e73dac846f4acc3Timo Sirainen /* fallback to using as ~name */
83c21c990eb2a370f0da56240e73dac846f4acc3Timo Sirainen return name;
83c21c990eb2a370f0da56240e73dac846f4acc3Timo Sirainen }
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen p = strrchr(name, '/');
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen if (p == NULL)
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen return name;
63ca9cacc5d2d1b1cebfc430bb89637f8c138e4cTimo Sirainen return maildir_list_get_dirname_path(list, t_strdup_until(name, p),
63ca9cacc5d2d1b1cebfc430bb89637f8c138e4cTimo Sirainen p+1);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen}
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainenstatic char maildir_list_get_hierarchy_sep(struct mailbox_list *_list)
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen{
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen struct maildir_mailbox_list *list =
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen (struct maildir_mailbox_list *)_list;
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen return list->sep;
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen}
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainenstatic int
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainenmaildir_list_get_path(struct mailbox_list *_list, const char *name,
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen enum mailbox_list_path_type type, const char **path_r)
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen{
3c493c276f599d9b9cd10764876d648003046954Timo Sirainen const char *root_dir;
3c493c276f599d9b9cd10764876d648003046954Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen if (name == NULL) {
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen /* return root directories */
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen return mailbox_list_set_get_root_path(&_list->set, type,
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen path_r) ? 1 : 0;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen }
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen if (_list->mail_set->mail_full_filesystem_access &&
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen (*name == '/' || *name == '~')) {
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen *path_r = maildir_list_get_absolute_path(_list, name);
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen return 1;
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen }
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
3c493c276f599d9b9cd10764876d648003046954Timo Sirainen root_dir = _list->set.root_dir;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen switch (type) {
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen case MAILBOX_LIST_PATH_TYPE_DIR:
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen case MAILBOX_LIST_PATH_TYPE_MAILBOX:
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen break;
3c493c276f599d9b9cd10764876d648003046954Timo Sirainen case MAILBOX_LIST_PATH_TYPE_ALT_DIR:
3c493c276f599d9b9cd10764876d648003046954Timo Sirainen case MAILBOX_LIST_PATH_TYPE_ALT_MAILBOX:
3c493c276f599d9b9cd10764876d648003046954Timo Sirainen if (_list->set.alt_dir == NULL)
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen return 0;
3c493c276f599d9b9cd10764876d648003046954Timo Sirainen root_dir = _list->set.alt_dir;
3c493c276f599d9b9cd10764876d648003046954Timo Sirainen break;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen case MAILBOX_LIST_PATH_TYPE_CONTROL:
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen if (_list->set.control_dir != NULL) {
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen *path_r = maildir_list_get_dirname_path(_list,
63ca9cacc5d2d1b1cebfc430bb89637f8c138e4cTimo Sirainen _list->set.control_dir, name);
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen return 1;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen }
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen break;
638600575ee95f2513c683ef09cb188f76eacd22Timo Sirainen case MAILBOX_LIST_PATH_TYPE_INDEX_CACHE:
638600575ee95f2513c683ef09cb188f76eacd22Timo Sirainen if (_list->set.index_cache_dir != NULL) {
638600575ee95f2513c683ef09cb188f76eacd22Timo Sirainen *path_r = maildir_list_get_dirname_path(_list,
638600575ee95f2513c683ef09cb188f76eacd22Timo Sirainen _list->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 (_list->set.index_dir != NULL) {
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen if (*_list->set.index_dir == '\0')
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen return 0;
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen *path_r = maildir_list_get_dirname_path(_list,
63ca9cacc5d2d1b1cebfc430bb89637f8c138e4cTimo Sirainen _list->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 (_list->set.index_pvt_dir == NULL)
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen return 0;
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen *path_r = maildir_list_get_dirname_path(_list,
5da1aa5197a43d83f0fb3eeb83125c7cd73d1b62Timo Sirainen _list->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 */
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen } else if (strcmp(name, "INBOX") == 0 && _list->set.inbox_path != NULL) {
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen *path_r = _list->set.inbox_path;
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen return 1;
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen }
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen *path_r = maildir_list_get_dirname_path(_list, root_dir, name);
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen return 1;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen}
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainenstatic const char *
c040ee67d0ac0fb7375bb543965bf67dcae6affaTimo Sirainenmaildir_list_get_temp_prefix(struct mailbox_list *_list, bool global)
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen{
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen struct maildir_mailbox_list *list =
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen (struct maildir_mailbox_list *)_list;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
c040ee67d0ac0fb7375bb543965bf67dcae6affaTimo Sirainen return global ? list->global_temp_prefix : list->temp_prefix;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen}
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainenstatic int maildir_list_set_subscribed(struct mailbox_list *_list,
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen const char *name, bool set)
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen{
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen struct maildir_mailbox_list *list =
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen (struct maildir_mailbox_list *)_list;
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
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen path = t_strconcat(_list->set.control_dir != NULL ?
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen _list->set.control_dir : _list->set.root_dir,
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen "/", _list->set.subscription_fname, NULL);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen return subsfile_set_subscribed(_list, path, list->temp_prefix,
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen name, set);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen}
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainenstatic const char *
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainenmailbox_list_maildir_get_trash_dir(struct mailbox_list *_list)
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen{
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen struct maildir_mailbox_list *list =
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen (struct maildir_mailbox_list *)_list;
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/%c%c"MAILBOX_LIST_MAILDIR_TRASH_DIR_NAME,
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen root_dir, list->sep, list->sep);
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen}
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainenstatic int
c18c8b130311374a5145226be03cda903047b1f8Timo Sirainenmaildir_list_delete_maildir(struct mailbox_list *list, const char *name)
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen{
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen const char *path, *trash_dir;
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen int ret = 0;
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen trash_dir = mailbox_list_maildir_get_trash_dir(list);
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen ret = mailbox_list_delete_maildir_via_trash(list, name, trash_dir);
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen if (ret < 0)
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen return -1;
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen if (ret == 0) {
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen /* we could actually use just unlink_directory()
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen but error handling is easier this way :) */
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen if (mailbox_list_get_path(list, name,
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen MAILBOX_LIST_PATH_TYPE_MAILBOX,
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen &path) <= 0)
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen i_unreached();
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen if (mailbox_list_delete_mailbox_nonrecursive(list, name,
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen path, TRUE) < 0)
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen return -1;
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen }
c18c8b130311374a5145226be03cda903047b1f8Timo Sirainen return 0;
c18c8b130311374a5145226be03cda903047b1f8Timo Sirainen}
c18c8b130311374a5145226be03cda903047b1f8Timo Sirainen
c18c8b130311374a5145226be03cda903047b1f8Timo Sirainenstatic int
c18c8b130311374a5145226be03cda903047b1f8Timo Sirainenmaildir_list_delete_mailbox(struct mailbox_list *list, const char *name)
c18c8b130311374a5145226be03cda903047b1f8Timo Sirainen{
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen const char *path;
fd057522c580091ec9803c0dceb4747d8bcaece5Timo Sirainen int ret;
fd057522c580091ec9803c0dceb4747d8bcaece5Timo Sirainen
c18c8b130311374a5145226be03cda903047b1f8Timo Sirainen if ((list->flags & MAILBOX_LIST_FLAG_MAILBOX_FILES) != 0) {
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen ret = mailbox_list_get_path(list, name,
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen MAILBOX_LIST_PATH_TYPE_MAILBOX,
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen &path);
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen if (ret < 0)
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen return -1;
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen i_assert(ret > 0);
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen ret = mailbox_list_delete_mailbox_file(list, name, path);
c18c8b130311374a5145226be03cda903047b1f8Timo Sirainen } else {
fd057522c580091ec9803c0dceb4747d8bcaece5Timo Sirainen ret = maildir_list_delete_maildir(list, name);
c18c8b130311374a5145226be03cda903047b1f8Timo Sirainen }
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen
3fb442057c352645e918314815f8fe2a12b6ee2bTimo Sirainen i_assert(ret <= 0);
3fb442057c352645e918314815f8fe2a12b6ee2bTimo Sirainen return mailbox_list_delete_finish_ret(list, name, ret == 0);
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen}
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen
2f30b72d49fbff0c4096125c139e4bdfef45669cTimo Sirainenstatic int maildir_list_delete_dir(struct mailbox_list *list, const char *name)
2f30b72d49fbff0c4096125c139e4bdfef45669cTimo Sirainen{
2f30b72d49fbff0c4096125c139e4bdfef45669cTimo Sirainen const char *path;
2f30b72d49fbff0c4096125c139e4bdfef45669cTimo Sirainen struct stat st;
2f30b72d49fbff0c4096125c139e4bdfef45669cTimo Sirainen
2f30b72d49fbff0c4096125c139e4bdfef45669cTimo Sirainen /* with maildir++ there aren't any non-selectable mailboxes.
2f30b72d49fbff0c4096125c139e4bdfef45669cTimo Sirainen we'll always fail. */
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen if (mailbox_list_get_path(list, name, MAILBOX_LIST_PATH_TYPE_DIR,
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen &path) <= 0)
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen i_unreached();
2f30b72d49fbff0c4096125c139e4bdfef45669cTimo Sirainen if (stat(path, &st) == 0) {
2f30b72d49fbff0c4096125c139e4bdfef45669cTimo Sirainen mailbox_list_set_error(list, MAIL_ERROR_EXISTS,
2f30b72d49fbff0c4096125c139e4bdfef45669cTimo Sirainen "Mailbox exists");
1e4623e33bc4e37e61fcdc1e24e22327e49e303aTimo Sirainen } else 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));
2f30b72d49fbff0c4096125c139e4bdfef45669cTimo Sirainen } else {
2f30b72d49fbff0c4096125c139e4bdfef45669cTimo Sirainen mailbox_list_set_critical(list, "stat(%s) failed: %m", path);
2f30b72d49fbff0c4096125c139e4bdfef45669cTimo Sirainen }
2f30b72d49fbff0c4096125c139e4bdfef45669cTimo Sirainen return -1;
2f30b72d49fbff0c4096125c139e4bdfef45669cTimo Sirainen}
2f30b72d49fbff0c4096125c139e4bdfef45669cTimo Sirainen
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainenstatic int rename_dir(struct mailbox_list *oldlist, const char *oldname,
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen struct mailbox_list *newlist, const char *newname,
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen enum mailbox_list_path_type type)
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen{
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen const char *oldpath, *newpath;
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo 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;
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen if (strcmp(oldpath, newpath) == 0)
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen return 0;
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen if (rename(oldpath, newpath) < 0 && errno != ENOENT) {
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen mailbox_list_set_critical(oldlist, "rename(%s, %s) failed: %m",
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen oldpath, newpath);
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen return -1;
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen }
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen return 0;
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen}
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainenstatic int
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainenmaildir_rename_children(struct mailbox_list *oldlist, const char *oldname,
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen struct mailbox_list *newlist, const char *newname)
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen{
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen struct mailbox_list_iterate_context *iter;
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen const struct mailbox_info *info;
4ee00532a265bdfb38539d811fcd12d51210ac35Timo Sirainen ARRAY(const char *) names_arr;
c19f0dd4d274c15ef7b592dcc9d8c2c8c1e22abeTimo Sirainen const char *pattern, *oldpath, *newpath, *old_childname, *new_childname;
c19f0dd4d274c15ef7b592dcc9d8c2c8c1e22abeTimo Sirainen const char *const *names, *old_vname, *new_vname;
2ac5f36aa7c2e7a07ba8815d43a6d7483f62e74cTimo Sirainen unsigned int i, count;
2ac5f36aa7c2e7a07ba8815d43a6d7483f62e74cTimo Sirainen size_t old_vnamelen;
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen pool_t pool;
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen char old_ns_sep;
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen int ret;
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen ret = 0;
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen /* first get the list of the children and save them to memory, because
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen we can't rely on readdir() not skipping files while the directory
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen is being modified. this doesn't protect against modifications by
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen other processes though. */
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen pool = pool_alloconly_create("Maildir++ children list", 1024);
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen i_array_init(&names_arr, 64);
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen old_vname = mailbox_list_get_vname(oldlist, oldname);
5a01a2c1f18a5ebd3dba9d1203bc043819ac912aTimo Sirainen old_vnamelen = strlen(old_vname);
c19f0dd4d274c15ef7b592dcc9d8c2c8c1e22abeTimo Sirainen
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen new_vname = mailbox_list_get_vname(newlist, newname);
c19f0dd4d274c15ef7b592dcc9d8c2c8c1e22abeTimo Sirainen
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen old_ns_sep = mail_namespace_get_sep(oldlist->ns);
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen pattern = t_strdup_printf("%s%c*", old_vname, old_ns_sep);
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen iter = mailbox_list_iter_init(oldlist, pattern,
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen MAILBOX_LIST_ITER_RETURN_NO_FLAGS |
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen MAILBOX_LIST_ITER_RAW_LIST);
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen while ((info = mailbox_list_iter_next(iter)) != NULL) {
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen const char *name;
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen /* verify that the prefix matches, otherwise we could have
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen problems with mailbox names containing '%' and '*' chars */
402e999a878e0cc41a0afb830fea0a93afc75f0dTimo Sirainen if (strncmp(info->vname, old_vname, old_vnamelen) == 0 &&
402e999a878e0cc41a0afb830fea0a93afc75f0dTimo Sirainen info->vname[old_vnamelen] == old_ns_sep) {
402e999a878e0cc41a0afb830fea0a93afc75f0dTimo Sirainen name = p_strdup(pool, info->vname + old_vnamelen);
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen array_append(&names_arr, &name, 1);
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen }
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen }
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen if (mailbox_list_iter_deinit(&iter) < 0) {
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen ret = -1;
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen names = NULL; count = 0;
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen } else {
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen names = array_get(&names_arr, &count);
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen }
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen for (i = 0; i < count; i++) {
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen old_childname = mailbox_list_get_storage_name(oldlist,
c19f0dd4d274c15ef7b592dcc9d8c2c8c1e22abeTimo Sirainen t_strconcat(old_vname, names[i], NULL));
c19f0dd4d274c15ef7b592dcc9d8c2c8c1e22abeTimo Sirainen if (strcmp(old_childname, new_vname) == 0) {
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen /* When doing RENAME "a" "a.b" we see "a.b" here.
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen We don't want to rename it anymore to "a.b.b". */
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen continue;
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen }
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen new_childname = mailbox_list_get_storage_name(newlist,
c19f0dd4d274c15ef7b592dcc9d8c2c8c1e22abeTimo Sirainen t_strconcat(new_vname, names[i], NULL));
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen if (mailbox_list_get_path(oldlist, old_childname,
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen MAILBOX_LIST_PATH_TYPE_MAILBOX,
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen &oldpath) <= 0 ||
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen mailbox_list_get_path(newlist, new_childname,
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen MAILBOX_LIST_PATH_TYPE_MAILBOX,
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen &newpath) <= 0)
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen i_unreached();
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen /* FIXME: it's possible to merge two mailboxes if either one of
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen them doesn't have existing root mailbox. We could check this
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen but I'm not sure if it's worth it. It could be even
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen considered as a feature.
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen Anyway, the bug with merging is that if both mailboxes have
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen identically named child mailbox they conflict. Just ignore
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen those and leave them under the old mailbox. */
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen if (rename(oldpath, newpath) == 0 || EDESTDIREXISTS(errno))
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen ret = 1;
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen else {
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen mailbox_list_set_critical(oldlist,
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen "rename(%s, %s) failed: %m", oldpath, newpath);
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen ret = -1;
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen break;
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen }
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen
c19f0dd4d274c15ef7b592dcc9d8c2c8c1e22abeTimo Sirainen (void)rename_dir(oldlist, old_childname, newlist, new_childname,
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen MAILBOX_LIST_PATH_TYPE_CONTROL);
c19f0dd4d274c15ef7b592dcc9d8c2c8c1e22abeTimo Sirainen (void)rename_dir(oldlist, old_childname, newlist, new_childname,
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen MAILBOX_LIST_PATH_TYPE_INDEX);
638600575ee95f2513c683ef09cb188f76eacd22Timo Sirainen (void)rename_dir(oldlist, old_childname, newlist, new_childname,
638600575ee95f2513c683ef09cb188f76eacd22Timo Sirainen MAILBOX_LIST_PATH_TYPE_INDEX_CACHE);
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen }
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen array_free(&names_arr);
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen pool_unref(&pool);
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen return ret;
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen}
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen
91b203fd2132510a47a4b34252c0ae0efd688a19Timo Sirainenstatic int
91b203fd2132510a47a4b34252c0ae0efd688a19Timo Sirainenmaildir_list_rename_mailbox(struct mailbox_list *oldlist, const char *oldname,
71e88fae3be360e9a93b3398e743f99a6f05d2edTimo Sirainen struct mailbox_list *newlist, const char *newname)
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen{
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen const char *oldpath, *newpath, *root_path;
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen int ret;
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen bool found;
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen
7fc0f80480063a9d4cb9e8c07b50db2a5627799eTimo Sirainen /* NOTE: it's possible to rename a nonexistent mailbox which has
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen children. In that case we should ignore the rename() error. */
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen if (mailbox_list_get_path(oldlist, oldname,
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen MAILBOX_LIST_PATH_TYPE_MAILBOX, &oldpath) <= 0 ||
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen mailbox_list_get_path(newlist, newname,
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen MAILBOX_LIST_PATH_TYPE_MAILBOX, &newpath) <= 0)
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen i_unreached();
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen root_path = mailbox_list_get_root_forced(oldlist,
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen 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 }
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo 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 struct mailbox_permissions old_perm, new_perm;
4b2e3b39bc79281211ba9887ab1ebc6fa21da79aTimo Sirainen
47d5cc09738defd0020c797866e2a25a344aa65aTimo Sirainen mailbox_list_get_permissions(oldlist, oldname, &old_perm);
47d5cc09738defd0020c797866e2a25a344aa65aTimo Sirainen mailbox_list_get_permissions(newlist, newname, &new_perm);
4b2e3b39bc79281211ba9887ab1ebc6fa21da79aTimo Sirainen
47d5cc09738defd0020c797866e2a25a344aa65aTimo Sirainen if ((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 }
4b2e3b39bc79281211ba9887ab1ebc6fa21da79aTimo Sirainen
4b2e3b39bc79281211ba9887ab1ebc6fa21da79aTimo Sirainen
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen ret = rename(oldpath, newpath);
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen if (ret == 0 || errno == ENOENT) {
91b203fd2132510a47a4b34252c0ae0efd688a19Timo Sirainen (void)rename_dir(oldlist, oldname, newlist, newname,
91b203fd2132510a47a4b34252c0ae0efd688a19Timo Sirainen MAILBOX_LIST_PATH_TYPE_CONTROL);
91b203fd2132510a47a4b34252c0ae0efd688a19Timo Sirainen (void)rename_dir(oldlist, oldname, newlist, newname,
91b203fd2132510a47a4b34252c0ae0efd688a19Timo Sirainen MAILBOX_LIST_PATH_TYPE_INDEX);
638600575ee95f2513c683ef09cb188f76eacd22Timo Sirainen (void)rename_dir(oldlist, oldname, newlist, newname,
638600575ee95f2513c683ef09cb188f76eacd22Timo Sirainen MAILBOX_LIST_PATH_TYPE_INDEX_CACHE);
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen found = ret == 0;
71e88fae3be360e9a93b3398e743f99a6f05d2edTimo Sirainen T_BEGIN {
91b203fd2132510a47a4b34252c0ae0efd688a19Timo Sirainen ret = maildir_rename_children(oldlist, oldname,
91b203fd2132510a47a4b34252c0ae0efd688a19Timo Sirainen newlist, newname);
19e8adccba16ff419f5675b1575358c2956dce83Timo Sirainen } T_END;
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen if (ret < 0)
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen return -1;
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen if (!found && ret == 0) {
91b203fd2132510a47a4b34252c0ae0efd688a19Timo Sirainen mailbox_list_set_error(oldlist, MAIL_ERROR_NOTFOUND,
bdb026e2dc8a7c77585ed5ba489f0056df8074d4Timo Sirainen T_MAILBOX_LIST_ERR_NOT_FOUND(oldlist, oldname));
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen return -1;
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen }
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen return 0;
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen }
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen if (EDESTDIREXISTS(errno)) {
91b203fd2132510a47a4b34252c0ae0efd688a19Timo Sirainen mailbox_list_set_error(oldlist, MAIL_ERROR_EXISTS,
ff7056842f14fd3b30a2d327dfab165b9d15dd30Timo Sirainen "Target mailbox already exists");
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen } else {
91b203fd2132510a47a4b34252c0ae0efd688a19Timo Sirainen mailbox_list_set_critical(oldlist, "rename(%s, %s) failed: %m",
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen oldpath, newpath);
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen }
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen return -1;
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen}
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainenstruct mailbox_list maildir_mailbox_list = {
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen .name = MAILBOX_LIST_NAME_MAILDIRPLUSPLUS,
3c493c276f599d9b9cd10764876d648003046954Timo Sirainen .props = MAILBOX_LIST_PROP_NO_MAILDIR_NAME |
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen MAILBOX_LIST_PROP_NO_ALT_DIR |
2a86a88fb41f4777a937dec3b2d54dedd47ed6ccTimo Sirainen MAILBOX_LIST_PROP_NO_NOSELECT |
2a86a88fb41f4777a937dec3b2d54dedd47ed6ccTimo Sirainen MAILBOX_LIST_PROP_NO_INTERNAL_NAMES,
48ca4c43ebca6fa3eee217bd4439cba5b5376dd4Timo Sirainen .mailbox_name_max_length = MAILBOX_LIST_NAME_MAX_LENGTH,
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a384b1fccb51884e8afe0f571420961851a2149dTimo Sirainen .v = {
a384b1fccb51884e8afe0f571420961851a2149dTimo Sirainen .alloc = maildir_list_alloc,
a384b1fccb51884e8afe0f571420961851a2149dTimo Sirainen .deinit = maildir_list_deinit,
a384b1fccb51884e8afe0f571420961851a2149dTimo Sirainen .get_hierarchy_sep = maildir_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 = maildir_list_get_path,
a384b1fccb51884e8afe0f571420961851a2149dTimo Sirainen .get_temp_prefix = maildir_list_get_temp_prefix,
a384b1fccb51884e8afe0f571420961851a2149dTimo Sirainen .iter_init = maildir_list_iter_init,
a384b1fccb51884e8afe0f571420961851a2149dTimo Sirainen .iter_next = maildir_list_iter_next,
a384b1fccb51884e8afe0f571420961851a2149dTimo Sirainen .iter_deinit = maildir_list_iter_deinit,
a384b1fccb51884e8afe0f571420961851a2149dTimo Sirainen .get_mailbox_flags = maildir_list_get_mailbox_flags,
a384b1fccb51884e8afe0f571420961851a2149dTimo Sirainen .subscriptions_refresh = mailbox_list_subscriptions_refresh,
a384b1fccb51884e8afe0f571420961851a2149dTimo Sirainen .set_subscribed = maildir_list_set_subscribed,
a384b1fccb51884e8afe0f571420961851a2149dTimo Sirainen .delete_mailbox = maildir_list_delete_mailbox,
a384b1fccb51884e8afe0f571420961851a2149dTimo Sirainen .delete_dir = maildir_list_delete_dir,
a384b1fccb51884e8afe0f571420961851a2149dTimo Sirainen .delete_symlink = mailbox_list_delete_symlink_default,
a384b1fccb51884e8afe0f571420961851a2149dTimo Sirainen .rename_mailbox = maildir_list_rename_mailbox,
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen }
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen};
63ca9cacc5d2d1b1cebfc430bb89637f8c138e4cTimo Sirainen
63ca9cacc5d2d1b1cebfc430bb89637f8c138e4cTimo Sirainenstruct mailbox_list imapdir_mailbox_list = {
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen .name = MAILBOX_LIST_NAME_IMAPDIR,
3c493c276f599d9b9cd10764876d648003046954Timo Sirainen .props = MAILBOX_LIST_PROP_NO_MAILDIR_NAME |
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen MAILBOX_LIST_PROP_NO_ALT_DIR |
2a86a88fb41f4777a937dec3b2d54dedd47ed6ccTimo Sirainen MAILBOX_LIST_PROP_NO_NOSELECT |
2a86a88fb41f4777a937dec3b2d54dedd47ed6ccTimo Sirainen MAILBOX_LIST_PROP_NO_INTERNAL_NAMES,
48ca4c43ebca6fa3eee217bd4439cba5b5376dd4Timo Sirainen .mailbox_name_max_length = MAILBOX_LIST_NAME_MAX_LENGTH,
63ca9cacc5d2d1b1cebfc430bb89637f8c138e4cTimo Sirainen
a384b1fccb51884e8afe0f571420961851a2149dTimo Sirainen .v = {
a384b1fccb51884e8afe0f571420961851a2149dTimo Sirainen .alloc = imapdir_list_alloc,
a384b1fccb51884e8afe0f571420961851a2149dTimo Sirainen .deinit = maildir_list_deinit,
a384b1fccb51884e8afe0f571420961851a2149dTimo Sirainen .get_hierarchy_sep = maildir_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 = maildir_list_get_path,
a384b1fccb51884e8afe0f571420961851a2149dTimo Sirainen .get_temp_prefix = maildir_list_get_temp_prefix,
a384b1fccb51884e8afe0f571420961851a2149dTimo Sirainen .iter_init = maildir_list_iter_init,
a384b1fccb51884e8afe0f571420961851a2149dTimo Sirainen .iter_next = maildir_list_iter_next,
a384b1fccb51884e8afe0f571420961851a2149dTimo Sirainen .iter_deinit = maildir_list_iter_deinit,
a384b1fccb51884e8afe0f571420961851a2149dTimo Sirainen .get_mailbox_flags = maildir_list_get_mailbox_flags,
a384b1fccb51884e8afe0f571420961851a2149dTimo Sirainen .subscriptions_refresh = mailbox_list_subscriptions_refresh,
a384b1fccb51884e8afe0f571420961851a2149dTimo Sirainen .set_subscribed = maildir_list_set_subscribed,
a384b1fccb51884e8afe0f571420961851a2149dTimo Sirainen .delete_mailbox = maildir_list_delete_mailbox,
a384b1fccb51884e8afe0f571420961851a2149dTimo Sirainen .delete_dir = maildir_list_delete_dir,
a384b1fccb51884e8afe0f571420961851a2149dTimo Sirainen .delete_symlink = mailbox_list_delete_symlink_default,
a384b1fccb51884e8afe0f571420961851a2149dTimo Sirainen .rename_mailbox = maildir_list_rename_mailbox,
63ca9cacc5d2d1b1cebfc430bb89637f8c138e4cTimo Sirainen }
63ca9cacc5d2d1b1cebfc430bb89637f8c138e4cTimo Sirainen};