bcb4e51a409d94ae670de96afb8483a4f7855294Stephan Bosch/* Copyright (c) 2007-2018 Dovecot authors, see the included COPYING file */
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;
b90c23a9862b91594959b918b035d73f7bc0b265Timo Sirainenint mdbox_storage_create(struct mail_storage *_storage,
b90c23a9862b91594959b918b035d73f7bc0b265Timo Sirainen struct mail_namespace *ns, const char **error_r)
b67974c4b89ab6950c2694cce8dfb1b6561cc084Josef 'Jeff' Sipek struct mdbox_storage *storage = MDBOX_STORAGE(_storage);
46e917c9fa05cbe7bddf805d3a9838b61e3960e1Timo Sirainen storage->set = mail_namespace_get_driver_settings(ns, _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);
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen dir = mailbox_list_get_root_forced(ns->list, MAILBOX_LIST_PATH_TYPE_DIR);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen storage->storage_dir = p_strconcat(_storage->pool, dir,
7279da2bd6f969071743fbb8b35b934215365833Baofeng 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);
b90c23a9862b91594959b918b035d73f7bc0b265Timo Sirainenvoid mdbox_storage_destroy(struct mail_storage *_storage)
b67974c4b89ab6950c2694cce8dfb1b6561cc084Josef 'Jeff' Sipek struct mdbox_storage *storage = MDBOX_STORAGE(_storage);
0d1b8b6bec79746c5d89d57dd8c1688946bd9237Josef 'Jeff' Sipek 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))
13307d0b3f41c6d940ae263f4828cf557258f9b9Timo Sirainenstatic const char *
13307d0b3f41c6d940ae263f4828cf557258f9b9Timo Sirainenmdbox_storage_find_root_dir(const struct mail_namespace *ns)
13307d0b3f41c6d940ae263f4828cf557258f9b9Timo Sirainen i_debug("mdbox: access(%s, rwx): failed: %m", path);
13307d0b3f41c6d940ae263f4828cf557258f9b9Timo Sirainenstatic bool mdbox_storage_autodetect(const struct mail_namespace *ns,
13307d0b3f41c6d940ae263f4828cf557258f9b9Timo Sirainen path = t_strconcat(root_dir, "/"MDBOX_GLOBAL_DIR_NAME, NULL);
13307d0b3f41c6d940ae263f4828cf557258f9b9Timo Sirainen i_debug("mdbox autodetect: stat(%s) failed: %m", path);
13307d0b3f41c6d940ae263f4828cf557258f9b9Timo Sirainen i_debug("mdbox autodetect: %s not a directory", path);
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainenstatic struct mailbox *
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);
8c909e451d14075c05d90382cf8eebc4e354f569Timo Sirainen index_storage_mailbox_alloc(&mbox->box, vname, flags, MAIL_INDEX_PREFIX);
d22301419109ed4a38351715e6760011421dadecTimo Sirainen ibox->index_flags |= MAIL_INDEX_OPEN_FLAG_KEEP_BACKUPS |
b67974c4b89ab6950c2694cce8dfb1b6561cc084Josef 'Jeff' Sipek struct mdbox_mailbox *mbox = MDBOX_MAILBOX(box);
7b15788793354ca0fd4fdb4dda8e426ca1e9e9d7Timo Sirainen if (dbox_mailbox_check_existence(box, &path_ctime) < 0)
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)
b67974c4b89ab6950c2694cce8dfb1b6561cc084Josef 'Jeff' Sipek struct mdbox_storage *mstorage = MDBOX_STORAGE(box->storage);
5b62dea2f88165f3f4d87bba9011343f3ff415ffTimo Sirainen if (mstorage->corrupted && !mstorage->rebuilding_storage)
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainenint mdbox_read_header(struct mdbox_mailbox *mbox,
9865d9e7c5713e41db939222ed9c0225a11fb99eTimo Sirainen struct mdbox_index_header *hdr, bool *need_resize_r)
d22301419109ed4a38351715e6760011421dadecTimo Sirainen mail_index_get_header_ext(mbox->box.view, mbox->hdr_ext_id,
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen if (data_size < MDBOX_INDEX_HEADER_MIN_SIZE &&
d4002fe1f64d25a792f76fb102ef7dc519cd4e24Martti Rannanjärvi "mdbox: Invalid dbox header size: %"PRIuSIZE_T,
6d404348751c19ac37cfb42375abdd3c5f298e30Timo Sirainen memcpy(hdr, data, I_MIN(data_size, sizeof(*hdr)));
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainenvoid mdbox_update_header(struct mdbox_mailbox *mbox,
737ddab12d0d1b2ba09a23eb4ff2cd6f6838f414Timo Sirainen if (mdbox_read_header(mbox, &hdr, &need_resize) < 0) {
de62ce819d59a529530da4b57be1b8d6dad13d6bTimo Sirainen if (update != NULL && !guid_128_is_empty(update->mailbox_guid)) {
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen memcpy(new_hdr.mailbox_guid, update->mailbox_guid,
de62ce819d59a529530da4b57be1b8d6dad13d6bTimo Sirainen } else if (guid_128_is_empty(new_hdr.mailbox_guid)) {
c18ff860dc22960fd37c272d929f889c7939a2c8Timo Sirainen mdbox_map_get_uid_validity(mbox->storage->map);
9865d9e7c5713e41db939222ed9c0225a11fb99eTimo Sirainen mail_index_ext_resize_hdr(trans, mbox->hdr_ext_id,
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen if (memcmp(&hdr, &new_hdr, sizeof(hdr)) != 0) {
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen mail_index_update_header_ext(trans, mbox->hdr_ext_id, 0,
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);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen offsetof(struct mail_index_header, uid_validity),
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen if (update != NULL && hdr->next_uid < update->min_next_uid) {
ee9254cc7875519a9c71cc58a40610e6f320e907Timo Sirainen if (update != NULL && update->min_first_recent_uid != 0 &&
29337701451b9c9f9dd26b2aec23a31ab5203822Timo Sirainen hdr->first_recent_uid < update->min_first_recent_uid) {
29337701451b9c9f9dd26b2aec23a31ab5203822Timo Sirainen uint32_t first_recent_uid = update->min_first_recent_uid;
29337701451b9c9f9dd26b2aec23a31ab5203822Timo Sirainen offsetof(struct mail_index_header, first_recent_uid),
29337701451b9c9f9dd26b2aec23a31ab5203822Timo Sirainen &first_recent_uid, sizeof(first_recent_uid), FALSE);
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen if (update != NULL && update->min_highest_modseq != 0 &&
14e4afa9f52bc2150fe92b5cc737ad0354078391Timo Sirainen mail_index_modseq_get_highest(view) < update->min_highest_modseq) {
5bcac2212ca86e72289faa7db2c509841fbdbd59Timo Sirainen /* initialize pop3-uidl header when creating mailbox
5bcac2212ca86e72289faa7db2c509841fbdbd59Timo Sirainen (not on mailbox_update()) */
dd4f30895ebbddd77e000472fbadcb3128ae2883Timo Sirainen if (mail_index_transaction_commit(&new_trans) < 0) {
f605df8a4c15cc7a11e16fdde994d51473700890Timo Sirainenint mdbox_mailbox_create_indexes(struct mailbox *box,
b67974c4b89ab6950c2694cce8dfb1b6561cc084Josef 'Jeff' Sipek struct mdbox_mailbox *mbox = 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)
b90c23a9862b91594959b918b035d73f7bc0b265Timo Sirainenvoid mdbox_set_mailbox_corrupted(struct mailbox *box)
b67974c4b89ab6950c2694cce8dfb1b6561cc084Josef 'Jeff' Sipek struct mdbox_storage *mstorage = MDBOX_STORAGE(box->storage);
b90c23a9862b91594959b918b035d73f7bc0b265Timo Sirainenvoid mdbox_set_file_corrupted(struct dbox_file *file)
b67974c4b89ab6950c2694cce8dfb1b6561cc084Josef 'Jeff' Sipek struct mdbox_storage *mstorage = MDBOX_DBOX_STORAGE(file->storage);
de62ce819d59a529530da4b57be1b8d6dad13d6bTimo Sirainenmdbox_mailbox_get_guid(struct mdbox_mailbox *mbox, guid_128_t guid_r)
d6d4d8beede5f8efbba052c1e3e4f964ce489bd2Timo Sirainen /* there's a race condition between mkdir and getting the mailbox GUID.
d6d4d8beede5f8efbba052c1e3e4f964ce489bd2Timo Sirainen normally this is handled by mdbox syncing, but GUID can be looked up
48d8312488089dc1a8360991f0881d91095c21eaTimo Sirainen without syncing. when we detect this situation we'll try to finish
48d8312488089dc1a8360991f0881d91095c21eaTimo Sirainen creating the indexes first, which usually means just waiting for
48d8312488089dc1a8360991f0881d91095c21eaTimo Sirainen the sync lock to get unlocked by the other process creating them. */
d6d4d8beede5f8efbba052c1e3e4f964ce489bd2Timo Sirainen idx_hdr = mail_index_get_header(mbox->box.view);
48d8312488089dc1a8360991f0881d91095c21eaTimo Sirainen if (idx_hdr->uid_validity == 0 && idx_hdr->next_uid == 1) {
48d8312488089dc1a8360991f0881d91095c21eaTimo Sirainen if (dbox_mailbox_create_indexes(&mbox->box, NULL) < 0)
9865d9e7c5713e41db939222ed9c0225a11fb99eTimo Sirainen if (mdbox_read_header(mbox, &hdr, &need_resize) < 0)
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainen /* regenerate it */
51327f2489a4e0e615eb9f7d921473cf8512bb79Timo Sirainen if (mdbox_write_index_header(&mbox->box, NULL, NULL) < 0 ||
9865d9e7c5713e41db939222ed9c0225a11fb99eTimo Sirainen mdbox_read_header(mbox, &hdr, &need_resize) < 0)
d6d4d8beede5f8efbba052c1e3e4f964ce489bd2Timo Sirainen memcpy(guid_r, hdr.mailbox_guid, GUID_128_SIZE);
51327f2489a4e0e615eb9f7d921473cf8512bb79Timo Sirainenmdbox_mailbox_get_metadata(struct mailbox *box,
b67974c4b89ab6950c2694cce8dfb1b6561cc084Josef 'Jeff' Sipek struct mdbox_mailbox *mbox = MDBOX_MAILBOX(box);
206ed2f6fa3a6fb291498627b2da626581c07a18Timo Sirainen if (index_mailbox_get_metadata(box, items, metadata_r) < 0)
51327f2489a4e0e615eb9f7d921473cf8512bb79Timo Sirainen if (mdbox_mailbox_get_guid(mbox, metadata_r->guid) < 0)
1ac7c8e9040e0d0b7e9f849e45b94bfe919595a9Timo Sirainenmdbox_mailbox_update(struct mailbox *box, const struct mailbox_update *update)
f46885a5b78b15a8d2419f6e5d13b643bd85e41fTimo Sirainen if (mdbox_write_index_header(box, update, NULL) < 0)
f46885a5b78b15a8d2419f6e5d13b643bd85e41fTimo Sirainen return index_storage_mailbox_update_common(box, update);
8b31f966d9688e07672ef1958dcbdb7686523c04Timo Sirainen .class_flags = MAIL_STORAGE_CLASS_FLAG_UNIQUE_ROOT |
d46a1e3f999dda802dc5137e883adcd7a6629cd3Timo Sirainen MAIL_STORAGE_CLASS_FLAG_HAVE_MAIL_SAVE_GUIDS |