cydir-storage.c revision 6bc5fed79741503437c6d46d9f282b66bd029c6b
bcb4e51a409d94ae670de96afb8483a4f7855294Stephan Bosch/* Copyright (c) 2007-2009 Dovecot authors, see the included COPYING file */
5394bed8aaef2a6c1c870a34a23a7824e1f370bbStephan Bosch
5394bed8aaef2a6c1c870a34a23a7824e1f370bbStephan Bosch#include "lib.h"
5394bed8aaef2a6c1c870a34a23a7824e1f370bbStephan Bosch#include "array.h"
5394bed8aaef2a6c1c870a34a23a7824e1f370bbStephan Bosch#include "str.h"
5394bed8aaef2a6c1c870a34a23a7824e1f370bbStephan Bosch#include "mkdir-parents.h"
5394bed8aaef2a6c1c870a34a23a7824e1f370bbStephan Bosch#include "index-mail.h"
5394bed8aaef2a6c1c870a34a23a7824e1f370bbStephan Bosch#include "mail-copy.h"
5394bed8aaef2a6c1c870a34a23a7824e1f370bbStephan Bosch#include "cydir-sync.h"
5394bed8aaef2a6c1c870a34a23a7824e1f370bbStephan Bosch#include "cydir-storage.h"
5394bed8aaef2a6c1c870a34a23a7824e1f370bbStephan Bosch
5394bed8aaef2a6c1c870a34a23a7824e1f370bbStephan Bosch#include <unistd.h>
5394bed8aaef2a6c1c870a34a23a7824e1f370bbStephan Bosch#include <dirent.h>
5394bed8aaef2a6c1c870a34a23a7824e1f370bbStephan Bosch#include <sys/stat.h>
5394bed8aaef2a6c1c870a34a23a7824e1f370bbStephan Bosch
5394bed8aaef2a6c1c870a34a23a7824e1f370bbStephan Bosch#define CYDIR_LIST_CONTEXT(obj) \
5394bed8aaef2a6c1c870a34a23a7824e1f370bbStephan Bosch MODULE_CONTEXT(obj, cydir_mailbox_list_module)
5394bed8aaef2a6c1c870a34a23a7824e1f370bbStephan Bosch
5394bed8aaef2a6c1c870a34a23a7824e1f370bbStephan Boschstruct cydir_mailbox_list {
5394bed8aaef2a6c1c870a34a23a7824e1f370bbStephan Bosch union mailbox_list_module_context module_ctx;
5394bed8aaef2a6c1c870a34a23a7824e1f370bbStephan Bosch};
f74dbd3ff682fea040f60383e001620d1f1b09d3Stephan Bosch
5394bed8aaef2a6c1c870a34a23a7824e1f370bbStephan Boschextern struct mail_storage cydir_storage;
5394bed8aaef2a6c1c870a34a23a7824e1f370bbStephan Boschextern struct mailbox cydir_mailbox;
5394bed8aaef2a6c1c870a34a23a7824e1f370bbStephan Bosch
f74dbd3ff682fea040f60383e001620d1f1b09d3Stephan Boschstatic MODULE_CONTEXT_DEFINE_INIT(cydir_mailbox_list_module,
5394bed8aaef2a6c1c870a34a23a7824e1f370bbStephan Bosch &mailbox_list_module_register);
5394bed8aaef2a6c1c870a34a23a7824e1f370bbStephan Bosch
5394bed8aaef2a6c1c870a34a23a7824e1f370bbStephan Boschstatic struct mail_storage *cydir_storage_alloc(void)
f74dbd3ff682fea040f60383e001620d1f1b09d3Stephan Bosch{
f883bf3eff62f5d27df5ee9ee664edc38a77937fStephan Bosch struct cydir_storage *storage;
5394bed8aaef2a6c1c870a34a23a7824e1f370bbStephan Bosch pool_t pool;
5394bed8aaef2a6c1c870a34a23a7824e1f370bbStephan Bosch
5394bed8aaef2a6c1c870a34a23a7824e1f370bbStephan Bosch pool = pool_alloconly_create("cydir storage", 512+256);
f74dbd3ff682fea040f60383e001620d1f1b09d3Stephan Bosch storage = p_new(pool, struct cydir_storage, 1);
f74dbd3ff682fea040f60383e001620d1f1b09d3Stephan Bosch storage->storage = cydir_storage;
f74dbd3ff682fea040f60383e001620d1f1b09d3Stephan Bosch storage->storage.pool = pool;
5394bed8aaef2a6c1c870a34a23a7824e1f370bbStephan Bosch return &storage->storage;
5394bed8aaef2a6c1c870a34a23a7824e1f370bbStephan Bosch}
5394bed8aaef2a6c1c870a34a23a7824e1f370bbStephan Bosch
f74dbd3ff682fea040f60383e001620d1f1b09d3Stephan Boschstatic void
f74dbd3ff682fea040f60383e001620d1f1b09d3Stephan Boschcydir_storage_get_list_settings(const struct mail_namespace *ns ATTR_UNUSED,
f74dbd3ff682fea040f60383e001620d1f1b09d3Stephan Bosch struct mailbox_list_settings *set)
5394bed8aaef2a6c1c870a34a23a7824e1f370bbStephan Bosch{
5394bed8aaef2a6c1c870a34a23a7824e1f370bbStephan Bosch if (set->layout == NULL)
5394bed8aaef2a6c1c870a34a23a7824e1f370bbStephan Bosch set->layout = MAILBOX_LIST_NAME_FS;
f74dbd3ff682fea040f60383e001620d1f1b09d3Stephan Bosch if (set->subscription_fname == NULL)
f74dbd3ff682fea040f60383e001620d1f1b09d3Stephan Bosch set->subscription_fname = CYDIR_SUBSCRIPTION_FILE_NAME;
f74dbd3ff682fea040f60383e001620d1f1b09d3Stephan Bosch if (set->dir_guid_fname == NULL)
f883bf3eff62f5d27df5ee9ee664edc38a77937fStephan Bosch set->dir_guid_fname = CYDIR_DIR_GUID_FILE_NAME;
1e653c7406ec0b062c0bacfdf2e7568a3f860500Stephan Bosch}
1e653c7406ec0b062c0bacfdf2e7568a3f860500Stephan Bosch
1e653c7406ec0b062c0bacfdf2e7568a3f860500Stephan Boschstatic int create_cydir(struct mail_storage *storage, struct mailbox_list *list,
1e653c7406ec0b062c0bacfdf2e7568a3f860500Stephan Bosch const char *path)
f74dbd3ff682fea040f60383e001620d1f1b09d3Stephan Bosch{
f74dbd3ff682fea040f60383e001620d1f1b09d3Stephan Bosch const char *origin;
1e653c7406ec0b062c0bacfdf2e7568a3f860500Stephan Bosch mode_t mode;
1e653c7406ec0b062c0bacfdf2e7568a3f860500Stephan Bosch gid_t gid;
1e653c7406ec0b062c0bacfdf2e7568a3f860500Stephan Bosch
1e653c7406ec0b062c0bacfdf2e7568a3f860500Stephan Bosch mailbox_list_get_dir_permissions(list, NULL, &mode, &gid, &origin);
f74dbd3ff682fea040f60383e001620d1f1b09d3Stephan Bosch if (mkdir_parents_chgrp(path, mode, gid, origin) < 0 &&
1e653c7406ec0b062c0bacfdf2e7568a3f860500Stephan Bosch errno != EEXIST) {
1e653c7406ec0b062c0bacfdf2e7568a3f860500Stephan Bosch if (!mail_storage_set_error_from_errno(storage)) {
1e653c7406ec0b062c0bacfdf2e7568a3f860500Stephan Bosch mail_storage_set_critical(storage,
1e653c7406ec0b062c0bacfdf2e7568a3f860500Stephan Bosch "mkdir(%s) failed: %m", path);
1e653c7406ec0b062c0bacfdf2e7568a3f860500Stephan Bosch }
f74dbd3ff682fea040f60383e001620d1f1b09d3Stephan Bosch return -1;
1e653c7406ec0b062c0bacfdf2e7568a3f860500Stephan Bosch }
5394bed8aaef2a6c1c870a34a23a7824e1f370bbStephan Bosch return 0;
5394bed8aaef2a6c1c870a34a23a7824e1f370bbStephan Bosch}
5394bed8aaef2a6c1c870a34a23a7824e1f370bbStephan Bosch
5394bed8aaef2a6c1c870a34a23a7824e1f370bbStephan Boschstatic struct mailbox *
5394bed8aaef2a6c1c870a34a23a7824e1f370bbStephan Boschcydir_mailbox_alloc(struct mail_storage *storage, struct mailbox_list *list,
f74dbd3ff682fea040f60383e001620d1f1b09d3Stephan Bosch const char *name, struct istream *input,
5394bed8aaef2a6c1c870a34a23a7824e1f370bbStephan Bosch enum mailbox_flags flags)
bf3dbfd29e4d65f485b963bb5598b653e65b5f82Phil Carmody{
bf3dbfd29e4d65f485b963bb5598b653e65b5f82Phil Carmody struct cydir_mailbox *mbox;
bf3dbfd29e4d65f485b963bb5598b653e65b5f82Phil Carmody pool_t pool;
bf3dbfd29e4d65f485b963bb5598b653e65b5f82Phil Carmody
bf3dbfd29e4d65f485b963bb5598b653e65b5f82Phil Carmody /* cydir can't work without index files */
bf3dbfd29e4d65f485b963bb5598b653e65b5f82Phil Carmody flags &= ~MAILBOX_FLAG_NO_INDEX_FILES;
bf3dbfd29e4d65f485b963bb5598b653e65b5f82Phil Carmody
bf3dbfd29e4d65f485b963bb5598b653e65b5f82Phil Carmody pool = pool_alloconly_create("cydir mailbox", 1024+512);
bf3dbfd29e4d65f485b963bb5598b653e65b5f82Phil Carmody mbox = p_new(pool, struct cydir_mailbox, 1);
bf3dbfd29e4d65f485b963bb5598b653e65b5f82Phil Carmody mbox->ibox.box = cydir_mailbox;
bf3dbfd29e4d65f485b963bb5598b653e65b5f82Phil Carmody mbox->ibox.box.pool = pool;
bf3dbfd29e4d65f485b963bb5598b653e65b5f82Phil Carmody mbox->ibox.box.storage = storage;
f74dbd3ff682fea040f60383e001620d1f1b09d3Stephan Bosch mbox->ibox.box.list = list;
bf3dbfd29e4d65f485b963bb5598b653e65b5f82Phil Carmody mbox->ibox.mail_vfuncs = &cydir_mail_vfuncs;
bf3dbfd29e4d65f485b963bb5598b653e65b5f82Phil Carmody
bf3dbfd29e4d65f485b963bb5598b653e65b5f82Phil Carmody mbox->ibox.save_commit_pre = cydir_transaction_save_commit_pre;
bf3dbfd29e4d65f485b963bb5598b653e65b5f82Phil Carmody mbox->ibox.save_commit_post = cydir_transaction_save_commit_post;
bf3dbfd29e4d65f485b963bb5598b653e65b5f82Phil Carmody mbox->ibox.save_rollback = cydir_transaction_save_rollback;
f74dbd3ff682fea040f60383e001620d1f1b09d3Stephan Bosch
bf3dbfd29e4d65f485b963bb5598b653e65b5f82Phil Carmody index_storage_mailbox_alloc(&mbox->ibox, name, input, flags,
5394bed8aaef2a6c1c870a34a23a7824e1f370bbStephan Bosch CYDIR_INDEX_PREFIX);
5394bed8aaef2a6c1c870a34a23a7824e1f370bbStephan Bosch mail_index_set_fsync_types(mbox->ibox.index,
5394bed8aaef2a6c1c870a34a23a7824e1f370bbStephan Bosch MAIL_INDEX_SYNC_TYPE_APPEND |
5394bed8aaef2a6c1c870a34a23a7824e1f370bbStephan Bosch MAIL_INDEX_SYNC_TYPE_EXPUNGE);
5394bed8aaef2a6c1c870a34a23a7824e1f370bbStephan Bosch
f74dbd3ff682fea040f60383e001620d1f1b09d3Stephan Bosch mbox->storage = (struct cydir_storage *)storage;
5394bed8aaef2a6c1c870a34a23a7824e1f370bbStephan Bosch return &mbox->ibox.box;
5394bed8aaef2a6c1c870a34a23a7824e1f370bbStephan Bosch}
5394bed8aaef2a6c1c870a34a23a7824e1f370bbStephan Bosch
5394bed8aaef2a6c1c870a34a23a7824e1f370bbStephan Boschstatic int cydir_mailbox_open(struct mailbox *box)
5394bed8aaef2a6c1c870a34a23a7824e1f370bbStephan Bosch{
5394bed8aaef2a6c1c870a34a23a7824e1f370bbStephan Bosch struct stat st;
5394bed8aaef2a6c1c870a34a23a7824e1f370bbStephan Bosch
5394bed8aaef2a6c1c870a34a23a7824e1f370bbStephan Bosch if (box->input != NULL) {
5394bed8aaef2a6c1c870a34a23a7824e1f370bbStephan Bosch mail_storage_set_critical(box->storage,
5394bed8aaef2a6c1c870a34a23a7824e1f370bbStephan Bosch "cydir doesn't support streamed mailboxes");
5394bed8aaef2a6c1c870a34a23a7824e1f370bbStephan Bosch return -1;
5394bed8aaef2a6c1c870a34a23a7824e1f370bbStephan Bosch }
5394bed8aaef2a6c1c870a34a23a7824e1f370bbStephan Bosch
5394bed8aaef2a6c1c870a34a23a7824e1f370bbStephan Bosch if (stat(box->path, &st) == 0) {
5394bed8aaef2a6c1c870a34a23a7824e1f370bbStephan Bosch /* exists, open it */
f74dbd3ff682fea040f60383e001620d1f1b09d3Stephan Bosch } else if (errno == ENOENT && strcmp(box->name, "INBOX") == 0) {
f74dbd3ff682fea040f60383e001620d1f1b09d3Stephan Bosch /* INBOX always exists, create it */
5394bed8aaef2a6c1c870a34a23a7824e1f370bbStephan Bosch if (create_cydir(box->storage, box->list, box->path) < 0)
5394bed8aaef2a6c1c870a34a23a7824e1f370bbStephan Bosch return -1;
f74dbd3ff682fea040f60383e001620d1f1b09d3Stephan Bosch } else if (errno == ENOENT) {
f74dbd3ff682fea040f60383e001620d1f1b09d3Stephan Bosch mail_storage_set_error(box->storage, MAIL_ERROR_NOTFOUND,
5394bed8aaef2a6c1c870a34a23a7824e1f370bbStephan Bosch T_MAIL_ERR_MAILBOX_NOT_FOUND(box->name));
5394bed8aaef2a6c1c870a34a23a7824e1f370bbStephan Bosch return -1;
f74dbd3ff682fea040f60383e001620d1f1b09d3Stephan Bosch } else if (errno == EACCES) {
f74dbd3ff682fea040f60383e001620d1f1b09d3Stephan Bosch mail_storage_set_critical(box->storage, "%s",
5394bed8aaef2a6c1c870a34a23a7824e1f370bbStephan Bosch mail_error_eacces_msg("stat", box->path));
5394bed8aaef2a6c1c870a34a23a7824e1f370bbStephan Bosch return -1;
f74dbd3ff682fea040f60383e001620d1f1b09d3Stephan Bosch } else {
f74dbd3ff682fea040f60383e001620d1f1b09d3Stephan Bosch mail_storage_set_critical(box->storage, "stat(%s) failed: %m",
5394bed8aaef2a6c1c870a34a23a7824e1f370bbStephan Bosch box->path);
5394bed8aaef2a6c1c870a34a23a7824e1f370bbStephan Bosch return -1;
f74dbd3ff682fea040f60383e001620d1f1b09d3Stephan Bosch }
f74dbd3ff682fea040f60383e001620d1f1b09d3Stephan Bosch return index_storage_mailbox_open(box);
5394bed8aaef2a6c1c870a34a23a7824e1f370bbStephan Bosch}
5394bed8aaef2a6c1c870a34a23a7824e1f370bbStephan Bosch
f74dbd3ff682fea040f60383e001620d1f1b09d3Stephan Boschstatic int
f74dbd3ff682fea040f60383e001620d1f1b09d3Stephan Boschcydir_mailbox_create(struct mailbox *box, const struct mailbox_update *update,
5394bed8aaef2a6c1c870a34a23a7824e1f370bbStephan Bosch bool directory)
5394bed8aaef2a6c1c870a34a23a7824e1f370bbStephan Bosch{
f74dbd3ff682fea040f60383e001620d1f1b09d3Stephan Bosch const char *path;
f74dbd3ff682fea040f60383e001620d1f1b09d3Stephan Bosch struct stat st;
5394bed8aaef2a6c1c870a34a23a7824e1f370bbStephan Bosch
5394bed8aaef2a6c1c870a34a23a7824e1f370bbStephan Bosch path = mailbox_list_get_path(box->list, box->name,
5394bed8aaef2a6c1c870a34a23a7824e1f370bbStephan Bosch MAILBOX_LIST_PATH_TYPE_MAILBOX);
f74dbd3ff682fea040f60383e001620d1f1b09d3Stephan Bosch if (stat(path, &st) == 0) {
f74dbd3ff682fea040f60383e001620d1f1b09d3Stephan Bosch mail_storage_set_error(box->storage, MAIL_ERROR_EXISTS,
5394bed8aaef2a6c1c870a34a23a7824e1f370bbStephan Bosch "Mailbox already exists");
5394bed8aaef2a6c1c870a34a23a7824e1f370bbStephan Bosch return -1;
5394bed8aaef2a6c1c870a34a23a7824e1f370bbStephan Bosch }
5394bed8aaef2a6c1c870a34a23a7824e1f370bbStephan Bosch
f74dbd3ff682fea040f60383e001620d1f1b09d3Stephan Bosch if (create_cydir(box->storage, box->list, path) < 0)
f74dbd3ff682fea040f60383e001620d1f1b09d3Stephan Bosch return -1;
5394bed8aaef2a6c1c870a34a23a7824e1f370bbStephan Bosch
5394bed8aaef2a6c1c870a34a23a7824e1f370bbStephan Bosch return directory || update == NULL ? 0 :
5394bed8aaef2a6c1c870a34a23a7824e1f370bbStephan Bosch index_storage_mailbox_update(box, update);
5394bed8aaef2a6c1c870a34a23a7824e1f370bbStephan Bosch}
f74dbd3ff682fea040f60383e001620d1f1b09d3Stephan Bosch
f74dbd3ff682fea040f60383e001620d1f1b09d3Stephan Boschstatic int
5394bed8aaef2a6c1c870a34a23a7824e1f370bbStephan Boschcydir_delete_nonrecursive(struct mailbox_list *list, const char *path,
5394bed8aaef2a6c1c870a34a23a7824e1f370bbStephan Bosch const char *name)
5394bed8aaef2a6c1c870a34a23a7824e1f370bbStephan Bosch{
f74dbd3ff682fea040f60383e001620d1f1b09d3Stephan Bosch DIR *dir;
f74dbd3ff682fea040f60383e001620d1f1b09d3Stephan Bosch struct dirent *d;
5394bed8aaef2a6c1c870a34a23a7824e1f370bbStephan Bosch string_t *full_path;
5394bed8aaef2a6c1c870a34a23a7824e1f370bbStephan Bosch unsigned int dir_len;
f74dbd3ff682fea040f60383e001620d1f1b09d3Stephan Bosch bool unlinked_something = FALSE;
f74dbd3ff682fea040f60383e001620d1f1b09d3Stephan Bosch
5394bed8aaef2a6c1c870a34a23a7824e1f370bbStephan Bosch dir = opendir(path);
5394bed8aaef2a6c1c870a34a23a7824e1f370bbStephan Bosch if (dir == NULL) {
5394bed8aaef2a6c1c870a34a23a7824e1f370bbStephan Bosch if (!mailbox_list_set_error_from_errno(list)) {
5394bed8aaef2a6c1c870a34a23a7824e1f370bbStephan Bosch mailbox_list_set_critical(list,
f74dbd3ff682fea040f60383e001620d1f1b09d3Stephan Bosch "opendir(%s) failed: %m", path);
f74dbd3ff682fea040f60383e001620d1f1b09d3Stephan Bosch }
5394bed8aaef2a6c1c870a34a23a7824e1f370bbStephan Bosch return -1;
5394bed8aaef2a6c1c870a34a23a7824e1f370bbStephan Bosch }
5394bed8aaef2a6c1c870a34a23a7824e1f370bbStephan Bosch
f74dbd3ff682fea040f60383e001620d1f1b09d3Stephan Bosch full_path = t_str_new(256);
f74dbd3ff682fea040f60383e001620d1f1b09d3Stephan Bosch str_append(full_path, path);
5394bed8aaef2a6c1c870a34a23a7824e1f370bbStephan Bosch str_append_c(full_path, '/');
5394bed8aaef2a6c1c870a34a23a7824e1f370bbStephan Bosch dir_len = str_len(full_path);
f74dbd3ff682fea040f60383e001620d1f1b09d3Stephan Bosch
f74dbd3ff682fea040f60383e001620d1f1b09d3Stephan Bosch errno = 0;
5394bed8aaef2a6c1c870a34a23a7824e1f370bbStephan Bosch while ((d = readdir(dir)) != NULL) {
5394bed8aaef2a6c1c870a34a23a7824e1f370bbStephan Bosch if (d->d_name[0] == '.') {
f74dbd3ff682fea040f60383e001620d1f1b09d3Stephan Bosch /* skip . and .. */
f74dbd3ff682fea040f60383e001620d1f1b09d3Stephan Bosch if (d->d_name[1] == '\0')
5394bed8aaef2a6c1c870a34a23a7824e1f370bbStephan Bosch continue;
5394bed8aaef2a6c1c870a34a23a7824e1f370bbStephan Bosch if (d->d_name[1] == '.' && d->d_name[2] == '\0')
f74dbd3ff682fea040f60383e001620d1f1b09d3Stephan Bosch continue;
f74dbd3ff682fea040f60383e001620d1f1b09d3Stephan Bosch }
5394bed8aaef2a6c1c870a34a23a7824e1f370bbStephan Bosch
5394bed8aaef2a6c1c870a34a23a7824e1f370bbStephan Bosch str_truncate(full_path, dir_len);
f74dbd3ff682fea040f60383e001620d1f1b09d3Stephan Bosch str_append(full_path, d->d_name);
f74dbd3ff682fea040f60383e001620d1f1b09d3Stephan Bosch
5394bed8aaef2a6c1c870a34a23a7824e1f370bbStephan Bosch /* trying to unlink() a directory gives either EPERM or EISDIR
5394bed8aaef2a6c1c870a34a23a7824e1f370bbStephan Bosch (non-POSIX). it doesn't really work anywhere in practise,
f74dbd3ff682fea040f60383e001620d1f1b09d3Stephan Bosch so don't bother stat()ing the file first */
f74dbd3ff682fea040f60383e001620d1f1b09d3Stephan Bosch if (unlink(str_c(full_path)) == 0)
5394bed8aaef2a6c1c870a34a23a7824e1f370bbStephan Bosch unlinked_something = TRUE;
5394bed8aaef2a6c1c870a34a23a7824e1f370bbStephan Bosch else if (errno != ENOENT && errno != EISDIR && errno != EPERM) {
f74dbd3ff682fea040f60383e001620d1f1b09d3Stephan Bosch mailbox_list_set_critical(list, "unlink(%s) failed: %m",
f74dbd3ff682fea040f60383e001620d1f1b09d3Stephan Bosch str_c(full_path));
5394bed8aaef2a6c1c870a34a23a7824e1f370bbStephan Bosch }
5394bed8aaef2a6c1c870a34a23a7824e1f370bbStephan Bosch }
f74dbd3ff682fea040f60383e001620d1f1b09d3Stephan Bosch
f74dbd3ff682fea040f60383e001620d1f1b09d3Stephan Bosch if (closedir(dir) < 0) {
5394bed8aaef2a6c1c870a34a23a7824e1f370bbStephan Bosch mailbox_list_set_critical(list, "closedir(%s) failed: %m",
5394bed8aaef2a6c1c870a34a23a7824e1f370bbStephan Bosch path);
f74dbd3ff682fea040f60383e001620d1f1b09d3Stephan Bosch }
f74dbd3ff682fea040f60383e001620d1f1b09d3Stephan Bosch
5394bed8aaef2a6c1c870a34a23a7824e1f370bbStephan Bosch if (rmdir(path) == 0)
5394bed8aaef2a6c1c870a34a23a7824e1f370bbStephan Bosch unlinked_something = TRUE;
5394bed8aaef2a6c1c870a34a23a7824e1f370bbStephan Bosch else if (errno != ENOENT && errno != ENOTEMPTY) {
5394bed8aaef2a6c1c870a34a23a7824e1f370bbStephan Bosch mailbox_list_set_critical(list, "rmdir(%s) failed: %m", path);
5394bed8aaef2a6c1c870a34a23a7824e1f370bbStephan Bosch return -1;
f74dbd3ff682fea040f60383e001620d1f1b09d3Stephan Bosch }
f74dbd3ff682fea040f60383e001620d1f1b09d3Stephan Bosch
5394bed8aaef2a6c1c870a34a23a7824e1f370bbStephan Bosch if (!unlinked_something) {
5394bed8aaef2a6c1c870a34a23a7824e1f370bbStephan Bosch mailbox_list_set_error(list, MAIL_ERROR_NOTFOUND,
f74dbd3ff682fea040f60383e001620d1f1b09d3Stephan Bosch t_strdup_printf("Directory %s isn't empty, "
f74dbd3ff682fea040f60383e001620d1f1b09d3Stephan Bosch "can't delete it.", name));
5394bed8aaef2a6c1c870a34a23a7824e1f370bbStephan Bosch return -1;
5394bed8aaef2a6c1c870a34a23a7824e1f370bbStephan Bosch }
f74dbd3ff682fea040f60383e001620d1f1b09d3Stephan Bosch return 0;
f74dbd3ff682fea040f60383e001620d1f1b09d3Stephan Bosch}
5394bed8aaef2a6c1c870a34a23a7824e1f370bbStephan Bosch
5394bed8aaef2a6c1c870a34a23a7824e1f370bbStephan Boschstatic int
f74dbd3ff682fea040f60383e001620d1f1b09d3Stephan Boschcydir_list_delete_mailbox(struct mailbox_list *list, const char *name)
f74dbd3ff682fea040f60383e001620d1f1b09d3Stephan Bosch{
5394bed8aaef2a6c1c870a34a23a7824e1f370bbStephan Bosch struct cydir_mailbox_list *mlist = CYDIR_LIST_CONTEXT(list);
5394bed8aaef2a6c1c870a34a23a7824e1f370bbStephan Bosch struct stat st;
f74dbd3ff682fea040f60383e001620d1f1b09d3Stephan Bosch const char *src;
f74dbd3ff682fea040f60383e001620d1f1b09d3Stephan Bosch
5394bed8aaef2a6c1c870a34a23a7824e1f370bbStephan Bosch /* Make sure the indexes are closed before trying to delete the
5394bed8aaef2a6c1c870a34a23a7824e1f370bbStephan Bosch directory that contains them. It can still fail with some NFS
f74dbd3ff682fea040f60383e001620d1f1b09d3Stephan Bosch implementations if indexes are opened by another session, but
f74dbd3ff682fea040f60383e001620d1f1b09d3Stephan Bosch that can't really be helped. */
5394bed8aaef2a6c1c870a34a23a7824e1f370bbStephan Bosch index_storage_destroy_unrefed();
5394bed8aaef2a6c1c870a34a23a7824e1f370bbStephan Bosch
f74dbd3ff682fea040f60383e001620d1f1b09d3Stephan Bosch /* delete the index and control directories */
f74dbd3ff682fea040f60383e001620d1f1b09d3Stephan Bosch if (mlist->module_ctx.super.delete_mailbox(list, name) < 0)
5394bed8aaef2a6c1c870a34a23a7824e1f370bbStephan Bosch return -1;
5394bed8aaef2a6c1c870a34a23a7824e1f370bbStephan Bosch
f74dbd3ff682fea040f60383e001620d1f1b09d3Stephan Bosch /* check if the mailbox actually exists */
f74dbd3ff682fea040f60383e001620d1f1b09d3Stephan Bosch src = mailbox_list_get_path(list, name, MAILBOX_LIST_PATH_TYPE_MAILBOX);
5394bed8aaef2a6c1c870a34a23a7824e1f370bbStephan Bosch if (stat(src, &st) != 0 && errno == ENOENT) {
5394bed8aaef2a6c1c870a34a23a7824e1f370bbStephan Bosch mailbox_list_set_error(list, MAIL_ERROR_NOTFOUND,
f74dbd3ff682fea040f60383e001620d1f1b09d3Stephan Bosch T_MAIL_ERR_MAILBOX_NOT_FOUND(name));
f74dbd3ff682fea040f60383e001620d1f1b09d3Stephan Bosch return -1;
5394bed8aaef2a6c1c870a34a23a7824e1f370bbStephan Bosch }
5394bed8aaef2a6c1c870a34a23a7824e1f370bbStephan Bosch
f74dbd3ff682fea040f60383e001620d1f1b09d3Stephan Bosch return cydir_delete_nonrecursive(list, src, name);
f74dbd3ff682fea040f60383e001620d1f1b09d3Stephan Bosch}
5394bed8aaef2a6c1c870a34a23a7824e1f370bbStephan Bosch
5394bed8aaef2a6c1c870a34a23a7824e1f370bbStephan Boschstatic void cydir_notify_changes(struct mailbox *box)
f74dbd3ff682fea040f60383e001620d1f1b09d3Stephan Bosch{
f74dbd3ff682fea040f60383e001620d1f1b09d3Stephan Bosch struct cydir_mailbox *mbox = (struct cydir_mailbox *)box;
5394bed8aaef2a6c1c870a34a23a7824e1f370bbStephan Bosch
5394bed8aaef2a6c1c870a34a23a7824e1f370bbStephan Bosch if (box->notify_callback == NULL)
f74dbd3ff682fea040f60383e001620d1f1b09d3Stephan Bosch index_mailbox_check_remove_all(&mbox->ibox);
f74dbd3ff682fea040f60383e001620d1f1b09d3Stephan Bosch else
5394bed8aaef2a6c1c870a34a23a7824e1f370bbStephan Bosch index_mailbox_check_add(&mbox->ibox, mbox->ibox.box.path);
5394bed8aaef2a6c1c870a34a23a7824e1f370bbStephan Bosch}
f74dbd3ff682fea040f60383e001620d1f1b09d3Stephan Bosch
f74dbd3ff682fea040f60383e001620d1f1b09d3Stephan Boschstatic int cydir_list_iter_is_mailbox(struct mailbox_list_iterate_context *ctx
5394bed8aaef2a6c1c870a34a23a7824e1f370bbStephan Bosch ATTR_UNUSED,
5394bed8aaef2a6c1c870a34a23a7824e1f370bbStephan Bosch const char *dir, const char *fname,
f74dbd3ff682fea040f60383e001620d1f1b09d3Stephan Bosch const char *mailbox_name ATTR_UNUSED,
f74dbd3ff682fea040f60383e001620d1f1b09d3Stephan Bosch enum mailbox_list_file_type type,
5394bed8aaef2a6c1c870a34a23a7824e1f370bbStephan Bosch enum mailbox_info_flags *flags)
5394bed8aaef2a6c1c870a34a23a7824e1f370bbStephan Bosch{
f74dbd3ff682fea040f60383e001620d1f1b09d3Stephan Bosch const char *mail_path;
f74dbd3ff682fea040f60383e001620d1f1b09d3Stephan Bosch struct stat st;
5394bed8aaef2a6c1c870a34a23a7824e1f370bbStephan Bosch int ret = 1;
5394bed8aaef2a6c1c870a34a23a7824e1f370bbStephan Bosch
f74dbd3ff682fea040f60383e001620d1f1b09d3Stephan Bosch /* try to avoid stat() with these checks */
f74dbd3ff682fea040f60383e001620d1f1b09d3Stephan Bosch if (type != MAILBOX_LIST_FILE_TYPE_DIR &&
5394bed8aaef2a6c1c870a34a23a7824e1f370bbStephan Bosch type != MAILBOX_LIST_FILE_TYPE_SYMLINK &&
5394bed8aaef2a6c1c870a34a23a7824e1f370bbStephan Bosch type != MAILBOX_LIST_FILE_TYPE_UNKNOWN) {
5394bed8aaef2a6c1c870a34a23a7824e1f370bbStephan Bosch /* it's a file */
f74dbd3ff682fea040f60383e001620d1f1b09d3Stephan Bosch *flags |= MAILBOX_NOSELECT | MAILBOX_NOINFERIORS;
5394bed8aaef2a6c1c870a34a23a7824e1f370bbStephan Bosch return 0;
f74dbd3ff682fea040f60383e001620d1f1b09d3Stephan Bosch }
5394bed8aaef2a6c1c870a34a23a7824e1f370bbStephan Bosch
5394bed8aaef2a6c1c870a34a23a7824e1f370bbStephan Bosch /* need to stat() then */
5394bed8aaef2a6c1c870a34a23a7824e1f370bbStephan Bosch mail_path = t_strconcat(dir, "/", fname, NULL);
f74dbd3ff682fea040f60383e001620d1f1b09d3Stephan Bosch if (stat(mail_path, &st) == 0) {
5394bed8aaef2a6c1c870a34a23a7824e1f370bbStephan Bosch if (!S_ISDIR(st.st_mode)) {
f74dbd3ff682fea040f60383e001620d1f1b09d3Stephan Bosch /* non-directory */
5394bed8aaef2a6c1c870a34a23a7824e1f370bbStephan Bosch *flags |= MAILBOX_NOSELECT | MAILBOX_NOINFERIORS;
5394bed8aaef2a6c1c870a34a23a7824e1f370bbStephan Bosch ret = 0;
5394bed8aaef2a6c1c870a34a23a7824e1f370bbStephan Bosch } else if (st.st_nlink == 2) {
5394bed8aaef2a6c1c870a34a23a7824e1f370bbStephan Bosch /* no subdirectories */
5394bed8aaef2a6c1c870a34a23a7824e1f370bbStephan Bosch *flags |= MAILBOX_NOCHILDREN;
5394bed8aaef2a6c1c870a34a23a7824e1f370bbStephan Bosch } else if (*ctx->list->set.maildir_name != '\0') {
5394bed8aaef2a6c1c870a34a23a7824e1f370bbStephan Bosch /* non-default configuration: we have one directory
5394bed8aaef2a6c1c870a34a23a7824e1f370bbStephan Bosch containing the mailboxes. if there are 3 links,
5394bed8aaef2a6c1c870a34a23a7824e1f370bbStephan Bosch either this is a selectable mailbox without children
5394bed8aaef2a6c1c870a34a23a7824e1f370bbStephan Bosch or non-selectable mailbox with children */
5394bed8aaef2a6c1c870a34a23a7824e1f370bbStephan Bosch if (st.st_nlink > 3)
5394bed8aaef2a6c1c870a34a23a7824e1f370bbStephan Bosch *flags |= MAILBOX_CHILDREN;
5394bed8aaef2a6c1c870a34a23a7824e1f370bbStephan Bosch } else {
5394bed8aaef2a6c1c870a34a23a7824e1f370bbStephan Bosch /* default configuration: all subdirectories are
5394bed8aaef2a6c1c870a34a23a7824e1f370bbStephan Bosch child mailboxes. */
5394bed8aaef2a6c1c870a34a23a7824e1f370bbStephan Bosch if (st.st_nlink > 2)
5394bed8aaef2a6c1c870a34a23a7824e1f370bbStephan Bosch *flags |= MAILBOX_CHILDREN;
5394bed8aaef2a6c1c870a34a23a7824e1f370bbStephan Bosch }
5394bed8aaef2a6c1c870a34a23a7824e1f370bbStephan Bosch } else if (errno == ENOENT) {
f74dbd3ff682fea040f60383e001620d1f1b09d3Stephan Bosch /* doesn't exist - probably a non-existing subscribed mailbox */
d45ab3fff7c47f1719b9cd310228c0dac2bdd1b2Timo Sirainen *flags |= MAILBOX_NONEXISTENT;
5394bed8aaef2a6c1c870a34a23a7824e1f370bbStephan Bosch } else {
5394bed8aaef2a6c1c870a34a23a7824e1f370bbStephan Bosch /* non-selectable. probably either access denied, or symlink
5394bed8aaef2a6c1c870a34a23a7824e1f370bbStephan Bosch destination not found. don't bother logging errors. */
5394bed8aaef2a6c1c870a34a23a7824e1f370bbStephan Bosch *flags |= MAILBOX_NOSELECT;
5394bed8aaef2a6c1c870a34a23a7824e1f370bbStephan Bosch }
f74dbd3ff682fea040f60383e001620d1f1b09d3Stephan Bosch return ret;
f74dbd3ff682fea040f60383e001620d1f1b09d3Stephan Bosch}
5394bed8aaef2a6c1c870a34a23a7824e1f370bbStephan Bosch
f74dbd3ff682fea040f60383e001620d1f1b09d3Stephan Boschstatic void cydir_storage_add_list(struct mail_storage *storage ATTR_UNUSED,
5394bed8aaef2a6c1c870a34a23a7824e1f370bbStephan Bosch struct mailbox_list *list)
f883bf3eff62f5d27df5ee9ee664edc38a77937fStephan Bosch{
f74dbd3ff682fea040f60383e001620d1f1b09d3Stephan Bosch struct cydir_mailbox_list *mlist;
1e653c7406ec0b062c0bacfdf2e7568a3f860500Stephan Bosch
29ba46818861793cc016013ce2c30e3f3d2a7d11Timo Sirainen mlist = p_new(list->pool, struct cydir_mailbox_list, 1);
1e653c7406ec0b062c0bacfdf2e7568a3f860500Stephan Bosch mlist->module_ctx.super = list->v;
29ba46818861793cc016013ce2c30e3f3d2a7d11Timo Sirainen
1e653c7406ec0b062c0bacfdf2e7568a3f860500Stephan Bosch list->v.iter_is_mailbox = cydir_list_iter_is_mailbox;
1e653c7406ec0b062c0bacfdf2e7568a3f860500Stephan Bosch list->v.delete_mailbox = cydir_list_delete_mailbox;
29ba46818861793cc016013ce2c30e3f3d2a7d11Timo Sirainen
1e653c7406ec0b062c0bacfdf2e7568a3f860500Stephan Bosch MODULE_CONTEXT_SET(list, cydir_mailbox_list_module, mlist);
29ba46818861793cc016013ce2c30e3f3d2a7d11Timo Sirainen}
1e653c7406ec0b062c0bacfdf2e7568a3f860500Stephan Bosch
5394bed8aaef2a6c1c870a34a23a7824e1f370bbStephan Boschstruct mail_storage cydir_storage = {
29ba46818861793cc016013ce2c30e3f3d2a7d11Timo Sirainen MEMBER(name) CYDIR_STORAGE_NAME,
5394bed8aaef2a6c1c870a34a23a7824e1f370bbStephan Bosch MEMBER(class_flags) 0,
29ba46818861793cc016013ce2c30e3f3d2a7d11Timo Sirainen
5394bed8aaef2a6c1c870a34a23a7824e1f370bbStephan Bosch {
5394bed8aaef2a6c1c870a34a23a7824e1f370bbStephan Bosch NULL,
29ba46818861793cc016013ce2c30e3f3d2a7d11Timo Sirainen cydir_storage_alloc,
5394bed8aaef2a6c1c870a34a23a7824e1f370bbStephan Bosch NULL,
29ba46818861793cc016013ce2c30e3f3d2a7d11Timo Sirainen index_storage_destroy,
5394bed8aaef2a6c1c870a34a23a7824e1f370bbStephan Bosch cydir_storage_add_list,
5394bed8aaef2a6c1c870a34a23a7824e1f370bbStephan Bosch cydir_storage_get_list_settings,
29ba46818861793cc016013ce2c30e3f3d2a7d11Timo Sirainen NULL,
5394bed8aaef2a6c1c870a34a23a7824e1f370bbStephan Bosch cydir_mailbox_alloc,
29ba46818861793cc016013ce2c30e3f3d2a7d11Timo Sirainen NULL
5394bed8aaef2a6c1c870a34a23a7824e1f370bbStephan Bosch }
5394bed8aaef2a6c1c870a34a23a7824e1f370bbStephan Bosch};
5394bed8aaef2a6c1c870a34a23a7824e1f370bbStephan Bosch
5394bed8aaef2a6c1c870a34a23a7824e1f370bbStephan Boschstruct mailbox cydir_mailbox = {
5394bed8aaef2a6c1c870a34a23a7824e1f370bbStephan Bosch MEMBER(name) NULL,
5394bed8aaef2a6c1c870a34a23a7824e1f370bbStephan Bosch MEMBER(storage) NULL,
5394bed8aaef2a6c1c870a34a23a7824e1f370bbStephan Bosch MEMBER(list) NULL,
5394bed8aaef2a6c1c870a34a23a7824e1f370bbStephan Bosch
5394bed8aaef2a6c1c870a34a23a7824e1f370bbStephan Bosch {
5394bed8aaef2a6c1c870a34a23a7824e1f370bbStephan Bosch index_storage_is_readonly,
5394bed8aaef2a6c1c870a34a23a7824e1f370bbStephan Bosch index_storage_allow_new_keywords,
5394bed8aaef2a6c1c870a34a23a7824e1f370bbStephan Bosch index_storage_mailbox_enable,
5394bed8aaef2a6c1c870a34a23a7824e1f370bbStephan Bosch cydir_mailbox_open,
5394bed8aaef2a6c1c870a34a23a7824e1f370bbStephan Bosch index_storage_mailbox_close,
5394bed8aaef2a6c1c870a34a23a7824e1f370bbStephan Bosch cydir_mailbox_create,
5394bed8aaef2a6c1c870a34a23a7824e1f370bbStephan Bosch index_storage_mailbox_update,
5394bed8aaef2a6c1c870a34a23a7824e1f370bbStephan Bosch index_storage_get_status,
5394bed8aaef2a6c1c870a34a23a7824e1f370bbStephan Bosch NULL,
5394bed8aaef2a6c1c870a34a23a7824e1f370bbStephan Bosch NULL,
5394bed8aaef2a6c1c870a34a23a7824e1f370bbStephan Bosch cydir_storage_sync_init,
5394bed8aaef2a6c1c870a34a23a7824e1f370bbStephan Bosch index_mailbox_sync_next,
5394bed8aaef2a6c1c870a34a23a7824e1f370bbStephan Bosch index_mailbox_sync_deinit,
5394bed8aaef2a6c1c870a34a23a7824e1f370bbStephan Bosch NULL,
5394bed8aaef2a6c1c870a34a23a7824e1f370bbStephan Bosch cydir_notify_changes,
5394bed8aaef2a6c1c870a34a23a7824e1f370bbStephan Bosch index_transaction_begin,
5394bed8aaef2a6c1c870a34a23a7824e1f370bbStephan Bosch index_transaction_commit,
5394bed8aaef2a6c1c870a34a23a7824e1f370bbStephan Bosch index_transaction_rollback,
5394bed8aaef2a6c1c870a34a23a7824e1f370bbStephan Bosch index_transaction_set_max_modseq,
5394bed8aaef2a6c1c870a34a23a7824e1f370bbStephan Bosch index_keywords_create,
5394bed8aaef2a6c1c870a34a23a7824e1f370bbStephan Bosch index_keywords_create_from_indexes,
5394bed8aaef2a6c1c870a34a23a7824e1f370bbStephan Bosch index_keywords_ref,
5394bed8aaef2a6c1c870a34a23a7824e1f370bbStephan Bosch index_keywords_unref,
5394bed8aaef2a6c1c870a34a23a7824e1f370bbStephan Bosch index_keyword_is_valid,
5394bed8aaef2a6c1c870a34a23a7824e1f370bbStephan Bosch index_storage_get_seq_range,
5394bed8aaef2a6c1c870a34a23a7824e1f370bbStephan Bosch index_storage_get_uid_range,
5394bed8aaef2a6c1c870a34a23a7824e1f370bbStephan Bosch index_storage_get_expunges,
5394bed8aaef2a6c1c870a34a23a7824e1f370bbStephan Bosch NULL,
5394bed8aaef2a6c1c870a34a23a7824e1f370bbStephan Bosch NULL,
5394bed8aaef2a6c1c870a34a23a7824e1f370bbStephan Bosch NULL,
ffb2949c6cc3a72b4193c47a2f7fd8ddc7fd69e7Phil Carmody index_mail_alloc,
ffb2949c6cc3a72b4193c47a2f7fd8ddc7fd69e7Phil Carmody index_header_lookup_init,
ffb2949c6cc3a72b4193c47a2f7fd8ddc7fd69e7Phil Carmody index_header_lookup_deinit,
5394bed8aaef2a6c1c870a34a23a7824e1f370bbStephan Bosch index_storage_search_init,
5394bed8aaef2a6c1c870a34a23a7824e1f370bbStephan Bosch index_storage_search_deinit,
5394bed8aaef2a6c1c870a34a23a7824e1f370bbStephan Bosch index_storage_search_next_nonblock,
5394bed8aaef2a6c1c870a34a23a7824e1f370bbStephan Bosch index_storage_search_next_update_seq,
5394bed8aaef2a6c1c870a34a23a7824e1f370bbStephan Bosch cydir_save_alloc,
5394bed8aaef2a6c1c870a34a23a7824e1f370bbStephan Bosch cydir_save_begin,
5394bed8aaef2a6c1c870a34a23a7824e1f370bbStephan Bosch cydir_save_continue,
5394bed8aaef2a6c1c870a34a23a7824e1f370bbStephan Bosch cydir_save_finish,
5394bed8aaef2a6c1c870a34a23a7824e1f370bbStephan Bosch cydir_save_cancel,
5394bed8aaef2a6c1c870a34a23a7824e1f370bbStephan Bosch mail_storage_copy,
5394bed8aaef2a6c1c870a34a23a7824e1f370bbStephan Bosch index_storage_is_inconsistent
5394bed8aaef2a6c1c870a34a23a7824e1f370bbStephan Bosch }
5394bed8aaef2a6c1c870a34a23a7824e1f370bbStephan Bosch};
5394bed8aaef2a6c1c870a34a23a7824e1f370bbStephan Bosch