summaryrefslogtreecommitdiffstats
path: root/src/lib-storage/index/dbox-single/sdbox-mail.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib-storage/index/dbox-single/sdbox-mail.c')
-rw-r--r--src/lib-storage/index/dbox-single/sdbox-mail.c182
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,
+};