cydir-storage.c revision 563273bdac80393af63b9520cbf4d24cc0efd028
45312f52ff3a3d4c137447be4c7556500c2f8bf2Timo Sirainen/* Copyright (c) 2007-2009 Dovecot authors, see the included COPYING file */
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen MODULE_CONTEXT(obj, cydir_mailbox_list_module)
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainenstatic MODULE_CONTEXT_DEFINE_INIT(cydir_mailbox_list_module,
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainenstatic struct mail_storage *cydir_storage_alloc(void)
f7539a17ea306191b53b8f5e752e228937df9ec3Timo Sirainen pool = pool_alloconly_create("cydir storage", 512+256);
f7539a17ea306191b53b8f5e752e228937df9ec3Timo Sirainen storage = p_new(pool, struct cydir_storage, 1);
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainencydir_storage_get_list_settings(const struct mail_namespace *ns ATTR_UNUSED,
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen set->subscription_fname = CYDIR_SUBSCRIPTION_FILE_NAME;
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainenstatic int create_cydir(struct mail_storage *storage, struct mail_namespace *ns,
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen mailbox_list_get_dir_permissions(ns->list, NULL, &mode, &gid);
fea7b8b3fc182e415b1875d79587c0aa1adb09d7Timo Sirainen if (mkdir_parents_chown(path, mode, (uid_t)-1, gid) < 0 &&
ff7056842f14fd3b30a2d327dfab165b9d15dd30Timo Sirainen if (!mail_storage_set_error_from_errno(storage)) {
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainenstatic struct mailbox *
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainencydir_open(struct mail_storage *storage, struct mailbox_list *list,
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen const char *name, enum mailbox_open_flags flags)
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen index = index_storage_alloc(list, name, flags, CYDIR_INDEX_PREFIX);
ab8cf8fb93579981a687942e53bdb361b3b61bafTimo Sirainen mail_index_set_fsync_types(index, MAIL_INDEX_SYNC_TYPE_APPEND |
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen pool = pool_alloconly_create("cydir mailbox", 1024+512);
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen mbox->storage = (struct cydir_storage *)storage;
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen index_storage_mailbox_init(&mbox->ibox, name, flags, FALSE);
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainenstatic struct mailbox *
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainencydir_mailbox_open(struct mail_storage *storage, struct mailbox_list *list,
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen "cydir doesn't support streamed mailboxes");
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen return cydir_open(storage, list, name, flags);
32ee977e189266744ef69ac4e832fd3111d6f949Timo Sirainen /* INBOX always exists, create it */
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen if (create_cydir(storage, list->ns, path) < 0) {
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen return cydir_open(storage, list, "INBOX", flags);
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen mail_storage_set_error(storage, MAIL_ERROR_NOTFOUND,
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen mail_storage_set_critical(storage, "stat(%s) failed: %m",
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainencydir_mailbox_create(struct mail_storage *storage, struct mailbox_list *list,
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen mail_storage_set_error(storage, MAIL_ERROR_EXISTS,
ff7056842f14fd3b30a2d327dfab165b9d15dd30Timo Sirainen "Mailbox already exists");
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainencydir_delete_nonrecursive(struct mailbox_list *list, const char *path,
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen unsigned int dir_len;
ff7056842f14fd3b30a2d327dfab165b9d15dd30Timo Sirainen if (!mailbox_list_set_error_from_errno(list)) {
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen /* skip . and .. */
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen if (d->d_name[1] == '.' && d->d_name[2] == '\0')
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen /* trying to unlink() a directory gives either EPERM or EISDIR
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen (non-POSIX). it doesn't really work anywhere in practise,
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen so don't bother stat()ing the file first */
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen else if (errno != ENOENT && errno != EISDIR && errno != EPERM) {
71c4ac143fefd57aeec6298489c4559b6f13c67bTimo Sirainen mailbox_list_set_critical(list, "unlink(%s) failed: %m",
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen mailbox_list_set_critical(list, "closedir(%s) failed: %m",
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen else if (errno != ENOENT && errno != ENOTEMPTY) {
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen mailbox_list_set_critical(list, "rmdir(%s) failed: %m", path);
4321f6c969e7b8f6b243ff5bb6b8d297921676f6Timo Sirainen mailbox_list_set_error(list, MAIL_ERROR_NOTFOUND,
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainencydir_list_delete_mailbox(struct mailbox_list *list, const char *name)
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen struct cydir_mailbox_list *mlist = CYDIR_LIST_CONTEXT(list);
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen const char *src;
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen /* Make sure the indexes are closed before trying to delete the
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen directory that contains them. It can still fail with some NFS
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen implementations if indexes are opened by another session, but
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen that can't really be helped. */
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen /* delete the index and control directories */
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen if (mlist->module_ctx.super.delete_mailbox(list, name) < 0)
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen /* check if the mailbox actually exists */
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen src = mailbox_list_get_path(list, name, MAILBOX_LIST_PATH_TYPE_MAILBOX);
ff7056842f14fd3b30a2d327dfab165b9d15dd30Timo Sirainen mailbox_list_set_error(list, MAIL_ERROR_NOTFOUND,
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen return cydir_delete_nonrecursive(list, src, name);
f81f4bc282cd1944cec187bae89c0701a416ed2aTimo Sirainenstatic void cydir_notify_changes(struct mailbox *box)
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen struct cydir_mailbox *mbox = (struct cydir_mailbox *)box;
f81f4bc282cd1944cec187bae89c0701a416ed2aTimo Sirainen index_mailbox_check_add(&mbox->ibox, mbox->path);
cc0bb7692b8a47abca3279abbb49b073f7a27f21Timo Sirainenstatic int cydir_list_iter_is_mailbox(struct mailbox_list_iterate_context *ctx
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen /* try to avoid stat() with these checks */
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen /* it's a file */
cc0bb7692b8a47abca3279abbb49b073f7a27f21Timo Sirainen *flags |= MAILBOX_NOSELECT | MAILBOX_NOINFERIORS;
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen /* need to stat() then */
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen mail_path = t_strconcat(dir, "/", fname, NULL);
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen /* non-directory */
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainen *flags |= MAILBOX_NOSELECT | MAILBOX_NOINFERIORS;
34f284752605dafdc7aefc343bb5b6cd2d2184b5Timo Sirainen /* no subdirectories */
34f284752605dafdc7aefc343bb5b6cd2d2184b5Timo Sirainen } else if (*ctx->list->set.maildir_name != '\0') {
34f284752605dafdc7aefc343bb5b6cd2d2184b5Timo Sirainen /* non-default configuration: we have one directory
34f284752605dafdc7aefc343bb5b6cd2d2184b5Timo Sirainen containing the mailboxes. if there are 3 links,
34f284752605dafdc7aefc343bb5b6cd2d2184b5Timo Sirainen either this is a selectable mailbox without children
34f284752605dafdc7aefc343bb5b6cd2d2184b5Timo Sirainen or non-selectable mailbox with children */
34f284752605dafdc7aefc343bb5b6cd2d2184b5Timo Sirainen /* default configuration: all subdirectories are
34f284752605dafdc7aefc343bb5b6cd2d2184b5Timo Sirainen child mailboxes. */
c2ced58969b446666ab1067c6bfdf495367ed621Timo Sirainen /* doesn't exist - probably a non-existing subscribed mailbox */
cc0bb7692b8a47abca3279abbb49b073f7a27f21Timo Sirainen /* non-selectable. probably either access denied, or symlink
cc0bb7692b8a47abca3279abbb49b073f7a27f21Timo Sirainen destination not found. don't bother logging errors. */
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainenstatic void cydir_class_init(void)
c6a57378d3c54988f525f81e19c0c5d132a0770dTimo Sirainenstatic void cydir_class_deinit(void)
563273bdac80393af63b9520cbf4d24cc0efd028Timo Sirainenstatic void cydir_storage_add_list(struct mail_storage *storage ATTR_UNUSED,
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen mlist = p_new(list->pool, struct cydir_mailbox_list, 1);
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen list->v.iter_is_mailbox = cydir_list_iter_is_mailbox;
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen list->v.delete_mailbox = cydir_list_delete_mailbox;