cydir-storage.c revision 3e1318a9fce68df4d179241dcc0739ed525d0cd9
bcb4e51a409d94ae670de96afb8483a4f7855294Stephan Bosch/* Copyright (C) 2007 Timo Sirainen */
10962368c30afde135743fd9796122e88a708e87Stephan Bosch
10962368c30afde135743fd9796122e88a708e87Stephan Bosch#include "lib.h"
10962368c30afde135743fd9796122e88a708e87Stephan Bosch#include "array.h"
10962368c30afde135743fd9796122e88a708e87Stephan Bosch#include "ioloop.h"
10962368c30afde135743fd9796122e88a708e87Stephan Bosch#include "str.h"
10962368c30afde135743fd9796122e88a708e87Stephan Bosch#include "mkdir-parents.h"
10962368c30afde135743fd9796122e88a708e87Stephan Bosch#include "unlink-directory.h"
10962368c30afde135743fd9796122e88a708e87Stephan Bosch#include "index-mail.h"
10962368c30afde135743fd9796122e88a708e87Stephan Bosch#include "mail-copy.h"
10962368c30afde135743fd9796122e88a708e87Stephan Bosch#include "cydir-sync.h"
10962368c30afde135743fd9796122e88a708e87Stephan Bosch#include "cydir-storage.h"
10962368c30afde135743fd9796122e88a708e87Stephan Bosch
10962368c30afde135743fd9796122e88a708e87Stephan Bosch#include <stdio.h>
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch#include <stdlib.h>
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch#include <unistd.h>
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch#include <dirent.h>
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch#include <sys/stat.h>
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch
10962368c30afde135743fd9796122e88a708e87Stephan Bosch#define CREATE_MODE 0770 /* umask() should limit it more */
10962368c30afde135743fd9796122e88a708e87Stephan Bosch
10962368c30afde135743fd9796122e88a708e87Stephan Bosch#define CYDIR_LIST_CONTEXT(obj) \
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch MODULE_CONTEXT(obj, cydir_mailbox_list_module)
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch
1faa520084b901b15d83d3d68baaee2535051defStephan Boschextern struct mail_storage cydir_storage;
1faa520084b901b15d83d3d68baaee2535051defStephan Boschextern struct mailbox cydir_mailbox;
10962368c30afde135743fd9796122e88a708e87Stephan Bosch
10962368c30afde135743fd9796122e88a708e87Stephan Boschstatic MODULE_CONTEXT_DEFINE_INIT(cydir_mailbox_list_module,
10962368c30afde135743fd9796122e88a708e87Stephan Bosch &mailbox_list_module_register);
10962368c30afde135743fd9796122e88a708e87Stephan Bosch
1faa520084b901b15d83d3d68baaee2535051defStephan Boschstatic int
1faa520084b901b15d83d3d68baaee2535051defStephan Boschcydir_list_delete_mailbox(struct mailbox_list *list, const char *name);
7ebcb054e0d3cc4be54038cbf763ec4189d9725bStephan Boschstatic int cydir_list_iter_is_mailbox(struct mailbox_list_iterate_context *ctx,
7ebcb054e0d3cc4be54038cbf763ec4189d9725bStephan Bosch const char *dir, const char *fname,
10962368c30afde135743fd9796122e88a708e87Stephan Bosch enum mailbox_list_file_type type,
10962368c30afde135743fd9796122e88a708e87Stephan Bosch enum mailbox_info_flags *flags);
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch
10962368c30afde135743fd9796122e88a708e87Stephan Boschstatic int
10962368c30afde135743fd9796122e88a708e87Stephan Boschcydir_get_list_settings(struct mailbox_list_settings *list_set,
10962368c30afde135743fd9796122e88a708e87Stephan Bosch const char *data, enum mail_storage_flags flags,
10962368c30afde135743fd9796122e88a708e87Stephan Bosch const char **error_r)
10962368c30afde135743fd9796122e88a708e87Stephan Bosch{
10962368c30afde135743fd9796122e88a708e87Stephan Bosch bool debug = (flags & MAIL_STORAGE_FLAG_DEBUG) != 0;
10962368c30afde135743fd9796122e88a708e87Stephan Bosch const char *p;
10962368c30afde135743fd9796122e88a708e87Stephan Bosch size_t len;
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch
f74dbd3ff682fea040f60383e001620d1f1b09d3Stephan Bosch memset(list_set, 0, sizeof(*list_set));
10962368c30afde135743fd9796122e88a708e87Stephan Bosch list_set->subscription_fname = CYDIR_SUBSCRIPTION_FILE_NAME;
10962368c30afde135743fd9796122e88a708e87Stephan Bosch list_set->maildir_name = "";
10962368c30afde135743fd9796122e88a708e87Stephan Bosch
10962368c30afde135743fd9796122e88a708e87Stephan Bosch if (data == NULL || *data == '\0' || *data == ':') {
10962368c30afde135743fd9796122e88a708e87Stephan Bosch /* we won't do any guessing for this format. */
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch if (debug)
10962368c30afde135743fd9796122e88a708e87Stephan Bosch i_info("cydir: mailbox location not given");
10962368c30afde135743fd9796122e88a708e87Stephan Bosch *error_r = "Root mail directory not given";
10962368c30afde135743fd9796122e88a708e87Stephan Bosch return -1;
10962368c30afde135743fd9796122e88a708e87Stephan Bosch }
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch
f74dbd3ff682fea040f60383e001620d1f1b09d3Stephan Bosch /* <root dir> [:INDEX=<dir>] */
10962368c30afde135743fd9796122e88a708e87Stephan Bosch if (debug)
10962368c30afde135743fd9796122e88a708e87Stephan Bosch i_info("cydir: data=%s", data);
10962368c30afde135743fd9796122e88a708e87Stephan Bosch p = strchr(data, ':');
10962368c30afde135743fd9796122e88a708e87Stephan Bosch if (p == NULL)
10962368c30afde135743fd9796122e88a708e87Stephan Bosch list_set->root_dir = data;
10962368c30afde135743fd9796122e88a708e87Stephan Bosch else {
10962368c30afde135743fd9796122e88a708e87Stephan Bosch list_set->root_dir = t_strdup_until(data, p);
10962368c30afde135743fd9796122e88a708e87Stephan Bosch
10962368c30afde135743fd9796122e88a708e87Stephan Bosch do {
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch p++;
f74dbd3ff682fea040f60383e001620d1f1b09d3Stephan Bosch if (strncmp(p, "INDEX=", 6) == 0)
f74dbd3ff682fea040f60383e001620d1f1b09d3Stephan Bosch list_set->index_dir = t_strcut(p+6, ':');
f74dbd3ff682fea040f60383e001620d1f1b09d3Stephan Bosch p = strchr(p, ':');
10962368c30afde135743fd9796122e88a708e87Stephan Bosch } while (p != NULL);
10962368c30afde135743fd9796122e88a708e87Stephan Bosch }
10962368c30afde135743fd9796122e88a708e87Stephan Bosch
10962368c30afde135743fd9796122e88a708e87Stephan Bosch /* strip trailing '/' */
10962368c30afde135743fd9796122e88a708e87Stephan Bosch len = strlen(list_set->root_dir);
10962368c30afde135743fd9796122e88a708e87Stephan Bosch if (len > 1 && list_set->root_dir[len-1] == '/')
10962368c30afde135743fd9796122e88a708e87Stephan Bosch list_set->root_dir = t_strndup(list_set->root_dir, len-1);
10962368c30afde135743fd9796122e88a708e87Stephan Bosch
10962368c30afde135743fd9796122e88a708e87Stephan Bosch if (list_set->index_dir != NULL &&
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch strcmp(list_set->index_dir, "MEMORY") == 0)
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch list_set->index_dir = "";
f74dbd3ff682fea040f60383e001620d1f1b09d3Stephan Bosch return 0;
f883bf3eff62f5d27df5ee9ee664edc38a77937fStephan Bosch}
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch
1faa520084b901b15d83d3d68baaee2535051defStephan Boschstatic struct mail_storage *cydir_alloc(void)
10962368c30afde135743fd9796122e88a708e87Stephan Bosch{
10962368c30afde135743fd9796122e88a708e87Stephan Bosch struct cydir_storage *storage;
10962368c30afde135743fd9796122e88a708e87Stephan Bosch pool_t pool;
10962368c30afde135743fd9796122e88a708e87Stephan Bosch
10962368c30afde135743fd9796122e88a708e87Stephan Bosch pool = pool_alloconly_create("cydir storage", 512+256);
10962368c30afde135743fd9796122e88a708e87Stephan Bosch storage = p_new(pool, struct cydir_storage, 1);
10962368c30afde135743fd9796122e88a708e87Stephan Bosch storage->storage = cydir_storage;
10962368c30afde135743fd9796122e88a708e87Stephan Bosch storage->storage.pool = pool;
10962368c30afde135743fd9796122e88a708e87Stephan Bosch
10962368c30afde135743fd9796122e88a708e87Stephan Bosch return &storage->storage;
10962368c30afde135743fd9796122e88a708e87Stephan Bosch}
10962368c30afde135743fd9796122e88a708e87Stephan Bosch
f74dbd3ff682fea040f60383e001620d1f1b09d3Stephan Boschstatic int cydir_create(struct mail_storage *_storage, const char *data,
f74dbd3ff682fea040f60383e001620d1f1b09d3Stephan Bosch const char **error_r)
f74dbd3ff682fea040f60383e001620d1f1b09d3Stephan Bosch{
10962368c30afde135743fd9796122e88a708e87Stephan Bosch struct cydir_storage *storage = (struct cydir_storage *)_storage;
10962368c30afde135743fd9796122e88a708e87Stephan Bosch struct mailbox_list_settings list_set;
10962368c30afde135743fd9796122e88a708e87Stephan Bosch struct stat st;
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch if (cydir_get_list_settings(&list_set, data, _storage->flags,
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch error_r) < 0)
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch return -1;
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch list_set.mail_storage_flags = &_storage->flags;
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch list_set.lock_method = &_storage->lock_method;
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch if ((_storage->flags & MAIL_STORAGE_FLAG_NO_AUTOCREATE) != 0) {
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch if (stat(list_set.root_dir, &st) < 0) {
f74dbd3ff682fea040f60383e001620d1f1b09d3Stephan Bosch if (errno != ENOENT) {
f74dbd3ff682fea040f60383e001620d1f1b09d3Stephan Bosch *error_r = t_strdup_printf(
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch "stat(%s) failed: %m",
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch list_set.root_dir);
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch } else {
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch *error_r = t_strdup_printf(
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch "Root mail directory doesn't exist: %s",
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch list_set.root_dir);
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch }
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch return -1;
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch }
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch } else {
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch if (mkdir_parents(list_set.root_dir, CREATE_MODE) < 0 &&
f74dbd3ff682fea040f60383e001620d1f1b09d3Stephan Bosch errno != EEXIST) {
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch *error_r = t_strdup_printf("mkdir(%s) failed: %m",
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch list_set.root_dir);
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch return -1;
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch }
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch }
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch if (mailbox_list_init(_storage->ns, "fs", &list_set,
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch mail_storage_get_list_flags(_storage->flags),
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch &_storage->list, error_r) < 0)
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch return -1;
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch storage->list_module_ctx.super = _storage->list->v;
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch _storage->list->v.iter_is_mailbox = cydir_list_iter_is_mailbox;
f74dbd3ff682fea040f60383e001620d1f1b09d3Stephan Bosch _storage->list->v.delete_mailbox = cydir_list_delete_mailbox;
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch MODULE_CONTEXT_SET_FULL(_storage->list, cydir_mailbox_list_module,
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch storage, &storage->list_module_ctx);
d577bb9027e4ceb19ada88d6884265efa5e16b15Stephan Bosch return 0;
d577bb9027e4ceb19ada88d6884265efa5e16b15Stephan Bosch}
d577bb9027e4ceb19ada88d6884265efa5e16b15Stephan Bosch
d577bb9027e4ceb19ada88d6884265efa5e16b15Stephan Boschstatic int create_cydir(struct mail_storage *storage, const char *path)
d577bb9027e4ceb19ada88d6884265efa5e16b15Stephan Bosch{
d577bb9027e4ceb19ada88d6884265efa5e16b15Stephan Bosch if (mkdir_parents(path, CREATE_MODE) < 0 && errno != EEXIST) {
d577bb9027e4ceb19ada88d6884265efa5e16b15Stephan Bosch if (!mail_storage_set_error_from_errno(storage)) {
d577bb9027e4ceb19ada88d6884265efa5e16b15Stephan Bosch mail_storage_set_critical(storage,
d577bb9027e4ceb19ada88d6884265efa5e16b15Stephan Bosch "mkdir(%s) failed: %m", path);
d577bb9027e4ceb19ada88d6884265efa5e16b15Stephan Bosch }
d577bb9027e4ceb19ada88d6884265efa5e16b15Stephan Bosch return -1;
d577bb9027e4ceb19ada88d6884265efa5e16b15Stephan Bosch }
6e62aa36a3190ef7193bd86158a4245da49132f0Stephan Bosch return 0;
6e62aa36a3190ef7193bd86158a4245da49132f0Stephan Bosch}
6e62aa36a3190ef7193bd86158a4245da49132f0Stephan Bosch
6e62aa36a3190ef7193bd86158a4245da49132f0Stephan Boschstatic struct mailbox *
6e62aa36a3190ef7193bd86158a4245da49132f0Stephan Boschcydir_open(struct cydir_storage *storage, const char *name,
6e62aa36a3190ef7193bd86158a4245da49132f0Stephan Bosch enum mailbox_open_flags flags)
6e62aa36a3190ef7193bd86158a4245da49132f0Stephan Bosch{
6e62aa36a3190ef7193bd86158a4245da49132f0Stephan Bosch struct mail_storage *_storage = &storage->storage;
6e62aa36a3190ef7193bd86158a4245da49132f0Stephan Bosch struct cydir_mailbox *mbox;
6e62aa36a3190ef7193bd86158a4245da49132f0Stephan Bosch struct mail_index *index;
6e62aa36a3190ef7193bd86158a4245da49132f0Stephan Bosch const char *path;
6e62aa36a3190ef7193bd86158a4245da49132f0Stephan Bosch pool_t pool;
6e62aa36a3190ef7193bd86158a4245da49132f0Stephan Bosch
10962368c30afde135743fd9796122e88a708e87Stephan Bosch path = mailbox_list_get_path(_storage->list, name,
10962368c30afde135743fd9796122e88a708e87Stephan Bosch MAILBOX_LIST_PATH_TYPE_MAILBOX);
10962368c30afde135743fd9796122e88a708e87Stephan Bosch if (create_cydir(_storage, path) < 0)
ba592dc74a004ad47dfe58edcfc1ca7297551e39Phil Carmody return NULL;
10962368c30afde135743fd9796122e88a708e87Stephan Bosch
10962368c30afde135743fd9796122e88a708e87Stephan Bosch index = index_storage_alloc(_storage, name, flags, CYDIR_INDEX_PREFIX);
10962368c30afde135743fd9796122e88a708e87Stephan Bosch
10962368c30afde135743fd9796122e88a708e87Stephan Bosch pool = pool_alloconly_create("cydir mailbox", 1024+512);
10962368c30afde135743fd9796122e88a708e87Stephan Bosch mbox = p_new(pool, struct cydir_mailbox, 1);
10962368c30afde135743fd9796122e88a708e87Stephan Bosch mbox->ibox.box = cydir_mailbox;
10962368c30afde135743fd9796122e88a708e87Stephan Bosch mbox->ibox.box.pool = pool;
10962368c30afde135743fd9796122e88a708e87Stephan Bosch mbox->ibox.storage = &storage->storage;
10962368c30afde135743fd9796122e88a708e87Stephan Bosch mbox->ibox.mail_vfuncs = &cydir_mail_vfuncs;
10962368c30afde135743fd9796122e88a708e87Stephan Bosch mbox->ibox.index = index;
10962368c30afde135743fd9796122e88a708e87Stephan Bosch
10962368c30afde135743fd9796122e88a708e87Stephan Bosch mbox->storage = storage;
10962368c30afde135743fd9796122e88a708e87Stephan Bosch mbox->path = p_strdup(pool, path);
10962368c30afde135743fd9796122e88a708e87Stephan Bosch
10962368c30afde135743fd9796122e88a708e87Stephan Bosch index_storage_mailbox_init(&mbox->ibox, name, flags, FALSE);
10962368c30afde135743fd9796122e88a708e87Stephan Bosch return &mbox->ibox.box;
10962368c30afde135743fd9796122e88a708e87Stephan Bosch}
10962368c30afde135743fd9796122e88a708e87Stephan Bosch
10962368c30afde135743fd9796122e88a708e87Stephan Boschstatic struct mailbox *
10962368c30afde135743fd9796122e88a708e87Stephan Boschcydir_mailbox_open(struct mail_storage *_storage, const char *name,
10962368c30afde135743fd9796122e88a708e87Stephan Bosch struct istream *input, enum mailbox_open_flags flags)
10962368c30afde135743fd9796122e88a708e87Stephan Bosch{
10962368c30afde135743fd9796122e88a708e87Stephan Bosch struct cydir_storage *storage = (struct cydir_storage *)_storage;
10962368c30afde135743fd9796122e88a708e87Stephan Bosch const char *path;
10962368c30afde135743fd9796122e88a708e87Stephan Bosch struct stat st;
10962368c30afde135743fd9796122e88a708e87Stephan Bosch
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch if (input != NULL) {
10962368c30afde135743fd9796122e88a708e87Stephan Bosch mail_storage_set_critical(_storage,
b9ee73a064b38d8aeec754b964cc34b23487387aTimo Sirainen "cydir doesn't support streamed mailboxes");
10962368c30afde135743fd9796122e88a708e87Stephan Bosch return NULL;
10962368c30afde135743fd9796122e88a708e87Stephan Bosch }
10962368c30afde135743fd9796122e88a708e87Stephan Bosch
10962368c30afde135743fd9796122e88a708e87Stephan Bosch if (strcmp(name, "INBOX") == 0)
10962368c30afde135743fd9796122e88a708e87Stephan Bosch return cydir_open(storage, "INBOX", flags);
10962368c30afde135743fd9796122e88a708e87Stephan Bosch
10962368c30afde135743fd9796122e88a708e87Stephan Bosch path = mailbox_list_get_path(_storage->list, name,
10962368c30afde135743fd9796122e88a708e87Stephan Bosch MAILBOX_LIST_PATH_TYPE_MAILBOX);
10962368c30afde135743fd9796122e88a708e87Stephan Bosch if (stat(path, &st) == 0) {
7ebcb054e0d3cc4be54038cbf763ec4189d9725bStephan Bosch return cydir_open(storage, name, flags);
10962368c30afde135743fd9796122e88a708e87Stephan Bosch } else if (errno == ENOENT) {
10962368c30afde135743fd9796122e88a708e87Stephan Bosch mail_storage_set_error(_storage, MAIL_ERROR_NOTFOUND,
10962368c30afde135743fd9796122e88a708e87Stephan Bosch T_MAIL_ERR_MAILBOX_NOT_FOUND(name));
10962368c30afde135743fd9796122e88a708e87Stephan Bosch return NULL;
10962368c30afde135743fd9796122e88a708e87Stephan Bosch } else {
10962368c30afde135743fd9796122e88a708e87Stephan Bosch mail_storage_set_critical(_storage, "stat(%s) failed: %m",
10962368c30afde135743fd9796122e88a708e87Stephan Bosch path);
b9ee73a064b38d8aeec754b964cc34b23487387aTimo Sirainen return NULL;
10962368c30afde135743fd9796122e88a708e87Stephan Bosch }
10962368c30afde135743fd9796122e88a708e87Stephan Bosch}
5968fa8151eecd191b1973b44dd8bec9b75810a6Phil Carmody
b9ee73a064b38d8aeec754b964cc34b23487387aTimo Sirainenstatic int cydir_mailbox_create(struct mail_storage *_storage,
5968fa8151eecd191b1973b44dd8bec9b75810a6Phil Carmody const char *name,
10962368c30afde135743fd9796122e88a708e87Stephan Bosch bool directory __attr_unused__)
10962368c30afde135743fd9796122e88a708e87Stephan Bosch{
10962368c30afde135743fd9796122e88a708e87Stephan Bosch const char *path;
10962368c30afde135743fd9796122e88a708e87Stephan Bosch struct stat st;
10962368c30afde135743fd9796122e88a708e87Stephan Bosch
378e6cb162b355d6f103526505bc00b9a78962e7Timo Sirainen path = mailbox_list_get_path(_storage->list, name,
10962368c30afde135743fd9796122e88a708e87Stephan Bosch MAILBOX_LIST_PATH_TYPE_MAILBOX);
10962368c30afde135743fd9796122e88a708e87Stephan Bosch if (stat(path, &st) == 0) {
10962368c30afde135743fd9796122e88a708e87Stephan Bosch mail_storage_set_error(_storage, MAIL_ERROR_NOTPOSSIBLE,
10962368c30afde135743fd9796122e88a708e87Stephan Bosch "Mailbox already exists");
10962368c30afde135743fd9796122e88a708e87Stephan Bosch return -1;
10962368c30afde135743fd9796122e88a708e87Stephan Bosch }
b9ee73a064b38d8aeec754b964cc34b23487387aTimo Sirainen
10962368c30afde135743fd9796122e88a708e87Stephan Bosch return create_cydir(_storage, path);
10962368c30afde135743fd9796122e88a708e87Stephan Bosch}
10962368c30afde135743fd9796122e88a708e87Stephan Bosch
10962368c30afde135743fd9796122e88a708e87Stephan Boschstatic int
10962368c30afde135743fd9796122e88a708e87Stephan Boschcydir_delete_nonrecursive(struct mailbox_list *list, const char *path,
10962368c30afde135743fd9796122e88a708e87Stephan Bosch const char *name)
10962368c30afde135743fd9796122e88a708e87Stephan Bosch{
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch DIR *dir;
10962368c30afde135743fd9796122e88a708e87Stephan Bosch struct dirent *d;
10962368c30afde135743fd9796122e88a708e87Stephan Bosch string_t *full_path;
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch unsigned int dir_len;
10962368c30afde135743fd9796122e88a708e87Stephan Bosch bool unlinked_something = FALSE;
10962368c30afde135743fd9796122e88a708e87Stephan Bosch
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch dir = opendir(path);
10962368c30afde135743fd9796122e88a708e87Stephan Bosch if (dir == NULL) {
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch if (!mailbox_list_set_error_from_errno(list)) {
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch mailbox_list_set_critical(list,
10962368c30afde135743fd9796122e88a708e87Stephan Bosch "opendir(%s) failed: %m", path);
10962368c30afde135743fd9796122e88a708e87Stephan Bosch }
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch return -1;
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch }
10962368c30afde135743fd9796122e88a708e87Stephan Bosch
10962368c30afde135743fd9796122e88a708e87Stephan Bosch full_path = t_str_new(256);
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch str_append(full_path, path);
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch str_append_c(full_path, '/');
f74dbd3ff682fea040f60383e001620d1f1b09d3Stephan Bosch dir_len = str_len(full_path);
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch
f74dbd3ff682fea040f60383e001620d1f1b09d3Stephan Bosch errno = 0;
f74dbd3ff682fea040f60383e001620d1f1b09d3Stephan Bosch while ((d = readdir(dir)) != NULL) {
f74dbd3ff682fea040f60383e001620d1f1b09d3Stephan Bosch if (d->d_name[0] == '.') {
f74dbd3ff682fea040f60383e001620d1f1b09d3Stephan Bosch /* skip . and .. */
f74dbd3ff682fea040f60383e001620d1f1b09d3Stephan Bosch if (d->d_name[1] == '\0')
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch continue;
f74dbd3ff682fea040f60383e001620d1f1b09d3Stephan Bosch if (d->d_name[1] == '.' && d->d_name[2] == '\0')
f74dbd3ff682fea040f60383e001620d1f1b09d3Stephan Bosch continue;
f74dbd3ff682fea040f60383e001620d1f1b09d3Stephan Bosch }
f74dbd3ff682fea040f60383e001620d1f1b09d3Stephan Bosch
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch str_truncate(full_path, dir_len);
f883bf3eff62f5d27df5ee9ee664edc38a77937fStephan Bosch str_append(full_path, d->d_name);
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch
f883bf3eff62f5d27df5ee9ee664edc38a77937fStephan Bosch /* trying to unlink() a directory gives either EPERM or EISDIR
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch (non-POSIX). it doesn't really work anywhere in practise,
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch so don't bother stat()ing the file first */
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch if (unlink(str_c(full_path)) == 0)
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch unlinked_something = TRUE;
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch else if (errno != ENOENT && errno != EISDIR && errno != EPERM) {
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch mailbox_list_set_critical(list,
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch "unlink_directory(%s) failed: %m",
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch str_c(full_path));
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch }
10962368c30afde135743fd9796122e88a708e87Stephan Bosch }
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch
10962368c30afde135743fd9796122e88a708e87Stephan Bosch if (closedir(dir) < 0) {
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch mailbox_list_set_critical(list, "closedir(%s) failed: %m",
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch path);
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch }
10962368c30afde135743fd9796122e88a708e87Stephan Bosch
10962368c30afde135743fd9796122e88a708e87Stephan Bosch if (rmdir(path) == 0)
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch unlinked_something = TRUE;
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch else if (errno != ENOENT && errno != ENOTEMPTY) {
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch mailbox_list_set_critical(list, "rmdir(%s) failed: %m", path);
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch return -1;
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch }
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch if (!unlinked_something) {
10962368c30afde135743fd9796122e88a708e87Stephan Bosch mailbox_list_set_error(list, MAIL_ERROR_NOTPOSSIBLE,
10962368c30afde135743fd9796122e88a708e87Stephan Bosch t_strdup_printf("Directory %s isn't empty, "
10962368c30afde135743fd9796122e88a708e87Stephan Bosch "can't delete it.", name));
10962368c30afde135743fd9796122e88a708e87Stephan Bosch return -1;
10962368c30afde135743fd9796122e88a708e87Stephan Bosch }
10962368c30afde135743fd9796122e88a708e87Stephan Bosch return 0;
10962368c30afde135743fd9796122e88a708e87Stephan Bosch}
10962368c30afde135743fd9796122e88a708e87Stephan Bosch
10962368c30afde135743fd9796122e88a708e87Stephan Boschstatic int
10962368c30afde135743fd9796122e88a708e87Stephan Boschcydir_list_delete_mailbox(struct mailbox_list *list, const char *name)
10962368c30afde135743fd9796122e88a708e87Stephan Bosch{
10962368c30afde135743fd9796122e88a708e87Stephan Bosch struct cydir_storage *storage = CYDIR_LIST_CONTEXT(list);
10962368c30afde135743fd9796122e88a708e87Stephan Bosch struct stat st;
10962368c30afde135743fd9796122e88a708e87Stephan Bosch const char *src;
10962368c30afde135743fd9796122e88a708e87Stephan Bosch
10962368c30afde135743fd9796122e88a708e87Stephan Bosch /* Make sure the indexes are closed before trying to delete the
10962368c30afde135743fd9796122e88a708e87Stephan Bosch directory that contains them. It can still fail with some NFS
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch implementations if indexes are opened by another session, but
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch that can't really be helped. */
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch index_storage_destroy_unrefed();
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch /* delete the index and control directories */
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch if (storage->list_module_ctx.super.delete_mailbox(list, name) < 0)
7ebcb054e0d3cc4be54038cbf763ec4189d9725bStephan Bosch return -1;
7ebcb054e0d3cc4be54038cbf763ec4189d9725bStephan Bosch
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch /* check if the mailbox actually exists */
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch src = mailbox_list_get_path(list, name, MAILBOX_LIST_PATH_TYPE_MAILBOX);
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch if (stat(src, &st) != 0 && errno == ENOENT) {
ba592dc74a004ad47dfe58edcfc1ca7297551e39Phil Carmody mailbox_list_set_error(list, MAIL_ERROR_NOTFOUND,
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch T_MAIL_ERR_MAILBOX_NOT_FOUND(name));
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch return -1;
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch }
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch return cydir_delete_nonrecursive(list, src, name);
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch}
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch
1faa520084b901b15d83d3d68baaee2535051defStephan Boschstatic void cydir_notify_changes(struct mailbox *box)
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch{
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch struct cydir_mailbox *mbox = (struct cydir_mailbox *)box;
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch if (box->notify_callback == NULL)
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch index_mailbox_check_remove_all(&mbox->ibox);
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch else
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch index_mailbox_check_add(&mbox->ibox, mbox->path);
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch}
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch
1faa520084b901b15d83d3d68baaee2535051defStephan Boschstatic int cydir_list_iter_is_mailbox(struct mailbox_list_iterate_context *ctx,
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch const char *dir, const char *fname,
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch enum mailbox_list_file_type type,
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch enum mailbox_info_flags *flags)
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch{
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch const char *mail_path;
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch struct stat st;
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch int ret = 1;
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch /* try to avoid stat() with these checks */
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch if (type != MAILBOX_LIST_FILE_TYPE_DIR &&
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch type != MAILBOX_LIST_FILE_TYPE_SYMLINK &&
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch type != MAILBOX_LIST_FILE_TYPE_UNKNOWN &&
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch (ctx->flags & MAILBOX_LIST_ITER_RETURN_NO_FLAGS) != 0) {
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch /* it's a file */
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch return 0;
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch }
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch /* need to stat() then */
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch t_push();
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch mail_path = t_strconcat(dir, "/", fname, NULL);
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch if (stat(mail_path, &st) == 0) {
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch if (!S_ISDIR(st.st_mode)) {
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch /* non-directory */
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch *flags |= MAILBOX_NOSELECT | MAILBOX_NOINFERIORS;
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch ret = 0;
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch }
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch } else {
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch /* non-selectable, but may contain subdirs */
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch *flags |= MAILBOX_NOSELECT;
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch }
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch t_pop();
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch return ret;
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch}
d577bb9027e4ceb19ada88d6884265efa5e16b15Stephan Bosch
d577bb9027e4ceb19ada88d6884265efa5e16b15Stephan Boschstatic void cydir_class_init(void)
d577bb9027e4ceb19ada88d6884265efa5e16b15Stephan Bosch{
d577bb9027e4ceb19ada88d6884265efa5e16b15Stephan Bosch cydir_transaction_class_init();
d577bb9027e4ceb19ada88d6884265efa5e16b15Stephan Bosch}
d577bb9027e4ceb19ada88d6884265efa5e16b15Stephan Bosch
d577bb9027e4ceb19ada88d6884265efa5e16b15Stephan Boschstatic void cydir_class_deinit(void)
d577bb9027e4ceb19ada88d6884265efa5e16b15Stephan Bosch{
6e62aa36a3190ef7193bd86158a4245da49132f0Stephan Bosch cydir_transaction_class_deinit();
6e62aa36a3190ef7193bd86158a4245da49132f0Stephan Bosch}
6e62aa36a3190ef7193bd86158a4245da49132f0Stephan Bosch
6e62aa36a3190ef7193bd86158a4245da49132f0Stephan Boschstruct mail_storage cydir_storage = {
6e62aa36a3190ef7193bd86158a4245da49132f0Stephan Bosch MEMBER(name) CYDIR_STORAGE_NAME,
6e62aa36a3190ef7193bd86158a4245da49132f0Stephan Bosch MEMBER(mailbox_is_file) FALSE,
6e62aa36a3190ef7193bd86158a4245da49132f0Stephan Bosch
6e62aa36a3190ef7193bd86158a4245da49132f0Stephan Bosch {
6e62aa36a3190ef7193bd86158a4245da49132f0Stephan Bosch cydir_class_init,
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch cydir_class_deinit,
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch cydir_alloc,
10962368c30afde135743fd9796122e88a708e87Stephan Bosch cydir_create,
10962368c30afde135743fd9796122e88a708e87Stephan Bosch NULL,
ba592dc74a004ad47dfe58edcfc1ca7297551e39Phil Carmody NULL,
10962368c30afde135743fd9796122e88a708e87Stephan Bosch cydir_mailbox_open,
10962368c30afde135743fd9796122e88a708e87Stephan Bosch cydir_mailbox_create
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch }
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch};
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch
1faa520084b901b15d83d3d68baaee2535051defStephan Boschstruct mailbox cydir_mailbox = {
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch MEMBER(name) NULL,
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch MEMBER(storage) NULL,
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch {
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch index_storage_is_readonly,
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch index_storage_allow_new_keywords,
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch index_storage_mailbox_close,
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch index_storage_get_status,
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch NULL,
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch NULL,
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch cydir_storage_sync_init,
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch index_mailbox_sync_next,
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch index_mailbox_sync_deinit,
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch NULL,
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch cydir_notify_changes,
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch index_transaction_begin,
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch index_transaction_commit,
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch index_transaction_rollback,
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch index_keywords_create,
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch index_keywords_free,
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch index_storage_get_uids,
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch index_mail_alloc,
10962368c30afde135743fd9796122e88a708e87Stephan Bosch index_header_lookup_init,
10962368c30afde135743fd9796122e88a708e87Stephan Bosch index_header_lookup_deinit,
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch index_storage_search_init,
10962368c30afde135743fd9796122e88a708e87Stephan Bosch index_storage_search_deinit,
10962368c30afde135743fd9796122e88a708e87Stephan Bosch index_storage_search_next_nonblock,
10962368c30afde135743fd9796122e88a708e87Stephan Bosch index_storage_search_next_update_seq,
10962368c30afde135743fd9796122e88a708e87Stephan Bosch cydir_save_init,
10962368c30afde135743fd9796122e88a708e87Stephan Bosch cydir_save_continue,
10962368c30afde135743fd9796122e88a708e87Stephan Bosch cydir_save_finish,
10962368c30afde135743fd9796122e88a708e87Stephan Bosch cydir_save_cancel,
10962368c30afde135743fd9796122e88a708e87Stephan Bosch mail_storage_copy,
10962368c30afde135743fd9796122e88a708e87Stephan Bosch index_storage_is_inconsistent
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch }
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch};
10962368c30afde135743fd9796122e88a708e87Stephan Bosch