mdbox-mail.c revision 767ff4367960efd5fa868f3b56f850fd4c205c8b
bcb4e51a409d94ae670de96afb8483a4f7855294Stephan Bosch/* Copyright (c) 2007-2010 Dovecot authors, see the included COPYING file */
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch#include "lib.h"
bdd36cfdba3ff66d25570a9ff568d69e1eb543cfTimo Sirainen#include "ioloop.h"
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch#include "istream.h"
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch#include "str.h"
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch#include "index-mail.h"
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch#include "dbox-mail.h"
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch#include "mdbox-storage.h"
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch#include "mdbox-map.h"
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch#include "mdbox-file.h"
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch#include <stdlib.h>
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch#include <sys/stat.h>
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Boschint mdbox_mail_lookup(struct mdbox_mailbox *mbox, struct mail_index_view *view,
e9c433c5b8ef9a1b4246ebe10beb90fa01e05cafPhil Carmody uint32_t seq, uint32_t *map_uid_r)
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch{
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch const struct mdbox_mail_index_record *dbox_rec;
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch struct mdbox_index_header hdr;
66134fbce11778241ca9f8458ee2a0488a05bde0Stephan Bosch const void *data;
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch uint32_t uid, cur_map_uid_validity;
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch bool expunged;
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch
66134fbce11778241ca9f8458ee2a0488a05bde0Stephan Bosch mail_index_lookup_ext(view, seq, mbox->ext_id, &data, &expunged);
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch dbox_rec = data;
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch if (dbox_rec == NULL || dbox_rec->map_uid == 0) {
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch mail_index_lookup_uid(view, seq, &uid);
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch mail_storage_set_critical(&mbox->storage->storage.storage,
66134fbce11778241ca9f8458ee2a0488a05bde0Stephan Bosch "dbox %s: map uid lost for uid %u",
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch mbox->box.path, uid);
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch mbox->storage->storage.files_corrupted = TRUE;
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch return -1;
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch }
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch
66134fbce11778241ca9f8458ee2a0488a05bde0Stephan Bosch if (mbox->map_uid_validity == 0) {
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch if (mdbox_read_header(mbox, &hdr) < 0) {
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch mbox->storage->storage.files_corrupted = TRUE;
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch return -1;
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch }
66134fbce11778241ca9f8458ee2a0488a05bde0Stephan Bosch mbox->map_uid_validity = hdr.map_uid_validity;
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch }
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch if (dbox_map_open(mbox->storage->map, TRUE) < 0)
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch return -1;
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch cur_map_uid_validity = dbox_map_get_uid_validity(mbox->storage->map);
66134fbce11778241ca9f8458ee2a0488a05bde0Stephan Bosch if (cur_map_uid_validity != mbox->map_uid_validity) {
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch mail_storage_set_critical(&mbox->storage->storage.storage,
f883bf3eff62f5d27df5ee9ee664edc38a77937fStephan Bosch "dbox %s: map uidvalidity mismatch (%u vs %u)",
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch mbox->box.path, mbox->map_uid_validity,
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch cur_map_uid_validity);
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch mbox->storage->storage.files_corrupted = TRUE;
66134fbce11778241ca9f8458ee2a0488a05bde0Stephan Bosch return -1;
66134fbce11778241ca9f8458ee2a0488a05bde0Stephan Bosch }
66134fbce11778241ca9f8458ee2a0488a05bde0Stephan Bosch *map_uid_r = dbox_rec->map_uid;
f883bf3eff62f5d27df5ee9ee664edc38a77937fStephan Bosch return 0;
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch}
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Boschstatic void dbox_mail_set_expunged(struct dbox_mail *mail, uint32_t map_uid)
66134fbce11778241ca9f8458ee2a0488a05bde0Stephan Bosch{
66134fbce11778241ca9f8458ee2a0488a05bde0Stephan Bosch struct mail *_mail = &mail->imail.mail.mail;
66134fbce11778241ca9f8458ee2a0488a05bde0Stephan Bosch struct mdbox_mailbox *mbox = (struct mdbox_mailbox *)_mail->box;
f883bf3eff62f5d27df5ee9ee664edc38a77937fStephan Bosch
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch (void)mail_index_refresh(_mail->box->index);
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch if (mail_index_is_expunged(_mail->transaction->view, _mail->seq)) {
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch mail_set_expunged(_mail);
66134fbce11778241ca9f8458ee2a0488a05bde0Stephan Bosch return;
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch }
f883bf3eff62f5d27df5ee9ee664edc38a77937fStephan Bosch
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch dbox_map_set_corrupted(mbox->storage->map,
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch "Unexpectedly lost %s uid=%u map_uid=%u",
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch mailbox_get_vname(_mail->box),
66134fbce11778241ca9f8458ee2a0488a05bde0Stephan Bosch _mail->uid, map_uid);
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch mbox->storage->storage.files_corrupted = TRUE;
f883bf3eff62f5d27df5ee9ee664edc38a77937fStephan Bosch}
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Boschstatic int dbox_mail_open_init(struct dbox_mail *mail, uint32_t map_uid)
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch{
66134fbce11778241ca9f8458ee2a0488a05bde0Stephan Bosch struct mdbox_mailbox *mbox =
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch (struct mdbox_mailbox *)mail->imail.mail.mail.box;
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch uint32_t file_id;
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch int ret;
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch if ((ret = dbox_map_lookup(mbox->storage->map, map_uid,
66134fbce11778241ca9f8458ee2a0488a05bde0Stephan Bosch &file_id, &mail->offset)) <= 0) {
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch if (ret < 0)
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch return -1;
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch /* map_uid doesn't exist anymore. either it
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch got just expunged or the map index is
66134fbce11778241ca9f8458ee2a0488a05bde0Stephan Bosch corrupted. */
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch dbox_mail_set_expunged(mail, map_uid);
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch return -1;
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch } else {
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch mail->open_file = mdbox_file_init(mbox->storage, file_id);
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch }
66134fbce11778241ca9f8458ee2a0488a05bde0Stephan Bosch return 0;
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch}
62aa68310d6f42467ca26880f678173bf1d26a83Stephan Bosch
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Boschint mdbox_mail_open(struct dbox_mail *mail, uoff_t *offset_r,
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch struct dbox_file **file_r)
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch{
66134fbce11778241ca9f8458ee2a0488a05bde0Stephan Bosch struct mail *_mail = &mail->imail.mail.mail;
62aa68310d6f42467ca26880f678173bf1d26a83Stephan Bosch struct mdbox_mailbox *mbox = (struct mdbox_mailbox *)_mail->box;
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch uint32_t prev_file_id = 0, map_uid = 0;
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch bool deleted;
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch
66134fbce11778241ca9f8458ee2a0488a05bde0Stephan Bosch if (_mail->lookup_abort != MAIL_LOOKUP_ABORT_NEVER) {
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch mail_set_aborted(_mail);
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch return -1;
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch }
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch do {
66134fbce11778241ca9f8458ee2a0488a05bde0Stephan Bosch if (mail->open_file != NULL) {
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch /* already open */
62aa68310d6f42467ca26880f678173bf1d26a83Stephan Bosch } else if (_mail->uid != 0) {
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch if (mdbox_mail_lookup(mbox, _mail->transaction->view,
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch _mail->seq, &map_uid) < 0)
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch return -1;
66134fbce11778241ca9f8458ee2a0488a05bde0Stephan Bosch if (dbox_mail_open_init(mail, map_uid) < 0)
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch return -1;
62aa68310d6f42467ca26880f678173bf1d26a83Stephan Bosch } else {
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch /* mail is being saved in this transaction */
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch mail->open_file =
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch mdbox_save_file_get_file(_mail->transaction,
66134fbce11778241ca9f8458ee2a0488a05bde0Stephan Bosch _mail->seq,
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch &mail->offset);
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch }
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch if (!dbox_file_is_open(mail->open_file))
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch mail->imail.mail.stats_open_lookup_count++;
66134fbce11778241ca9f8458ee2a0488a05bde0Stephan Bosch if (dbox_file_open(mail->open_file, &deleted) <= 0)
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch return -1;
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch if (deleted) {
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch /* either it's expunged now or moved to another file. */
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch struct mdbox_file *mfile =
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch (struct mdbox_file *)mail->open_file;
66134fbce11778241ca9f8458ee2a0488a05bde0Stephan Bosch
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch if (mfile->file_id == prev_file_id) {
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch dbox_mail_set_expunged(mail, map_uid);
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch return -1;
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch }
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch prev_file_id = mfile->file_id;
66134fbce11778241ca9f8458ee2a0488a05bde0Stephan Bosch if (dbox_map_refresh(mbox->storage->map) < 0)
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch return -1;
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch dbox_file_unref(&mail->open_file);
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch }
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch } while (mail->open_file == NULL);
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch
66134fbce11778241ca9f8458ee2a0488a05bde0Stephan Bosch *file_r = mail->open_file;
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch *offset_r = mail->offset;
62aa68310d6f42467ca26880f678173bf1d26a83Stephan Bosch return 0;
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch}
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Boschstatic int mdbox_mail_get_save_date(struct mail *mail, time_t *date_r)
66134fbce11778241ca9f8458ee2a0488a05bde0Stephan Bosch{
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch struct mdbox_mailbox *mbox =
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch (struct mdbox_mailbox *)mail->transaction->box;
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch const struct mdbox_mail_index_record *dbox_rec;
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch const void *data;
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch bool expunged;
66134fbce11778241ca9f8458ee2a0488a05bde0Stephan Bosch
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch mail_index_lookup_ext(mail->transaction->view, mail->seq,
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch mbox->ext_id, &data, &expunged);
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch dbox_rec = data;
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch if (dbox_rec == NULL || dbox_rec->map_uid == 0) {
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch /* lost for some reason, use fallback */
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch return dbox_mail_get_save_date(mail, date_r);
66134fbce11778241ca9f8458ee2a0488a05bde0Stephan Bosch }
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch *date_r = dbox_rec->save_date;
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch return TRUE;
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch}
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Boschstruct mail_vfuncs mdbox_mail_vfuncs = {
66134fbce11778241ca9f8458ee2a0488a05bde0Stephan Bosch dbox_mail_close,
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch index_mail_free,
62aa68310d6f42467ca26880f678173bf1d26a83Stephan Bosch index_mail_set_seq,
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch index_mail_set_uid,
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch index_mail_set_uid_cache_updates,
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch index_mail_get_flags,
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch index_mail_get_keywords,
66134fbce11778241ca9f8458ee2a0488a05bde0Stephan Bosch index_mail_get_keyword_indexes,
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch index_mail_get_modseq,
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch index_mail_get_parts,
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch index_mail_get_date,
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch dbox_mail_get_received_date,
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch mdbox_mail_get_save_date,
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch dbox_mail_get_virtual_size,
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch dbox_mail_get_physical_size,
66134fbce11778241ca9f8458ee2a0488a05bde0Stephan Bosch index_mail_get_first_header,
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch index_mail_get_headers,
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch index_mail_get_header_stream,
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch dbox_mail_get_stream,
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch dbox_mail_get_special,
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch index_mail_update_flags,
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch index_mail_update_keywords,
66134fbce11778241ca9f8458ee2a0488a05bde0Stephan Bosch index_mail_update_modseq,
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch index_mail_update_uid,
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch NULL,
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch index_mail_expunge,
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch index_mail_set_cache_corrupted,
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch index_mail_get_index_mail
6ae6496c225238a2c55a8cd96744ad976c44a726Stephan Bosch};
66134fbce11778241ca9f8458ee2a0488a05bde0Stephan Bosch