mdbox-storage.c revision e59faf65ce864fe95dc00f5d52b8323cdbd0608a
bcb4e51a409d94ae670de96afb8483a4f7855294Stephan Bosch/* Copyright (c) 2007-2010 Dovecot authors, see the included COPYING file */
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomiextern struct dbox_storage_vfuncs mdbox_dbox_storage_vfuncs;
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomistatic MODULE_CONTEXT_DEFINE_INIT(mdbox_mailbox_list_module,
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomistatic struct mail_storage *mdbox_storage_alloc(void)
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi pool = pool_alloconly_create("dbox storage", 512+256);
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomimdbox_storage_create(struct mail_storage *_storage, struct mail_namespace *ns,
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi const char **error_r)
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi struct mdbox_storage *storage = (struct mdbox_storage *)_storage;
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi const char *dir;
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi storage->set = mail_storage_get_driver_settings(_storage);
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi i_assert(storage->set->mdbox_max_open_files >= 2);
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi dir = mailbox_list_get_path(ns->list, NULL, MAILBOX_LIST_PATH_TYPE_DIR);
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi storage->storage_dir = p_strconcat(_storage->pool, dir,
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi storage->alt_storage_dir = p_strconcat(_storage->pool,
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi storage->map = dbox_map_init(storage, ns->list, storage->storage_dir);
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomistatic void mdbox_storage_destroy(struct mail_storage *_storage)
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi struct mdbox_storage *storage = (struct mdbox_storage *)_storage;
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomimdbox_mailbox_alloc(struct mail_storage *storage, struct mailbox_list *list,
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi /* dbox can't work without index files */
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi pool = pool_alloconly_create("mdbox mailbox", 1024+512);
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi mbox->ibox.save_commit_pre = mdbox_transaction_save_commit_pre;
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi mbox->ibox.save_commit_post = mdbox_transaction_save_commit_post;
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi mbox->ibox.save_rollback = mdbox_transaction_save_rollback;
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi index_storage_mailbox_alloc(&mbox->ibox, name, input, flags,
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi mbox->ibox.index_flags |= MAIL_INDEX_OPEN_FLAG_KEEP_BACKUPS |
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi mail_index_ext_register(mbox->ibox.index, "mdbox", 0,
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi mail_index_ext_register(mbox->ibox.index, "mdbox-hdr",
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi sizeof(struct mdbox_index_header), 0, 0);
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi const void *data;
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi mail_index_get_header_ext(mbox->ibox.view, mbox->hdr_ext_id,
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi mail_storage_set_critical(&mbox->storage->storage.storage,
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi "dbox %s: Invalid dbox header size",
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi memcpy(hdr, data, I_MIN(data_size, sizeof(*hdr)));
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomivoid mdbox_update_header(struct mdbox_mailbox *mbox,
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi if (update != NULL && !mail_guid_128_is_empty(update->mailbox_guid)) {
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi memcpy(new_hdr.mailbox_guid, update->mailbox_guid,
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi } else if (mail_guid_128_is_empty(new_hdr.mailbox_guid)) {
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi mail_index_update_header_ext(trans, mbox->hdr_ext_id, 0,
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomistatic int mdbox_write_index_header(struct mailbox *box,
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi struct mdbox_mailbox *mbox = (struct mdbox_mailbox *)box;
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi trans = mail_index_transaction_begin(mbox->ibox.view, 0);
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi else if (uid_validity == 0) {
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi /* set uidvalidity */
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi uid_validity = dbox_get_uidvalidity_next(box->list);
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi if (update != NULL && hdr->next_uid < update->min_next_uid) {
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi if (update != NULL && update->min_highest_modseq != 0 &&
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomistatic int mdbox_mailbox_create_indexes(struct mailbox *box,
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi struct mdbox_mailbox *mbox = (struct mdbox_mailbox *)box;
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi const char *origin;
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi mailbox_list_get_dir_permissions(box->list, NULL, &mode, &gid, &origin);
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi if (mkdir_parents_chgrp(box->path, mode, gid, origin) == 0) {
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi /* create indexes immediately with the dbox header */
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi if (!mail_storage_set_error_from_errno(box->storage)) {
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomistatic void mdbox_storage_get_status_guid(struct mailbox *box,
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi struct mdbox_mailbox *mbox = (struct mdbox_mailbox *)box;
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi /* regenerate it */
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomimdbox_storage_get_status(struct mailbox *box, enum mailbox_status_items items,
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomimdbox_mailbox_update(struct mailbox *box, const struct mailbox_update *update)
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomimdbox_mailbox_unref_mails(struct mailbox_list *list, const char *path)
bf7dc750b95039981c0e9d728f313d50cf38a156Martti Rannanjärvi struct dbox_map_transaction_context *map_trans;
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi const void *data;
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi box = mdbox_mailbox_alloc(&storage->storage.storage, list, path, NULL,
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi /* get a list of all map_uids in this mailbox */
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi for (seq = 1; seq <= hdr->messages_count; seq++) {
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi mail_index_lookup_ext(mbox->ibox.view, seq, mbox->ext_id,
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi /* no multi-mails */
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi /* unreference the map_uids */
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi map_trans = dbox_map_transaction_begin(storage->map, FALSE);
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi ret = dbox_map_update_refcounts(map_trans, &map_uids, -1);
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomimdbox_list_delete_mailbox(struct mailbox_list *list, const char *name)
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi struct mdbox_mailbox_list *mlist = MDBOX_LIST_CONTEXT(list);
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi /* Make sure the indexes are closed before trying to delete the
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi directory that contains them. It can still fail with some NFS
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi implementations if indexes are opened by another session, but
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi that can't really be helped. */
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi /* delete the index and control directories */
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi if (mlist->module_ctx.super.delete_mailbox(list, name) < 0)
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi if ((ret = dbox_list_delete_mailbox1(list, name, &trash_dest)) < 0)
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi if (mdbox_mailbox_unref_mails(list, trash_dest) < 0) {
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi /* we've already renamed it. there's no going back. */
bf7dc750b95039981c0e9d728f313d50cf38a156Martti Rannanjärvi return dbox_list_delete_mailbox2(list, name, ret, trash_dest);
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomimdbox_list_rename_mailbox(struct mailbox_list *oldlist, const char *oldname,
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi struct mailbox_list *newlist, const char *newname,
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi struct mdbox_mailbox_list *oldmlist = MDBOX_LIST_CONTEXT(oldlist);
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi rename_mailbox(oldlist, oldname, newlist, newname,
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi return dbox_list_rename_mailbox(oldlist, oldname, newlist, newname,
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomistatic void dbox_storage_add_list(struct mail_storage *storage ATTR_UNUSED,
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi mlist = p_new(list->pool, struct mdbox_mailbox_list, 1);
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi list->v.iter_is_mailbox = dbox_list_iter_is_mailbox;
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi list->v.delete_mailbox = mdbox_list_delete_mailbox;
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi list->v.rename_mailbox = mdbox_list_rename_mailbox;
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi list->v.rename_mailbox_pre = dbox_list_rename_mailbox_pre;
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi MODULE_CONTEXT_SET(list, mdbox_mailbox_list_module, mlist);
4c78d9e646c4a1158d7167806937c02d86cdfc25Aki Tuomi .class_flags = MAIL_STORAGE_CLASS_FLAG_UNIQUE_ROOT,