bcb4e51a409d94ae670de96afb8483a4f7855294Stephan Bosch/* Copyright (c) 2010-2018 Dovecot authors, see the included COPYING file */
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen#include "lib.h"
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen#include "str.h"
375ef0ee80a734b45647476b89c0eab76f2e24a1Timo Sirainen#include "hex-binary.h"
375ef0ee80a734b45647476b89c0eab76f2e24a1Timo Sirainen#include "hostpid.h"
375ef0ee80a734b45647476b89c0eab76f2e24a1Timo Sirainen#include "randgen.h"
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen#include "unlink-directory.h"
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen#include "mailbox-list-private.h"
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen#include "mailbox-list-delete.h"
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen#include <stdio.h>
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen#include <dirent.h>
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen#include <unistd.h>
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainenstatic int
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainenmailbox_list_check_root_delete(struct mailbox_list *list, const char *name,
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen const char *path)
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen{
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen const char *root_dir;
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen root_dir = mailbox_list_get_root_forced(list, MAILBOX_LIST_PATH_TYPE_DIR);
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen if (strcmp(root_dir, path) != 0)
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen return 0;
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen if (strcmp(name, "INBOX") == 0 &&
eb64c3586d854cddd693f0b811d897399076a441Timo Sirainen (list->ns->flags & NAMESPACE_FLAG_INBOX_ANY) != 0) {
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen mailbox_list_set_error(list, MAIL_ERROR_NOTPOSSIBLE,
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen "INBOX can't be deleted.");
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen return -1;
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen }
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen mailbox_list_set_error(list, MAIL_ERROR_NOTPOSSIBLE,
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen "Mail storage root can't be deleted.");
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen return -1;
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen}
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen
375ef0ee80a734b45647476b89c0eab76f2e24a1Timo Sirainenstatic const char *unique_fname(void)
375ef0ee80a734b45647476b89c0eab76f2e24a1Timo Sirainen{
375ef0ee80a734b45647476b89c0eab76f2e24a1Timo Sirainen unsigned char randbuf[8];
375ef0ee80a734b45647476b89c0eab76f2e24a1Timo Sirainen
2a628a8c90839439baff5b45116f89f2b3cd9e37Aki Tuomi random_fill(randbuf, sizeof(randbuf));
375ef0ee80a734b45647476b89c0eab76f2e24a1Timo Sirainen return t_strdup_printf("%s.%s.%s", my_hostname, my_pid,
375ef0ee80a734b45647476b89c0eab76f2e24a1Timo Sirainen binary_to_hex(randbuf, sizeof(randbuf)));
375ef0ee80a734b45647476b89c0eab76f2e24a1Timo Sirainen
375ef0ee80a734b45647476b89c0eab76f2e24a1Timo Sirainen}
375ef0ee80a734b45647476b89c0eab76f2e24a1Timo Sirainen
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainenint mailbox_list_delete_maildir_via_trash(struct mailbox_list *list,
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen const char *name,
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen const char *trash_dir)
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen{
97e511960951550338d69cac98fb5f3ca2badb09Timo Sirainen const char *src, *trash_dest, *error;
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen unsigned int count;
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen if (mailbox_list_get_path(list, name, MAILBOX_LIST_PATH_TYPE_MAILBOX,
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen &src) <= 0)
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen i_unreached();
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen if (mailbox_list_check_root_delete(list, name, src) < 0)
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen return -1;
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen /* rename the mailbox dir to trash dir, which atomically
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen marks it as being deleted. */
375ef0ee80a734b45647476b89c0eab76f2e24a1Timo Sirainen count = 0; trash_dest = trash_dir;
375ef0ee80a734b45647476b89c0eab76f2e24a1Timo Sirainen for (; rename(src, trash_dest) < 0; count++) {
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen if (ENOTFOUND(errno)) {
375ef0ee80a734b45647476b89c0eab76f2e24a1Timo Sirainen if (trash_dest != trash_dir && count < 5) {
375ef0ee80a734b45647476b89c0eab76f2e24a1Timo Sirainen /* either the source was just deleted or
375ef0ee80a734b45647476b89c0eab76f2e24a1Timo Sirainen the trash dir was deleted. */
375ef0ee80a734b45647476b89c0eab76f2e24a1Timo Sirainen trash_dest = trash_dir;
375ef0ee80a734b45647476b89c0eab76f2e24a1Timo Sirainen continue;
375ef0ee80a734b45647476b89c0eab76f2e24a1Timo Sirainen }
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen mailbox_list_set_error(list, MAIL_ERROR_NOTFOUND,
bdb026e2dc8a7c77585ed5ba489f0056df8074d4Timo Sirainen T_MAILBOX_LIST_ERR_NOT_FOUND(list, name));
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen return -1;
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen }
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen if (errno == EXDEV) {
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen /* can't do this the fast way */
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen return 0;
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen }
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen if (!EDESTDIREXISTS(errno)) {
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen if (mailbox_list_set_error_from_errno(list))
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen return -1;
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen mailbox_list_set_critical(list,
375ef0ee80a734b45647476b89c0eab76f2e24a1Timo Sirainen "rename(%s, %s) failed: %m", src, trash_dest);
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen return -1;
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen }
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen
375ef0ee80a734b45647476b89c0eab76f2e24a1Timo Sirainen /* trash dir already exists. the reasons for this are:
375ef0ee80a734b45647476b89c0eab76f2e24a1Timo Sirainen
375ef0ee80a734b45647476b89c0eab76f2e24a1Timo Sirainen a) another process is in the middle of deleting it
375ef0ee80a734b45647476b89c0eab76f2e24a1Timo Sirainen b) previous process crashed and didn't delete it
375ef0ee80a734b45647476b89c0eab76f2e24a1Timo Sirainen c) NFS: mailbox was recently deleted, but some connection
375ef0ee80a734b45647476b89c0eab76f2e24a1Timo Sirainen still has that mailbox open. the directory contains .nfs*
375ef0ee80a734b45647476b89c0eab76f2e24a1Timo Sirainen files that can't be deleted until the mailbox is closed.
375ef0ee80a734b45647476b89c0eab76f2e24a1Timo Sirainen
375ef0ee80a734b45647476b89c0eab76f2e24a1Timo Sirainen Because of c) we'll first try to rename the mailbox under
375ef0ee80a734b45647476b89c0eab76f2e24a1Timo Sirainen the trash directory and only later try to delete the entire
375ef0ee80a734b45647476b89c0eab76f2e24a1Timo Sirainen trash directory. */
375ef0ee80a734b45647476b89c0eab76f2e24a1Timo Sirainen if (trash_dir == trash_dest) {
375ef0ee80a734b45647476b89c0eab76f2e24a1Timo Sirainen trash_dest = t_strconcat(trash_dir, "/",
375ef0ee80a734b45647476b89c0eab76f2e24a1Timo Sirainen unique_fname(), NULL);
97e511960951550338d69cac98fb5f3ca2badb09Timo Sirainen } else if (mailbox_list_delete_trash(trash_dest, &error) < 0 &&
375ef0ee80a734b45647476b89c0eab76f2e24a1Timo Sirainen (errno != ENOTEMPTY || count >= 5)) {
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen mailbox_list_set_critical(list,
97e511960951550338d69cac98fb5f3ca2badb09Timo Sirainen "unlink_directory(%s) failed: %s", trash_dest, error);
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen return -1;
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen }
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen }
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen
97e511960951550338d69cac98fb5f3ca2badb09Timo Sirainen if (mailbox_list_delete_trash(trash_dir, &error) < 0 &&
361ac49a38750e74b82497e3b5bc06936bbf2a8fTimo Sirainen errno != ENOTEMPTY && errno != EBUSY) {
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen mailbox_list_set_critical(list,
97e511960951550338d69cac98fb5f3ca2badb09Timo Sirainen "unlink_directory(%s) failed: %s", trash_dir, error);
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen /* it's already renamed to trash dir, which means it's
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen deleted as far as the client is concerned. Report
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen success. */
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen }
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen return 1;
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen}
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainenint mailbox_list_delete_mailbox_file(struct mailbox_list *list,
e0aff4c7e3336ec4b5edbcfc3a72e1e118603ee2Timo Sirainen const char *name, const char *path)
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen{
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen /* we can simply unlink() the file */
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen if (unlink(path) == 0)
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen return 0;
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen else if (ENOTFOUND(errno)) {
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen mailbox_list_set_error(list, MAIL_ERROR_NOTFOUND,
bdb026e2dc8a7c77585ed5ba489f0056df8074d4Timo Sirainen T_MAILBOX_LIST_ERR_NOT_FOUND(list, name));
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen return -1;
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen } else {
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen if (!mailbox_list_set_error_from_errno(list)) {
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen mailbox_list_set_critical(list,
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen "unlink(%s) failed: %m", path);
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen }
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen return -1;
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen }
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen}
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainenint mailbox_list_delete_mailbox_nonrecursive(struct mailbox_list *list,
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen const char *name, const char *path,
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen bool rmdir_path)
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen{
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen DIR *dir;
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen struct dirent *d;
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen string_t *full_path;
2ac5f36aa7c2e7a07ba8815d43a6d7483f62e74cTimo Sirainen size_t dir_len;
97e511960951550338d69cac98fb5f3ca2badb09Timo Sirainen const char *error;
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen bool mailbox_dir, unlinked_something = FALSE;
d851acd16c8b42a1afb7ccab8a20b9279998a5daTimo Sirainen int ret = 0;
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen if (mailbox_list_check_root_delete(list, name, path) < 0)
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen return -1;
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen dir = opendir(path);
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen if (dir == NULL) {
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen if (errno == ENOENT) {
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen mailbox_list_set_error(list, MAIL_ERROR_NOTFOUND,
bdb026e2dc8a7c77585ed5ba489f0056df8074d4Timo Sirainen T_MAILBOX_LIST_ERR_NOT_FOUND(list, name));
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen } else {
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen if (!mailbox_list_set_error_from_errno(list)) {
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen mailbox_list_set_critical(list,
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen "opendir(%s) failed: %m", path);
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen }
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen }
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen return -1;
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen }
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen full_path = t_str_new(256);
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen str_append(full_path, path);
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen str_append_c(full_path, '/');
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen dir_len = str_len(full_path);
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen for (errno = 0; (d = readdir(dir)) != NULL; errno = 0) {
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen if (d->d_name[0] == '.') {
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen /* skip . and .. */
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen if (d->d_name[1] == '\0')
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen continue;
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen if (d->d_name[1] == '.' && d->d_name[2] == '\0')
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen continue;
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen }
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen
dca6d617a23e3f93af3b8df59acb46478179fe55Timo Sirainen mailbox_dir = list->v.is_internal_name != NULL &&
dca6d617a23e3f93af3b8df59acb46478179fe55Timo Sirainen list->v.is_internal_name(list, d->d_name);
dca6d617a23e3f93af3b8df59acb46478179fe55Timo Sirainen
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen str_truncate(full_path, dir_len);
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen str_append(full_path, d->d_name);
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen if (mailbox_dir) {
97e511960951550338d69cac98fb5f3ca2badb09Timo Sirainen if (mailbox_list_delete_trash(str_c(full_path), &error) < 0) {
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen mailbox_list_set_critical(list,
97e511960951550338d69cac98fb5f3ca2badb09Timo Sirainen "unlink_directory(%s) failed: %s",
97e511960951550338d69cac98fb5f3ca2badb09Timo Sirainen str_c(full_path), error);
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen } else {
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen unlinked_something = TRUE;
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen }
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen continue;
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen }
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen /* trying to unlink() a directory gives either EPERM or EISDIR
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen (non-POSIX). it doesn't really work anywhere in practise,
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen so don't bother stat()ing the file first */
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen if (unlink(str_c(full_path)) == 0)
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen unlinked_something = TRUE;
aaaa6e07cf961038cf030d623540a8296c0ffe24Timo Sirainen else if (errno != ENOENT && !UNLINK_EISDIR(errno)) {
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen mailbox_list_set_critical(list,
61786203245e441635043dde7540e868a5532685Timo Sirainen "unlink(%s) failed: %m", str_c(full_path));
d851acd16c8b42a1afb7ccab8a20b9279998a5daTimo Sirainen ret = -1;
97ffd8e0b0374b9ccbbc788cf796e15d021ad090Timo Sirainen } else {
97ffd8e0b0374b9ccbbc788cf796e15d021ad090Timo Sirainen /* child directories still exist */
97ffd8e0b0374b9ccbbc788cf796e15d021ad090Timo Sirainen rmdir_path = FALSE;
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen }
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen }
d851acd16c8b42a1afb7ccab8a20b9279998a5daTimo Sirainen if (errno != 0) {
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen mailbox_list_set_critical(list, "readdir(%s) failed: %m", path);
d851acd16c8b42a1afb7ccab8a20b9279998a5daTimo Sirainen ret = -1;
d851acd16c8b42a1afb7ccab8a20b9279998a5daTimo Sirainen }
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen if (closedir(dir) < 0) {
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen mailbox_list_set_critical(list, "closedir(%s) failed: %m",
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen path);
d851acd16c8b42a1afb7ccab8a20b9279998a5daTimo Sirainen ret = -1;
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen }
d851acd16c8b42a1afb7ccab8a20b9279998a5daTimo Sirainen if (ret < 0)
d851acd16c8b42a1afb7ccab8a20b9279998a5daTimo Sirainen return -1;
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen if (rmdir_path) {
97ffd8e0b0374b9ccbbc788cf796e15d021ad090Timo Sirainen unsigned int try_count = 0;
97ffd8e0b0374b9ccbbc788cf796e15d021ad090Timo Sirainen int ret = rmdir(path);
97ffd8e0b0374b9ccbbc788cf796e15d021ad090Timo Sirainen while (ret < 0 && errno == ENOTEMPTY && try_count++ < 10) {
97ffd8e0b0374b9ccbbc788cf796e15d021ad090Timo Sirainen /* We didn't see any child directories, so this is
97ffd8e0b0374b9ccbbc788cf796e15d021ad090Timo Sirainen either a race condition or .nfs* files were left
97ffd8e0b0374b9ccbbc788cf796e15d021ad090Timo Sirainen lying around. In case it's .nfs* files, retry after
97ffd8e0b0374b9ccbbc788cf796e15d021ad090Timo Sirainen waiting a bit. Hopefully all processes keeping those
97ffd8e0b0374b9ccbbc788cf796e15d021ad090Timo Sirainen files open will have closed them by then. */
97ffd8e0b0374b9ccbbc788cf796e15d021ad090Timo Sirainen usleep(100000);
97ffd8e0b0374b9ccbbc788cf796e15d021ad090Timo Sirainen ret = rmdir(path);
97ffd8e0b0374b9ccbbc788cf796e15d021ad090Timo Sirainen }
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen if (rmdir(path) == 0)
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen unlinked_something = TRUE;
d851acd16c8b42a1afb7ccab8a20b9279998a5daTimo Sirainen else if (errno == ENOENT) {
d851acd16c8b42a1afb7ccab8a20b9279998a5daTimo Sirainen /* race condition with another process, which finished
d851acd16c8b42a1afb7ccab8a20b9279998a5daTimo Sirainen deleting it first. */
d851acd16c8b42a1afb7ccab8a20b9279998a5daTimo Sirainen mailbox_list_set_error(list, MAIL_ERROR_NOTFOUND,
d851acd16c8b42a1afb7ccab8a20b9279998a5daTimo Sirainen T_MAILBOX_LIST_ERR_NOT_FOUND(list, name));
d851acd16c8b42a1afb7ccab8a20b9279998a5daTimo Sirainen } else if (errno != ENOTEMPTY && errno != EEXIST) {
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen mailbox_list_set_critical(list, "rmdir(%s) failed: %m",
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen path);
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen return -1;
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen }
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen }
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen if (!unlinked_something) {
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen mailbox_list_set_error(list, MAIL_ERROR_NOTPOSSIBLE,
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen "Mailbox has children, can't delete it");
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen return -1;
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen }
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen return 0;
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen}
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen
5693411c1b19c99b9a91a3d9af6c9e681d2d0263Timo Sirainenstatic bool mailbox_list_path_is_index(struct mailbox_list *list,
5693411c1b19c99b9a91a3d9af6c9e681d2d0263Timo Sirainen enum mailbox_list_path_type type)
5693411c1b19c99b9a91a3d9af6c9e681d2d0263Timo Sirainen{
5693411c1b19c99b9a91a3d9af6c9e681d2d0263Timo Sirainen const char *index_root, *type_root;
5693411c1b19c99b9a91a3d9af6c9e681d2d0263Timo Sirainen
5693411c1b19c99b9a91a3d9af6c9e681d2d0263Timo Sirainen if (type == MAILBOX_LIST_PATH_TYPE_INDEX)
5693411c1b19c99b9a91a3d9af6c9e681d2d0263Timo Sirainen return TRUE;
5693411c1b19c99b9a91a3d9af6c9e681d2d0263Timo Sirainen
5693411c1b19c99b9a91a3d9af6c9e681d2d0263Timo Sirainen /* e.g. CONTROL dir could point to the same INDEX dir. */
5693411c1b19c99b9a91a3d9af6c9e681d2d0263Timo Sirainen type_root = mailbox_list_get_root_forced(list, type);
5693411c1b19c99b9a91a3d9af6c9e681d2d0263Timo Sirainen index_root = mailbox_list_get_root_forced(list, MAILBOX_LIST_PATH_TYPE_INDEX);
5693411c1b19c99b9a91a3d9af6c9e681d2d0263Timo Sirainen return strcmp(type_root, index_root) == 0;
5693411c1b19c99b9a91a3d9af6c9e681d2d0263Timo Sirainen}
5693411c1b19c99b9a91a3d9af6c9e681d2d0263Timo Sirainen
ae1a57954535642c09c3b8aee184736ddbb06cdfTimo Sirainenvoid mailbox_list_delete_until_root(struct mailbox_list *list, const char *path,
ae1a57954535642c09c3b8aee184736ddbb06cdfTimo Sirainen enum mailbox_list_path_type type)
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen{
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen const char *root_dir, *p;
2ac5f36aa7c2e7a07ba8815d43a6d7483f62e74cTimo Sirainen size_t len;
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen
eaa2d473ed2ecdb9856cd98a33f4d3063cfaf2a1Timo Sirainen if (list->set.iter_from_index_dir && !list->set.no_noselect &&
5693411c1b19c99b9a91a3d9af6c9e681d2d0263Timo Sirainen mailbox_list_path_is_index(list, type)) {
5693411c1b19c99b9a91a3d9af6c9e681d2d0263Timo Sirainen /* Don't auto-rmdir parent index directories with ITERINDEX.
5693411c1b19c99b9a91a3d9af6c9e681d2d0263Timo Sirainen Otherwise it'll get us into inconsistent state with a
5693411c1b19c99b9a91a3d9af6c9e681d2d0263Timo Sirainen \NoSelect mailbox in the mail directory but not in index
5693411c1b19c99b9a91a3d9af6c9e681d2d0263Timo Sirainen directory. */
5693411c1b19c99b9a91a3d9af6c9e681d2d0263Timo Sirainen return;
5693411c1b19c99b9a91a3d9af6c9e681d2d0263Timo Sirainen }
5693411c1b19c99b9a91a3d9af6c9e681d2d0263Timo Sirainen
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen root_dir = mailbox_list_get_root_forced(list, type);
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen if (strncmp(path, root_dir, strlen(root_dir)) != 0) {
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen /* mbox workaround: name=child/box, root_dir=mail/.imap/,
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen path=mail/child/.imap/box. we'll want to try to delete
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen the .imap/ part, but no further. */
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen len = strlen(path);
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen while (len > 0 && path[len-1] != '/')
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen len--;
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen if (len == 0)
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen return;
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen len--;
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen while (len > 0 && path[len-1] != '/')
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen len--;
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen if (len == 0)
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen return;
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen root_dir = t_strndup(path, len-1);
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen }
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen while (strcmp(path, root_dir) != 0) {
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen if (rmdir(path) < 0 && errno != ENOENT) {
10a2e8716e9040908fb60fcda56b5315ea4c1312Timo Sirainen if (errno == ENOTEMPTY || errno == EEXIST)
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen return;
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen mailbox_list_set_critical(list, "rmdir(%s) failed: %m",
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen path);
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen return;
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen }
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen p = strrchr(path, '/');
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen if (p == NULL)
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen break;
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen path = t_strdup_until(path, p);
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen }
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen}
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen
d823c19df414cac96c7f50a6f78a13fd03bcb27eTimo Sirainenvoid mailbox_list_delete_mailbox_until_root(struct mailbox_list *list,
d823c19df414cac96c7f50a6f78a13fd03bcb27eTimo Sirainen const char *storage_name)
d823c19df414cac96c7f50a6f78a13fd03bcb27eTimo Sirainen{
d823c19df414cac96c7f50a6f78a13fd03bcb27eTimo Sirainen enum mailbox_list_path_type types[] = {
d823c19df414cac96c7f50a6f78a13fd03bcb27eTimo Sirainen MAILBOX_LIST_PATH_TYPE_DIR,
d823c19df414cac96c7f50a6f78a13fd03bcb27eTimo Sirainen MAILBOX_LIST_PATH_TYPE_ALT_DIR,
d823c19df414cac96c7f50a6f78a13fd03bcb27eTimo Sirainen MAILBOX_LIST_PATH_TYPE_CONTROL,
d823c19df414cac96c7f50a6f78a13fd03bcb27eTimo Sirainen MAILBOX_LIST_PATH_TYPE_INDEX,
d823c19df414cac96c7f50a6f78a13fd03bcb27eTimo Sirainen MAILBOX_LIST_PATH_TYPE_INDEX_PRIVATE,
638600575ee95f2513c683ef09cb188f76eacd22Timo Sirainen MAILBOX_LIST_PATH_TYPE_INDEX_CACHE,
d823c19df414cac96c7f50a6f78a13fd03bcb27eTimo Sirainen };
d823c19df414cac96c7f50a6f78a13fd03bcb27eTimo Sirainen const char *path;
d823c19df414cac96c7f50a6f78a13fd03bcb27eTimo Sirainen
d823c19df414cac96c7f50a6f78a13fd03bcb27eTimo Sirainen for (unsigned int i = 0; i < N_ELEMENTS(types); i++) {
d823c19df414cac96c7f50a6f78a13fd03bcb27eTimo Sirainen if (mailbox_list_get_path(list, storage_name, types[i], &path) > 0)
d823c19df414cac96c7f50a6f78a13fd03bcb27eTimo Sirainen mailbox_list_delete_until_root(list, path, types[i]);
d823c19df414cac96c7f50a6f78a13fd03bcb27eTimo Sirainen }
d823c19df414cac96c7f50a6f78a13fd03bcb27eTimo Sirainen}
d823c19df414cac96c7f50a6f78a13fd03bcb27eTimo Sirainen
a1bef9db6db683360e6e7be59a7f9e9718cf6ff5Timo Sirainenstatic int mailbox_list_try_delete(struct mailbox_list *list, const char *name,
a1bef9db6db683360e6e7be59a7f9e9718cf6ff5Timo Sirainen enum mailbox_list_path_type type)
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen{
3aa1816a6b10a137c8f6242d02e31d479123c8b5Timo Sirainen const char *mailbox_path, *index_path, *path, *error;
a1bef9db6db683360e6e7be59a7f9e9718cf6ff5Timo Sirainen int ret;
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen if (mailbox_list_get_path(list, name, MAILBOX_LIST_PATH_TYPE_MAILBOX,
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen &mailbox_path) <= 0 ||
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen mailbox_list_get_path(list, name, type, &path) <= 0 ||
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen strcmp(path, mailbox_path) == 0)
a1bef9db6db683360e6e7be59a7f9e9718cf6ff5Timo Sirainen return 0;
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen
3aa1816a6b10a137c8f6242d02e31d479123c8b5Timo Sirainen if (type == MAILBOX_LIST_PATH_TYPE_CONTROL &&
3aa1816a6b10a137c8f6242d02e31d479123c8b5Timo Sirainen mailbox_list_get_path(list, name, MAILBOX_LIST_PATH_TYPE_INDEX,
3aa1816a6b10a137c8f6242d02e31d479123c8b5Timo Sirainen &index_path) > 0 &&
3aa1816a6b10a137c8f6242d02e31d479123c8b5Timo Sirainen strcmp(index_path, path) == 0) {
3aa1816a6b10a137c8f6242d02e31d479123c8b5Timo Sirainen /* CONTROL dir is the same as INDEX dir, which we already
3aa1816a6b10a137c8f6242d02e31d479123c8b5Timo Sirainen deleted. We don't want to continue especially with
3aa1816a6b10a137c8f6242d02e31d479123c8b5Timo Sirainen iter_from_index_dir=yes, because it could be deleting the
3aa1816a6b10a137c8f6242d02e31d479123c8b5Timo Sirainen index directory. */
3aa1816a6b10a137c8f6242d02e31d479123c8b5Timo Sirainen return 0;
3aa1816a6b10a137c8f6242d02e31d479123c8b5Timo Sirainen }
3aa1816a6b10a137c8f6242d02e31d479123c8b5Timo Sirainen
0784c6f498b36afe6fb079c51e3c3d7c20e26e2cTimo Sirainen /* Note that only ALT currently uses maildir_name in paths.
0784c6f498b36afe6fb079c51e3c3d7c20e26e2cTimo Sirainen INDEX and CONTROL don't. */
0784c6f498b36afe6fb079c51e3c3d7c20e26e2cTimo Sirainen if (type != MAILBOX_LIST_PATH_TYPE_ALT_MAILBOX ||
0784c6f498b36afe6fb079c51e3c3d7c20e26e2cTimo Sirainen *list->set.maildir_name == '\0') {
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen /* this directory may contain also child mailboxes' data.
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen we don't want to delete that. */
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen bool rmdir_path = *list->set.maildir_name != '\0';
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen if (mailbox_list_delete_mailbox_nonrecursive(list, name, path,
a1bef9db6db683360e6e7be59a7f9e9718cf6ff5Timo Sirainen rmdir_path) == 0)
a1bef9db6db683360e6e7be59a7f9e9718cf6ff5Timo Sirainen ret = 1;
a1bef9db6db683360e6e7be59a7f9e9718cf6ff5Timo Sirainen else {
a1bef9db6db683360e6e7be59a7f9e9718cf6ff5Timo Sirainen enum mail_error error =
a1bef9db6db683360e6e7be59a7f9e9718cf6ff5Timo Sirainen mailbox_list_get_last_mail_error(list);
a1bef9db6db683360e6e7be59a7f9e9718cf6ff5Timo Sirainen if (error != MAIL_ERROR_NOTFOUND &&
a1bef9db6db683360e6e7be59a7f9e9718cf6ff5Timo Sirainen error != MAIL_ERROR_NOTPOSSIBLE)
a1bef9db6db683360e6e7be59a7f9e9718cf6ff5Timo Sirainen return -1;
a1bef9db6db683360e6e7be59a7f9e9718cf6ff5Timo Sirainen ret = 0;
a1bef9db6db683360e6e7be59a7f9e9718cf6ff5Timo Sirainen }
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen } else {
a1bef9db6db683360e6e7be59a7f9e9718cf6ff5Timo Sirainen if (mailbox_list_delete_trash(path, &error) == 0)
a1bef9db6db683360e6e7be59a7f9e9718cf6ff5Timo Sirainen ret = 1;
1d9053f57383a2382c70f76b0790a7bf192aa891Sergey Kitov else if (errno == ENOTEMPTY)
a1bef9db6db683360e6e7be59a7f9e9718cf6ff5Timo Sirainen ret = 0;
a1bef9db6db683360e6e7be59a7f9e9718cf6ff5Timo Sirainen else {
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen mailbox_list_set_critical(list,
97e511960951550338d69cac98fb5f3ca2badb09Timo Sirainen "unlink_directory(%s) failed: %s", path, error);
a1bef9db6db683360e6e7be59a7f9e9718cf6ff5Timo Sirainen return -1;
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen }
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen }
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen
5693411c1b19c99b9a91a3d9af6c9e681d2d0263Timo Sirainen /* Avoid leaving empty parent directories lying around.
5693411c1b19c99b9a91a3d9af6c9e681d2d0263Timo Sirainen These parent directories' existence or removal doesn't
5693411c1b19c99b9a91a3d9af6c9e681d2d0263Timo Sirainen affect our return value. */
5693411c1b19c99b9a91a3d9af6c9e681d2d0263Timo Sirainen mailbox_list_delete_until_root(list, path, type);
a1bef9db6db683360e6e7be59a7f9e9718cf6ff5Timo Sirainen return ret;
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen}
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen
a1bef9db6db683360e6e7be59a7f9e9718cf6ff5Timo Sirainenint mailbox_list_delete_finish(struct mailbox_list *list, const char *name)
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen{
a1bef9db6db683360e6e7be59a7f9e9718cf6ff5Timo Sirainen int ret, ret2;
a1bef9db6db683360e6e7be59a7f9e9718cf6ff5Timo Sirainen
a1bef9db6db683360e6e7be59a7f9e9718cf6ff5Timo Sirainen ret = mailbox_list_try_delete(list, name, MAILBOX_LIST_PATH_TYPE_INDEX);
638600575ee95f2513c683ef09cb188f76eacd22Timo Sirainen ret2 = mailbox_list_try_delete(list, name, MAILBOX_LIST_PATH_TYPE_INDEX_CACHE);
638600575ee95f2513c683ef09cb188f76eacd22Timo Sirainen if (ret == 0 || ret2 < 0)
638600575ee95f2513c683ef09cb188f76eacd22Timo Sirainen ret = ret2;
a1bef9db6db683360e6e7be59a7f9e9718cf6ff5Timo Sirainen ret2 = mailbox_list_try_delete(list, name, MAILBOX_LIST_PATH_TYPE_CONTROL);
a1bef9db6db683360e6e7be59a7f9e9718cf6ff5Timo Sirainen if (ret == 0 || ret2 < 0)
a1bef9db6db683360e6e7be59a7f9e9718cf6ff5Timo Sirainen ret = ret2;
a1bef9db6db683360e6e7be59a7f9e9718cf6ff5Timo Sirainen ret2 = mailbox_list_try_delete(list, name, MAILBOX_LIST_PATH_TYPE_ALT_MAILBOX);
a1bef9db6db683360e6e7be59a7f9e9718cf6ff5Timo Sirainen if (ret == 0 || ret2 < 0)
a1bef9db6db683360e6e7be59a7f9e9718cf6ff5Timo Sirainen ret = ret2;
a1bef9db6db683360e6e7be59a7f9e9718cf6ff5Timo Sirainen return ret;
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen}
4cdfd6cc490503ed4176a6796140470916d06e01Timo Sirainen
12bd6ddfeb75d81ccc09bf34b374b0637dfe890fTimo Sirainenint mailbox_list_delete_finish_ret(struct mailbox_list *list,
12bd6ddfeb75d81ccc09bf34b374b0637dfe890fTimo Sirainen const char *name, bool root_delete_success)
12bd6ddfeb75d81ccc09bf34b374b0637dfe890fTimo Sirainen{
12bd6ddfeb75d81ccc09bf34b374b0637dfe890fTimo Sirainen int ret2;
12bd6ddfeb75d81ccc09bf34b374b0637dfe890fTimo Sirainen
12bd6ddfeb75d81ccc09bf34b374b0637dfe890fTimo Sirainen if (!root_delete_success &&
12bd6ddfeb75d81ccc09bf34b374b0637dfe890fTimo Sirainen mailbox_list_get_last_mail_error(list) != MAIL_ERROR_NOTFOUND) {
12bd6ddfeb75d81ccc09bf34b374b0637dfe890fTimo Sirainen /* unexpected error - preserve it */
12bd6ddfeb75d81ccc09bf34b374b0637dfe890fTimo Sirainen return -1;
12bd6ddfeb75d81ccc09bf34b374b0637dfe890fTimo Sirainen } else if ((ret2 = mailbox_list_delete_finish(list, name)) < 0) {
12bd6ddfeb75d81ccc09bf34b374b0637dfe890fTimo Sirainen /* unexpected error */
12bd6ddfeb75d81ccc09bf34b374b0637dfe890fTimo Sirainen return -1;
12bd6ddfeb75d81ccc09bf34b374b0637dfe890fTimo Sirainen } else if (ret2 > 0) {
12bd6ddfeb75d81ccc09bf34b374b0637dfe890fTimo Sirainen /* successfully deleted */
12bd6ddfeb75d81ccc09bf34b374b0637dfe890fTimo Sirainen return 0;
12bd6ddfeb75d81ccc09bf34b374b0637dfe890fTimo Sirainen } else if (root_delete_success) {
12bd6ddfeb75d81ccc09bf34b374b0637dfe890fTimo Sirainen /* nothing deleted by us, but root was successfully deleted */
12bd6ddfeb75d81ccc09bf34b374b0637dfe890fTimo Sirainen return 0;
12bd6ddfeb75d81ccc09bf34b374b0637dfe890fTimo Sirainen } else {
12bd6ddfeb75d81ccc09bf34b374b0637dfe890fTimo Sirainen /* nothing deleted by us and the root didn't exist either.
12bd6ddfeb75d81ccc09bf34b374b0637dfe890fTimo Sirainen make sure the list has the correct error set, since it
12bd6ddfeb75d81ccc09bf34b374b0637dfe890fTimo Sirainen could have been changed. */
12bd6ddfeb75d81ccc09bf34b374b0637dfe890fTimo Sirainen mailbox_list_set_error(list, MAIL_ERROR_NOTFOUND,
12bd6ddfeb75d81ccc09bf34b374b0637dfe890fTimo Sirainen T_MAILBOX_LIST_ERR_NOT_FOUND(list, name));
12bd6ddfeb75d81ccc09bf34b374b0637dfe890fTimo Sirainen return -1;
12bd6ddfeb75d81ccc09bf34b374b0637dfe890fTimo Sirainen }
12bd6ddfeb75d81ccc09bf34b374b0637dfe890fTimo Sirainen}
12bd6ddfeb75d81ccc09bf34b374b0637dfe890fTimo Sirainen
97e511960951550338d69cac98fb5f3ca2badb09Timo Sirainenint mailbox_list_delete_trash(const char *path, const char **error_r)
4cdfd6cc490503ed4176a6796140470916d06e01Timo Sirainen{
97e511960951550338d69cac98fb5f3ca2badb09Timo Sirainen if (unlink_directory(path, UNLINK_DIRECTORY_FLAG_RMDIR, error_r) < 0) {
4cdfd6cc490503ed4176a6796140470916d06e01Timo Sirainen if (errno == ELOOP) {
4cdfd6cc490503ed4176a6796140470916d06e01Timo Sirainen /* it's a symlink? try just deleting it */
4cdfd6cc490503ed4176a6796140470916d06e01Timo Sirainen if (unlink(path) == 0)
4cdfd6cc490503ed4176a6796140470916d06e01Timo Sirainen return 0;
4cdfd6cc490503ed4176a6796140470916d06e01Timo Sirainen errno = ELOOP;
4cdfd6cc490503ed4176a6796140470916d06e01Timo Sirainen return -1;
4cdfd6cc490503ed4176a6796140470916d06e01Timo Sirainen }
e83bc61375901bf997ee3a09580674ffb4892348Timo Sirainen return -1;
4cdfd6cc490503ed4176a6796140470916d06e01Timo Sirainen }
4cdfd6cc490503ed4176a6796140470916d06e01Timo Sirainen return 0;
4cdfd6cc490503ed4176a6796140470916d06e01Timo Sirainen}
0b25846ba794ce19536a24d4065beaf2a0bd9464Timo Sirainen
0b25846ba794ce19536a24d4065beaf2a0bd9464Timo Sirainenint mailbox_list_delete_symlink_default(struct mailbox_list *list,
0b25846ba794ce19536a24d4065beaf2a0bd9464Timo Sirainen const char *name)
0b25846ba794ce19536a24d4065beaf2a0bd9464Timo Sirainen{
0b25846ba794ce19536a24d4065beaf2a0bd9464Timo Sirainen const char *path;
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen int ret;
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen ret = mailbox_list_get_path(list, name, MAILBOX_LIST_PATH_TYPE_DIR,
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen &path);
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen if (ret < 0)
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen return -1;
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen i_assert(ret > 0);
0b25846ba794ce19536a24d4065beaf2a0bd9464Timo Sirainen
0b25846ba794ce19536a24d4065beaf2a0bd9464Timo Sirainen if (unlink(path) == 0)
0b25846ba794ce19536a24d4065beaf2a0bd9464Timo Sirainen return 0;
0b25846ba794ce19536a24d4065beaf2a0bd9464Timo Sirainen
0b25846ba794ce19536a24d4065beaf2a0bd9464Timo Sirainen if (errno == ENOENT) {
0b25846ba794ce19536a24d4065beaf2a0bd9464Timo Sirainen mailbox_list_set_error(list, MAIL_ERROR_NOTFOUND,
bdb026e2dc8a7c77585ed5ba489f0056df8074d4Timo Sirainen T_MAILBOX_LIST_ERR_NOT_FOUND(list, name));
aaaa6e07cf961038cf030d623540a8296c0ffe24Timo Sirainen } else if (UNLINK_EISDIR(errno)) {
0b25846ba794ce19536a24d4065beaf2a0bd9464Timo Sirainen mailbox_list_set_error(list, MAIL_ERROR_NOTPOSSIBLE,
0b25846ba794ce19536a24d4065beaf2a0bd9464Timo Sirainen "Mailbox isn't a symlink");
0b25846ba794ce19536a24d4065beaf2a0bd9464Timo Sirainen } else {
46eecdfa411d6bd2582b181be1085010f76f9635Timo Sirainen mailbox_list_set_critical(list, "unlink(%s) failed: %m", path);
0b25846ba794ce19536a24d4065beaf2a0bd9464Timo Sirainen }
0b25846ba794ce19536a24d4065beaf2a0bd9464Timo Sirainen return -1;
0b25846ba794ce19536a24d4065beaf2a0bd9464Timo Sirainen}