int mdbox_mail_open(struct dbox_mail *mail, uoff_t *offset_r, struct dbox_file **file_r) { struct mail *_mail = &mail->imail.mail.mail; struct mdbox_mailbox *mbox = (struct mdbox_mailbox *)_mail->box; uint32_t prev_file_id = 0, map_uid = 0; bool deleted; if (_mail->lookup_abort != MAIL_LOOKUP_ABORT_NEVER) { mail_set_aborted(_mail); return -1; } do { if (mail->open_file != NULL) { /* already open */ } else if (!_mail->saving) { if (mdbox_mail_lookup(mbox, _mail->transaction->view, _mail->seq, &map_uid) < 0) return -1; if (dbox_mail_open_init(mail, map_uid) < 0) return -1; } else { /* mail is being saved in this transaction */ mail->open_file = mdbox_save_file_get_file(_mail->transaction, _mail->seq, &mail->offset); } if (!dbox_file_is_open(mail->open_file)) mail->imail.mail.stats_open_lookup_count++; if (dbox_file_open(mail->open_file, &deleted) <= 0) return -1; if (deleted) { /* either it's expunged now or moved to another file. */ struct mdbox_file *mfile = (struct mdbox_file *)mail->open_file; if (mfile->file_id == prev_file_id) { dbox_mail_set_expunged(mail, map_uid); return -1; } prev_file_id = mfile->file_id; if (mdbox_map_refresh(mbox->storage->map) < 0) return -1; dbox_file_unref(&mail->open_file); } } while (mail->open_file == NULL); *file_r = mail->open_file; *offset_r = mail->offset; return 0; }
static int mdbox_map_get_seq(struct mdbox_map *map, uint32_t map_uid, uint32_t *seq_r) { if (!mail_index_lookup_seq(map->view, map_uid, seq_r)) { /* not found - try again after a refresh */ if (mdbox_map_refresh(map) < 0) return -1; if (!mail_index_lookup_seq(map->view, map_uid, seq_r)) return 0; } return 1; }
static int mdbox_map_open_internal(struct mdbox_map *map, bool create_missing) { enum mail_index_open_flags open_flags; struct mailbox_permissions perm; int ret = 0; if (map->view != NULL) { /* already opened */ return 1; } mailbox_list_get_root_permissions(map->root_list, &perm); mail_index_set_permissions(map->index, perm.file_create_mode, perm.file_create_gid, perm.file_create_gid_origin); open_flags = MAIL_INDEX_OPEN_FLAG_NEVER_IN_MEMORY | mail_storage_settings_to_index_flags(MAP_STORAGE(map)->set); if (create_missing) { if ((ret = mdbox_map_mkdir_storage(map)) < 0) return -1; if (ret > 0) { /* storage/ directory already existed. the index should exist also. */ } else { open_flags |= MAIL_INDEX_OPEN_FLAG_CREATE; } } ret = mail_index_open(map->index, open_flags); if (ret == 0 && create_missing) { /* storage/ already existed, but indexes didn't. we'll need to take extra steps to make sure we won't overwrite any m.* files that may already exist. */ map->verify_existing_file_ids = TRUE; open_flags |= MAIL_INDEX_OPEN_FLAG_CREATE; ret = mail_index_open(map->index, open_flags); } if (ret < 0) { mail_storage_set_internal_error(MAP_STORAGE(map)); mail_index_reset_error(map->index); return -1; } if (ret == 0) { /* index not found - for now just return failure */ i_assert(!create_missing); return 0; } map->view = mail_index_view_open(map->index); mdbox_map_cleanup(map); if (mail_index_get_header(map->view)->uid_validity == 0) { if (mdbox_map_generate_uid_validity(map) < 0 || mdbox_map_refresh(map) < 0) { mail_storage_set_internal_error(MAP_STORAGE(map)); mail_index_reset_error(map->index); mail_index_close(map->index); return -1; } } return 1; }