mailbox-list-maildir.c revision 441f0e0d84082eb498e620327ebf4de509052d15
5f5870385cff47efd2f58e7892f251cf13761528Timo Sirainen/* Copyright (c) 2006-2015 Dovecot authors, see the included COPYING file */
c664d0da658c8d3200d88ea3c4cd580afd33fa73Timo Sirainen
c664d0da658c8d3200d88ea3c4cd580afd33fa73Timo Sirainen#include "lib.h"
134582c78f038b4d9b9fde127399aefa50935a53Timo Sirainen#include "array.h"
c664d0da658c8d3200d88ea3c4cd580afd33fa73Timo Sirainen#include "hostpid.h"
c664d0da658c8d3200d88ea3c4cd580afd33fa73Timo Sirainen#include "eacces-error.h"
c664d0da658c8d3200d88ea3c4cd580afd33fa73Timo Sirainen#include "mkdir-parents.h"
c664d0da658c8d3200d88ea3c4cd580afd33fa73Timo Sirainen#include "str.h"
c664d0da658c8d3200d88ea3c4cd580afd33fa73Timo Sirainen#include "subscription-file.h"
c664d0da658c8d3200d88ea3c4cd580afd33fa73Timo Sirainen#include "mailbox-list-subscriptions.h"
134582c78f038b4d9b9fde127399aefa50935a53Timo Sirainen#include "mailbox-list-delete.h"
134582c78f038b4d9b9fde127399aefa50935a53Timo Sirainen#include "mailbox-list-maildir.h"
134582c78f038b4d9b9fde127399aefa50935a53Timo Sirainen
134582c78f038b4d9b9fde127399aefa50935a53Timo Sirainen#include <stdio.h>
134582c78f038b4d9b9fde127399aefa50935a53Timo Sirainen#include <sys/stat.h>
134582c78f038b4d9b9fde127399aefa50935a53Timo Sirainen
c664d0da658c8d3200d88ea3c4cd580afd33fa73Timo Sirainen#define MAILDIR_GLOBAL_TEMP_PREFIX "temp."
c664d0da658c8d3200d88ea3c4cd580afd33fa73Timo Sirainen#define IMAPDIR_GLOBAL_TEMP_PREFIX ".temp."
c664d0da658c8d3200d88ea3c4cd580afd33fa73Timo Sirainen
c664d0da658c8d3200d88ea3c4cd580afd33fa73Timo Sirainenextern struct mailbox_list maildir_mailbox_list;
134582c78f038b4d9b9fde127399aefa50935a53Timo Sirainenextern struct mailbox_list imapdir_mailbox_list;
c664d0da658c8d3200d88ea3c4cd580afd33fa73Timo Sirainen
134582c78f038b4d9b9fde127399aefa50935a53Timo Sirainenstatic struct mailbox_list *maildir_list_alloc(void)
134582c78f038b4d9b9fde127399aefa50935a53Timo Sirainen{
134582c78f038b4d9b9fde127399aefa50935a53Timo Sirainen struct maildir_mailbox_list *list;
c664d0da658c8d3200d88ea3c4cd580afd33fa73Timo Sirainen pool_t pool;
c664d0da658c8d3200d88ea3c4cd580afd33fa73Timo Sirainen
c664d0da658c8d3200d88ea3c4cd580afd33fa73Timo Sirainen pool = pool_alloconly_create("maildir++ list", 2048);
c664d0da658c8d3200d88ea3c4cd580afd33fa73Timo Sirainen list = p_new(pool, struct maildir_mailbox_list, 1);
c664d0da658c8d3200d88ea3c4cd580afd33fa73Timo Sirainen list->list = maildir_mailbox_list;
c664d0da658c8d3200d88ea3c4cd580afd33fa73Timo Sirainen list->list.pool = pool;
c664d0da658c8d3200d88ea3c4cd580afd33fa73Timo Sirainen list->sep = '.';
134582c78f038b4d9b9fde127399aefa50935a53Timo Sirainen
c664d0da658c8d3200d88ea3c4cd580afd33fa73Timo Sirainen list->global_temp_prefix = MAILDIR_GLOBAL_TEMP_PREFIX;
134582c78f038b4d9b9fde127399aefa50935a53Timo Sirainen list->temp_prefix = p_strconcat(pool, list->global_temp_prefix,
134582c78f038b4d9b9fde127399aefa50935a53Timo Sirainen my_hostname, ".", my_pid, ".", NULL);
134582c78f038b4d9b9fde127399aefa50935a53Timo Sirainen return &list->list;
c664d0da658c8d3200d88ea3c4cd580afd33fa73Timo Sirainen}
c664d0da658c8d3200d88ea3c4cd580afd33fa73Timo Sirainen
c664d0da658c8d3200d88ea3c4cd580afd33fa73Timo Sirainenstatic struct mailbox_list *imapdir_list_alloc(void)
c664d0da658c8d3200d88ea3c4cd580afd33fa73Timo Sirainen{
c664d0da658c8d3200d88ea3c4cd580afd33fa73Timo Sirainen struct maildir_mailbox_list *list;
c664d0da658c8d3200d88ea3c4cd580afd33fa73Timo Sirainen pool_t pool;
c664d0da658c8d3200d88ea3c4cd580afd33fa73Timo Sirainen
c664d0da658c8d3200d88ea3c4cd580afd33fa73Timo Sirainen pool = pool_alloconly_create("imapdir list", 1024);
c664d0da658c8d3200d88ea3c4cd580afd33fa73Timo Sirainen list = p_new(pool, struct maildir_mailbox_list, 1);
c664d0da658c8d3200d88ea3c4cd580afd33fa73Timo Sirainen list->list = imapdir_mailbox_list;
c664d0da658c8d3200d88ea3c4cd580afd33fa73Timo Sirainen list->list.pool = pool;
c664d0da658c8d3200d88ea3c4cd580afd33fa73Timo Sirainen list->sep = '.';
c664d0da658c8d3200d88ea3c4cd580afd33fa73Timo Sirainen
c664d0da658c8d3200d88ea3c4cd580afd33fa73Timo Sirainen list->global_temp_prefix = IMAPDIR_GLOBAL_TEMP_PREFIX;
c664d0da658c8d3200d88ea3c4cd580afd33fa73Timo Sirainen list->temp_prefix = p_strconcat(pool, list->global_temp_prefix,
c664d0da658c8d3200d88ea3c4cd580afd33fa73Timo Sirainen my_hostname, ".", my_pid, ".", NULL);
c664d0da658c8d3200d88ea3c4cd580afd33fa73Timo Sirainen return &list->list;
c664d0da658c8d3200d88ea3c4cd580afd33fa73Timo Sirainen}
c664d0da658c8d3200d88ea3c4cd580afd33fa73Timo Sirainen
c664d0da658c8d3200d88ea3c4cd580afd33fa73Timo Sirainenstatic void maildir_list_deinit(struct mailbox_list *_list)
c664d0da658c8d3200d88ea3c4cd580afd33fa73Timo Sirainen{
c664d0da658c8d3200d88ea3c4cd580afd33fa73Timo Sirainen struct maildir_mailbox_list *list =
c664d0da658c8d3200d88ea3c4cd580afd33fa73Timo Sirainen (struct maildir_mailbox_list *)_list;
c664d0da658c8d3200d88ea3c4cd580afd33fa73Timo Sirainen
c664d0da658c8d3200d88ea3c4cd580afd33fa73Timo Sirainen pool_unref(&list->list.pool);
c664d0da658c8d3200d88ea3c4cd580afd33fa73Timo Sirainen}
c664d0da658c8d3200d88ea3c4cd580afd33fa73Timo Sirainen
c664d0da658c8d3200d88ea3c4cd580afd33fa73Timo Sirainenstatic const char *
4f77d2f0f0743ad09d2a34e18be8eacf8014b7e0Pascal Volkmaildir_list_get_dirname_path(struct mailbox_list *list, const char *dir,
4f77d2f0f0743ad09d2a34e18be8eacf8014b7e0Pascal Volk const char *name)
5fbccc935e3f7b916aa7c6e302a212821072e83aTimo Sirainen{
4f77d2f0f0743ad09d2a34e18be8eacf8014b7e0Pascal Volk if (*name == '\0')
5fbccc935e3f7b916aa7c6e302a212821072e83aTimo Sirainen return dir;
5fbccc935e3f7b916aa7c6e302a212821072e83aTimo Sirainen else if (list->name == imapdir_mailbox_list.name)
5fbccc935e3f7b916aa7c6e302a212821072e83aTimo Sirainen return t_strdup_printf("%s/%s", dir, name);
c664d0da658c8d3200d88ea3c4cd580afd33fa73Timo Sirainen
c664d0da658c8d3200d88ea3c4cd580afd33fa73Timo Sirainen return t_strdup_printf("%s/%c%s", dir,
c664d0da658c8d3200d88ea3c4cd580afd33fa73Timo Sirainen mailbox_list_get_hierarchy_sep(list), name);
c664d0da658c8d3200d88ea3c4cd580afd33fa73Timo Sirainen}
c664d0da658c8d3200d88ea3c4cd580afd33fa73Timo Sirainen
c664d0da658c8d3200d88ea3c4cd580afd33fa73Timo Sirainenstatic const char *
c664d0da658c8d3200d88ea3c4cd580afd33fa73Timo Sirainenmaildir_list_get_absolute_path(struct mailbox_list *list, const char *name)
c664d0da658c8d3200d88ea3c4cd580afd33fa73Timo Sirainen{
bde78a7bf5f9000f1ae4dc7ce6cabd012e1f8b79Pascal Volk const char *p;
c664d0da658c8d3200d88ea3c4cd580afd33fa73Timo Sirainen
134582c78f038b4d9b9fde127399aefa50935a53Timo Sirainen if (!mailbox_list_try_get_absolute_path(list, &name)) {
134582c78f038b4d9b9fde127399aefa50935a53Timo Sirainen /* fallback to using as ~name */
f05f569c2ee0d1f5216614856ff0ae7bd60f27faTimo Sirainen return name;
134582c78f038b4d9b9fde127399aefa50935a53Timo Sirainen }
134582c78f038b4d9b9fde127399aefa50935a53Timo Sirainen
134582c78f038b4d9b9fde127399aefa50935a53Timo Sirainen p = strrchr(name, '/');
134582c78f038b4d9b9fde127399aefa50935a53Timo Sirainen if (p == NULL)
134582c78f038b4d9b9fde127399aefa50935a53Timo Sirainen return name;
134582c78f038b4d9b9fde127399aefa50935a53Timo Sirainen return maildir_list_get_dirname_path(list, t_strdup_until(name, p),
4f77d2f0f0743ad09d2a34e18be8eacf8014b7e0Pascal Volk p+1);
4f77d2f0f0743ad09d2a34e18be8eacf8014b7e0Pascal Volk}
4f77d2f0f0743ad09d2a34e18be8eacf8014b7e0Pascal Volk
4f77d2f0f0743ad09d2a34e18be8eacf8014b7e0Pascal Volkstatic char maildir_list_get_hierarchy_sep(struct mailbox_list *_list)
4f77d2f0f0743ad09d2a34e18be8eacf8014b7e0Pascal Volk{
4f77d2f0f0743ad09d2a34e18be8eacf8014b7e0Pascal Volk struct maildir_mailbox_list *list =
4f77d2f0f0743ad09d2a34e18be8eacf8014b7e0Pascal Volk (struct maildir_mailbox_list *)_list;
4f77d2f0f0743ad09d2a34e18be8eacf8014b7e0Pascal Volk
4f77d2f0f0743ad09d2a34e18be8eacf8014b7e0Pascal Volk return list->sep;
4f77d2f0f0743ad09d2a34e18be8eacf8014b7e0Pascal Volk}
134582c78f038b4d9b9fde127399aefa50935a53Timo Sirainen
134582c78f038b4d9b9fde127399aefa50935a53Timo Sirainenstatic int
134582c78f038b4d9b9fde127399aefa50935a53Timo Sirainenmaildir_list_get_path(struct mailbox_list *_list, const char *name,
134582c78f038b4d9b9fde127399aefa50935a53Timo Sirainen enum mailbox_list_path_type type, const char **path_r)
134582c78f038b4d9b9fde127399aefa50935a53Timo Sirainen{
134582c78f038b4d9b9fde127399aefa50935a53Timo Sirainen const char *root_dir;
134582c78f038b4d9b9fde127399aefa50935a53Timo Sirainen
134582c78f038b4d9b9fde127399aefa50935a53Timo Sirainen if (name == NULL) {
134582c78f038b4d9b9fde127399aefa50935a53Timo Sirainen /* return root directories */
134582c78f038b4d9b9fde127399aefa50935a53Timo Sirainen return mailbox_list_set_get_root_path(&_list->set, type,
134582c78f038b4d9b9fde127399aefa50935a53Timo Sirainen path_r) ? 1 : 0;
134582c78f038b4d9b9fde127399aefa50935a53Timo Sirainen }
134582c78f038b4d9b9fde127399aefa50935a53Timo Sirainen
if (_list->mail_set->mail_full_filesystem_access &&
(*name == '/' || *name == '~')) {
*path_r = maildir_list_get_absolute_path(_list, name);
return 1;
}
root_dir = _list->set.root_dir;
switch (type) {
case MAILBOX_LIST_PATH_TYPE_DIR:
case MAILBOX_LIST_PATH_TYPE_MAILBOX:
break;
case MAILBOX_LIST_PATH_TYPE_ALT_DIR:
case MAILBOX_LIST_PATH_TYPE_ALT_MAILBOX:
if (_list->set.alt_dir == NULL)
return 0;
root_dir = _list->set.alt_dir;
break;
case MAILBOX_LIST_PATH_TYPE_CONTROL:
if (_list->set.control_dir != NULL) {
*path_r = maildir_list_get_dirname_path(_list,
_list->set.control_dir, name);
return 1;
}
break;
case MAILBOX_LIST_PATH_TYPE_INDEX:
if (_list->set.index_dir != NULL) {
if (*_list->set.index_dir == '\0')
return 0;
*path_r = maildir_list_get_dirname_path(_list,
_list->set.index_dir, name);
return 1;
}
break;
case MAILBOX_LIST_PATH_TYPE_INDEX_PRIVATE:
if (_list->set.index_pvt_dir == NULL)
return 0;
*path_r = maildir_list_get_dirname_path(_list,
_list->set.index_pvt_dir, name);
return 1;
}
if (type == MAILBOX_LIST_PATH_TYPE_ALT_DIR ||
type == MAILBOX_LIST_PATH_TYPE_ALT_MAILBOX) {
/* don't use inbox_path */
} else if (strcmp(name, "INBOX") == 0 && _list->set.inbox_path != NULL) {
*path_r = _list->set.inbox_path;
return 1;
}
*path_r = maildir_list_get_dirname_path(_list, root_dir, name);
return 1;
}
static const char *
maildir_list_get_temp_prefix(struct mailbox_list *_list, bool global)
{
struct maildir_mailbox_list *list =
(struct maildir_mailbox_list *)_list;
return global ? list->global_temp_prefix : list->temp_prefix;
}
static int maildir_list_set_subscribed(struct mailbox_list *_list,
const char *name, bool set)
{
struct maildir_mailbox_list *list =
(struct maildir_mailbox_list *)_list;
const char *path;
if (_list->set.subscription_fname == NULL) {
mailbox_list_set_error(_list, MAIL_ERROR_NOTPOSSIBLE,
"Subscriptions not supported");
return -1;
}
path = t_strconcat(_list->set.control_dir != NULL ?
_list->set.control_dir : _list->set.root_dir,
"/", _list->set.subscription_fname, NULL);
return subsfile_set_subscribed(_list, path, list->temp_prefix,
name, set);
}
static const char *
mailbox_list_maildir_get_trash_dir(struct mailbox_list *_list)
{
struct maildir_mailbox_list *list =
(struct maildir_mailbox_list *)_list;
const char *root_dir;
root_dir = mailbox_list_get_root_forced(_list, MAILBOX_LIST_PATH_TYPE_DIR);
return t_strdup_printf("%s/%c%c"MAILBOX_LIST_MAILDIR_TRASH_DIR_NAME,
root_dir, list->sep, list->sep);
}
static int
maildir_list_delete_maildir(struct mailbox_list *list, const char *name)
{
const char *path, *trash_dir;
int ret = 0;
trash_dir = mailbox_list_maildir_get_trash_dir(list);
ret = mailbox_list_delete_maildir_via_trash(list, name, trash_dir);
if (ret < 0)
return -1;
if (ret == 0) {
/* we could actually use just unlink_directory()
but error handling is easier this way :) */
if (mailbox_list_get_path(list, name,
MAILBOX_LIST_PATH_TYPE_MAILBOX,
&path) <= 0)
i_unreached();
if (mailbox_list_delete_mailbox_nonrecursive(list, name,
path, TRUE) < 0)
return -1;
}
return 0;
}
static int
maildir_list_delete_mailbox(struct mailbox_list *list, const char *name)
{
const char *path;
int ret;
if ((list->flags & MAILBOX_LIST_FLAG_MAILBOX_FILES) != 0) {
ret = mailbox_list_get_path(list, name,
MAILBOX_LIST_PATH_TYPE_MAILBOX,
&path);
if (ret < 0)
return -1;
i_assert(ret > 0);
ret = mailbox_list_delete_mailbox_file(list, name, path);
} else {
ret = maildir_list_delete_maildir(list, name);
}
if (ret == 0 || (list->props & MAILBOX_LIST_PROP_AUTOCREATE_DIRS) != 0)
mailbox_list_delete_finish(list, name);
return ret;
}
static int maildir_list_delete_dir(struct mailbox_list *list, const char *name)
{
const char *path;
struct stat st;
/* with maildir++ there aren't any non-selectable mailboxes.
we'll always fail. */
if (mailbox_list_get_path(list, name, MAILBOX_LIST_PATH_TYPE_DIR,
&path) <= 0)
i_unreached();
if (stat(path, &st) == 0) {
mailbox_list_set_error(list, MAIL_ERROR_EXISTS,
"Mailbox exists");
} else if (errno == ENOENT || errno == ENOTDIR) {
mailbox_list_set_error(list, MAIL_ERROR_NOTFOUND,
T_MAILBOX_LIST_ERR_NOT_FOUND(list, name));
} else {
mailbox_list_set_critical(list, "stat(%s) failed: %m", path);
}
return -1;
}
static int rename_dir(struct mailbox_list *oldlist, const char *oldname,
struct mailbox_list *newlist, const char *newname,
enum mailbox_list_path_type type)
{
const char *oldpath, *newpath;
if (mailbox_list_get_path(oldlist, oldname, type, &oldpath) <= 0 ||
mailbox_list_get_path(newlist, newname, type, &newpath) <= 0)
return 0;
if (strcmp(oldpath, newpath) == 0)
return 0;
if (rename(oldpath, newpath) < 0 && errno != ENOENT) {
mailbox_list_set_critical(oldlist, "rename(%s, %s) failed: %m",
oldpath, newpath);
return -1;
}
return 0;
}
static int
maildir_rename_children(struct mailbox_list *oldlist, const char *oldname,
struct mailbox_list *newlist, const char *newname)
{
struct mailbox_list_iterate_context *iter;
const struct mailbox_info *info;
ARRAY(const char *) names_arr;
const char *pattern, *oldpath, *newpath, *old_childname, *new_childname;
const char *const *names, *old_vname, *new_vname;
unsigned int i, count, old_vnamelen;
pool_t pool;
char old_ns_sep;
int ret;
ret = 0;
/* first get the list of the children and save them to memory, because
we can't rely on readdir() not skipping files while the directory
is being modified. this doesn't protect against modifications by
other processes though. */
pool = pool_alloconly_create("Maildir++ children list", 1024);
i_array_init(&names_arr, 64);
old_vname = mailbox_list_get_vname(oldlist, oldname);
old_vnamelen = strlen(old_vname);
new_vname = mailbox_list_get_vname(newlist, newname);
old_ns_sep = mail_namespace_get_sep(oldlist->ns);
pattern = t_strdup_printf("%s%c*", old_vname, old_ns_sep);
iter = mailbox_list_iter_init(oldlist, pattern,
MAILBOX_LIST_ITER_RETURN_NO_FLAGS |
MAILBOX_LIST_ITER_RAW_LIST);
while ((info = mailbox_list_iter_next(iter)) != NULL) {
const char *name;
/* verify that the prefix matches, otherwise we could have
problems with mailbox names containing '%' and '*' chars */
if (strncmp(info->vname, old_vname, old_vnamelen) == 0 &&
info->vname[old_vnamelen] == old_ns_sep) {
name = p_strdup(pool, info->vname + old_vnamelen);
array_append(&names_arr, &name, 1);
}
}
if (mailbox_list_iter_deinit(&iter) < 0) {
ret = -1;
names = NULL; count = 0;
} else {
names = array_get(&names_arr, &count);
}
for (i = 0; i < count; i++) {
old_childname = mailbox_list_get_storage_name(oldlist,
t_strconcat(old_vname, names[i], NULL));
if (strcmp(old_childname, new_vname) == 0) {
/* When doing RENAME "a" "a.b" we see "a.b" here.
We don't want to rename it anymore to "a.b.b". */
continue;
}
new_childname = mailbox_list_get_storage_name(newlist,
t_strconcat(new_vname, names[i], NULL));
if (mailbox_list_get_path(oldlist, old_childname,
MAILBOX_LIST_PATH_TYPE_MAILBOX,
&oldpath) <= 0 ||
mailbox_list_get_path(newlist, new_childname,
MAILBOX_LIST_PATH_TYPE_MAILBOX,
&newpath) <= 0)
i_unreached();
/* FIXME: it's possible to merge two mailboxes if either one of
them doesn't have existing root mailbox. We could check this
but I'm not sure if it's worth it. It could be even
considered as a feature.
Anyway, the bug with merging is that if both mailboxes have
identically named child mailbox they conflict. Just ignore
those and leave them under the old mailbox. */
if (rename(oldpath, newpath) == 0 || EDESTDIREXISTS(errno))
ret = 1;
else {
mailbox_list_set_critical(oldlist,
"rename(%s, %s) failed: %m", oldpath, newpath);
ret = -1;
break;
}
(void)rename_dir(oldlist, old_childname, newlist, new_childname,
MAILBOX_LIST_PATH_TYPE_CONTROL);
(void)rename_dir(oldlist, old_childname, newlist, new_childname,
MAILBOX_LIST_PATH_TYPE_INDEX);
}
array_free(&names_arr);
pool_unref(&pool);
return ret;
}
static int
maildir_list_rename_mailbox(struct mailbox_list *oldlist, const char *oldname,
struct mailbox_list *newlist, const char *newname)
{
const char *oldpath, *newpath, *root_path;
int ret;
bool found;
/* NOTE: it's possible to rename a nonexistent mailbox which has
children. In that case we should ignore the rename() error. */
if (mailbox_list_get_path(oldlist, oldname,
MAILBOX_LIST_PATH_TYPE_MAILBOX, &oldpath) <= 0 ||
mailbox_list_get_path(newlist, newname,
MAILBOX_LIST_PATH_TYPE_MAILBOX, &newpath) <= 0)
i_unreached();
root_path = mailbox_list_get_root_forced(oldlist,
MAILBOX_LIST_PATH_TYPE_MAILBOX);
if (strcmp(oldpath, root_path) == 0) {
/* most likely INBOX */
mailbox_list_set_error(oldlist, MAIL_ERROR_NOTPOSSIBLE,
t_strdup_printf("Renaming %s isn't supported.",
oldname));
return -1;
}
/* if we're renaming under another mailbox, require its permissions
to be same as ours. */
if (strchr(newname, mailbox_list_get_hierarchy_sep(newlist)) != NULL) {
struct mailbox_permissions old_perm, new_perm;
mailbox_list_get_permissions(oldlist, oldname, &old_perm);
mailbox_list_get_permissions(newlist, newname, &new_perm);
if ((new_perm.file_create_mode != old_perm.file_create_mode ||
new_perm.dir_create_mode != old_perm.dir_create_mode ||
new_perm.file_create_gid != old_perm.file_create_gid)) {
mailbox_list_set_error(oldlist, MAIL_ERROR_NOTPOSSIBLE,
"Renaming not supported across conflicting "
"directory permissions");
return -1;
}
}
ret = rename(oldpath, newpath);
if (ret == 0 || errno == ENOENT) {
(void)rename_dir(oldlist, oldname, newlist, newname,
MAILBOX_LIST_PATH_TYPE_CONTROL);
(void)rename_dir(oldlist, oldname, newlist, newname,
MAILBOX_LIST_PATH_TYPE_INDEX);
found = ret == 0;
T_BEGIN {
ret = maildir_rename_children(oldlist, oldname,
newlist, newname);
} T_END;
if (ret < 0)
return -1;
if (!found && ret == 0) {
mailbox_list_set_error(oldlist, MAIL_ERROR_NOTFOUND,
T_MAILBOX_LIST_ERR_NOT_FOUND(oldlist, oldname));
return -1;
}
return 0;
}
if (EDESTDIREXISTS(errno)) {
mailbox_list_set_error(oldlist, MAIL_ERROR_EXISTS,
"Target mailbox already exists");
} else {
mailbox_list_set_critical(oldlist, "rename(%s, %s) failed: %m",
oldpath, newpath);
}
return -1;
}
struct mailbox_list maildir_mailbox_list = {
.name = MAILBOX_LIST_NAME_MAILDIRPLUSPLUS,
.props = MAILBOX_LIST_PROP_NO_MAILDIR_NAME |
MAILBOX_LIST_PROP_NO_ALT_DIR |
MAILBOX_LIST_PROP_NO_NOSELECT,
.mailbox_name_max_length = MAILBOX_LIST_NAME_MAX_LENGTH,
{
maildir_list_alloc,
NULL,
maildir_list_deinit,
NULL,
maildir_list_get_hierarchy_sep,
mailbox_list_default_get_vname,
mailbox_list_default_get_storage_name,
maildir_list_get_path,
maildir_list_get_temp_prefix,
NULL,
maildir_list_iter_init,
maildir_list_iter_next,
maildir_list_iter_deinit,
maildir_list_get_mailbox_flags,
NULL,
mailbox_list_subscriptions_refresh,
maildir_list_set_subscribed,
maildir_list_delete_mailbox,
maildir_list_delete_dir,
mailbox_list_delete_symlink_default,
maildir_list_rename_mailbox,
NULL, NULL, NULL, NULL
}
};
struct mailbox_list imapdir_mailbox_list = {
.name = MAILBOX_LIST_NAME_IMAPDIR,
.props = MAILBOX_LIST_PROP_NO_MAILDIR_NAME |
MAILBOX_LIST_PROP_NO_ALT_DIR |
MAILBOX_LIST_PROP_NO_NOSELECT,
.mailbox_name_max_length = MAILBOX_LIST_NAME_MAX_LENGTH,
{
imapdir_list_alloc,
NULL,
maildir_list_deinit,
NULL,
maildir_list_get_hierarchy_sep,
mailbox_list_default_get_vname,
mailbox_list_default_get_storage_name,
maildir_list_get_path,
maildir_list_get_temp_prefix,
NULL,
maildir_list_iter_init,
maildir_list_iter_next,
maildir_list_iter_deinit,
maildir_list_get_mailbox_flags,
NULL,
mailbox_list_subscriptions_refresh,
maildir_list_set_subscribed,
maildir_list_delete_mailbox,
maildir_list_delete_dir,
mailbox_list_delete_symlink_default,
maildir_list_rename_mailbox,
NULL, NULL, NULL, NULL
}
};