cydir-storage.c revision 4645cc6c911a95991d7af43b40f88e99506ea5e9
2454dfa32c93c20a8522c6ed42fe057baaac9f9aStephan Bosch/* Copyright (c) 2007 Dovecot authors, see the included COPYING file */
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen#include "lib.h"
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen#include "array.h"
735259c24eda6f272c8e21eab0f4d0c6bb022fd6Timo Sirainen#include "ioloop.h"
735259c24eda6f272c8e21eab0f4d0c6bb022fd6Timo Sirainen#include "str.h"
735259c24eda6f272c8e21eab0f4d0c6bb022fd6Timo Sirainen#include "mkdir-parents.h"
735259c24eda6f272c8e21eab0f4d0c6bb022fd6Timo Sirainen#include "unlink-directory.h"
fd16501d913e6e61a5cb9ae8f05b1fa7c19a1faeBaofeng Wang#include "index-mail.h"
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen#include "mail-copy.h"
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen#include "cydir-sync.h"
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen#include "cydir-storage.h"
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen
1537d20b852cbbf0d6971790b84e0cce5ca61307Timo Sirainen#include <stdio.h>
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen#include <stdlib.h>
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen#include <unistd.h>
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen#include <dirent.h>
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen#include <sys/stat.h>
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen#define CREATE_MODE 0770 /* umask() should limit it more */
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen#define CYDIR_LIST_CONTEXT(obj) \
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen MODULE_CONTEXT(obj, cydir_mailbox_list_module)
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainenextern struct mail_storage cydir_storage;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainenextern struct mailbox cydir_mailbox;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainenstatic MODULE_CONTEXT_DEFINE_INIT(cydir_mailbox_list_module,
735259c24eda6f272c8e21eab0f4d0c6bb022fd6Timo Sirainen &mailbox_list_module_register);
735259c24eda6f272c8e21eab0f4d0c6bb022fd6Timo Sirainen
735259c24eda6f272c8e21eab0f4d0c6bb022fd6Timo Sirainenstatic int
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainencydir_list_delete_mailbox(struct mailbox_list *list, const char *name);
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainenstatic int cydir_list_iter_is_mailbox(struct mailbox_list_iterate_context *ctx,
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen const char *dir, const char *fname,
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen enum mailbox_list_file_type type,
2bc82f0d7e717f600bcaaa15356cf9bfe26fb633Aki Tuomi enum mailbox_info_flags *flags);
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainenstatic int
2bc82f0d7e717f600bcaaa15356cf9bfe26fb633Aki Tuomicydir_get_list_settings(struct mailbox_list_settings *list_set,
2bc82f0d7e717f600bcaaa15356cf9bfe26fb633Aki Tuomi const char *data, enum mail_storage_flags flags,
a0c453a8edaec90fb0d945c874de0b1845bc7d7eTimo Sirainen const char **layout_r, const char **error_r)
a0c453a8edaec90fb0d945c874de0b1845bc7d7eTimo Sirainen{
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen bool debug = (flags & MAIL_STORAGE_FLAG_DEBUG) != 0;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen *layout_r = "fs";
fd16501d913e6e61a5cb9ae8f05b1fa7c19a1faeBaofeng Wang
88dc563319efecd6e68bad16b0d92672da05584aTimo Sirainen memset(list_set, 0, sizeof(*list_set));
88dc563319efecd6e68bad16b0d92672da05584aTimo Sirainen list_set->subscription_fname = CYDIR_SUBSCRIPTION_FILE_NAME;
85a4ae7e8df7ea45a7665828e5edf48a5fc85730Timo Sirainen list_set->maildir_name = "";
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainen if (data == NULL || *data == '\0' || *data == ':') {
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen /* we won't do any guessing for this format. */
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen if (debug)
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen i_info("cydir: mailbox location not given");
77124c580f127107f1ffae2a137dcd4eb498bd7bTimo Sirainen *error_r = "Root mail directory not given";
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen return -1;
0dffa25d211be541ee3c953b23566a1a990789dfTimo Sirainen }
0dffa25d211be541ee3c953b23566a1a990789dfTimo Sirainen
0dffa25d211be541ee3c953b23566a1a990789dfTimo Sirainen if (debug)
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen i_info("cydir: data=%s", data);
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainen return mailbox_list_settings_parse(data, list_set, layout_r, NULL,
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen error_r);
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen}
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainenstatic struct mail_storage *cydir_alloc(void)
0dffa25d211be541ee3c953b23566a1a990789dfTimo Sirainen{
85a4ae7e8df7ea45a7665828e5edf48a5fc85730Timo Sirainen struct cydir_storage *storage;
85a4ae7e8df7ea45a7665828e5edf48a5fc85730Timo Sirainen pool_t pool;
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen pool = pool_alloconly_create("cydir storage", 512+256);
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen storage = p_new(pool, struct cydir_storage, 1);
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen storage->storage = cydir_storage;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen storage->storage.pool = pool;
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen return &storage->storage;
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen}
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainenstatic int cydir_create(struct mail_storage *_storage, const char *data,
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen const char **error_r)
e7f8009c974ed6a6a5a0e88633d98fff2867fa92Timo Sirainen{
e7f8009c974ed6a6a5a0e88633d98fff2867fa92Timo Sirainen struct cydir_storage *storage = (struct cydir_storage *)_storage;
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen struct mailbox_list_settings list_set;
e7f8009c974ed6a6a5a0e88633d98fff2867fa92Timo Sirainen struct stat st;
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen const char *layout;
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen if (cydir_get_list_settings(&list_set, data, _storage->flags,
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen &layout, error_r) < 0)
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen return -1;
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen list_set.mail_storage_flags = &_storage->flags;
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen list_set.lock_method = &_storage->lock_method;
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen if ((_storage->flags & MAIL_STORAGE_FLAG_NO_AUTOCREATE) != 0) {
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen if (stat(list_set.root_dir, &st) < 0) {
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen if (errno != ENOENT) {
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen *error_r = t_strdup_printf(
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen "stat(%s) failed: %m",
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen list_set.root_dir);
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen } else {
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen *error_r = t_strdup_printf(
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen "Root mail directory doesn't exist: %s",
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen list_set.root_dir);
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen }
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen return -1;
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen }
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen } else {
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen if (mkdir_parents(list_set.root_dir, CREATE_MODE) < 0 &&
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen errno != EEXIST) {
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen *error_r = t_strdup_printf("mkdir(%s) failed: %m",
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen list_set.root_dir);
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen return -1;
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen }
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen }
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen if (mailbox_list_alloc(layout, &_storage->list, error_r) < 0)
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen return -1;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen storage->list_module_ctx.super = _storage->list->v;
88dc563319efecd6e68bad16b0d92672da05584aTimo Sirainen _storage->list->v.iter_is_mailbox = cydir_list_iter_is_mailbox;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen _storage->list->v.delete_mailbox = cydir_list_delete_mailbox;
0fd246126fece57712566c725d6353f255f5fcfaTimo Sirainen
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen MODULE_CONTEXT_SET_FULL(_storage->list, cydir_mailbox_list_module,
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen storage, &storage->list_module_ctx);
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen /* finish list init after we've overridden vfuncs */
d0ef8bc2b961a68dd0f75662c2160bd296b9476bTimo Sirainen mailbox_list_init(_storage->list, _storage->ns, &list_set,
f4616f1875297fb2f583d913c0f01b075bdecd5bTimo Sirainen mail_storage_get_list_flags(_storage->flags));
f4616f1875297fb2f583d913c0f01b075bdecd5bTimo Sirainen return 0;
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen}
f4616f1875297fb2f583d913c0f01b075bdecd5bTimo Sirainen
bc93929cdd9000ca560a5f42a27f50ab307f1efbTimo Sirainenstatic int create_cydir(struct mail_storage *storage, const char *path)
1537d20b852cbbf0d6971790b84e0cce5ca61307Timo Sirainen{
1537d20b852cbbf0d6971790b84e0cce5ca61307Timo Sirainen if (mkdir_parents(path, CREATE_MODE) < 0 && errno != EEXIST) {
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen if (!mail_storage_set_error_from_errno(storage)) {
bc93929cdd9000ca560a5f42a27f50ab307f1efbTimo Sirainen mail_storage_set_critical(storage,
1537d20b852cbbf0d6971790b84e0cce5ca61307Timo Sirainen "mkdir(%s) failed: %m", path);
1537d20b852cbbf0d6971790b84e0cce5ca61307Timo Sirainen }
1537d20b852cbbf0d6971790b84e0cce5ca61307Timo Sirainen return -1;
1537d20b852cbbf0d6971790b84e0cce5ca61307Timo Sirainen }
1537d20b852cbbf0d6971790b84e0cce5ca61307Timo Sirainen return 0;
1537d20b852cbbf0d6971790b84e0cce5ca61307Timo Sirainen}
bc93929cdd9000ca560a5f42a27f50ab307f1efbTimo Sirainen
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainenstatic struct mailbox *
1537d20b852cbbf0d6971790b84e0cce5ca61307Timo Sirainencydir_open(struct cydir_storage *storage, const char *name,
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen enum mailbox_open_flags flags)
d54ab8987e482a8df250615b44f41fa040c38741Timo Sirainen{
bc93929cdd9000ca560a5f42a27f50ab307f1efbTimo Sirainen struct mail_storage *_storage = &storage->storage;
bc93929cdd9000ca560a5f42a27f50ab307f1efbTimo Sirainen struct cydir_mailbox *mbox;
bc93929cdd9000ca560a5f42a27f50ab307f1efbTimo Sirainen struct mail_index *index;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen const char *path;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen pool_t pool;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen path = mailbox_list_get_path(_storage->list, name,
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen MAILBOX_LIST_PATH_TYPE_MAILBOX);
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen if (create_cydir(_storage, path) < 0)
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen return NULL;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen index = index_storage_alloc(_storage, name, flags, CYDIR_INDEX_PREFIX);
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen pool = pool_alloconly_create("cydir mailbox", 1024+512);
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen mbox = p_new(pool, struct cydir_mailbox, 1);
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen mbox->ibox.box = cydir_mailbox;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen mbox->ibox.box.pool = pool;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen mbox->ibox.storage = &storage->storage;
cbc8f9d71483a2cf71610f7e7e1f2dc9884bd556Baofeng Wang mbox->ibox.mail_vfuncs = &cydir_mail_vfuncs;
cbc8f9d71483a2cf71610f7e7e1f2dc9884bd556Baofeng Wang mbox->ibox.index = index;
cbc8f9d71483a2cf71610f7e7e1f2dc9884bd556Baofeng Wang
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen mbox->storage = storage;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen mbox->path = p_strdup(pool, path);
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen index_storage_mailbox_init(&mbox->ibox, name, flags, FALSE);
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen return &mbox->ibox.box;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen}
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen
a693adf01b5f9256b273bee0b38efb69bc2b0182Timo Sirainenstatic struct mailbox *
a693adf01b5f9256b273bee0b38efb69bc2b0182Timo Sirainencydir_mailbox_open(struct mail_storage *_storage, const char *name,
a693adf01b5f9256b273bee0b38efb69bc2b0182Timo Sirainen struct istream *input, enum mailbox_open_flags flags)
a693adf01b5f9256b273bee0b38efb69bc2b0182Timo Sirainen{
a693adf01b5f9256b273bee0b38efb69bc2b0182Timo Sirainen struct cydir_storage *storage = (struct cydir_storage *)_storage;
a693adf01b5f9256b273bee0b38efb69bc2b0182Timo Sirainen const char *path;
a693adf01b5f9256b273bee0b38efb69bc2b0182Timo Sirainen struct stat st;
a693adf01b5f9256b273bee0b38efb69bc2b0182Timo Sirainen
a693adf01b5f9256b273bee0b38efb69bc2b0182Timo Sirainen if (input != NULL) {
a693adf01b5f9256b273bee0b38efb69bc2b0182Timo Sirainen mail_storage_set_critical(_storage,
a693adf01b5f9256b273bee0b38efb69bc2b0182Timo Sirainen "cydir doesn't support streamed mailboxes");
a693adf01b5f9256b273bee0b38efb69bc2b0182Timo Sirainen return NULL;
a693adf01b5f9256b273bee0b38efb69bc2b0182Timo Sirainen }
a693adf01b5f9256b273bee0b38efb69bc2b0182Timo Sirainen
a693adf01b5f9256b273bee0b38efb69bc2b0182Timo Sirainen if (strcmp(name, "INBOX") == 0)
a693adf01b5f9256b273bee0b38efb69bc2b0182Timo Sirainen return cydir_open(storage, "INBOX", flags);
a693adf01b5f9256b273bee0b38efb69bc2b0182Timo Sirainen
a693adf01b5f9256b273bee0b38efb69bc2b0182Timo Sirainen path = mailbox_list_get_path(_storage->list, name,
a693adf01b5f9256b273bee0b38efb69bc2b0182Timo Sirainen MAILBOX_LIST_PATH_TYPE_MAILBOX);
88dc563319efecd6e68bad16b0d92672da05584aTimo Sirainen if (stat(path, &st) == 0) {
88dc563319efecd6e68bad16b0d92672da05584aTimo Sirainen return cydir_open(storage, name, flags);
c4b376dd6e0c423006d7ac83a39253bcaf8e7c47Timo Sirainen } else if (errno == ENOENT) {
eef4ba0cc3e78f8c26804c1c9251a76580a41f0cTimo Sirainen mail_storage_set_error(_storage, MAIL_ERROR_NOTFOUND,
eef4ba0cc3e78f8c26804c1c9251a76580a41f0cTimo Sirainen T_MAIL_ERR_MAILBOX_NOT_FOUND(name));
eef4ba0cc3e78f8c26804c1c9251a76580a41f0cTimo Sirainen return NULL;
88dc563319efecd6e68bad16b0d92672da05584aTimo Sirainen } else {
a0c453a8edaec90fb0d945c874de0b1845bc7d7eTimo Sirainen mail_storage_set_critical(_storage, "stat(%s) failed: %m",
88dc563319efecd6e68bad16b0d92672da05584aTimo Sirainen path);
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen return NULL;
88dc563319efecd6e68bad16b0d92672da05584aTimo Sirainen }
88dc563319efecd6e68bad16b0d92672da05584aTimo Sirainen}
88dc563319efecd6e68bad16b0d92672da05584aTimo Sirainen
eef4ba0cc3e78f8c26804c1c9251a76580a41f0cTimo Sirainenstatic int cydir_mailbox_create(struct mail_storage *_storage,
eef4ba0cc3e78f8c26804c1c9251a76580a41f0cTimo Sirainen const char *name,
88dc563319efecd6e68bad16b0d92672da05584aTimo Sirainen bool directory ATTR_UNUSED)
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen{
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen const char *path;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen struct stat st;
88dc563319efecd6e68bad16b0d92672da05584aTimo Sirainen
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen path = mailbox_list_get_path(_storage->list, name,
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen MAILBOX_LIST_PATH_TYPE_MAILBOX);
bc93929cdd9000ca560a5f42a27f50ab307f1efbTimo Sirainen if (stat(path, &st) == 0) {
88dc563319efecd6e68bad16b0d92672da05584aTimo Sirainen mail_storage_set_error(_storage, MAIL_ERROR_NOTPOSSIBLE,
a5e89374cb2fb2cad575fee6c3b33a9487ab9b3aTimo Sirainen "Mailbox already exists");
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen return -1;
aa41b2e17912d6cad3151babea6a85dd88539d28Timo Sirainen }
0211537cbf53ad17348408103fdb0c06de56ed5eTimo Sirainen
71748cca1bacd74451fd228db5536828bdfeb190Baofeng Wang return create_cydir(_storage, path);
71748cca1bacd74451fd228db5536828bdfeb190Baofeng Wang}
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainenstatic int
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainencydir_delete_nonrecursive(struct mailbox_list *list, const char *path,
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen const char *name)
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen{
88dc563319efecd6e68bad16b0d92672da05584aTimo Sirainen DIR *dir;
a693adf01b5f9256b273bee0b38efb69bc2b0182Timo Sirainen struct dirent *d;
a693adf01b5f9256b273bee0b38efb69bc2b0182Timo Sirainen string_t *full_path;
a693adf01b5f9256b273bee0b38efb69bc2b0182Timo Sirainen unsigned int dir_len;
71748cca1bacd74451fd228db5536828bdfeb190Baofeng Wang bool unlinked_something = FALSE;
71748cca1bacd74451fd228db5536828bdfeb190Baofeng Wang
117fb8c00336dc54bab9cfa547249df7a4970611Timo Sirainen dir = opendir(path);
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen if (dir == NULL) {
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen if (!mailbox_list_set_error_from_errno(list)) {
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen mailbox_list_set_critical(list,
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen "opendir(%s) failed: %m", path);
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen }
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen return -1;
a0c453a8edaec90fb0d945c874de0b1845bc7d7eTimo Sirainen }
0211537cbf53ad17348408103fdb0c06de56ed5eTimo Sirainen
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen full_path = t_str_new(256);
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen str_append(full_path, path);
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen str_append_c(full_path, '/');
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen dir_len = str_len(full_path);
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen errno = 0;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen while ((d = readdir(dir)) != NULL) {
88dc563319efecd6e68bad16b0d92672da05584aTimo Sirainen if (d->d_name[0] == '.') {
88dc563319efecd6e68bad16b0d92672da05584aTimo Sirainen /* skip . and .. */
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen if (d->d_name[1] == '\0')
bc93929cdd9000ca560a5f42a27f50ab307f1efbTimo Sirainen continue;
6f368f8571092c5ad94357752cfea34f69ef66d7Timo Sirainen if (d->d_name[1] == '.' && d->d_name[2] == '\0')
6f368f8571092c5ad94357752cfea34f69ef66d7Timo Sirainen continue;
6f368f8571092c5ad94357752cfea34f69ef66d7Timo Sirainen }
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen
6f368f8571092c5ad94357752cfea34f69ef66d7Timo Sirainen str_truncate(full_path, dir_len);
6f368f8571092c5ad94357752cfea34f69ef66d7Timo Sirainen str_append(full_path, d->d_name);
6f368f8571092c5ad94357752cfea34f69ef66d7Timo Sirainen
6f368f8571092c5ad94357752cfea34f69ef66d7Timo Sirainen /* trying to unlink() a directory gives either EPERM or EISDIR
6f368f8571092c5ad94357752cfea34f69ef66d7Timo Sirainen (non-POSIX). it doesn't really work anywhere in practise,
6f368f8571092c5ad94357752cfea34f69ef66d7Timo Sirainen so don't bother stat()ing the file first */
6f368f8571092c5ad94357752cfea34f69ef66d7Timo Sirainen if (unlink(str_c(full_path)) == 0)
6f368f8571092c5ad94357752cfea34f69ef66d7Timo Sirainen unlinked_something = TRUE;
6f368f8571092c5ad94357752cfea34f69ef66d7Timo Sirainen else if (errno != ENOENT && errno != EISDIR && errno != EPERM) {
6f368f8571092c5ad94357752cfea34f69ef66d7Timo Sirainen mailbox_list_set_critical(list,
6f368f8571092c5ad94357752cfea34f69ef66d7Timo Sirainen "unlink_directory(%s) failed: %m",
6f368f8571092c5ad94357752cfea34f69ef66d7Timo Sirainen str_c(full_path));
6f368f8571092c5ad94357752cfea34f69ef66d7Timo Sirainen }
6f368f8571092c5ad94357752cfea34f69ef66d7Timo Sirainen }
b66d803de86bfb411165b3465b0d9ef64ecfe2a1Timo Sirainen
b66d803de86bfb411165b3465b0d9ef64ecfe2a1Timo Sirainen if (closedir(dir) < 0) {
88dc563319efecd6e68bad16b0d92672da05584aTimo Sirainen mailbox_list_set_critical(list, "closedir(%s) failed: %m",
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen path);
64b61cd24d630223478ccbe1934b9f60f0881f59Timo Sirainen }
64b61cd24d630223478ccbe1934b9f60f0881f59Timo Sirainen
64b61cd24d630223478ccbe1934b9f60f0881f59Timo Sirainen if (rmdir(path) == 0)
64b61cd24d630223478ccbe1934b9f60f0881f59Timo Sirainen unlinked_something = TRUE;
437a8b0fe254057b0c1f1723d689bafa91cae2abTimo Sirainen else if (errno != ENOENT && errno != ENOTEMPTY) {
64b61cd24d630223478ccbe1934b9f60f0881f59Timo Sirainen mailbox_list_set_critical(list, "rmdir(%s) failed: %m", path);
64b61cd24d630223478ccbe1934b9f60f0881f59Timo Sirainen return -1;
6d41944c73171cdb64b0a00bff368d212452e924Timo Sirainen }
04f70d9dc154761eb262f485415f27ed0345ece4Timo Sirainen
04f70d9dc154761eb262f485415f27ed0345ece4Timo Sirainen if (!unlinked_something) {
04f70d9dc154761eb262f485415f27ed0345ece4Timo Sirainen mailbox_list_set_error(list, MAIL_ERROR_NOTPOSSIBLE,
04f70d9dc154761eb262f485415f27ed0345ece4Timo Sirainen t_strdup_printf("Directory %s isn't empty, "
04f70d9dc154761eb262f485415f27ed0345ece4Timo Sirainen "can't delete it.", name));
04f70d9dc154761eb262f485415f27ed0345ece4Timo Sirainen return -1;
04f70d9dc154761eb262f485415f27ed0345ece4Timo Sirainen }
64b61cd24d630223478ccbe1934b9f60f0881f59Timo Sirainen return 0;
2e5170d1dce33cf055cfc2f6fa4b4a61df35d1c5Timo Sirainen}
6f368f8571092c5ad94357752cfea34f69ef66d7Timo Sirainen
6f368f8571092c5ad94357752cfea34f69ef66d7Timo Sirainenstatic int
6f368f8571092c5ad94357752cfea34f69ef66d7Timo Sirainencydir_list_delete_mailbox(struct mailbox_list *list, const char *name)
6f368f8571092c5ad94357752cfea34f69ef66d7Timo Sirainen{
6f368f8571092c5ad94357752cfea34f69ef66d7Timo Sirainen struct cydir_storage *storage = CYDIR_LIST_CONTEXT(list);
6f368f8571092c5ad94357752cfea34f69ef66d7Timo Sirainen struct stat st;
6f368f8571092c5ad94357752cfea34f69ef66d7Timo Sirainen const char *src;
6f368f8571092c5ad94357752cfea34f69ef66d7Timo Sirainen
6f368f8571092c5ad94357752cfea34f69ef66d7Timo Sirainen /* Make sure the indexes are closed before trying to delete the
6d41944c73171cdb64b0a00bff368d212452e924Timo Sirainen directory that contains them. It can still fail with some NFS
2e5170d1dce33cf055cfc2f6fa4b4a61df35d1c5Timo Sirainen implementations if indexes are opened by another session, but
2e5170d1dce33cf055cfc2f6fa4b4a61df35d1c5Timo Sirainen that can't really be helped. */
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainen index_storage_destroy_unrefed();
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen
eef4ba0cc3e78f8c26804c1c9251a76580a41f0cTimo Sirainen /* delete the index and control directories */
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainen if (storage->list_module_ctx.super.delete_mailbox(list, name) < 0)
88dc563319efecd6e68bad16b0d92672da05584aTimo Sirainen return -1;
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainen
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen /* check if the mailbox actually exists */
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen src = mailbox_list_get_path(list, name, MAILBOX_LIST_PATH_TYPE_MAILBOX);
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainen if (stat(src, &st) != 0 && errno == ENOENT) {
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen mailbox_list_set_error(list, MAIL_ERROR_NOTFOUND,
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen T_MAIL_ERR_MAILBOX_NOT_FOUND(name));
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainen return -1;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen }
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainen
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen return cydir_delete_nonrecursive(list, src, name);
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen}
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainenstatic void cydir_notify_changes(struct mailbox *box)
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen{
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen struct cydir_mailbox *mbox = (struct cydir_mailbox *)box;
f4616f1875297fb2f583d913c0f01b075bdecd5bTimo Sirainen
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen if (box->notify_callback == NULL)
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen index_mailbox_check_remove_all(&mbox->ibox);
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen else
f4616f1875297fb2f583d913c0f01b075bdecd5bTimo Sirainen index_mailbox_check_add(&mbox->ibox, mbox->path);
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen}
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainenstatic int cydir_list_iter_is_mailbox(struct mailbox_list_iterate_context *ctx
f4616f1875297fb2f583d913c0f01b075bdecd5bTimo Sirainen ATTR_UNUSED,
f4616f1875297fb2f583d913c0f01b075bdecd5bTimo Sirainen const char *dir, const char *fname,
bd1b2615928a1e8be190cb0405754f0aec8cac2fTimo Sirainen enum mailbox_list_file_type type,
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen enum mailbox_info_flags *flags)
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen{
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen const char *mail_path;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen struct stat st;
94f90df2cfb7587bb5af432b2ba065d1c364e1f7Timo Sirainen int ret = 1;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen /* try to avoid stat() with these checks */
009ec18ed6bc25a0331d8645a5d4380cb6f70c7bTimo Sirainen if (type != MAILBOX_LIST_FILE_TYPE_DIR &&
6d41944c73171cdb64b0a00bff368d212452e924Timo Sirainen type != MAILBOX_LIST_FILE_TYPE_SYMLINK &&
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen type != MAILBOX_LIST_FILE_TYPE_UNKNOWN) {
c63c3c4d548416914b8c6734fe18dd69bb900775Timo Sirainen /* it's a file */
94f90df2cfb7587bb5af432b2ba065d1c364e1f7Timo Sirainen *flags |= MAILBOX_NOSELECT | MAILBOX_NOINFERIORS;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen return 0;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen }
3852872e6954b7132e637294132005e86b8ebd4aTimo Sirainen
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen /* need to stat() then */
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen t_push();
ecdce39e5ef4b62eefa9f5818f17d153fd5d710aTimo Sirainen mail_path = t_strconcat(dir, "/", fname, NULL);
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen if (stat(mail_path, &st) == 0) {
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen if (!S_ISDIR(st.st_mode)) {
ecdce39e5ef4b62eefa9f5818f17d153fd5d710aTimo Sirainen /* non-directory */
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen *flags |= MAILBOX_NOSELECT | MAILBOX_NOINFERIORS;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen ret = 0;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen }
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen } else {
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen /* non-selectable. probably either access denied, or symlink
ecdce39e5ef4b62eefa9f5818f17d153fd5d710aTimo Sirainen destination not found. don't bother logging errors. */
ecdce39e5ef4b62eefa9f5818f17d153fd5d710aTimo Sirainen *flags |= MAILBOX_NOSELECT;
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen }
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen t_pop();
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen return ret;
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen}
6d41944c73171cdb64b0a00bff368d212452e924Timo Sirainen
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainenstatic void cydir_class_init(void)
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen{
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen cydir_transaction_class_init();
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen}
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainenstatic void cydir_class_deinit(void)
6d41944c73171cdb64b0a00bff368d212452e924Timo Sirainen{
6d41944c73171cdb64b0a00bff368d212452e924Timo Sirainen cydir_transaction_class_deinit();
0211537cbf53ad17348408103fdb0c06de56ed5eTimo Sirainen}
0211537cbf53ad17348408103fdb0c06de56ed5eTimo Sirainen
0211537cbf53ad17348408103fdb0c06de56ed5eTimo Sirainenstruct mail_storage cydir_storage = {
0211537cbf53ad17348408103fdb0c06de56ed5eTimo Sirainen MEMBER(name) CYDIR_STORAGE_NAME,
0211537cbf53ad17348408103fdb0c06de56ed5eTimo Sirainen MEMBER(mailbox_is_file) FALSE,
0211537cbf53ad17348408103fdb0c06de56ed5eTimo Sirainen
a0c453a8edaec90fb0d945c874de0b1845bc7d7eTimo Sirainen {
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen cydir_class_init,
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen cydir_class_deinit,
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen cydir_alloc,
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen cydir_create,
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen NULL,
04f70d9dc154761eb262f485415f27ed0345ece4Timo Sirainen NULL,
04f70d9dc154761eb262f485415f27ed0345ece4Timo Sirainen cydir_mailbox_open,
04f70d9dc154761eb262f485415f27ed0345ece4Timo Sirainen cydir_mailbox_create
88dc563319efecd6e68bad16b0d92672da05584aTimo Sirainen }
6d41944c73171cdb64b0a00bff368d212452e924Timo Sirainen};
6d41944c73171cdb64b0a00bff368d212452e924Timo Sirainen
6d41944c73171cdb64b0a00bff368d212452e924Timo Sirainenstruct mailbox cydir_mailbox = {
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen MEMBER(name) NULL,
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen MEMBER(storage) NULL,
fde0b1793a2842da00eaa105d5e13fec465f0443Timo Sirainen
a0c453a8edaec90fb0d945c874de0b1845bc7d7eTimo Sirainen {
a0c453a8edaec90fb0d945c874de0b1845bc7d7eTimo Sirainen index_storage_is_readonly,
a0c453a8edaec90fb0d945c874de0b1845bc7d7eTimo Sirainen index_storage_allow_new_keywords,
a0c453a8edaec90fb0d945c874de0b1845bc7d7eTimo Sirainen index_storage_mailbox_close,
a0c453a8edaec90fb0d945c874de0b1845bc7d7eTimo Sirainen index_storage_get_status,
a0c453a8edaec90fb0d945c874de0b1845bc7d7eTimo Sirainen NULL,
a0c453a8edaec90fb0d945c874de0b1845bc7d7eTimo Sirainen NULL,
a0c453a8edaec90fb0d945c874de0b1845bc7d7eTimo Sirainen cydir_storage_sync_init,
a0c453a8edaec90fb0d945c874de0b1845bc7d7eTimo Sirainen index_mailbox_sync_next,
a0c453a8edaec90fb0d945c874de0b1845bc7d7eTimo Sirainen index_mailbox_sync_deinit,
a0c453a8edaec90fb0d945c874de0b1845bc7d7eTimo Sirainen NULL,
a0c453a8edaec90fb0d945c874de0b1845bc7d7eTimo Sirainen cydir_notify_changes,
a0c453a8edaec90fb0d945c874de0b1845bc7d7eTimo Sirainen index_transaction_begin,
fd14806f879f6cd4f023750e0c4cac27a7f94fbbTimo Sirainen index_transaction_commit,
a0c453a8edaec90fb0d945c874de0b1845bc7d7eTimo Sirainen index_transaction_rollback,
a0c453a8edaec90fb0d945c874de0b1845bc7d7eTimo Sirainen index_keywords_create,
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen index_keywords_free,
fde0b1793a2842da00eaa105d5e13fec465f0443Timo Sirainen index_storage_get_uids,
a0c453a8edaec90fb0d945c874de0b1845bc7d7eTimo Sirainen index_mail_alloc,
a0c453a8edaec90fb0d945c874de0b1845bc7d7eTimo Sirainen index_header_lookup_init,
a0c453a8edaec90fb0d945c874de0b1845bc7d7eTimo Sirainen index_header_lookup_deinit,
e34d170f8f0e084bd94bfbc1a7085ece67e508dfTimo Sirainen index_storage_search_init,
e34d170f8f0e084bd94bfbc1a7085ece67e508dfTimo Sirainen index_storage_search_deinit,
e34d170f8f0e084bd94bfbc1a7085ece67e508dfTimo Sirainen index_storage_search_next_nonblock,
a0c453a8edaec90fb0d945c874de0b1845bc7d7eTimo Sirainen index_storage_search_next_update_seq,
a0c453a8edaec90fb0d945c874de0b1845bc7d7eTimo Sirainen cydir_save_init,
a0c453a8edaec90fb0d945c874de0b1845bc7d7eTimo Sirainen cydir_save_continue,
a0c453a8edaec90fb0d945c874de0b1845bc7d7eTimo Sirainen cydir_save_finish,
a0c453a8edaec90fb0d945c874de0b1845bc7d7eTimo Sirainen cydir_save_cancel,
fda168427e1950518acd6d600f1a10a29a5baef0Timo Sirainen mail_storage_copy,
fda168427e1950518acd6d600f1a10a29a5baef0Timo Sirainen index_storage_is_inconsistent
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen }
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen};
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen