cydir-storage.c revision 563273bdac80393af63b9520cbf4d24cc0efd028
45312f52ff3a3d4c137447be4c7556500c2f8bf2Timo Sirainen/* Copyright (c) 2007-2009 Dovecot authors, see the included COPYING file */
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen#include "lib.h"
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen#include "array.h"
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen#include "str.h"
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen#include "mkdir-parents.h"
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen#include "index-mail.h"
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen#include "mail-copy.h"
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen#include "cydir-sync.h"
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen#include "cydir-storage.h"
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen#include <unistd.h>
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen#include <dirent.h>
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen#include <sys/stat.h>
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen#define CYDIR_LIST_CONTEXT(obj) \
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen MODULE_CONTEXT(obj, cydir_mailbox_list_module)
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainenstruct cydir_mailbox_list {
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen union mailbox_list_module_context module_ctx;
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen};
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainenextern struct mail_storage cydir_storage;
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainenextern struct mailbox cydir_mailbox;
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainenstatic MODULE_CONTEXT_DEFINE_INIT(cydir_mailbox_list_module,
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen &mailbox_list_module_register);
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainenstatic struct mail_storage *cydir_storage_alloc(void)
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen{
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen struct cydir_storage *storage;
f7539a17ea306191b53b8f5e752e228937df9ec3Timo Sirainen pool_t pool;
f7539a17ea306191b53b8f5e752e228937df9ec3Timo Sirainen
f7539a17ea306191b53b8f5e752e228937df9ec3Timo Sirainen pool = pool_alloconly_create("cydir storage", 512+256);
f7539a17ea306191b53b8f5e752e228937df9ec3Timo Sirainen storage = p_new(pool, struct cydir_storage, 1);
f7539a17ea306191b53b8f5e752e228937df9ec3Timo Sirainen storage->storage = cydir_storage;
f7539a17ea306191b53b8f5e752e228937df9ec3Timo Sirainen storage->storage.pool = pool;
f7539a17ea306191b53b8f5e752e228937df9ec3Timo Sirainen return &storage->storage;
f7539a17ea306191b53b8f5e752e228937df9ec3Timo Sirainen}
f7539a17ea306191b53b8f5e752e228937df9ec3Timo Sirainen
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainenstatic void
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainencydir_storage_get_list_settings(const struct mail_namespace *ns ATTR_UNUSED,
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen struct mailbox_list_settings *set)
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen{
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen if (set->layout == NULL)
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen set->layout = MAILBOX_LIST_NAME_FS;
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen if (set->subscription_fname == NULL)
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen set->subscription_fname = CYDIR_SUBSCRIPTION_FILE_NAME;
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen}
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainenstatic int create_cydir(struct mail_storage *storage, struct mail_namespace *ns,
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen const char *path)
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen{
fea7b8b3fc182e415b1875d79587c0aa1adb09d7Timo Sirainen mode_t mode;
fea7b8b3fc182e415b1875d79587c0aa1adb09d7Timo Sirainen gid_t gid;
fea7b8b3fc182e415b1875d79587c0aa1adb09d7Timo Sirainen
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen mailbox_list_get_dir_permissions(ns->list, NULL, &mode, &gid);
fea7b8b3fc182e415b1875d79587c0aa1adb09d7Timo Sirainen if (mkdir_parents_chown(path, mode, (uid_t)-1, gid) < 0 &&
fea7b8b3fc182e415b1875d79587c0aa1adb09d7Timo Sirainen errno != EEXIST) {
ff7056842f14fd3b30a2d327dfab165b9d15dd30Timo Sirainen if (!mail_storage_set_error_from_errno(storage)) {
ff7056842f14fd3b30a2d327dfab165b9d15dd30Timo Sirainen mail_storage_set_critical(storage,
ff7056842f14fd3b30a2d327dfab165b9d15dd30Timo Sirainen "mkdir(%s) failed: %m", path);
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen }
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen return -1;
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen }
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen return 0;
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen}
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainenstatic struct mailbox *
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainencydir_open(struct mail_storage *storage, struct mailbox_list *list,
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen const char *name, enum mailbox_open_flags flags)
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen{
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen struct cydir_mailbox *mbox;
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen struct mail_index *index;
c72d5f1aa95544dbfbc66d72bfa3205f8876d91cTimo Sirainen const char *path;
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen pool_t pool;
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen path = mailbox_list_get_path(list, name,
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen MAILBOX_LIST_PATH_TYPE_MAILBOX);
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen index = index_storage_alloc(list, name, flags, CYDIR_INDEX_PREFIX);
ab8cf8fb93579981a687942e53bdb361b3b61bafTimo Sirainen mail_index_set_fsync_types(index, MAIL_INDEX_SYNC_TYPE_APPEND |
ab8cf8fb93579981a687942e53bdb361b3b61bafTimo Sirainen MAIL_INDEX_SYNC_TYPE_EXPUNGE);
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen pool = pool_alloconly_create("cydir mailbox", 1024+512);
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen mbox = p_new(pool, struct cydir_mailbox, 1);
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen mbox->ibox.box = cydir_mailbox;
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen mbox->ibox.box.pool = pool;
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen mbox->ibox.box.storage = storage;
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen mbox->ibox.mail_vfuncs = &cydir_mail_vfuncs;
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen mbox->ibox.index = index;
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen mbox->storage = (struct cydir_storage *)storage;
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen mbox->path = p_strdup(pool, path);
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen index_storage_mailbox_init(&mbox->ibox, name, flags, FALSE);
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen return &mbox->ibox.box;
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen}
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainenstatic struct mailbox *
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainencydir_mailbox_open(struct mail_storage *storage, struct mailbox_list *list,
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen const char *name, struct istream *input,
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen enum mailbox_open_flags flags)
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen{
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen const char *path;
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen struct stat st;
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen if (input != NULL) {
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen mailbox_list_set_critical(list,
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen "cydir doesn't support streamed mailboxes");
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen return NULL;
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen }
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen path = mailbox_list_get_path(list, name,
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen MAILBOX_LIST_PATH_TYPE_MAILBOX);
32ee977e189266744ef69ac4e832fd3111d6f949Timo Sirainen if (stat(path, &st) == 0)
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen return cydir_open(storage, list, name, flags);
32ee977e189266744ef69ac4e832fd3111d6f949Timo Sirainen else if (errno == ENOENT) {
32ee977e189266744ef69ac4e832fd3111d6f949Timo Sirainen if (strcmp(name, "INBOX") == 0) {
32ee977e189266744ef69ac4e832fd3111d6f949Timo Sirainen /* INBOX always exists, create it */
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen if (create_cydir(storage, list->ns, path) < 0) {
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen mailbox_list_set_error_from_storage(list,
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen storage);
32ee977e189266744ef69ac4e832fd3111d6f949Timo Sirainen return NULL;
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen }
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen return cydir_open(storage, list, "INBOX", flags);
32ee977e189266744ef69ac4e832fd3111d6f949Timo Sirainen }
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen mail_storage_set_error(storage, MAIL_ERROR_NOTFOUND,
ff7056842f14fd3b30a2d327dfab165b9d15dd30Timo Sirainen T_MAIL_ERR_MAILBOX_NOT_FOUND(name));
b42697a5749b85659a24316d97f1c208d469e4e8Timo Sirainen } else if (errno == EACCES) {
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen mail_storage_set_critical(storage, "%s",
9e9f0cf3cc3ce546e8a433990c92dd9be6665df6Timo Sirainen mail_error_eacces_msg("stat", path));
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen } else {
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen mail_storage_set_critical(storage, "stat(%s) failed: %m",
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen path);
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen }
b42697a5749b85659a24316d97f1c208d469e4e8Timo Sirainen return NULL;
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen}
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainenstatic int
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainencydir_mailbox_create(struct mail_storage *storage, struct mailbox_list *list,
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen const char *name, bool directory ATTR_UNUSED)
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen{
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen const char *path;
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen struct stat st;
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen path = mailbox_list_get_path(list, name,
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen MAILBOX_LIST_PATH_TYPE_MAILBOX);
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen if (stat(path, &st) == 0) {
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen mail_storage_set_error(storage, MAIL_ERROR_EXISTS,
ff7056842f14fd3b30a2d327dfab165b9d15dd30Timo Sirainen "Mailbox already exists");
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen return -1;
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen }
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen return create_cydir(storage, list->ns, path);
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen}
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainenstatic int
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainencydir_delete_nonrecursive(struct mailbox_list *list, const char *path,
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen const char *name)
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen{
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen DIR *dir;
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen struct dirent *d;
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen string_t *full_path;
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen unsigned int dir_len;
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen bool unlinked_something = FALSE;
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen dir = opendir(path);
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen if (dir == NULL) {
ff7056842f14fd3b30a2d327dfab165b9d15dd30Timo Sirainen if (!mailbox_list_set_error_from_errno(list)) {
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen mailbox_list_set_critical(list,
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen "opendir(%s) failed: %m", path);
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen }
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen return -1;
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen }
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen full_path = t_str_new(256);
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen str_append(full_path, path);
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen str_append_c(full_path, '/');
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen dir_len = str_len(full_path);
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen errno = 0;
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen while ((d = readdir(dir)) != NULL) {
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen if (d->d_name[0] == '.') {
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen /* skip . and .. */
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen if (d->d_name[1] == '\0')
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen continue;
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen if (d->d_name[1] == '.' && d->d_name[2] == '\0')
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen continue;
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen }
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen str_truncate(full_path, dir_len);
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen str_append(full_path, d->d_name);
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen /* trying to unlink() a directory gives either EPERM or EISDIR
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen (non-POSIX). it doesn't really work anywhere in practise,
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen so don't bother stat()ing the file first */
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen if (unlink(str_c(full_path)) == 0)
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen unlinked_something = TRUE;
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen else if (errno != ENOENT && errno != EISDIR && errno != EPERM) {
71c4ac143fefd57aeec6298489c4559b6f13c67bTimo Sirainen mailbox_list_set_critical(list, "unlink(%s) failed: %m",
71c4ac143fefd57aeec6298489c4559b6f13c67bTimo Sirainen str_c(full_path));
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen }
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen }
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen if (closedir(dir) < 0) {
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen mailbox_list_set_critical(list, "closedir(%s) failed: %m",
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen path);
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen }
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen if (rmdir(path) == 0)
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen unlinked_something = TRUE;
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen else if (errno != ENOENT && errno != ENOTEMPTY) {
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen mailbox_list_set_critical(list, "rmdir(%s) failed: %m", path);
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen return -1;
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen }
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen if (!unlinked_something) {
4321f6c969e7b8f6b243ff5bb6b8d297921676f6Timo Sirainen mailbox_list_set_error(list, MAIL_ERROR_NOTFOUND,
ff7056842f14fd3b30a2d327dfab165b9d15dd30Timo Sirainen t_strdup_printf("Directory %s isn't empty, "
ff7056842f14fd3b30a2d327dfab165b9d15dd30Timo Sirainen "can't delete it.", name));
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen return -1;
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen }
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen return 0;
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen}
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainenstatic int
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainencydir_list_delete_mailbox(struct mailbox_list *list, const char *name)
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen{
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen struct cydir_mailbox_list *mlist = CYDIR_LIST_CONTEXT(list);
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen struct stat st;
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen const char *src;
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen /* Make sure the indexes are closed before trying to delete the
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen directory that contains them. It can still fail with some NFS
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen implementations if indexes are opened by another session, but
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen that can't really be helped. */
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen index_storage_destroy_unrefed();
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen /* delete the index and control directories */
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen if (mlist->module_ctx.super.delete_mailbox(list, name) < 0)
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen return -1;
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen /* check if the mailbox actually exists */
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen src = mailbox_list_get_path(list, name, MAILBOX_LIST_PATH_TYPE_MAILBOX);
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen if (stat(src, &st) != 0 && errno == ENOENT) {
ff7056842f14fd3b30a2d327dfab165b9d15dd30Timo Sirainen mailbox_list_set_error(list, MAIL_ERROR_NOTFOUND,
ff7056842f14fd3b30a2d327dfab165b9d15dd30Timo Sirainen T_MAIL_ERR_MAILBOX_NOT_FOUND(name));
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen return -1;
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen }
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen return cydir_delete_nonrecursive(list, src, name);
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen}
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen
f81f4bc282cd1944cec187bae89c0701a416ed2aTimo Sirainenstatic void cydir_notify_changes(struct mailbox *box)
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen{
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen struct cydir_mailbox *mbox = (struct cydir_mailbox *)box;
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen
f81f4bc282cd1944cec187bae89c0701a416ed2aTimo Sirainen if (box->notify_callback == NULL)
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen index_mailbox_check_remove_all(&mbox->ibox);
f81f4bc282cd1944cec187bae89c0701a416ed2aTimo Sirainen else
f81f4bc282cd1944cec187bae89c0701a416ed2aTimo Sirainen index_mailbox_check_add(&mbox->ibox, mbox->path);
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen}
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen
cc0bb7692b8a47abca3279abbb49b073f7a27f21Timo Sirainenstatic int cydir_list_iter_is_mailbox(struct mailbox_list_iterate_context *ctx
43d32cbe60fdaef2699d99f1ca259053e9350411Timo Sirainen ATTR_UNUSED,
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen const char *dir, const char *fname,
7230352f1177a8ed2b924c6992e751fd2ab9bc27Timo Sirainen const char *mailbox_name ATTR_UNUSED,
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen enum mailbox_list_file_type type,
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen enum mailbox_info_flags *flags)
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen{
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen const char *mail_path;
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen struct stat st;
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen int ret = 1;
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen /* try to avoid stat() with these checks */
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen if (type != MAILBOX_LIST_FILE_TYPE_DIR &&
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen type != MAILBOX_LIST_FILE_TYPE_SYMLINK &&
cc0bb7692b8a47abca3279abbb49b073f7a27f21Timo Sirainen type != MAILBOX_LIST_FILE_TYPE_UNKNOWN) {
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen /* it's a file */
cc0bb7692b8a47abca3279abbb49b073f7a27f21Timo Sirainen *flags |= MAILBOX_NOSELECT | MAILBOX_NOINFERIORS;
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen return 0;
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen }
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen /* need to stat() then */
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen mail_path = t_strconcat(dir, "/", fname, NULL);
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen if (stat(mail_path, &st) == 0) {
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen if (!S_ISDIR(st.st_mode)) {
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen /* non-directory */
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen *flags |= MAILBOX_NOSELECT | MAILBOX_NOINFERIORS;
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen ret = 0;
34f284752605dafdc7aefc343bb5b6cd2d2184b5Timo Sirainen } else if (st.st_nlink == 2) {
34f284752605dafdc7aefc343bb5b6cd2d2184b5Timo Sirainen /* no subdirectories */
34f284752605dafdc7aefc343bb5b6cd2d2184b5Timo Sirainen *flags |= MAILBOX_NOCHILDREN;
34f284752605dafdc7aefc343bb5b6cd2d2184b5Timo Sirainen } else if (*ctx->list->set.maildir_name != '\0') {
34f284752605dafdc7aefc343bb5b6cd2d2184b5Timo Sirainen /* non-default configuration: we have one directory
34f284752605dafdc7aefc343bb5b6cd2d2184b5Timo Sirainen containing the mailboxes. if there are 3 links,
34f284752605dafdc7aefc343bb5b6cd2d2184b5Timo Sirainen either this is a selectable mailbox without children
34f284752605dafdc7aefc343bb5b6cd2d2184b5Timo Sirainen or non-selectable mailbox with children */
34f284752605dafdc7aefc343bb5b6cd2d2184b5Timo Sirainen if (st.st_nlink > 3)
34f284752605dafdc7aefc343bb5b6cd2d2184b5Timo Sirainen *flags |= MAILBOX_CHILDREN;
34f284752605dafdc7aefc343bb5b6cd2d2184b5Timo Sirainen } else {
34f284752605dafdc7aefc343bb5b6cd2d2184b5Timo Sirainen /* default configuration: all subdirectories are
34f284752605dafdc7aefc343bb5b6cd2d2184b5Timo Sirainen child mailboxes. */
34f284752605dafdc7aefc343bb5b6cd2d2184b5Timo Sirainen if (st.st_nlink > 2)
34f284752605dafdc7aefc343bb5b6cd2d2184b5Timo Sirainen *flags |= MAILBOX_CHILDREN;
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen }
c2ced58969b446666ab1067c6bfdf495367ed621Timo Sirainen } else if (errno == ENOENT) {
c2ced58969b446666ab1067c6bfdf495367ed621Timo Sirainen /* doesn't exist - probably a non-existing subscribed mailbox */
c2ced58969b446666ab1067c6bfdf495367ed621Timo Sirainen *flags |= MAILBOX_NONEXISTENT;
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen } else {
cc0bb7692b8a47abca3279abbb49b073f7a27f21Timo Sirainen /* non-selectable. probably either access denied, or symlink
cc0bb7692b8a47abca3279abbb49b073f7a27f21Timo Sirainen destination not found. don't bother logging errors. */
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen *flags |= MAILBOX_NOSELECT;
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen }
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen return ret;
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen}
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainenstatic void cydir_class_init(void)
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen{
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen cydir_transaction_class_init();
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen}
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainenstatic void cydir_class_deinit(void)
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen{
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen cydir_transaction_class_deinit();
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen}
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen
563273bdac80393af63b9520cbf4d24cc0efd028Timo Sirainenstatic void cydir_storage_add_list(struct mail_storage *storage ATTR_UNUSED,
563273bdac80393af63b9520cbf4d24cc0efd028Timo Sirainen struct mailbox_list *list)
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen{
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen struct cydir_mailbox_list *mlist;
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen mlist = p_new(list->pool, struct cydir_mailbox_list, 1);
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen mlist->module_ctx.super = list->v;
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen list->v.iter_is_mailbox = cydir_list_iter_is_mailbox;
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen list->v.delete_mailbox = cydir_list_delete_mailbox;
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen MODULE_CONTEXT_SET(list, cydir_mailbox_list_module, mlist);
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen}
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainenstruct mail_storage cydir_storage = {
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen MEMBER(name) CYDIR_STORAGE_NAME,
563273bdac80393af63b9520cbf4d24cc0efd028Timo Sirainen MEMBER(class_flags) 0,
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen {
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen NULL,
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen cydir_class_init,
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen cydir_class_deinit,
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen cydir_storage_alloc,
563273bdac80393af63b9520cbf4d24cc0efd028Timo Sirainen NULL,
a2a08c191a33bfaa758f9c68cafec2521b9a4472Timo Sirainen index_storage_destroy,
563273bdac80393af63b9520cbf4d24cc0efd028Timo Sirainen cydir_storage_add_list,
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen cydir_storage_get_list_settings,
1108376e39a19912e8394e64e19b1bc6f6691cf6Timo Sirainen NULL,
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen cydir_mailbox_open,
3e564425db51f3921ce4de11859777135fdedd15Timo Sirainen cydir_mailbox_create,
3e564425db51f3921ce4de11859777135fdedd15Timo Sirainen NULL
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen }
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen};
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainenstruct mailbox cydir_mailbox = {
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen MEMBER(name) NULL,
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen MEMBER(storage) NULL,
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen MEMBER(list) NULL,
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen {
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen index_storage_is_readonly,
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen index_storage_allow_new_keywords,
a2f250a332dfc1e6cd4ffd196c621eb9dbf7b8a1Timo Sirainen index_storage_mailbox_enable,
09c08fad8e7cc694a6c8d1711e67839acd3a2f04Timo Sirainen index_storage_mailbox_close,
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen index_storage_get_status,
d3442384ca53d4b18a493db7dd0b000f470419cfTimo Sirainen NULL,
d3442384ca53d4b18a493db7dd0b000f470419cfTimo Sirainen NULL,
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen cydir_storage_sync_init,
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen index_mailbox_sync_next,
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen index_mailbox_sync_deinit,
5137d2d80255938a0f5fb8f3c1a21b34cf11ada3Timo Sirainen NULL,
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen cydir_notify_changes,
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen index_transaction_begin,
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen index_transaction_commit,
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen index_transaction_rollback,
48270badadd82279bfe50ae3d187aea8b0b2b30eTimo Sirainen index_transaction_set_max_modseq,
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen index_keywords_create,
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen index_keywords_free,
e3796bfd2bc0fd5ba664893d346df9334a5b3af0Timo Sirainen index_keyword_is_valid,
5afa8e2edf4f313cd56e5909f92f39c3b5b7b4d3Timo Sirainen index_storage_get_seq_range,
408e5be344c9131fdebe771718a5bf49f88cc51cTimo Sirainen index_storage_get_uid_range,
923eb3dde28e4d8841c14fd6b4a69635b7070c3eTimo Sirainen index_storage_get_expunged_uids,
ecdce39e5ef4b62eefa9f5818f17d153fd5d710aTimo Sirainen NULL,
3852872e6954b7132e637294132005e86b8ebd4aTimo Sirainen NULL,
3852872e6954b7132e637294132005e86b8ebd4aTimo Sirainen NULL,
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen index_mail_alloc,
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen index_header_lookup_init,
f95b3d29bc56f139c18c880aa574a0ca72b0cffbTimo Sirainen index_header_lookup_ref,
f95b3d29bc56f139c18c880aa574a0ca72b0cffbTimo Sirainen index_header_lookup_unref,
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen index_storage_search_init,
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen index_storage_search_deinit,
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen index_storage_search_next_nonblock,
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen index_storage_search_next_update_seq,
e3aeeb634245e80d4f643f8d2eea11d6b72336d8Timo Sirainen cydir_save_alloc,
e3aeeb634245e80d4f643f8d2eea11d6b72336d8Timo Sirainen cydir_save_begin,
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen cydir_save_continue,
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen cydir_save_finish,
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen cydir_save_cancel,
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen mail_storage_copy,
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen index_storage_is_inconsistent
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen }
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen};