cydir-storage.c revision ad24d1a93178a4d9aec3d0ce73455d8fb50edbe1
a8c5a86d183db25a57bf193c06b41e092ec2e151Timo Sirainen/* Copyright (c) 2007-2009 Dovecot authors, see the included COPYING file */
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen#include "lib.h"
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen#include "array.h"
65cca8364f483126b396aeb2036dc879ad45ab8dTimo Sirainen#include "str.h"
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen#include "mkdir-parents.h"
472369cba85d9f7c995dda60e7cd01d78b4a960aTimo Sirainen#include "index-mail.h"
e28fa207d1a097fa6e4a867f74ee0761472ef1ceTimo Sirainen#include "mail-copy.h"
37847ec8eaec9ad55c9df10ae109efe7b37ac573Timo Sirainen#include "cydir-sync.h"
bd4e36a8cd7257cca7d1434c49a1e343ed7c5100Timo Sirainen#include "cydir-storage.h"
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen
b1f37113a5760bee842c5a7678bb5fa6f5bd8b60Timo Sirainen#include <unistd.h>
1c1cecd3dfaf71b0c9499b044023e631841e88aaTimo Sirainen#include <dirent.h>
94d8e51119003d2bc5a100c663f90141f297385dTimo Sirainen#include <sys/stat.h>
9393445a6dabd17ce62ebfc12fd73545b0065824Timo Sirainen
9393445a6dabd17ce62ebfc12fd73545b0065824Timo Sirainen#define CYDIR_LIST_CONTEXT(obj) \
e28fa207d1a097fa6e4a867f74ee0761472ef1ceTimo Sirainen MODULE_CONTEXT(obj, cydir_mailbox_list_module)
37847ec8eaec9ad55c9df10ae109efe7b37ac573Timo Sirainen
ef50336eefcb9ba99f73c6af37420eaf8857a39bTimo Sirainenstruct cydir_mailbox_list {
d2e74f2af690b8e2d536400f02f397cbed1334b7Timo Sirainen union mailbox_list_module_context module_ctx;
13d98ffa534f2e7d04a832c9d0153fc9c568b878Timo Sirainen};
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainenextern struct mail_storage cydir_storage;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainenextern struct mailbox cydir_mailbox;
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen
5694eeb99b69dea8033ca77ad69743c6b4871370Timo Sirainenstatic MODULE_CONTEXT_DEFINE_INIT(cydir_mailbox_list_module,
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen &mailbox_list_module_register);
5694eeb99b69dea8033ca77ad69743c6b4871370Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainenstatic struct mail_storage *cydir_storage_alloc(void)
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen{
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen struct cydir_storage *storage;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen pool_t pool;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen pool = pool_alloconly_create("cydir storage", 512+256);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen storage = p_new(pool, struct cydir_storage, 1);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen storage->storage = cydir_storage;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen storage->storage.pool = pool;
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen return &storage->storage;
220e21750948941dc6e33b8f11b552fa21d7f81eTimo Sirainen}
4ee00532a265bdfb38539d811fcd12d51210ac35Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainenstatic void
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainencydir_storage_get_list_settings(const struct mail_namespace *ns ATTR_UNUSED,
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainen struct mailbox_list_settings *set)
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainen{
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainen if (set->layout == NULL)
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainen set->layout = MAILBOX_LIST_NAME_FS;
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainen if (set->subscription_fname == NULL)
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainen set->subscription_fname = CYDIR_SUBSCRIPTION_FILE_NAME;
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainen}
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainen
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainenstatic int create_cydir(struct mail_storage *storage, struct mail_namespace *ns,
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen const char *path)
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen{
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen mode_t mode;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen gid_t gid;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen mailbox_list_get_dir_permissions(ns->list, NULL, &mode, &gid);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen if (mkdir_parents_chown(path, mode, (uid_t)-1, gid) < 0 &&
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen errno != EEXIST) {
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen if (!mail_storage_set_error_from_errno(storage)) {
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen mail_storage_set_critical(storage,
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen "mkdir(%s) failed: %m", path);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen }
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen return -1;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen }
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen return 0;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen}
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainenstatic struct mailbox *
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainencydir_open(struct mail_storage *storage, struct mailbox_list *list,
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainen const char *name, enum mailbox_open_flags flags)
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainen{
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainen struct cydir_mailbox *mbox;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen struct mail_index *index;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen const char *path;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen pool_t pool;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen path = mailbox_list_get_path(list, name,
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen MAILBOX_LIST_PATH_TYPE_MAILBOX);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen index = index_storage_alloc(list, name, flags, CYDIR_INDEX_PREFIX);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen mail_index_set_fsync_types(index, MAIL_INDEX_SYNC_TYPE_APPEND |
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen MAIL_INDEX_SYNC_TYPE_EXPUNGE);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen pool = pool_alloconly_create("cydir mailbox", 1024+512);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen mbox = p_new(pool, struct cydir_mailbox, 1);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen mbox->ibox.box = cydir_mailbox;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen mbox->ibox.box.pool = pool;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen mbox->ibox.box.storage = storage;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen mbox->ibox.mail_vfuncs = &cydir_mail_vfuncs;
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen mbox->ibox.index = index;
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen mbox->storage = (struct cydir_storage *)storage;
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen mbox->path = p_strdup(pool, path);
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen index_storage_mailbox_init(&mbox->ibox, name, flags, FALSE);
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen return &mbox->ibox.box;
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen}
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainenstatic struct mailbox *
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainencydir_mailbox_open(struct mail_storage *storage, struct mailbox_list *list,
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen const char *name, struct istream *input,
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen enum mailbox_open_flags flags)
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen{
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen const char *path;
db8b0a3f74a20528d66a3c4be7df920e5c4554c2Timo Sirainen struct stat st;
db8b0a3f74a20528d66a3c4be7df920e5c4554c2Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen if (input != NULL) {
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen mailbox_list_set_critical(list,
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen "cydir doesn't support streamed mailboxes");
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen return NULL;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen }
db8b0a3f74a20528d66a3c4be7df920e5c4554c2Timo Sirainen
db8b0a3f74a20528d66a3c4be7df920e5c4554c2Timo Sirainen /* cydir can't work without index files */
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen flags &= ~MAILBOX_OPEN_NO_INDEX_FILES;
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen path = mailbox_list_get_path(list, name,
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen MAILBOX_LIST_PATH_TYPE_MAILBOX);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen if (stat(path, &st) == 0)
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen return cydir_open(storage, list, name, flags);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen else if (errno == ENOENT) {
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen if (strcmp(name, "INBOX") == 0) {
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen /* INBOX always exists, create it */
1701e3f91107051b1704721bf1dc1e32491faaf9Timo Sirainen if (create_cydir(storage, list->ns, path) < 0) {
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen mailbox_list_set_error_from_storage(list,
63e207529879438e9f4412d97cdc34bdc82a3702Timo Sirainen storage);
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen return NULL;
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen }
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen return cydir_open(storage, list, "INBOX", flags);
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen }
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen mail_storage_set_error(storage, MAIL_ERROR_NOTFOUND,
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen T_MAIL_ERR_MAILBOX_NOT_FOUND(name));
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen } else if (errno == EACCES) {
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen mail_storage_set_critical(storage, "%s",
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen mail_error_eacces_msg("stat", path));
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen } else {
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen mail_storage_set_critical(storage, "stat(%s) failed: %m",
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen path);
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen }
1701e3f91107051b1704721bf1dc1e32491faaf9Timo Sirainen return NULL;
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen}
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainenstatic int
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainencydir_mailbox_create(struct mail_storage *storage, struct mailbox_list *list,
76b91bac787101e6b0075122ab6478dd98c8a884Timo Sirainen const char *name, bool directory ATTR_UNUSED)
76b91bac787101e6b0075122ab6478dd98c8a884Timo Sirainen{
76b91bac787101e6b0075122ab6478dd98c8a884Timo Sirainen const char *path;
3fe67ec75ccae1230bb9eb9f16affc48377f6441Timo Sirainen struct stat st;
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen path = mailbox_list_get_path(list, name,
2a6dcd984104fed84bed8795ccdfabb20e41ce52Timo Sirainen MAILBOX_LIST_PATH_TYPE_MAILBOX);
2a6dcd984104fed84bed8795ccdfabb20e41ce52Timo Sirainen if (stat(path, &st) == 0) {
2a6dcd984104fed84bed8795ccdfabb20e41ce52Timo Sirainen mail_storage_set_error(storage, MAIL_ERROR_EXISTS,
2a6dcd984104fed84bed8795ccdfabb20e41ce52Timo Sirainen "Mailbox already exists");
2a6dcd984104fed84bed8795ccdfabb20e41ce52Timo Sirainen return -1;
5da1aa5197a43d83f0fb3eeb83125c7cd73d1b62Timo Sirainen }
5da1aa5197a43d83f0fb3eeb83125c7cd73d1b62Timo Sirainen
5da1aa5197a43d83f0fb3eeb83125c7cd73d1b62Timo Sirainen return create_cydir(storage, list->ns, path);
2a6dcd984104fed84bed8795ccdfabb20e41ce52Timo Sirainen}
2a6dcd984104fed84bed8795ccdfabb20e41ce52Timo Sirainen
2a6dcd984104fed84bed8795ccdfabb20e41ce52Timo Sirainenstatic int
2a6dcd984104fed84bed8795ccdfabb20e41ce52Timo Sirainencydir_delete_nonrecursive(struct mailbox_list *list, const char *path,
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen const char *name)
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen{
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen DIR *dir;
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen struct dirent *d;
5214b67a7dabab87da74e04bb8b227f94b95bce4Timo Sirainen string_t *full_path;
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen unsigned int dir_len;
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen bool unlinked_something = FALSE;
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen
27586e4785d56aeb76e1fd96af8db799688dc64aTimo Sirainen dir = opendir(path);
360123b1b41b7aa8af6c4a91c39046be646cd349Timo Sirainen if (dir == NULL) {
12b4dbf933ee54f7b96968ba150095baa985fdafTimo Sirainen if (!mailbox_list_set_error_from_errno(list)) {
12b4dbf933ee54f7b96968ba150095baa985fdafTimo Sirainen mailbox_list_set_critical(list,
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen "opendir(%s) failed: %m", path);
5214b67a7dabab87da74e04bb8b227f94b95bce4Timo Sirainen }
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen return -1;
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen }
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen full_path = t_str_new(256);
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen str_append(full_path, path);
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen str_append_c(full_path, '/');
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen dir_len = str_len(full_path);
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen
1c1cecd3dfaf71b0c9499b044023e631841e88aaTimo Sirainen errno = 0;
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen while ((d = readdir(dir)) != NULL) {
917498e6f84969d2b93410c1e479735abe8e0ed7Timo Sirainen if (d->d_name[0] == '.') {
917498e6f84969d2b93410c1e479735abe8e0ed7Timo Sirainen /* skip . and .. */
917498e6f84969d2b93410c1e479735abe8e0ed7Timo Sirainen if (d->d_name[1] == '\0')
917498e6f84969d2b93410c1e479735abe8e0ed7Timo Sirainen continue;
917498e6f84969d2b93410c1e479735abe8e0ed7Timo Sirainen if (d->d_name[1] == '.' && d->d_name[2] == '\0')
917498e6f84969d2b93410c1e479735abe8e0ed7Timo Sirainen continue;
917498e6f84969d2b93410c1e479735abe8e0ed7Timo Sirainen }
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen
5da1aa5197a43d83f0fb3eeb83125c7cd73d1b62Timo Sirainen str_truncate(full_path, dir_len);
e5acc283bf030b0b5c79ca4e52d315c516a299faPascal Volk str_append(full_path, d->d_name);
e5acc283bf030b0b5c79ca4e52d315c516a299faPascal Volk
e5acc283bf030b0b5c79ca4e52d315c516a299faPascal Volk /* trying to unlink() a directory gives either EPERM or EISDIR
5da1aa5197a43d83f0fb3eeb83125c7cd73d1b62Timo Sirainen (non-POSIX). it doesn't really work anywhere in practise,
e5acc283bf030b0b5c79ca4e52d315c516a299faPascal Volk so don't bother stat()ing the file first */
e5acc283bf030b0b5c79ca4e52d315c516a299faPascal Volk if (unlink(str_c(full_path)) == 0)
e5acc283bf030b0b5c79ca4e52d315c516a299faPascal Volk unlinked_something = TRUE;
7920a47321690c932ffd4d286cd16b4048d22d41Timo Sirainen else if (errno != ENOENT && errno != EISDIR && errno != EPERM) {
7920a47321690c932ffd4d286cd16b4048d22d41Timo Sirainen mailbox_list_set_critical(list, "unlink(%s) failed: %m",
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen str_c(full_path));
db8b0a3f74a20528d66a3c4be7df920e5c4554c2Timo Sirainen }
db8b0a3f74a20528d66a3c4be7df920e5c4554c2Timo Sirainen }
db8b0a3f74a20528d66a3c4be7df920e5c4554c2Timo Sirainen
db8b0a3f74a20528d66a3c4be7df920e5c4554c2Timo Sirainen if (closedir(dir) < 0) {
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen mailbox_list_set_critical(list, "closedir(%s) failed: %m",
5666a3d6a7ea89362b8d9e8b39b15424cd9d6388Timo Sirainen path);
1701e3f91107051b1704721bf1dc1e32491faaf9Timo Sirainen }
1701e3f91107051b1704721bf1dc1e32491faaf9Timo Sirainen
1701e3f91107051b1704721bf1dc1e32491faaf9Timo Sirainen if (rmdir(path) == 0)
0bf25546c91ccafff9e2cc93368d2d25acb5c39eTimo Sirainen unlinked_something = TRUE;
94b0ff77495c3ed14bdd4b5d7ae1eb37e8c9efb5Timo Sirainen else if (errno != ENOENT && errno != ENOTEMPTY) {
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen mailbox_list_set_critical(list, "rmdir(%s) failed: %m", path);
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen return -1;
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen }
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen if (!unlinked_something) {
0bf25546c91ccafff9e2cc93368d2d25acb5c39eTimo Sirainen mailbox_list_set_error(list, MAIL_ERROR_NOTFOUND,
0bf25546c91ccafff9e2cc93368d2d25acb5c39eTimo Sirainen t_strdup_printf("Directory %s isn't empty, "
0bf25546c91ccafff9e2cc93368d2d25acb5c39eTimo Sirainen "can't delete it.", name));
94b0ff77495c3ed14bdd4b5d7ae1eb37e8c9efb5Timo Sirainen return -1;
94b0ff77495c3ed14bdd4b5d7ae1eb37e8c9efb5Timo Sirainen }
94b0ff77495c3ed14bdd4b5d7ae1eb37e8c9efb5Timo Sirainen return 0;
94b0ff77495c3ed14bdd4b5d7ae1eb37e8c9efb5Timo Sirainen}
94b0ff77495c3ed14bdd4b5d7ae1eb37e8c9efb5Timo Sirainen
94b0ff77495c3ed14bdd4b5d7ae1eb37e8c9efb5Timo Sirainenstatic int
94b0ff77495c3ed14bdd4b5d7ae1eb37e8c9efb5Timo Sirainencydir_list_delete_mailbox(struct mailbox_list *list, const char *name)
94b0ff77495c3ed14bdd4b5d7ae1eb37e8c9efb5Timo Sirainen{
94b0ff77495c3ed14bdd4b5d7ae1eb37e8c9efb5Timo Sirainen struct cydir_mailbox_list *mlist = CYDIR_LIST_CONTEXT(list);
b365bd121cdc87f63e1dd47c5085a27091118e00Timo Sirainen struct stat st;
94b0ff77495c3ed14bdd4b5d7ae1eb37e8c9efb5Timo Sirainen const char *src;
94b0ff77495c3ed14bdd4b5d7ae1eb37e8c9efb5Timo Sirainen
94b0ff77495c3ed14bdd4b5d7ae1eb37e8c9efb5Timo Sirainen /* Make sure the indexes are closed before trying to delete the
94b0ff77495c3ed14bdd4b5d7ae1eb37e8c9efb5Timo Sirainen directory that contains them. It can still fail with some NFS
94b0ff77495c3ed14bdd4b5d7ae1eb37e8c9efb5Timo Sirainen implementations if indexes are opened by another session, but
02e61e13a8360a9d3ec92c5fa5ae60c0f0181b71Timo Sirainen that can't really be helped. */
02e61e13a8360a9d3ec92c5fa5ae60c0f0181b71Timo Sirainen index_storage_destroy_unrefed();
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen /* delete the index and control directories */
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen if (mlist->module_ctx.super.delete_mailbox(list, name) < 0)
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen return -1;
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen /* check if the mailbox actually exists */
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen src = mailbox_list_get_path(list, name, MAILBOX_LIST_PATH_TYPE_MAILBOX);
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen if (stat(src, &st) != 0 && errno == ENOENT) {
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen mailbox_list_set_error(list, MAIL_ERROR_NOTFOUND,
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen T_MAIL_ERR_MAILBOX_NOT_FOUND(name));
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen return -1;
5c597df6aa8d81de4053c6986fab7739f3b44b20Timo Sirainen }
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen return cydir_delete_nonrecursive(list, src, name);
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen}
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainenstatic void cydir_notify_changes(struct mailbox *box)
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen{
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen struct cydir_mailbox *mbox = (struct cydir_mailbox *)box;
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen if (box->notify_callback == NULL)
0bf25546c91ccafff9e2cc93368d2d25acb5c39eTimo Sirainen index_mailbox_check_remove_all(&mbox->ibox);
0bf25546c91ccafff9e2cc93368d2d25acb5c39eTimo Sirainen else
0bf25546c91ccafff9e2cc93368d2d25acb5c39eTimo Sirainen index_mailbox_check_add(&mbox->ibox, mbox->path);
0bf25546c91ccafff9e2cc93368d2d25acb5c39eTimo Sirainen}
0bf25546c91ccafff9e2cc93368d2d25acb5c39eTimo Sirainen
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainenstatic int cydir_list_iter_is_mailbox(struct mailbox_list_iterate_context *ctx
94b0ff77495c3ed14bdd4b5d7ae1eb37e8c9efb5Timo Sirainen ATTR_UNUSED,
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen const char *dir, const char *fname,
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen const char *mailbox_name ATTR_UNUSED,
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen enum mailbox_list_file_type type,
b365bd121cdc87f63e1dd47c5085a27091118e00Timo Sirainen enum mailbox_info_flags *flags)
5214b67a7dabab87da74e04bb8b227f94b95bce4Timo Sirainen{
5214b67a7dabab87da74e04bb8b227f94b95bce4Timo Sirainen const char *mail_path;
b365bd121cdc87f63e1dd47c5085a27091118e00Timo Sirainen struct stat st;
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen int ret = 1;
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen /* try to avoid stat() with these checks */
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen if (type != MAILBOX_LIST_FILE_TYPE_DIR &&
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen type != MAILBOX_LIST_FILE_TYPE_SYMLINK &&
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen type != MAILBOX_LIST_FILE_TYPE_UNKNOWN) {
0bf25546c91ccafff9e2cc93368d2d25acb5c39eTimo Sirainen /* it's a file */
94b0ff77495c3ed14bdd4b5d7ae1eb37e8c9efb5Timo Sirainen *flags |= MAILBOX_NOSELECT | MAILBOX_NOINFERIORS;
02e61e13a8360a9d3ec92c5fa5ae60c0f0181b71Timo Sirainen return 0;
02e61e13a8360a9d3ec92c5fa5ae60c0f0181b71Timo Sirainen }
c58c12049c883b281c088d47a2a7278c21c390e1Timo Sirainen
c58c12049c883b281c088d47a2a7278c21c390e1Timo Sirainen /* need to stat() then */
c58c12049c883b281c088d47a2a7278c21c390e1Timo Sirainen mail_path = t_strconcat(dir, "/", fname, NULL);
c58c12049c883b281c088d47a2a7278c21c390e1Timo Sirainen if (stat(mail_path, &st) == 0) {
c58c12049c883b281c088d47a2a7278c21c390e1Timo Sirainen if (!S_ISDIR(st.st_mode)) {
c58c12049c883b281c088d47a2a7278c21c390e1Timo Sirainen /* non-directory */
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen *flags |= MAILBOX_NOSELECT | MAILBOX_NOINFERIORS;
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen ret = 0;
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen } else if (st.st_nlink == 2) {
1c1cecd3dfaf71b0c9499b044023e631841e88aaTimo Sirainen /* no subdirectories */
1c1cecd3dfaf71b0c9499b044023e631841e88aaTimo Sirainen *flags |= MAILBOX_NOCHILDREN;
1c1cecd3dfaf71b0c9499b044023e631841e88aaTimo Sirainen } else if (*ctx->list->set.maildir_name != '\0') {
1c1cecd3dfaf71b0c9499b044023e631841e88aaTimo Sirainen /* non-default configuration: we have one directory
1c1cecd3dfaf71b0c9499b044023e631841e88aaTimo Sirainen containing the mailboxes. if there are 3 links,
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen either this is a selectable mailbox without children
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen or non-selectable mailbox with children */
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen if (st.st_nlink > 3)
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen *flags |= MAILBOX_CHILDREN;
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen } else {
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen /* default configuration: all subdirectories are
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen child mailboxes. */
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen if (st.st_nlink > 2)
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen *flags |= MAILBOX_CHILDREN;
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen }
b365bd121cdc87f63e1dd47c5085a27091118e00Timo Sirainen } else if (errno == ENOENT) {
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen /* doesn't exist - probably a non-existing subscribed mailbox */
b365bd121cdc87f63e1dd47c5085a27091118e00Timo Sirainen *flags |= MAILBOX_NONEXISTENT;
5da1aa5197a43d83f0fb3eeb83125c7cd73d1b62Timo Sirainen } else {
5da1aa5197a43d83f0fb3eeb83125c7cd73d1b62Timo Sirainen /* non-selectable. probably either access denied, or symlink
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen destination not found. don't bother logging errors. */
b365bd121cdc87f63e1dd47c5085a27091118e00Timo Sirainen *flags |= MAILBOX_NOSELECT;
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen }
b365bd121cdc87f63e1dd47c5085a27091118e00Timo Sirainen return ret;
360123b1b41b7aa8af6c4a91c39046be646cd349Timo Sirainen}
360123b1b41b7aa8af6c4a91c39046be646cd349Timo Sirainen
360123b1b41b7aa8af6c4a91c39046be646cd349Timo Sirainenstatic void cydir_class_init(void)
360123b1b41b7aa8af6c4a91c39046be646cd349Timo Sirainen{
b365bd121cdc87f63e1dd47c5085a27091118e00Timo Sirainen cydir_transaction_class_init();
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen}
b365bd121cdc87f63e1dd47c5085a27091118e00Timo Sirainen
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainenstatic void cydir_class_deinit(void)
b365bd121cdc87f63e1dd47c5085a27091118e00Timo Sirainen{
5494a6bc149da8f02fd25c0434a9d612ac33f659Timo Sirainen cydir_transaction_class_deinit();
b365bd121cdc87f63e1dd47c5085a27091118e00Timo Sirainen}
12b4dbf933ee54f7b96968ba150095baa985fdafTimo Sirainen
12b4dbf933ee54f7b96968ba150095baa985fdafTimo Sirainenstatic void cydir_storage_add_list(struct mail_storage *storage ATTR_UNUSED,
12b4dbf933ee54f7b96968ba150095baa985fdafTimo Sirainen struct mailbox_list *list)
12b4dbf933ee54f7b96968ba150095baa985fdafTimo Sirainen{
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen struct cydir_mailbox_list *mlist;
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen
02e61e13a8360a9d3ec92c5fa5ae60c0f0181b71Timo Sirainen mlist = p_new(list->pool, struct cydir_mailbox_list, 1);
0bf25546c91ccafff9e2cc93368d2d25acb5c39eTimo Sirainen mlist->module_ctx.super = list->v;
94b0ff77495c3ed14bdd4b5d7ae1eb37e8c9efb5Timo Sirainen
02e61e13a8360a9d3ec92c5fa5ae60c0f0181b71Timo Sirainen list->v.iter_is_mailbox = cydir_list_iter_is_mailbox;
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen list->v.delete_mailbox = cydir_list_delete_mailbox;
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen MODULE_CONTEXT_SET(list, cydir_mailbox_list_module, mlist);
b365bd121cdc87f63e1dd47c5085a27091118e00Timo Sirainen}
b365bd121cdc87f63e1dd47c5085a27091118e00Timo Sirainen
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainenstruct mail_storage cydir_storage = {
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen MEMBER(name) CYDIR_STORAGE_NAME,
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen MEMBER(class_flags) 0,
0bf25546c91ccafff9e2cc93368d2d25acb5c39eTimo Sirainen
0bf25546c91ccafff9e2cc93368d2d25acb5c39eTimo Sirainen {
0bf25546c91ccafff9e2cc93368d2d25acb5c39eTimo Sirainen NULL,
0bf25546c91ccafff9e2cc93368d2d25acb5c39eTimo Sirainen cydir_class_init,
0bf25546c91ccafff9e2cc93368d2d25acb5c39eTimo Sirainen cydir_class_deinit,
0bf25546c91ccafff9e2cc93368d2d25acb5c39eTimo Sirainen cydir_storage_alloc,
0bf25546c91ccafff9e2cc93368d2d25acb5c39eTimo Sirainen NULL,
0bf25546c91ccafff9e2cc93368d2d25acb5c39eTimo Sirainen index_storage_destroy,
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen cydir_storage_add_list,
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen cydir_storage_get_list_settings,
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen NULL,
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen cydir_mailbox_open,
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen cydir_mailbox_create,
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen NULL
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen }
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen};
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen
94d8e51119003d2bc5a100c663f90141f297385dTimo Sirainenstruct mailbox cydir_mailbox = {
1433bf361ddb0bba8878c8ada5726d0284edad57Timo Sirainen MEMBER(name) NULL,
1433bf361ddb0bba8878c8ada5726d0284edad57Timo Sirainen MEMBER(storage) NULL,
1433bf361ddb0bba8878c8ada5726d0284edad57Timo Sirainen MEMBER(list) NULL,
1433bf361ddb0bba8878c8ada5726d0284edad57Timo Sirainen
94d8e51119003d2bc5a100c663f90141f297385dTimo Sirainen {
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen index_storage_is_readonly,
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen index_storage_allow_new_keywords,
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen index_storage_mailbox_enable,
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen index_storage_mailbox_close,
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen index_storage_get_status,
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen NULL,
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen NULL,
94d8e51119003d2bc5a100c663f90141f297385dTimo Sirainen cydir_storage_sync_init,
4a514fb20e04df397842cde11cc9ea92abfe9728Timo Sirainen index_mailbox_sync_next,
94d8e51119003d2bc5a100c663f90141f297385dTimo Sirainen index_mailbox_sync_deinit,
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen NULL,
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen cydir_notify_changes,
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen index_transaction_begin,
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen index_transaction_commit,
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen index_transaction_rollback,
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen index_transaction_set_max_modseq,
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen index_keywords_create,
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen index_keywords_free,
0bf25546c91ccafff9e2cc93368d2d25acb5c39eTimo Sirainen index_keyword_is_valid,
0bf25546c91ccafff9e2cc93368d2d25acb5c39eTimo Sirainen index_storage_get_seq_range,
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen index_storage_get_uid_range,
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen index_storage_get_expunged_uids,
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen NULL,
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen NULL,
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen NULL,
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen index_mail_alloc,
d508ab8db2b0f74b5e225d199b4aaa5293342746Timo Sirainen index_header_lookup_init,
d508ab8db2b0f74b5e225d199b4aaa5293342746Timo Sirainen index_header_lookup_ref,
d508ab8db2b0f74b5e225d199b4aaa5293342746Timo Sirainen index_header_lookup_unref,
d508ab8db2b0f74b5e225d199b4aaa5293342746Timo Sirainen index_storage_search_init,
d508ab8db2b0f74b5e225d199b4aaa5293342746Timo Sirainen index_storage_search_deinit,
d508ab8db2b0f74b5e225d199b4aaa5293342746Timo Sirainen index_storage_search_next_nonblock,
d508ab8db2b0f74b5e225d199b4aaa5293342746Timo Sirainen index_storage_search_next_update_seq,
d508ab8db2b0f74b5e225d199b4aaa5293342746Timo Sirainen cydir_save_alloc,
d508ab8db2b0f74b5e225d199b4aaa5293342746Timo Sirainen cydir_save_begin,
d508ab8db2b0f74b5e225d199b4aaa5293342746Timo Sirainen cydir_save_continue,
d508ab8db2b0f74b5e225d199b4aaa5293342746Timo Sirainen cydir_save_finish,
d508ab8db2b0f74b5e225d199b4aaa5293342746Timo Sirainen cydir_save_cancel,
d508ab8db2b0f74b5e225d199b4aaa5293342746Timo Sirainen mail_storage_copy,
d508ab8db2b0f74b5e225d199b4aaa5293342746Timo Sirainen index_storage_is_inconsistent
d508ab8db2b0f74b5e225d199b4aaa5293342746Timo Sirainen }
d508ab8db2b0f74b5e225d199b4aaa5293342746Timo Sirainen};
d508ab8db2b0f74b5e225d199b4aaa5293342746Timo Sirainen