diff options
Diffstat (limited to 'src/lib-storage/index/dbox-single/sdbox-mail.c')
-rw-r--r-- | src/lib-storage/index/dbox-single/sdbox-mail.c | 182 |
1 files changed, 182 insertions, 0 deletions
diff --git a/src/lib-storage/index/dbox-single/sdbox-mail.c b/src/lib-storage/index/dbox-single/sdbox-mail.c new file mode 100644 index 0000000..3b0352c --- /dev/null +++ b/src/lib-storage/index/dbox-single/sdbox-mail.c @@ -0,0 +1,182 @@ +/* Copyright (c) 2007-2018 Dovecot authors, see the included COPYING file */ + +#include "lib.h" +#include "ioloop.h" +#include "istream.h" +#include "str.h" +#include "index-mail.h" +#include "dbox-mail.h" +#include "sdbox-storage.h" +#include "sdbox-file.h" + +#include <sys/stat.h> + +static void sdbox_mail_set_expunged(struct dbox_mail *mail) +{ + struct mail *_mail = &mail->imail.mail.mail; + + mail_index_refresh(_mail->box->index); + if (mail_index_is_expunged(_mail->transaction->view, _mail->seq)) { + mail_set_expunged(_mail); + return; + } + + mail_set_critical(_mail, "dbox: Unexpectedly lost uid"); + sdbox_set_mailbox_corrupted(_mail->box); +} + +static int sdbox_mail_file_set(struct dbox_mail *mail) +{ + struct mail *_mail = &mail->imail.mail.mail; + struct sdbox_mailbox *mbox = SDBOX_MAILBOX(_mail->box); + bool deleted; + int ret; + + if (mail->open_file != NULL) { + /* already set */ + return 0; + } else if (!_mail->saving) { + mail->open_file = sdbox_file_init(mbox, _mail->uid); + return 0; + } else { + /* mail is being saved in this transaction */ + mail->open_file = + sdbox_save_file_get_file(_mail->transaction, + _mail->seq); + mail->open_file->refcount++; + + /* it doesn't have input stream yet */ + ret = dbox_file_open(mail->open_file, &deleted); + if (ret <= 0) { + mail_set_critical(_mail, + "dbox: Unexpectedly lost mail being saved"); + sdbox_set_mailbox_corrupted(_mail->box); + return -1; + } + return 1; + } +} + +static int +sdbox_mail_get_special(struct mail *_mail, enum mail_fetch_field field, + const char **value_r) +{ + struct sdbox_mailbox *mbox = SDBOX_MAILBOX(_mail->box); + struct dbox_mail *mail = DBOX_MAIL(_mail); + struct stat st; + + switch (field) { + case MAIL_FETCH_REFCOUNT: + if (sdbox_mail_file_set(mail) < 0) + return -1; + + _mail->transaction->stats.fstat_lookup_count++; + if (dbox_file_stat(mail->open_file, &st) < 0) { + if (errno == ENOENT) + mail_set_expunged(_mail); + return -1; + } + *value_r = p_strdup_printf(mail->imail.mail.data_pool, "%lu", + (unsigned long)st.st_nlink); + return 0; + case MAIL_FETCH_REFCOUNT_ID: + if (sdbox_mail_file_set(mail) < 0) + return -1; + + _mail->transaction->stats.fstat_lookup_count++; + if (dbox_file_stat(mail->open_file, &st) < 0) { + if (errno == ENOENT) + mail_set_expunged(_mail); + return -1; + } + *value_r = p_strdup_printf(mail->imail.mail.data_pool, "%llu", + (unsigned long long)st.st_ino); + return 0; + case MAIL_FETCH_UIDL_BACKEND: + if (!dbox_header_have_flag(&mbox->box, mbox->hdr_ext_id, + offsetof(struct sdbox_index_header, flags), + DBOX_INDEX_HEADER_FLAG_HAVE_POP3_UIDLS)) { + *value_r = ""; + return 0; + } + break; + case MAIL_FETCH_POP3_ORDER: + if (!dbox_header_have_flag(&mbox->box, mbox->hdr_ext_id, + offsetof(struct sdbox_index_header, flags), + DBOX_INDEX_HEADER_FLAG_HAVE_POP3_ORDERS)) { + *value_r = ""; + return 0; + } + break; + default: + break; + } + return dbox_mail_get_special(_mail, field, value_r); +} + +int sdbox_mail_open(struct dbox_mail *mail, uoff_t *offset_r, + struct dbox_file **file_r) +{ + struct mail *_mail = &mail->imail.mail.mail; + bool deleted; + int ret; + + if (!mail_stream_access_start(_mail)) + return -1; + + ret = sdbox_mail_file_set(mail); + if (ret < 0) + return -1; + if (ret == 0) { + if (!dbox_file_is_open(mail->open_file)) + _mail->transaction->stats.open_lookup_count++; + if (dbox_file_open(mail->open_file, &deleted) <= 0) + return -1; + if (deleted) { + sdbox_mail_set_expunged(mail); + return -1; + } + } + + *file_r = mail->open_file; + *offset_r = 0; + return 0; +} + +struct mail_vfuncs sdbox_mail_vfuncs = { + dbox_mail_close, + index_mail_free, + index_mail_set_seq, + index_mail_set_uid, + index_mail_set_uid_cache_updates, + index_mail_prefetch, + index_mail_precache, + index_mail_add_temp_wanted_fields, + + index_mail_get_flags, + index_mail_get_keywords, + index_mail_get_keyword_indexes, + index_mail_get_modseq, + index_mail_get_pvt_modseq, + index_mail_get_parts, + index_mail_get_date, + dbox_mail_get_received_date, + dbox_mail_get_save_date, + dbox_mail_get_virtual_size, + dbox_mail_get_physical_size, + index_mail_get_first_header, + index_mail_get_headers, + index_mail_get_header_stream, + dbox_mail_get_stream, + index_mail_get_binary_stream, + sdbox_mail_get_special, + index_mail_get_backend_mail, + index_mail_update_flags, + index_mail_update_keywords, + index_mail_update_modseq, + index_mail_update_pvt_modseq, + NULL, + index_mail_expunge, + index_mail_set_cache_corrupted, + index_mail_opened, +}; |