mailbox-list-maildir.c revision 0e5f8c4589cfeccb752307c8ac35a2f1633e4eca
76b43e4417bab52e913da39b5f5bc2a130d3f149Timo Sirainen/* Copyright (c) 2006-2008 Dovecot authors, see the included COPYING file */
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen#include "lib.h"
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen#include "array.h"
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen#include "hostpid.h"
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen#include "home-expand.h"
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen#include "subscription-file.h"
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen#include "mailbox-list-maildir.h"
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen#include <stdio.h>
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen#include <sys/stat.h>
c040ee67d0ac0fb7375bb543965bf67dcae6affaTimo Sirainen
c040ee67d0ac0fb7375bb543965bf67dcae6affaTimo Sirainen#define MAILDIR_GLOBAL_TEMP_PREFIX "temp."
c040ee67d0ac0fb7375bb543965bf67dcae6affaTimo Sirainen#define IMAPDIR_GLOBAL_TEMP_PREFIX ".temp."
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
63ca9cacc5d2d1b1cebfc430bb89637f8c138e4cTimo Sirainenextern struct mailbox_list maildir_mailbox_list;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo 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;
b5a084602a3dc2c118345f6d2990f47c1ff66264Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen pool = pool_alloconly_create("maildir++ list", 1024);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen list = p_new(pool, struct maildir_mailbox_list, 1);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen list->list = maildir_mailbox_list;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen list->list.pool = pool;
c040ee67d0ac0fb7375bb543965bf67dcae6affaTimo Sirainen
c040ee67d0ac0fb7375bb543965bf67dcae6affaTimo Sirainen list->global_temp_prefix = MAILDIR_GLOBAL_TEMP_PREFIX;
c040ee67d0ac0fb7375bb543965bf67dcae6affaTimo Sirainen list->temp_prefix = p_strconcat(pool, list->global_temp_prefix,
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen my_hostname, ".", my_pid, ".", NULL);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen return &list->list;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen}
63ca9cacc5d2d1b1cebfc430bb89637f8c138e4cTimo 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;
c040ee67d0ac0fb7375bb543965bf67dcae6affaTimo Sirainen
c040ee67d0ac0fb7375bb543965bf67dcae6affaTimo Sirainen list->global_temp_prefix = IMAPDIR_GLOBAL_TEMP_PREFIX;
c040ee67d0ac0fb7375bb543965bf67dcae6affaTimo Sirainen list->temp_prefix = p_strconcat(pool, list->global_temp_prefix,
63ca9cacc5d2d1b1cebfc430bb89637f8c138e4cTimo Sirainen my_hostname, ".", my_pid, ".", NULL);
63ca9cacc5d2d1b1cebfc430bb89637f8c138e4cTimo Sirainen return &list->list;
63ca9cacc5d2d1b1cebfc430bb89637f8c138e4cTimo Sirainen}
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo 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;
648d24583c1574441c4fa0331a90bd4d6e7996c5Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen pool_unref(&list->list.pool);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen}
63ca9cacc5d2d1b1cebfc430bb89637f8c138e4cTimo 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{
63ca9cacc5d2d1b1cebfc430bb89637f8c138e4cTimo Sirainen if (strcmp(list->name, MAILBOX_LIST_NAME_IMAPDIR) == 0)
63ca9cacc5d2d1b1cebfc430bb89637f8c138e4cTimo Sirainen return t_strdup_printf("%s/%s", dir, name);
63ca9cacc5d2d1b1cebfc430bb89637f8c138e4cTimo Sirainen
63ca9cacc5d2d1b1cebfc430bb89637f8c138e4cTimo Sirainen return t_strdup_printf("%s/%c%s", dir, list->hierarchy_sep, name);
63ca9cacc5d2d1b1cebfc430bb89637f8c138e4cTimo Sirainen}
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo 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;
96f2533c48ce5def0004931606a2fdf275578880Timo Sirainen
83c21c990eb2a370f0da56240e73dac846f4acc3Timo Sirainen if (home_try_expand(&name) < 0) {
83c21c990eb2a370f0da56240e73dac846f4acc3Timo Sirainen /* fallback to using as ~name */
83c21c990eb2a370f0da56240e73dac846f4acc3Timo Sirainen return name;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen }
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen p = strrchr(name, '/');
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen if (p == NULL)
63ca9cacc5d2d1b1cebfc430bb89637f8c138e4cTimo Sirainen return name;
63ca9cacc5d2d1b1cebfc430bb89637f8c138e4cTimo Sirainen return maildir_list_get_dirname_path(list, t_strdup_until(name, p),
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen p+1);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen}
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainenstatic bool
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainenmaildir_list_is_valid_common(struct mailbox_list *list, const char *name,
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen size_t *len_r)
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen{
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen size_t len;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen /* check that there are no adjacent hierarchy separators */
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen for (len = 0; name[len] != '\0'; len++) {
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen if (name[len] == list->hierarchy_sep &&
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen name[len+1] == list->hierarchy_sep)
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen return FALSE;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen }
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen if (len == 0 || name[len-1] == '/')
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen return FALSE;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen if (name[0] == list->hierarchy_sep ||
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen name[len-1] == list->hierarchy_sep)
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen return FALSE;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen *len_r = len;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen return TRUE;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen}
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainenstatic bool maildir_list_is_valid_common_nonfs(const char *name)
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen{
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen if (*name == '~' || strchr(name, '/') != NULL)
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen return FALSE;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen if (name[0] == '.' && (name[1] == '\0' ||
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen (name[1] == '.' && name[2] == '\0'))) {
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen /* "." and ".." aren't allowed. */
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen return FALSE;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen }
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen return TRUE;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen}
43d32cbe60fdaef2699d99f1ca259053e9350411Timo Sirainen
43d32cbe60fdaef2699d99f1ca259053e9350411Timo Sirainenstatic bool ATTR_NORETURN
43d32cbe60fdaef2699d99f1ca259053e9350411Timo Sirainenmaildir_is_valid_pattern(struct mailbox_list *list ATTR_UNUSED,
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen const char *pattern ATTR_UNUSED)
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen{
43d32cbe60fdaef2699d99f1ca259053e9350411Timo Sirainen i_unreached();
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen#ifndef ATTRS_DEFINED
65b7beb7cefce89e175920ef6c16118b1b0dbfb3Timo Sirainen return FALSE;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen#endif
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen}
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainenstatic bool
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainenmaildir_is_valid_existing_name(struct mailbox_list *list, const char *name)
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen{
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen size_t len;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen if (!maildir_list_is_valid_common(list, name, &len))
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen return FALSE;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen if ((list->flags & MAILBOX_LIST_FLAG_FULL_FS_ACCESS) != 0)
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen return TRUE;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen return maildir_list_is_valid_common_nonfs(name);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen}
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainenstatic bool
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainenmaildir_is_valid_create_name(struct mailbox_list *list, const char *name)
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen{
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen size_t len;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen if (!maildir_list_is_valid_common(list, name, &len))
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen return FALSE;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen if (len > MAILDIR_MAX_CREATE_MAILBOX_NAME_LENGTH)
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen return FALSE;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen if ((list->flags & MAILBOX_LIST_FLAG_FULL_FS_ACCESS) != 0)
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen return TRUE;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen if (!maildir_list_is_valid_common_nonfs(name))
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen return FALSE;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen if (mailbox_list_name_is_too_large(name, list->hierarchy_sep))
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen return FALSE;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen return TRUE;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen}
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainenstatic const char *
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainenmaildir_list_get_path(struct mailbox_list *_list, const char *name,
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen enum mailbox_list_path_type type)
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen{
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen struct maildir_mailbox_list *list =
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen (struct maildir_mailbox_list *)_list;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen if (name == NULL) {
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen /* return root directories */
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen switch (type) {
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen case MAILBOX_LIST_PATH_TYPE_DIR:
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen case MAILBOX_LIST_PATH_TYPE_MAILBOX:
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen return _list->set.root_dir;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen case MAILBOX_LIST_PATH_TYPE_CONTROL:
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen return _list->set.control_dir != NULL ?
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen _list->set.control_dir : _list->set.root_dir;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen case MAILBOX_LIST_PATH_TYPE_INDEX:
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen return _list->set.index_dir != NULL ?
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen _list->set.index_dir : _list->set.root_dir;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen }
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen i_unreached();
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen }
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen if ((list->list.flags & MAILBOX_LIST_FLAG_FULL_FS_ACCESS) != 0 &&
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen (*name == '/' || *name == '~'))
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen return maildir_list_get_absolute_path(_list, name);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen switch (type) {
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen case MAILBOX_LIST_PATH_TYPE_DIR:
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen case MAILBOX_LIST_PATH_TYPE_MAILBOX:
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen break;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen case MAILBOX_LIST_PATH_TYPE_CONTROL:
63ca9cacc5d2d1b1cebfc430bb89637f8c138e4cTimo Sirainen if (_list->set.control_dir != NULL) {
63ca9cacc5d2d1b1cebfc430bb89637f8c138e4cTimo Sirainen return maildir_list_get_dirname_path(_list,
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen _list->set.control_dir, name);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen }
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen break;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen case MAILBOX_LIST_PATH_TYPE_INDEX:
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen if (_list->set.index_dir != NULL) {
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen if (*_list->set.index_dir == '\0')
63ca9cacc5d2d1b1cebfc430bb89637f8c138e4cTimo Sirainen return "";
63ca9cacc5d2d1b1cebfc430bb89637f8c138e4cTimo Sirainen return maildir_list_get_dirname_path(_list,
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen _list->set.index_dir, name);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen }
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen break;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen }
1d266a7419fafa25f3505a12217452a8c647074fTimo Sirainen
1d266a7419fafa25f3505a12217452a8c647074fTimo Sirainen if (strcmp(name, "INBOX") == 0 && _list->set.inbox_path != NULL)
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen return _list->set.inbox_path;
63ca9cacc5d2d1b1cebfc430bb89637f8c138e4cTimo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen return maildir_list_get_dirname_path(_list, _list->set.root_dir, name);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen}
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainenstatic int
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainenmaildir_list_get_mailbox_name_status(struct mailbox_list *_list,
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen const char *name,
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen enum mailbox_name_status *status)
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen{
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen struct stat st;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen const char *path;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen path = mailbox_list_get_path(_list, name,
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen MAILBOX_LIST_PATH_TYPE_MAILBOX);
1d266a7419fafa25f3505a12217452a8c647074fTimo Sirainen
1d266a7419fafa25f3505a12217452a8c647074fTimo Sirainen if ((strcmp(name, "INBOX") == 0 &&
1d266a7419fafa25f3505a12217452a8c647074fTimo Sirainen (_list->ns->flags & NAMESPACE_FLAG_INBOX) != 0) ||
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen stat(path, &st) == 0) {
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen *status = MAILBOX_NAME_EXISTS;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen return 0;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen }
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen if (!mailbox_list_is_valid_create_name(_list, name)) {
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen *status = MAILBOX_NAME_INVALID;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen return 0;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen }
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen if (ENOTFOUND(errno) || errno == EACCES) {
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen *status = MAILBOX_NAME_VALID;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen return 0;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen } else {
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen mailbox_list_set_critical(_list, "stat(%s) failed: %m", path);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen return -1;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen }
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen}
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
c040ee67d0ac0fb7375bb543965bf67dcae6affaTimo Sirainenstatic const char *
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo 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;
c040ee67d0ac0fb7375bb543965bf67dcae6affaTimo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo 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
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}
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainenstatic int rename_dir(struct mailbox_list *list,
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen enum mailbox_list_path_type type,
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen const char *oldname, const char *newname)
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen{
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen const char *oldpath, *newpath;
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen oldpath = mailbox_list_get_path(list, oldname, type);
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen newpath = mailbox_list_get_path(list, newname, type);
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen if (strcmp(oldpath, newpath) == 0)
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen return 0;
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen if (rename(oldpath, newpath) < 0 && errno != ENOENT) {
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen mailbox_list_set_critical(list, "rename(%s, %s) failed: %m",
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen oldpath, newpath);
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen return -1;
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen }
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen return 0;
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen}
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainenstatic int rename_children(struct mailbox_list *list,
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen const char *oldname, const char *newname)
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen{
61e84692827b6a64912343f515c984853021483aTimo Sirainen struct mailbox_list_iterate_context *iter;
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen const struct mailbox_info *info;
533bfba437e4120aa29dd45bca2aa87e30ee28a2Timo Sirainen ARRAY_DEFINE(names_arr, const char *);
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen const char *pattern, *oldpath, *newpath, *old_listname, *new_listname;
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen const char *const *names;
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen unsigned int i, count;
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen size_t oldnamelen;
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen pool_t pool;
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen int ret;
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen ret = 0;
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen oldnamelen = strlen(oldname);
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen /* first get the list of the children and save them to memory, because
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen we can't rely on readdir() not skipping files while the directory
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen is being modified. this doesn't protect against modifications by
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen other processes though. */
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen pool = pool_alloconly_create("Maildir++ children list", 1024);
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen i_array_init(&names_arr, 64);
533bfba437e4120aa29dd45bca2aa87e30ee28a2Timo Sirainen
533bfba437e4120aa29dd45bca2aa87e30ee28a2Timo Sirainen pattern = t_strdup_printf("%s%c*", oldname,
533bfba437e4120aa29dd45bca2aa87e30ee28a2Timo Sirainen mailbox_list_get_hierarchy_sep(list));
18ffea71d9beeec3cc1d400f751926ee72807f62Timo Sirainen iter = mailbox_list_iter_init(list, pattern,
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen MAILBOX_LIST_ITER_RETURN_NO_FLAGS);
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen while ((info = mailbox_list_iter_next(iter)) != NULL) {
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen const char *name;
33f002135617b5b34577433b30c32560bd4b5e3cTimo Sirainen
33f002135617b5b34577433b30c32560bd4b5e3cTimo Sirainen /* verify that the prefix matches, otherwise we could have
33f002135617b5b34577433b30c32560bd4b5e3cTimo Sirainen problems with mailbox names containing '%' and '*' chars */
33f002135617b5b34577433b30c32560bd4b5e3cTimo Sirainen if (strncmp(info->name, oldname, oldnamelen) == 0 &&
33f002135617b5b34577433b30c32560bd4b5e3cTimo Sirainen info->name[oldnamelen] ==
33f002135617b5b34577433b30c32560bd4b5e3cTimo Sirainen mailbox_list_get_hierarchy_sep(list)) {
33f002135617b5b34577433b30c32560bd4b5e3cTimo Sirainen name = p_strdup(pool, info->name + oldnamelen);
33f002135617b5b34577433b30c32560bd4b5e3cTimo Sirainen array_append(&names_arr, &name, 1);
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen }
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen }
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen if (mailbox_list_iter_deinit(&iter) < 0) {
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen ret = -1;
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen names = NULL; count = 0;
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen } else {
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen names = array_get(&names_arr, &count);
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen }
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen for (i = 0; i < count; i++) {
738cb8e908b144d6dd6f6d7484a40ad67054aac5Timo Sirainen old_listname = t_strconcat(oldname, names[i], NULL);
738cb8e908b144d6dd6f6d7484a40ad67054aac5Timo Sirainen if (strcmp(old_listname, newname) == 0) {
738cb8e908b144d6dd6f6d7484a40ad67054aac5Timo Sirainen /* When doing RENAME "a" "a.b" we see "a.b" here.
738cb8e908b144d6dd6f6d7484a40ad67054aac5Timo Sirainen We don't want to rename it anymore to "a.b.b". */
738cb8e908b144d6dd6f6d7484a40ad67054aac5Timo Sirainen continue;
738cb8e908b144d6dd6f6d7484a40ad67054aac5Timo Sirainen }
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen new_listname = t_strconcat(newname, names[i], NULL);
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen oldpath = mailbox_list_get_path(list, old_listname,
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen MAILBOX_LIST_PATH_TYPE_MAILBOX);
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen newpath = mailbox_list_get_path(list, new_listname,
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen MAILBOX_LIST_PATH_TYPE_MAILBOX);
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen /* FIXME: it's possible to merge two mailboxes if either one of
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen them doesn't have existing root mailbox. We could check this
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen but I'm not sure if it's worth it. It could be even
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen considered as a feature.
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen Anyway, the bug with merging is that if both mailboxes have
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen identically named child mailbox they conflict. Just ignore
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen those and leave them under the old mailbox. */
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen if (rename(oldpath, newpath) == 0 || EDESTDIREXISTS(errno))
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen ret = 1;
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen else {
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen mailbox_list_set_critical(list,
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen "rename(%s, %s) failed: %m", oldpath, newpath);
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen ret = -1;
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen break;
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen }
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen (void)rename_dir(list, MAILBOX_LIST_PATH_TYPE_CONTROL,
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen old_listname, new_listname);
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen (void)rename_dir(list, MAILBOX_LIST_PATH_TYPE_INDEX,
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen old_listname, new_listname);
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen }
648d24583c1574441c4fa0331a90bd4d6e7996c5Timo Sirainen array_free(&names_arr);
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen pool_unref(&pool);
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen return ret;
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen}
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainenstatic int
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainenmaildir_list_delete_mailbox(struct mailbox_list *list, const char *name)
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen{
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen /* let the backend handle the rest */
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen return mailbox_list_delete_index_control(list, name);
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen}
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainenstatic int maildir_list_rename_mailbox(struct mailbox_list *list,
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen const char *oldname, const char *newname)
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen{
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen const char *oldpath, *newpath;
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen int ret;
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen bool found;
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen /* NOTE: it's possible to rename a nonexisting mailbox which has
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen children. In that case we should ignore the rename() error. */
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen oldpath = mailbox_list_get_path(list, oldname,
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen MAILBOX_LIST_PATH_TYPE_MAILBOX);
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen newpath = mailbox_list_get_path(list, newname,
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen MAILBOX_LIST_PATH_TYPE_MAILBOX);
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen ret = rename(oldpath, newpath);
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen if (ret == 0 || errno == ENOENT) {
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen (void)rename_dir(list, MAILBOX_LIST_PATH_TYPE_CONTROL,
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen oldname, newname);
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen (void)rename_dir(list, MAILBOX_LIST_PATH_TYPE_INDEX,
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen oldname, newname);
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen
19e8adccba16ff419f5675b1575358c2956dce83Timo Sirainen found = ret == 0;
eddd9bf1a1369aea4a2715f6be1137da6d17d293Timo Sirainen T_BEGIN {
19e8adccba16ff419f5675b1575358c2956dce83Timo Sirainen ret = rename_children(list, oldname, newname);
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen } T_END;
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen if (ret < 0)
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen return -1;
ff7056842f14fd3b30a2d327dfab165b9d15dd30Timo Sirainen if (!found && ret == 0) {
ff7056842f14fd3b30a2d327dfab165b9d15dd30Timo Sirainen mailbox_list_set_error(list, MAIL_ERROR_NOTFOUND,
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen T_MAIL_ERR_MAILBOX_NOT_FOUND(oldname));
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen return -1;
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen }
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen return 0;
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen }
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen
ff7056842f14fd3b30a2d327dfab165b9d15dd30Timo Sirainen if (EDESTDIREXISTS(errno)) {
ff7056842f14fd3b30a2d327dfab165b9d15dd30Timo Sirainen mailbox_list_set_error(list, MAIL_ERROR_NOTPOSSIBLE,
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen "Target mailbox already exists");
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen } else {
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen mailbox_list_set_critical(list, "rename(%s, %s) failed: %m",
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen oldpath, newpath);
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen }
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen return -1;
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen}
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
63ca9cacc5d2d1b1cebfc430bb89637f8c138e4cTimo Sirainenstruct mailbox_list maildir_mailbox_list = {
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen MEMBER(name) MAILBOX_LIST_NAME_MAILDIRPLUSPLUS,
bbd0a870f8639767e4e4011d2aedadac08d5c66fTimo Sirainen MEMBER(hierarchy_sep) '.',
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen MEMBER(mailbox_name_max_length) PATH_MAX,
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen {
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen maildir_list_alloc,
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen maildir_list_deinit,
533bfba437e4120aa29dd45bca2aa87e30ee28a2Timo Sirainen maildir_is_valid_pattern,
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen maildir_is_valid_existing_name,
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen maildir_is_valid_create_name,
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen maildir_list_get_path,
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen maildir_list_get_mailbox_name_status,
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen maildir_list_get_temp_prefix,
5160580b0ec3f3288a320987abdf12a990f09df5Timo Sirainen NULL,
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen maildir_list_iter_init,
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen maildir_list_iter_next,
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen maildir_list_iter_deinit,
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen NULL,
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen maildir_list_set_subscribed,
b039dabf4c53f72454e795930e7643b6e0e625f9Timo Sirainen maildir_list_delete_mailbox,
0e5f8c4589cfeccb752307c8ac35a2f1633e4ecaTimo Sirainen maildir_list_rename_mailbox,
0e5f8c4589cfeccb752307c8ac35a2f1633e4ecaTimo Sirainen NULL
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen }
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen};
63ca9cacc5d2d1b1cebfc430bb89637f8c138e4cTimo Sirainen
63ca9cacc5d2d1b1cebfc430bb89637f8c138e4cTimo Sirainenstruct mailbox_list imapdir_mailbox_list = {
63ca9cacc5d2d1b1cebfc430bb89637f8c138e4cTimo Sirainen MEMBER(name) MAILBOX_LIST_NAME_IMAPDIR,
63ca9cacc5d2d1b1cebfc430bb89637f8c138e4cTimo Sirainen MEMBER(hierarchy_sep) '.',
bbd0a870f8639767e4e4011d2aedadac08d5c66fTimo Sirainen MEMBER(mailbox_name_max_length) PATH_MAX,
63ca9cacc5d2d1b1cebfc430bb89637f8c138e4cTimo Sirainen
63ca9cacc5d2d1b1cebfc430bb89637f8c138e4cTimo Sirainen {
63ca9cacc5d2d1b1cebfc430bb89637f8c138e4cTimo Sirainen imapdir_list_alloc,
63ca9cacc5d2d1b1cebfc430bb89637f8c138e4cTimo Sirainen maildir_list_deinit,
63ca9cacc5d2d1b1cebfc430bb89637f8c138e4cTimo Sirainen maildir_is_valid_pattern,
63ca9cacc5d2d1b1cebfc430bb89637f8c138e4cTimo Sirainen maildir_is_valid_existing_name,
63ca9cacc5d2d1b1cebfc430bb89637f8c138e4cTimo Sirainen maildir_is_valid_create_name,
63ca9cacc5d2d1b1cebfc430bb89637f8c138e4cTimo Sirainen maildir_list_get_path,
63ca9cacc5d2d1b1cebfc430bb89637f8c138e4cTimo Sirainen maildir_list_get_mailbox_name_status,
63ca9cacc5d2d1b1cebfc430bb89637f8c138e4cTimo Sirainen maildir_list_get_temp_prefix,
63ca9cacc5d2d1b1cebfc430bb89637f8c138e4cTimo Sirainen NULL,
63ca9cacc5d2d1b1cebfc430bb89637f8c138e4cTimo Sirainen maildir_list_iter_init,
63ca9cacc5d2d1b1cebfc430bb89637f8c138e4cTimo Sirainen maildir_list_iter_next,
63ca9cacc5d2d1b1cebfc430bb89637f8c138e4cTimo Sirainen maildir_list_iter_deinit,
63ca9cacc5d2d1b1cebfc430bb89637f8c138e4cTimo Sirainen NULL,
63ca9cacc5d2d1b1cebfc430bb89637f8c138e4cTimo Sirainen maildir_list_set_subscribed,
63ca9cacc5d2d1b1cebfc430bb89637f8c138e4cTimo Sirainen maildir_list_delete_mailbox,
63ca9cacc5d2d1b1cebfc430bb89637f8c138e4cTimo Sirainen maildir_list_rename_mailbox,
0e5f8c4589cfeccb752307c8ac35a2f1633e4ecaTimo Sirainen NULL
0e5f8c4589cfeccb752307c8ac35a2f1633e4ecaTimo Sirainen }
63ca9cacc5d2d1b1cebfc430bb89637f8c138e4cTimo Sirainen};
63ca9cacc5d2d1b1cebfc430bb89637f8c138e4cTimo Sirainen