cydir-storage.c revision 4645cc6c911a95991d7af43b40f88e99506ea5e9
2454dfa32c93c20a8522c6ed42fe057baaac9f9aStephan Bosch/* Copyright (c) 2007 Dovecot authors, see the included COPYING file */
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainen#define CREATE_MODE 0770 /* umask() should limit it more */
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen MODULE_CONTEXT(obj, cydir_mailbox_list_module)
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainenstatic MODULE_CONTEXT_DEFINE_INIT(cydir_mailbox_list_module,
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,
2bc82f0d7e717f600bcaaa15356cf9bfe26fb633Aki Tuomicydir_get_list_settings(struct mailbox_list_settings *list_set,
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen bool debug = (flags & MAIL_STORAGE_FLAG_DEBUG) != 0;
88dc563319efecd6e68bad16b0d92672da05584aTimo Sirainen list_set->subscription_fname = CYDIR_SUBSCRIPTION_FILE_NAME;
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainen if (data == NULL || *data == '\0' || *data == ':') {
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen /* we won't do any guessing for this format. */
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainen return mailbox_list_settings_parse(data, list_set, layout_r, NULL,
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen pool = pool_alloconly_create("cydir storage", 512+256);
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen storage = p_new(pool, struct cydir_storage, 1);
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainenstatic int cydir_create(struct mail_storage *_storage, const char *data,
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen const char **error_r)
e7f8009c974ed6a6a5a0e88633d98fff2867fa92Timo Sirainen struct cydir_storage *storage = (struct cydir_storage *)_storage;
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen if (cydir_get_list_settings(&list_set, data, _storage->flags,
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen list_set.mail_storage_flags = &_storage->flags;
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen list_set.lock_method = &_storage->lock_method;
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen if ((_storage->flags & MAIL_STORAGE_FLAG_NO_AUTOCREATE) != 0) {
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen "stat(%s) failed: %m",
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen "Root mail directory doesn't exist: %s",
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen if (mkdir_parents(list_set.root_dir, CREATE_MODE) < 0 &&
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen *error_r = t_strdup_printf("mkdir(%s) failed: %m",
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen if (mailbox_list_alloc(layout, &_storage->list, error_r) < 0)
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;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen MODULE_CONTEXT_SET_FULL(_storage->list, cydir_mailbox_list_module,
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));
bc93929cdd9000ca560a5f42a27f50ab307f1efbTimo Sirainenstatic int create_cydir(struct mail_storage *storage, const char *path)
1537d20b852cbbf0d6971790b84e0cce5ca61307Timo Sirainen if (mkdir_parents(path, CREATE_MODE) < 0 && errno != EEXIST) {
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen if (!mail_storage_set_error_from_errno(storage)) {
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainenstatic struct mailbox *
1537d20b852cbbf0d6971790b84e0cce5ca61307Timo Sirainencydir_open(struct cydir_storage *storage, const char *name,
bc93929cdd9000ca560a5f42a27f50ab307f1efbTimo Sirainen struct mail_storage *_storage = &storage->storage;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen path = mailbox_list_get_path(_storage->list, name,
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen index = index_storage_alloc(_storage, name, flags, CYDIR_INDEX_PREFIX);
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen pool = pool_alloconly_create("cydir mailbox", 1024+512);
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen index_storage_mailbox_init(&mbox->ibox, name, flags, FALSE);
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 struct cydir_storage *storage = (struct cydir_storage *)_storage;
a693adf01b5f9256b273bee0b38efb69bc2b0182Timo Sirainen "cydir doesn't support streamed mailboxes");
a693adf01b5f9256b273bee0b38efb69bc2b0182Timo Sirainen path = mailbox_list_get_path(_storage->list, name,
eef4ba0cc3e78f8c26804c1c9251a76580a41f0cTimo Sirainen mail_storage_set_error(_storage, MAIL_ERROR_NOTFOUND,
a0c453a8edaec90fb0d945c874de0b1845bc7d7eTimo Sirainen mail_storage_set_critical(_storage, "stat(%s) failed: %m",
eef4ba0cc3e78f8c26804c1c9251a76580a41f0cTimo Sirainenstatic int cydir_mailbox_create(struct mail_storage *_storage,
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen path = mailbox_list_get_path(_storage->list, name,
88dc563319efecd6e68bad16b0d92672da05584aTimo Sirainen mail_storage_set_error(_storage, MAIL_ERROR_NOTPOSSIBLE,
a5e89374cb2fb2cad575fee6c3b33a9487ab9b3aTimo Sirainen "Mailbox already exists");
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainencydir_delete_nonrecursive(struct mailbox_list *list, const char *path,
a693adf01b5f9256b273bee0b38efb69bc2b0182Timo Sirainen unsigned int dir_len;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen if (!mailbox_list_set_error_from_errno(list)) {
88dc563319efecd6e68bad16b0d92672da05584aTimo Sirainen /* skip . and .. */
6f368f8571092c5ad94357752cfea34f69ef66d7Timo Sirainen if (d->d_name[1] == '.' && d->d_name[2] == '\0')
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 else if (errno != ENOENT && errno != EISDIR && errno != EPERM) {
6f368f8571092c5ad94357752cfea34f69ef66d7Timo Sirainen "unlink_directory(%s) failed: %m",
88dc563319efecd6e68bad16b0d92672da05584aTimo Sirainen mailbox_list_set_critical(list, "closedir(%s) failed: %m",
437a8b0fe254057b0c1f1723d689bafa91cae2abTimo Sirainen else if (errno != ENOENT && errno != ENOTEMPTY) {
64b61cd24d630223478ccbe1934b9f60f0881f59Timo Sirainen mailbox_list_set_critical(list, "rmdir(%s) failed: %m", path);
04f70d9dc154761eb262f485415f27ed0345ece4Timo Sirainen mailbox_list_set_error(list, MAIL_ERROR_NOTPOSSIBLE,
6f368f8571092c5ad94357752cfea34f69ef66d7Timo Sirainencydir_list_delete_mailbox(struct mailbox_list *list, const char *name)
6f368f8571092c5ad94357752cfea34f69ef66d7Timo Sirainen struct cydir_storage *storage = CYDIR_LIST_CONTEXT(list);
6f368f8571092c5ad94357752cfea34f69ef66d7Timo Sirainen const char *src;
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. */
eef4ba0cc3e78f8c26804c1c9251a76580a41f0cTimo Sirainen /* delete the index and control directories */
1b0cfbf3cc77a670b92fff5c30f7b1eb17a63ab1Timo Sirainen if (storage->list_module_ctx.super.delete_mailbox(list, name) < 0)
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen /* check if the mailbox actually exists */
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen src = mailbox_list_get_path(list, name, MAILBOX_LIST_PATH_TYPE_MAILBOX);
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen mailbox_list_set_error(list, MAIL_ERROR_NOTFOUND,
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen return cydir_delete_nonrecursive(list, src, name);
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainenstatic void cydir_notify_changes(struct mailbox *box)
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen struct cydir_mailbox *mbox = (struct cydir_mailbox *)box;
f4616f1875297fb2f583d913c0f01b075bdecd5bTimo Sirainen index_mailbox_check_add(&mbox->ibox, mbox->path);
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainenstatic int cydir_list_iter_is_mailbox(struct mailbox_list_iterate_context *ctx
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen /* try to avoid stat() with these checks */
c63c3c4d548416914b8c6734fe18dd69bb900775Timo Sirainen /* it's a file */
94f90df2cfb7587bb5af432b2ba065d1c364e1f7Timo Sirainen *flags |= MAILBOX_NOSELECT | MAILBOX_NOINFERIORS;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen /* need to stat() then */
ecdce39e5ef4b62eefa9f5818f17d153fd5d710aTimo Sirainen mail_path = t_strconcat(dir, "/", fname, NULL);
ecdce39e5ef4b62eefa9f5818f17d153fd5d710aTimo Sirainen /* non-directory */
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen *flags |= MAILBOX_NOSELECT | MAILBOX_NOINFERIORS;
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen /* non-selectable. probably either access denied, or symlink
ecdce39e5ef4b62eefa9f5818f17d153fd5d710aTimo Sirainen destination not found. don't bother logging errors. */
2793e3bd31d212d6506686aa70773e13d9d98195Timo Sirainenstatic void cydir_class_init(void)
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainenstatic void cydir_class_deinit(void)