cydir-storage.c revision 3e1318a9fce68df4d179241dcc0739ed525d0cd9
bcb4e51a409d94ae670de96afb8483a4f7855294Stephan Bosch/* Copyright (C) 2007 Timo Sirainen */
10962368c30afde135743fd9796122e88a708e87Stephan Bosch#define CREATE_MODE 0770 /* umask() should limit it more */
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch MODULE_CONTEXT(obj, cydir_mailbox_list_module)
10962368c30afde135743fd9796122e88a708e87Stephan Boschstatic MODULE_CONTEXT_DEFINE_INIT(cydir_mailbox_list_module,
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,
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 bool debug = (flags & MAIL_STORAGE_FLAG_DEBUG) != 0;
10962368c30afde135743fd9796122e88a708e87Stephan Bosch const char *p;
10962368c30afde135743fd9796122e88a708e87Stephan Bosch list_set->subscription_fname = CYDIR_SUBSCRIPTION_FILE_NAME;
10962368c30afde135743fd9796122e88a708e87Stephan Bosch if (data == NULL || *data == '\0' || *data == ':') {
10962368c30afde135743fd9796122e88a708e87Stephan Bosch /* we won't do any guessing for this format. */
f74dbd3ff682fea040f60383e001620d1f1b09d3Stephan Bosch /* <root dir> [:INDEX=<dir>] */
10962368c30afde135743fd9796122e88a708e87Stephan Bosch } while (p != NULL);
10962368c30afde135743fd9796122e88a708e87Stephan Bosch /* strip trailing '/' */
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 pool = pool_alloconly_create("cydir storage", 512+256);
10962368c30afde135743fd9796122e88a708e87Stephan Bosch storage = p_new(pool, struct cydir_storage, 1);
f74dbd3ff682fea040f60383e001620d1f1b09d3Stephan Boschstatic int cydir_create(struct mail_storage *_storage, const char *data,
f74dbd3ff682fea040f60383e001620d1f1b09d3Stephan Bosch const char **error_r)
10962368c30afde135743fd9796122e88a708e87Stephan Bosch struct cydir_storage *storage = (struct cydir_storage *)_storage;
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch if (cydir_get_list_settings(&list_set, data, _storage->flags,
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch list_set.mail_storage_flags = &_storage->flags;
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch list_set.lock_method = &_storage->lock_method;
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch if ((_storage->flags & MAIL_STORAGE_FLAG_NO_AUTOCREATE) != 0) {
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch "stat(%s) failed: %m",
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch "Root mail directory doesn't exist: %s",
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch if (mkdir_parents(list_set.root_dir, CREATE_MODE) < 0 &&
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch *error_r = t_strdup_printf("mkdir(%s) failed: %m",
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch if (mailbox_list_init(_storage->ns, "fs", &list_set,
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 MODULE_CONTEXT_SET_FULL(_storage->list, cydir_mailbox_list_module,
d577bb9027e4ceb19ada88d6884265efa5e16b15Stephan Boschstatic int create_cydir(struct mail_storage *storage, const char *path)
d577bb9027e4ceb19ada88d6884265efa5e16b15Stephan Bosch if (mkdir_parents(path, CREATE_MODE) < 0 && errno != EEXIST) {
d577bb9027e4ceb19ada88d6884265efa5e16b15Stephan Bosch if (!mail_storage_set_error_from_errno(storage)) {
6e62aa36a3190ef7193bd86158a4245da49132f0Stephan Boschstatic struct mailbox *
6e62aa36a3190ef7193bd86158a4245da49132f0Stephan Boschcydir_open(struct cydir_storage *storage, const char *name,
6e62aa36a3190ef7193bd86158a4245da49132f0Stephan Bosch struct mail_storage *_storage = &storage->storage;
10962368c30afde135743fd9796122e88a708e87Stephan Bosch path = mailbox_list_get_path(_storage->list, name,
10962368c30afde135743fd9796122e88a708e87Stephan Bosch index = index_storage_alloc(_storage, name, flags, CYDIR_INDEX_PREFIX);
10962368c30afde135743fd9796122e88a708e87Stephan Bosch pool = pool_alloconly_create("cydir mailbox", 1024+512);
10962368c30afde135743fd9796122e88a708e87Stephan Bosch index_storage_mailbox_init(&mbox->ibox, name, flags, FALSE);
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 struct cydir_storage *storage = (struct cydir_storage *)_storage;
b9ee73a064b38d8aeec754b964cc34b23487387aTimo Sirainen "cydir doesn't support streamed mailboxes");
10962368c30afde135743fd9796122e88a708e87Stephan Bosch path = mailbox_list_get_path(_storage->list, name,
10962368c30afde135743fd9796122e88a708e87Stephan Bosch mail_storage_set_error(_storage, MAIL_ERROR_NOTFOUND,
10962368c30afde135743fd9796122e88a708e87Stephan Bosch mail_storage_set_critical(_storage, "stat(%s) failed: %m",
b9ee73a064b38d8aeec754b964cc34b23487387aTimo Sirainenstatic int cydir_mailbox_create(struct mail_storage *_storage,
5968fa8151eecd191b1973b44dd8bec9b75810a6Phil Carmody const char *name,
378e6cb162b355d6f103526505bc00b9a78962e7Timo Sirainen path = mailbox_list_get_path(_storage->list, name,
10962368c30afde135743fd9796122e88a708e87Stephan Bosch mail_storage_set_error(_storage, MAIL_ERROR_NOTPOSSIBLE,
10962368c30afde135743fd9796122e88a708e87Stephan Bosch "Mailbox already exists");
10962368c30afde135743fd9796122e88a708e87Stephan Boschcydir_delete_nonrecursive(struct mailbox_list *list, const char *path,
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch unsigned int dir_len;
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch if (!mailbox_list_set_error_from_errno(list)) {
f74dbd3ff682fea040f60383e001620d1f1b09d3Stephan Bosch /* skip . and .. */
f74dbd3ff682fea040f60383e001620d1f1b09d3Stephan Bosch if (d->d_name[1] == '.' && d->d_name[2] == '\0')
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 else if (errno != ENOENT && errno != EISDIR && errno != EPERM) {
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch "unlink_directory(%s) failed: %m",
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch mailbox_list_set_critical(list, "closedir(%s) failed: %m",
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch else if (errno != ENOENT && errno != ENOTEMPTY) {
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch mailbox_list_set_critical(list, "rmdir(%s) failed: %m", path);
10962368c30afde135743fd9796122e88a708e87Stephan Bosch mailbox_list_set_error(list, MAIL_ERROR_NOTPOSSIBLE,
10962368c30afde135743fd9796122e88a708e87Stephan Boschcydir_list_delete_mailbox(struct mailbox_list *list, const char *name)
10962368c30afde135743fd9796122e88a708e87Stephan Bosch struct cydir_storage *storage = CYDIR_LIST_CONTEXT(list);
10962368c30afde135743fd9796122e88a708e87Stephan Bosch const char *src;
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 /* delete the index and control directories */
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch if (storage->list_module_ctx.super.delete_mailbox(list, name) < 0)
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch /* check if the mailbox actually exists */
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch src = mailbox_list_get_path(list, name, MAILBOX_LIST_PATH_TYPE_MAILBOX);
ba592dc74a004ad47dfe58edcfc1ca7297551e39Phil Carmody mailbox_list_set_error(list, MAIL_ERROR_NOTFOUND,
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch return cydir_delete_nonrecursive(list, src, name);
1faa520084b901b15d83d3d68baaee2535051defStephan Boschstatic void cydir_notify_changes(struct mailbox *box)
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch struct cydir_mailbox *mbox = (struct cydir_mailbox *)box;
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch index_mailbox_check_add(&mbox->ibox, mbox->path);
1faa520084b901b15d83d3d68baaee2535051defStephan Boschstatic int cydir_list_iter_is_mailbox(struct mailbox_list_iterate_context *ctx,
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch /* try to avoid stat() with these checks */
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch (ctx->flags & MAILBOX_LIST_ITER_RETURN_NO_FLAGS) != 0) {
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch /* it's a file */
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch /* need to stat() then */
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch mail_path = t_strconcat(dir, "/", fname, NULL);
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch /* non-directory */
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch *flags |= MAILBOX_NOSELECT | MAILBOX_NOINFERIORS;
1faa520084b901b15d83d3d68baaee2535051defStephan Bosch /* non-selectable, but may contain subdirs */
d577bb9027e4ceb19ada88d6884265efa5e16b15Stephan Boschstatic void cydir_class_init(void)
d577bb9027e4ceb19ada88d6884265efa5e16b15Stephan Boschstatic void cydir_class_deinit(void)