mdbox-storage.c revision ca98892a6b8a30ffc1fe26fcf02c7d59e3204e7e
e59faf65ce864fe95dc00f5d52b8323cdbd0608aTimo Sirainen/* Copyright (c) 2007-2010 Dovecot authors, see the included COPYING file */
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainenextern struct dbox_storage_vfuncs mdbox_dbox_storage_vfuncs;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainenstatic struct mail_storage *mdbox_storage_alloc(void)
4c1deab456fe8877bf025d11843167ac1f36327aTimo Sirainen pool = pool_alloconly_create("mdbox storage", 2048);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen storage = p_new(pool, struct mdbox_storage, 1);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen storage->storage.v = mdbox_dbox_storage_vfuncs;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainenmdbox_storage_create(struct mail_storage *_storage, struct mail_namespace *ns,
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen const char **error_r)
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen struct mdbox_storage *storage = (struct mdbox_storage *)_storage;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen const char *dir;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen storage->set = mail_storage_get_driver_settings(_storage);
f6aaada6101dd43cd80fe965ff1ab9bfaf776252Timo Sirainen storage->preallocate_space = storage->set->mdbox_preallocate_space;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen if (*ns->list->set.mailbox_dir_name == '\0') {
ddb018bc886680f462463b2c87f983fdedbf6cf0Timo Sirainen *error_r = "mdbox: MAILBOXDIR must not be empty";
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen p_strdup(_storage->pool, ns->list->set.root_dir);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen dir = mailbox_list_get_path(ns->list, NULL, MAILBOX_LIST_PATH_TYPE_DIR);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen storage->storage_dir = p_strconcat(_storage->pool, dir,
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen storage->alt_storage_dir = p_strconcat(_storage->pool,
02d72ab3d606033e9a720274ddc3dd83a0ad070dTimo Sirainen storage->map = mdbox_map_init(storage, ns->list);
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen return dbox_storage_create(_storage, ns, error_r);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainenstatic void mdbox_storage_destroy(struct mail_storage *_storage)
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen struct mdbox_storage *storage = (struct mdbox_storage *)_storage;
04c3ac276103b56185119bcff9a66de7a8bb0e68Timo Sirainen timeout_remove(&storage->to_close_unused_files);
5fb3f13537dffd15a31e997da133a721c0728af8Timo Sirainen if (array_is_created(&storage->move_from_alt_map_uids))
5fb3f13537dffd15a31e997da133a721c0728af8Timo Sirainen if (array_is_created(&storage->move_to_alt_map_uids))
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainenmdbox_mailbox_alloc(struct mail_storage *storage, struct mailbox_list *list,
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen /* dbox can't work without index files */
3b32bc12710240f86465a00fbb2bd1ef030e6c40Timo Sirainen pool = pool_alloconly_create("mdbox mailbox", 1024*3);
e5fd6dfd0a492e4708d4dbb7971d7fc5d7b8fd85Timo Sirainen index_storage_mailbox_alloc(&mbox->box, name, flags, DBOX_INDEX_PREFIX);
d22301419109ed4a38351715e6760011421dadecTimo Sirainen ibox->save_commit_pre = mdbox_transaction_save_commit_pre;
d22301419109ed4a38351715e6760011421dadecTimo Sirainen ibox->save_commit_post = mdbox_transaction_save_commit_post;
d22301419109ed4a38351715e6760011421dadecTimo Sirainen ibox->save_rollback = mdbox_transaction_save_rollback;
d22301419109ed4a38351715e6760011421dadecTimo Sirainen ibox->index_flags |= MAIL_INDEX_OPEN_FLAG_KEEP_BACKUPS |
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen mbox->storage = (struct mdbox_storage *)storage;
d22301419109ed4a38351715e6760011421dadecTimo Sirainen mail_index_ext_register(mbox->box.index, "mdbox", 0,
d22301419109ed4a38351715e6760011421dadecTimo Sirainen mail_index_ext_register(mbox->box.index, "mdbox-hdr",
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen sizeof(struct mdbox_index_header), 0, 0);
d22301419109ed4a38351715e6760011421dadecTimo Sirainen mail_index_ext_register(mbox->box.index, "guid",
1dd054126238349e1a7d3d1ffe7f8bc5fdbacb7aTimo Sirainenstatic void mdbox_mailbox_close(struct mailbox *box)
1dd054126238349e1a7d3d1ffe7f8bc5fdbacb7aTimo Sirainen struct mdbox_storage *mstorage = (struct mdbox_storage *)box->storage;
5b62dea2f88165f3f4d87bba9011343f3ff415ffTimo Sirainen if (mstorage->corrupted && !mstorage->rebuilding_storage)
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainenint mdbox_read_header(struct mdbox_mailbox *mbox,
d22301419109ed4a38351715e6760011421dadecTimo Sirainen mail_index_get_header_ext(mbox->box.view, mbox->hdr_ext_id,
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen if (data_size < MDBOX_INDEX_HEADER_MIN_SIZE &&
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen mail_storage_set_critical(&mbox->storage->storage.storage,
ddb018bc886680f462463b2c87f983fdedbf6cf0Timo Sirainen "mdbox %s: Invalid dbox header size: %"PRIuSIZE_T,
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen memcpy(hdr, data, I_MIN(data_size, sizeof(*hdr)));
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainenvoid mdbox_update_header(struct mdbox_mailbox *mbox,
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen if (update != NULL && !mail_guid_128_is_empty(update->mailbox_guid)) {
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen memcpy(new_hdr.mailbox_guid, update->mailbox_guid,
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen } else if (mail_guid_128_is_empty(new_hdr.mailbox_guid)) {
c18ff860dc22960fd37c272d929f889c7939a2c8Timo Sirainen mdbox_map_get_uid_validity(mbox->storage->map);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen if (memcmp(&hdr, &new_hdr, sizeof(hdr)) != 0) {
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen mail_index_update_header_ext(trans, mbox->hdr_ext_id, 0,
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainenstatic int mdbox_write_index_header(struct mailbox *box,
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen struct mdbox_mailbox *mbox = (struct mdbox_mailbox *)box;
dd4f30895ebbddd77e000472fbadcb3128ae2883Timo Sirainen struct mail_index_transaction *new_trans = NULL;
c18ff860dc22960fd37c272d929f889c7939a2c8Timo Sirainen if (mdbox_map_open_or_create(mbox->storage->map) < 0)
dd4f30895ebbddd77e000472fbadcb3128ae2883Timo Sirainen new_trans = mail_index_transaction_begin(box->view, 0);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen if (update != NULL && update->uid_validity != 0)
6d2c938f017a2fc55ae476f88839f03a3d3c5fbdTimo Sirainen else if (uid_validity == 0) {
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen /* set uidvalidity */
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen uid_validity = dbox_get_uidvalidity_next(box->list);
46219292a55094fa49aae33eee681ed075d30e17Timo Sirainen /* UIDVALIDITY change requires index to be reset */
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen offsetof(struct mail_index_header, uid_validity),
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen if (update != NULL && hdr->next_uid < update->min_next_uid) {
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen if (update != NULL && update->min_highest_modseq != 0 &&
dd4f30895ebbddd77e000472fbadcb3128ae2883Timo Sirainen if (mail_index_transaction_commit(&new_trans) < 0) {
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainenstatic int mdbox_mailbox_create_indexes(struct mailbox *box,
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen struct mdbox_mailbox *mbox = (struct mdbox_mailbox *)box;
dd4f30895ebbddd77e000472fbadcb3128ae2883Timo Sirainen ret = mdbox_write_index_header(box, update, trans);
5b62dea2f88165f3f4d87bba9011343f3ff415ffTimo Sirainenvoid mdbox_storage_set_corrupted(struct mdbox_storage *storage)
5b62dea2f88165f3f4d87bba9011343f3ff415ffTimo Sirainen /* already set it corrupted (possibly recursing back here) */
5b62dea2f88165f3f4d87bba9011343f3ff415ffTimo Sirainen storage->corrupted_rebuild_count = (uint32_t)-1;
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainenstatic const char *
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainenmdbox_get_attachment_path_suffix(struct dbox_file *file ATTR_UNUSED)
57bf90f66f393c2807b2fc543655013f61d1d9e4Timo Sirainenstatic void mdbox_set_mailbox_corrupted(struct mailbox *box)
57bf90f66f393c2807b2fc543655013f61d1d9e4Timo Sirainen struct mdbox_storage *mstorage = (struct mdbox_storage *)box->storage;
5b62dea2f88165f3f4d87bba9011343f3ff415ffTimo Sirainenstatic void mdbox_set_file_corrupted(struct dbox_file *file)
5b62dea2f88165f3f4d87bba9011343f3ff415ffTimo Sirainen struct mdbox_storage *mstorage = (struct mdbox_storage *)file->storage;
fbd918f47f591f8084fd52b207ef29515ddd11b9Timo Sirainenmdbox_mailbox_get_guid(struct mailbox *box, uint8_t guid[MAIL_GUID_128_SIZE])
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen struct mdbox_mailbox *mbox = (struct mdbox_mailbox *)box;
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen if (mail_guid_128_is_empty(hdr.mailbox_guid)) {
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen /* regenerate it */
dd4f30895ebbddd77e000472fbadcb3128ae2883Timo Sirainen if (mdbox_write_index_header(box, NULL, NULL) < 0 ||
fbd918f47f591f8084fd52b207ef29515ddd11b9Timo Sirainen memcpy(guid, hdr.mailbox_guid, MAIL_GUID_128_SIZE);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainenmdbox_mailbox_update(struct mailbox *box, const struct mailbox_update *update)
d22301419109ed4a38351715e6760011421dadecTimo Sirainen if (index_storage_mailbox_open(box, FALSE) < 0)
a46d8b27aa617c79f51dd8dfb363f5b3518b63e4Timo Sirainen index_storage_mailbox_update_cache_fields(box, update);
dd4f30895ebbddd77e000472fbadcb3128ae2883Timo Sirainen return mdbox_write_index_header(box, update, NULL);
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainenstatic int mdbox_mailbox_unref_mails(struct mdbox_mailbox *mbox)
c18ff860dc22960fd37c272d929f889c7939a2c8Timo Sirainen struct mdbox_map_transaction_context *map_trans;
08a8b3de61139ba02371afc8240ac85be0e8b17cTimo Sirainen atomic = mdbox_map_atomic_begin(mbox->storage->map);
08a8b3de61139ba02371afc8240ac85be0e8b17cTimo Sirainen map_trans = mdbox_map_transaction_begin(atomic, FALSE);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen for (seq = 1; seq <= hdr->messages_count; seq++) {
73a87c2ff65c6116cde6fb158dfddb8ef7346901Timo Sirainen if (mdbox_mail_lookup(mbox, mbox->box.view, seq,
c18ff860dc22960fd37c272d929f889c7939a2c8Timo Sirainen if (mdbox_map_update_refcount(map_trans, map_uid, -1) < 0) {
c18ff860dc22960fd37c272d929f889c7939a2c8Timo Sirainen ret = mdbox_map_transaction_commit(map_trans);
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainenstatic int mdbox_mailbox_delete(struct mailbox *box)
61b0637759146621cbb7edcbd0b03a71cfd66dfeTimo Sirainen struct mdbox_mailbox *mbox = (struct mdbox_mailbox *)box;
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen .class_flags = MAIL_STORAGE_CLASS_FLAG_UNIQUE_ROOT,