maildir-mail.c revision e0645d5232900a5c574780ef0c0362a5b7581aba
e59faf65ce864fe95dc00f5d52b8323cdbd0608aTimo Sirainen/* Copyright (c) 2003-2009 Dovecot authors, see the included COPYING file */
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen
08d6658a4e2ec8104cd1307f6baa75fdb07a24f8Mark Washenberger#include "lib.h"
b44650b0f48a4b5f0dc240ed836833a00b643b9fTimo Sirainen#include "istream.h"
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen#include "index-mail.h"
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen#include "maildir-storage.h"
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen#include "maildir-filename.h"
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen#include "maildir-uidlist.h"
be5c76fabc7439fd33bc799bc3ab3f570799977bTimo Sirainen#include "maildir-sync.h"
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen#include <stdlib.h>
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen#include <fcntl.h>
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen#include <unistd.h>
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen#include <sys/stat.h>
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainenstatic int
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainendo_open(struct maildir_mailbox *mbox, const char *path, int *fd)
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen{
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen *fd = open(path, O_RDONLY);
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen if (*fd != -1)
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen return 1;
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen if (errno == ENOENT)
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen return 0;
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen mail_storage_set_critical(&mbox->storage->storage,
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen "open(%s) failed: %m", path);
be5c76fabc7439fd33bc799bc3ab3f570799977bTimo Sirainen return -1;
be5c76fabc7439fd33bc799bc3ab3f570799977bTimo Sirainen}
be5c76fabc7439fd33bc799bc3ab3f570799977bTimo Sirainen
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainenstatic int
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainendo_stat(struct maildir_mailbox *mbox, const char *path, struct stat *st)
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen{
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen if (stat(path, st) == 0)
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen return 1;
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen if (errno == ENOENT)
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen return 0;
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen mail_storage_set_critical(&mbox->storage->storage,
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen "stat(%s) failed: %m", path);
788a0754cfd38dcfec1902844b085e4e84cfe7e6Timo Sirainen return -1;
788a0754cfd38dcfec1902844b085e4e84cfe7e6Timo Sirainen}
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainenstatic struct istream *
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainenmaildir_open_mail(struct maildir_mailbox *mbox, struct mail *mail,
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen bool *deleted_r)
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen{
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen const char *path;
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen int fd = -1;
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen *deleted_r = FALSE;
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen if (mail->uid != 0) {
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen if (maildir_file_do(mbox, mail->uid, do_open, &fd) < 0)
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen return NULL;
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen } else {
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen path = maildir_save_file_get_path(mail->transaction, mail->seq);
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen if (do_open(mbox, path, &fd) <= 0)
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen return NULL;
31597236d79ac38a5cea7ab65a9d0a3df64ed201Timo Sirainen }
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen if (fd == -1) {
31597236d79ac38a5cea7ab65a9d0a3df64ed201Timo Sirainen *deleted_r = TRUE;
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen return NULL;
9ed2951bd0bb1878a27437d7c00611b2baadd614Timo Sirainen }
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen return i_stream_create_fd(fd, MAIL_READ_BLOCK_SIZE, TRUE);
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen}
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainenstatic int maildir_mail_stat(struct mail *mail, struct stat *st)
31597236d79ac38a5cea7ab65a9d0a3df64ed201Timo Sirainen{
31597236d79ac38a5cea7ab65a9d0a3df64ed201Timo Sirainen struct maildir_mailbox *mbox = (struct maildir_mailbox *)mail->box;
31597236d79ac38a5cea7ab65a9d0a3df64ed201Timo Sirainen struct index_mail_data *data = &((struct index_mail *)mail)->data;
31597236d79ac38a5cea7ab65a9d0a3df64ed201Timo Sirainen const char *path;
7569ab8537418b7fc369265f26595b0ef9e4cb35Timo Sirainen int fd, ret;
7569ab8537418b7fc369265f26595b0ef9e4cb35Timo Sirainen
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen if (data->access_part != 0 && data->stream == NULL) {
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen /* we're going to open the mail anyway */
9ed2951bd0bb1878a27437d7c00611b2baadd614Timo Sirainen struct istream *input;
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen (void)mail_get_stream(mail, NULL, NULL, &input);
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen }
798cfe56c9871262770384da1239162b3800cce1Timo Sirainen
798cfe56c9871262770384da1239162b3800cce1Timo Sirainen if (data->stream != NULL) {
798cfe56c9871262770384da1239162b3800cce1Timo Sirainen fd = i_stream_get_fd(data->stream);
798cfe56c9871262770384da1239162b3800cce1Timo Sirainen i_assert(fd != -1);
798cfe56c9871262770384da1239162b3800cce1Timo Sirainen
798cfe56c9871262770384da1239162b3800cce1Timo Sirainen if (fstat(fd, st) < 0) {
798cfe56c9871262770384da1239162b3800cce1Timo Sirainen mail_storage_set_critical(&mbox->storage->storage,
798cfe56c9871262770384da1239162b3800cce1Timo Sirainen "fstat(maildir) failed: %m");
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen return -1;
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen }
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen } else if (mail->uid != 0) {
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen ret = maildir_file_do(mbox, mail->uid, do_stat, st);
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen if (ret <= 0) {
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen if (ret == 0)
3313a51ef9b245248d672c20f930c52a577a42f7Timo Sirainen mail_set_expunged(mail);
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen return -1;
47bb4a7615c85f212f061499f04f121d6d625387Timo Sirainen }
47bb4a7615c85f212f061499f04f121d6d625387Timo Sirainen } else {
47bb4a7615c85f212f061499f04f121d6d625387Timo Sirainen path = maildir_save_file_get_path(mail->transaction, mail->seq);
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen if (stat(path, st) < 0) {
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen mail_storage_set_critical(mail->box->storage,
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen "stat(%s) failed: %m", path);
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen return -1;
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen }
fc8d5f0ac909cca77840538e8beef98a8d40c21cTimo Sirainen }
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen return 0;
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen}
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainenstatic int maildir_mail_get_received_date(struct mail *_mail, time_t *date_r)
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen{
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen struct index_mail *mail = (struct index_mail *)_mail;
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen struct index_mail_data *data = &mail->data;
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen struct stat st;
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen
fc8d5f0ac909cca77840538e8beef98a8d40c21cTimo Sirainen if (index_mail_get_received_date(_mail, date_r) == 0)
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen return 0;
fc8d5f0ac909cca77840538e8beef98a8d40c21cTimo Sirainen
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen if (maildir_mail_stat(_mail, &st) < 0)
fc8d5f0ac909cca77840538e8beef98a8d40c21cTimo Sirainen return -1;
33dd58ab84a020c4f061d2f6031eb6d4c168df1bTimo Sirainen
33dd58ab84a020c4f061d2f6031eb6d4c168df1bTimo Sirainen *date_r = data->received_date = st.st_mtime;
33dd58ab84a020c4f061d2f6031eb6d4c168df1bTimo Sirainen return 0;
33dd58ab84a020c4f061d2f6031eb6d4c168df1bTimo Sirainen}
33dd58ab84a020c4f061d2f6031eb6d4c168df1bTimo Sirainen
3313a51ef9b245248d672c20f930c52a577a42f7Timo Sirainenstatic int maildir_mail_get_save_date(struct mail *_mail, time_t *date_r)
3313a51ef9b245248d672c20f930c52a577a42f7Timo Sirainen{
3313a51ef9b245248d672c20f930c52a577a42f7Timo Sirainen struct index_mail *mail = (struct index_mail *)_mail;
3313a51ef9b245248d672c20f930c52a577a42f7Timo Sirainen struct index_mail_data *data = &mail->data;
3313a51ef9b245248d672c20f930c52a577a42f7Timo Sirainen struct stat st;
3313a51ef9b245248d672c20f930c52a577a42f7Timo Sirainen
3313a51ef9b245248d672c20f930c52a577a42f7Timo Sirainen if (index_mail_get_save_date(_mail, date_r) == 0)
5d4855d7b4dcffb6975ed8e3c9c376dac74e5c8aTimo Sirainen return 0;
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen if (maildir_mail_stat(_mail, &st) < 0)
798cfe56c9871262770384da1239162b3800cce1Timo Sirainen return -1;
82f53ea81671bcc7b9bf24a34b04a4ba2752efd3Timo Sirainen
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen *date_r = data->save_date = st.st_ctime;
82f53ea81671bcc7b9bf24a34b04a4ba2752efd3Timo Sirainen return data->save_date;
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen}
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainenstatic bool
ce6b6093957885a74fd6e85c18801dbb727d61ecTimo Sirainenmaildir_mail_get_fname(struct maildir_mailbox *mbox, struct mail *mail,
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen const char **fname_r)
31597236d79ac38a5cea7ab65a9d0a3df64ed201Timo Sirainen{
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen enum maildir_uidlist_rec_flag flags;
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen struct mail_index_view *view;
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen uint32_t seq;
adc409a7ac9689d3baf811712ad5a5432cab2d87Timo Sirainen bool exists;
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen
8eb94c5190ba09bb6f6f068eec7bf96750f08d1dTimo Sirainen *fname_r = maildir_uidlist_lookup(mbox->uidlist, mail->uid, &flags);
e9503210d3521a6833ed62dc332fc42ffb0e7a13Timo Sirainen if (*fname_r != NULL)
31597236d79ac38a5cea7ab65a9d0a3df64ed201Timo Sirainen return TRUE;
31597236d79ac38a5cea7ab65a9d0a3df64ed201Timo Sirainen
e9503210d3521a6833ed62dc332fc42ffb0e7a13Timo Sirainen /* file exists in index file, but not in dovecot-uidlist anymore. */
ce6b6093957885a74fd6e85c18801dbb727d61ecTimo Sirainen mail_set_expunged(mail);
e9503210d3521a6833ed62dc332fc42ffb0e7a13Timo Sirainen
31597236d79ac38a5cea7ab65a9d0a3df64ed201Timo Sirainen /* one reason this could happen is if we delayed opening
31597236d79ac38a5cea7ab65a9d0a3df64ed201Timo Sirainen dovecot-uidlist and we're trying to open a mail that got recently
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen expunged. Let's test this theory first: */
31597236d79ac38a5cea7ab65a9d0a3df64ed201Timo Sirainen (void)mail_index_refresh(mbox->ibox.index);
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen view = mail_index_view_open(mbox->ibox.index);
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen exists = mail_index_lookup_seq(view, mail->uid, &seq);
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen mail_index_view_close(&view);
70c181da837ed85fc5b0426c010b65609bda5329Timo Sirainen
70c181da837ed85fc5b0426c010b65609bda5329Timo Sirainen if (exists) {
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen /* the message still exists in index. this means there's some
ce6b6093957885a74fd6e85c18801dbb727d61ecTimo Sirainen kind of a desync, which doesn't get fixed if cur/ mtime is
70c181da837ed85fc5b0426c010b65609bda5329Timo Sirainen the same as in index. fix this by forcing a resync. */
70c181da837ed85fc5b0426c010b65609bda5329Timo Sirainen (void)maildir_storage_sync_force(mbox, mail->uid);
adc409a7ac9689d3baf811712ad5a5432cab2d87Timo Sirainen }
3cf67672fdc87583cb23ce088c95bb5dee60e74dTimo Sirainen return FALSE;
adc409a7ac9689d3baf811712ad5a5432cab2d87Timo Sirainen}
adc409a7ac9689d3baf811712ad5a5432cab2d87Timo Sirainen
adc409a7ac9689d3baf811712ad5a5432cab2d87Timo Sirainenstatic int maildir_get_pop3_state(struct index_mail *mail)
adc409a7ac9689d3baf811712ad5a5432cab2d87Timo Sirainen{
9ed2951bd0bb1878a27437d7c00611b2baadd614Timo Sirainen const struct mail_cache_field *fields;
3cf67672fdc87583cb23ce088c95bb5dee60e74dTimo Sirainen unsigned int i, count, psize_idx, vsize_idx;
adc409a7ac9689d3baf811712ad5a5432cab2d87Timo Sirainen enum mail_cache_decision_type dec, vsize_dec;
adc409a7ac9689d3baf811712ad5a5432cab2d87Timo Sirainen enum mail_fetch_field allowed_pop3_fields;
adc409a7ac9689d3baf811712ad5a5432cab2d87Timo Sirainen bool not_pop3_only = FALSE;
8eb94c5190ba09bb6f6f068eec7bf96750f08d1dTimo Sirainen
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen if (mail->pop3_state_set)
ce6b6093957885a74fd6e85c18801dbb727d61ecTimo Sirainen return mail->pop3_state;
e9503210d3521a6833ed62dc332fc42ffb0e7a13Timo Sirainen
e9503210d3521a6833ed62dc332fc42ffb0e7a13Timo Sirainen /* if this mail itself has non-pop3 fields we know we're not
e9503210d3521a6833ed62dc332fc42ffb0e7a13Timo Sirainen pop3-only */
adc409a7ac9689d3baf811712ad5a5432cab2d87Timo Sirainen allowed_pop3_fields = MAIL_FETCH_FLAGS | MAIL_FETCH_STREAM_HEADER |
adc409a7ac9689d3baf811712ad5a5432cab2d87Timo Sirainen MAIL_FETCH_STREAM_BODY | MAIL_FETCH_UIDL_FILE_NAME |
b321df9603081896b70ec44635af96d674a9839aTimo Sirainen MAIL_FETCH_VIRTUAL_SIZE;
ce6b6093957885a74fd6e85c18801dbb727d61ecTimo Sirainen
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen if (mail->wanted_headers != NULL ||
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen (mail->wanted_fields & ~allowed_pop3_fields) != 0)
f968e62caa52a8924bd05ebf76ff515b5c18e17bTimo Sirainen not_pop3_only = TRUE;
b44650b0f48a4b5f0dc240ed836833a00b643b9fTimo Sirainen
b44650b0f48a4b5f0dc240ed836833a00b643b9fTimo Sirainen /* get vsize decisions */
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen psize_idx = mail->ibox->cache_fields[MAIL_CACHE_PHYSICAL_FULL_SIZE].idx;
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen vsize_idx = mail->ibox->cache_fields[MAIL_CACHE_VIRTUAL_FULL_SIZE].idx;
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen if (not_pop3_only) {
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen vsize_dec = mail_cache_field_get_decision(mail->ibox->cache,
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen vsize_idx);
3313a51ef9b245248d672c20f930c52a577a42f7Timo Sirainen vsize_dec &= ~MAIL_CACHE_DECISION_FORCED;
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen } else {
47bb4a7615c85f212f061499f04f121d6d625387Timo Sirainen /* also check if there are any non-[pv]size cached fields */
47bb4a7615c85f212f061499f04f121d6d625387Timo Sirainen vsize_dec = MAIL_CACHE_DECISION_NO;
47bb4a7615c85f212f061499f04f121d6d625387Timo Sirainen fields = mail_cache_register_get_list(mail->ibox->cache,
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen pool_datastack_create(),
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen &count);
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen for (i = 0; i < count; i++) {
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen dec = fields[i].decision & ~MAIL_CACHE_DECISION_FORCED;
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen if (fields[i].idx == vsize_idx)
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen vsize_dec = dec;
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen else if (dec != MAIL_CACHE_DECISION_NO &&
3313a51ef9b245248d672c20f930c52a577a42f7Timo Sirainen fields[i].idx != psize_idx)
3313a51ef9b245248d672c20f930c52a577a42f7Timo Sirainen not_pop3_only = TRUE;
3313a51ef9b245248d672c20f930c52a577a42f7Timo Sirainen }
3313a51ef9b245248d672c20f930c52a577a42f7Timo Sirainen }
3313a51ef9b245248d672c20f930c52a577a42f7Timo Sirainen
3313a51ef9b245248d672c20f930c52a577a42f7Timo Sirainen if (!not_pop3_only) {
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen /* either nothing is cached, or only vsize is cached. */
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen mail->pop3_state = 1;
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen } else if (vsize_dec != MAIL_CACHE_DECISION_YES &&
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen (mail->ibox->box.open_flags &
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen MAILBOX_OPEN_POP3_SESSION) == 0) {
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen /* if virtual size isn't cached permanently,
b44650b0f48a4b5f0dc240ed836833a00b643b9fTimo Sirainen POP3 isn't being used */
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen mail->pop3_state = -1;
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen } else {
137ea7ca34005345aa2304a940149b7f3774d727Timo Sirainen /* possibly a mixed pop3/imap */
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen mail->pop3_state = 0;
137ea7ca34005345aa2304a940149b7f3774d727Timo Sirainen }
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen mail->pop3_state_set = TRUE;
4376643cd2c7110e752c09f838f2c4eee6ed8ac6Timo Sirainen return mail->pop3_state;
938835576b218f6bb9498d829cef9514f8609c6fTimo Sirainen}
938835576b218f6bb9498d829cef9514f8609c6fTimo Sirainen
938835576b218f6bb9498d829cef9514f8609c6fTimo Sirainenstatic int maildir_quick_size_lookup(struct index_mail *mail, bool vsize,
938835576b218f6bb9498d829cef9514f8609c6fTimo Sirainen uoff_t *size_r)
938835576b218f6bb9498d829cef9514f8609c6fTimo Sirainen{
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen struct mail *_mail = &mail->mail.mail;
226259ee6fb9830dafc1a5ba1e95bf5a4345b406Timo Sirainen struct maildir_mailbox *mbox = (struct maildir_mailbox *)mail->ibox;
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen enum maildir_uidlist_rec_ext_key key;
798cfe56c9871262770384da1239162b3800cce1Timo Sirainen const char *path, *fname, *value;
82f53ea81671bcc7b9bf24a34b04a4ba2752efd3Timo Sirainen uoff_t size;
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen char *p;
82f53ea81671bcc7b9bf24a34b04a4ba2752efd3Timo Sirainen
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen if (_mail->uid != 0) {
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen if (!maildir_mail_get_fname(mbox, _mail, &fname))
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen return -1;
ce6b6093957885a74fd6e85c18801dbb727d61ecTimo Sirainen } else {
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen path = maildir_save_file_get_path(_mail->transaction,
31597236d79ac38a5cea7ab65a9d0a3df64ed201Timo Sirainen _mail->seq);
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen fname = strrchr(path, '/');
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen fname = fname != NULL ? fname + 1 : path;
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen }
a8e132559a7ebe54c8269d79ce29fa3338c76199Timo Sirainen
e2a700d0628e395d64cbcef4b5b4510816bf51c4Timo Sirainen /* size can be included in filename */
e9503210d3521a6833ed62dc332fc42ffb0e7a13Timo Sirainen if (maildir_filename_get_size(fname,
31597236d79ac38a5cea7ab65a9d0a3df64ed201Timo Sirainen vsize ? MAILDIR_EXTRA_VIRTUAL_SIZE :
31597236d79ac38a5cea7ab65a9d0a3df64ed201Timo Sirainen MAILDIR_EXTRA_FILE_SIZE,
e9503210d3521a6833ed62dc332fc42ffb0e7a13Timo Sirainen size_r))
ce6b6093957885a74fd6e85c18801dbb727d61ecTimo Sirainen return 1;
e9503210d3521a6833ed62dc332fc42ffb0e7a13Timo Sirainen
31597236d79ac38a5cea7ab65a9d0a3df64ed201Timo Sirainen /* size can be included in uidlist entry */
31597236d79ac38a5cea7ab65a9d0a3df64ed201Timo Sirainen if (_mail->uid != 0) {
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen key = vsize ? MAILDIR_UIDLIST_REC_EXT_VSIZE :
31597236d79ac38a5cea7ab65a9d0a3df64ed201Timo Sirainen MAILDIR_UIDLIST_REC_EXT_PSIZE;
a8e132559a7ebe54c8269d79ce29fa3338c76199Timo Sirainen value = maildir_uidlist_lookup_ext(mbox->uidlist, _mail->uid,
e9503210d3521a6833ed62dc332fc42ffb0e7a13Timo Sirainen key);
70c181da837ed85fc5b0426c010b65609bda5329Timo Sirainen if (value != NULL) {
70c181da837ed85fc5b0426c010b65609bda5329Timo Sirainen size = strtoull(value, &p, 10);
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen if (*p == '\0') {
ce6b6093957885a74fd6e85c18801dbb727d61ecTimo Sirainen *size_r = size;
70c181da837ed85fc5b0426c010b65609bda5329Timo Sirainen return 1;
70c181da837ed85fc5b0426c010b65609bda5329Timo Sirainen }
3cf67672fdc87583cb23ce088c95bb5dee60e74dTimo Sirainen }
e9503210d3521a6833ed62dc332fc42ffb0e7a13Timo Sirainen }
e9503210d3521a6833ed62dc332fc42ffb0e7a13Timo Sirainen return 0;
e2a700d0628e395d64cbcef4b5b4510816bf51c4Timo Sirainen}
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen
ce6b6093957885a74fd6e85c18801dbb727d61ecTimo Sirainenstatic void
e9503210d3521a6833ed62dc332fc42ffb0e7a13Timo Sirainenmaildir_handle_size_caching(struct index_mail *mail, bool quick_check,
e9503210d3521a6833ed62dc332fc42ffb0e7a13Timo Sirainen bool vsize)
e9503210d3521a6833ed62dc332fc42ffb0e7a13Timo Sirainen{
43358fffb1d9f3091fd94895e0ac4643c50e2388Timo Sirainen struct maildir_mailbox *mbox = (struct maildir_mailbox *)mail->ibox;
43358fffb1d9f3091fd94895e0ac4643c50e2388Timo Sirainen enum mail_fetch_field field;
43358fffb1d9f3091fd94895e0ac4643c50e2388Timo Sirainen uoff_t size;
ce6b6093957885a74fd6e85c18801dbb727d61ecTimo Sirainen int pop3_state;
43358fffb1d9f3091fd94895e0ac4643c50e2388Timo Sirainen
43358fffb1d9f3091fd94895e0ac4643c50e2388Timo Sirainen field = vsize ? MAIL_FETCH_VIRTUAL_SIZE : MAIL_FETCH_PHYSICAL_SIZE;
430c0b0c370bebeeceba2e206be76bc134742f41Timo Sirainen if ((mail->data.dont_cache_fetch_fields & field) != 0)
25ee72451d16374ed27fdbf829f4ec756c778352Timo Sirainen return;
a3dd97fb6d92a89c3de0597fed2d4b044c7aeb84Timo Sirainen
ce6b6093957885a74fd6e85c18801dbb727d61ecTimo Sirainen if (quick_check && maildir_quick_size_lookup(mail, vsize, &size) > 0) {
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen /* already in filename / uidlist. don't add it anywhere,
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen including to the uidlist if it's already in filename.
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen do some extra checks here to catch potential cache bugs. */
484e12acec34f16e5a8adc001e23ae48f1dda8c7Timo Sirainen if (vsize && mail->data.virtual_size != size) {
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen mail_cache_set_corrupted(mail->ibox->cache,
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen "Corrupted virtual size for uid=%u: "
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen "%"PRIuUOFF_T" != %"PRIuUOFF_T,
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen mail->mail.mail.uid,
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen mail->data.virtual_size, size);
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen mail->data.virtual_size = size;
484e12acec34f16e5a8adc001e23ae48f1dda8c7Timo Sirainen } else if (!vsize && mail->data.physical_size != size) {
798cfe56c9871262770384da1239162b3800cce1Timo Sirainen mail_cache_set_corrupted(mail->ibox->cache,
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen "Corrupted physical size for uid=%u: "
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen "%"PRIuUOFF_T" != %"PRIuUOFF_T,
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen mail->mail.mail.uid,
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen mail->data.physical_size, size);
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen mail->data.physical_size = size;
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen }
ce6b6093957885a74fd6e85c18801dbb727d61ecTimo Sirainen mail->data.dont_cache_fetch_fields |= field;
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen return;
31597236d79ac38a5cea7ab65a9d0a3df64ed201Timo Sirainen }
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen /* 1 = pop3-only, 0 = mixed, -1 = no pop3 */
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen pop3_state = maildir_get_pop3_state(mail);
31597236d79ac38a5cea7ab65a9d0a3df64ed201Timo Sirainen if (pop3_state >= 0 && mail->mail.mail.uid != 0) {
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen /* if size is wanted permanently, store it to uidlist
31597236d79ac38a5cea7ab65a9d0a3df64ed201Timo Sirainen so that in case cache file gets lost we can get it quickly */
31597236d79ac38a5cea7ab65a9d0a3df64ed201Timo Sirainen mail->data.dont_cache_fetch_fields |= field;
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen size = vsize ? mail->data.virtual_size :
ce6b6093957885a74fd6e85c18801dbb727d61ecTimo Sirainen mail->data.physical_size;
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen maildir_uidlist_set_ext(mbox->uidlist, mail->mail.mail.uid,
31597236d79ac38a5cea7ab65a9d0a3df64ed201Timo Sirainen vsize ? MAILDIR_UIDLIST_REC_EXT_VSIZE :
31597236d79ac38a5cea7ab65a9d0a3df64ed201Timo Sirainen MAILDIR_UIDLIST_REC_EXT_PSIZE,
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen dec2str(size));
31597236d79ac38a5cea7ab65a9d0a3df64ed201Timo Sirainen }
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen}
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainenstatic int maildir_mail_get_virtual_size(struct mail *_mail, uoff_t *size_r)
ce6b6093957885a74fd6e85c18801dbb727d61ecTimo Sirainen{
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen struct index_mail *mail = (struct index_mail *)_mail;
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen struct index_mail_data *data = &mail->data;
3cf67672fdc87583cb23ce088c95bb5dee60e74dTimo Sirainen struct message_size hdr_size, body_size;
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen struct istream *input;
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen uoff_t old_offset;
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen if (index_mail_get_cached_virtual_size(mail, size_r)) {
ce6b6093957885a74fd6e85c18801dbb727d61ecTimo Sirainen i_assert(mail->data.virtual_size != (uoff_t)-1);
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen maildir_handle_size_caching(mail, TRUE, TRUE);
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen return 0;
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen }
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen
31597236d79ac38a5cea7ab65a9d0a3df64ed201Timo Sirainen if (maildir_quick_size_lookup(mail, TRUE, &data->virtual_size) < 0)
ce6b6093957885a74fd6e85c18801dbb727d61ecTimo Sirainen return -1;
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen if (data->virtual_size != (uoff_t)-1) {
35136dd2baf8dc30e4e754294ed81ff48e8c1e64Timo Sirainen data->dont_cache_fetch_fields |= MAIL_FETCH_VIRTUAL_SIZE;
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen *size_r = data->virtual_size;
0f39a57760d93cddbce3ca43096d78e0fe2f42fdTimo Sirainen return 0;
137ea7ca34005345aa2304a940149b7f3774d727Timo Sirainen }
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen /* fallback to reading the file */
6fabfb7bbfd88d0c1de66981e52850f26067623bTimo Sirainen old_offset = data->stream == NULL ? 0 : data->stream->v_offset;
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen if (mail_get_stream(_mail, &hdr_size, &body_size, &input) < 0)
3313a51ef9b245248d672c20f930c52a577a42f7Timo Sirainen return -1;
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen i_stream_seek(data->stream, old_offset);
6fabfb7bbfd88d0c1de66981e52850f26067623bTimo Sirainen
6fabfb7bbfd88d0c1de66981e52850f26067623bTimo Sirainen maildir_handle_size_caching(mail, FALSE, TRUE);
6fabfb7bbfd88d0c1de66981e52850f26067623bTimo Sirainen *size_r = data->virtual_size;
0f39a57760d93cddbce3ca43096d78e0fe2f42fdTimo Sirainen return 0;
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen}
0f39a57760d93cddbce3ca43096d78e0fe2f42fdTimo Sirainen
0f39a57760d93cddbce3ca43096d78e0fe2f42fdTimo Sirainenstatic int maildir_mail_get_physical_size(struct mail *_mail, uoff_t *size_r)
0f39a57760d93cddbce3ca43096d78e0fe2f42fdTimo Sirainen{
3313a51ef9b245248d672c20f930c52a577a42f7Timo Sirainen struct index_mail *mail = (struct index_mail *)_mail;
3313a51ef9b245248d672c20f930c52a577a42f7Timo Sirainen struct maildir_mailbox *mbox = (struct maildir_mailbox *)mail->ibox;
3313a51ef9b245248d672c20f930c52a577a42f7Timo Sirainen struct index_mail_data *data = &mail->data;
3313a51ef9b245248d672c20f930c52a577a42f7Timo Sirainen struct stat st;
3313a51ef9b245248d672c20f930c52a577a42f7Timo Sirainen const char *path;
0f39a57760d93cddbce3ca43096d78e0fe2f42fdTimo Sirainen int ret;
0f39a57760d93cddbce3ca43096d78e0fe2f42fdTimo Sirainen
0f39a57760d93cddbce3ca43096d78e0fe2f42fdTimo Sirainen if (index_mail_get_physical_size(_mail, size_r) == 0) {
0f39a57760d93cddbce3ca43096d78e0fe2f42fdTimo Sirainen i_assert(mail->data.physical_size != (uoff_t)-1);
0f39a57760d93cddbce3ca43096d78e0fe2f42fdTimo Sirainen maildir_handle_size_caching(mail, TRUE, FALSE);
0f39a57760d93cddbce3ca43096d78e0fe2f42fdTimo Sirainen return 0;
137ea7ca34005345aa2304a940149b7f3774d727Timo Sirainen }
0f39a57760d93cddbce3ca43096d78e0fe2f42fdTimo Sirainen
0f39a57760d93cddbce3ca43096d78e0fe2f42fdTimo Sirainen if (maildir_quick_size_lookup(mail, FALSE, &data->physical_size) < 0)
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen return -1;
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen if (data->physical_size != (uoff_t)-1) {
798cfe56c9871262770384da1239162b3800cce1Timo Sirainen data->dont_cache_fetch_fields |= MAIL_FETCH_PHYSICAL_SIZE;
82f53ea81671bcc7b9bf24a34b04a4ba2752efd3Timo Sirainen *size_r = data->physical_size;
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen return 0;
82f53ea81671bcc7b9bf24a34b04a4ba2752efd3Timo Sirainen }
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen if (_mail->uid != 0) {
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen ret = maildir_file_do(mbox, _mail->uid, do_stat, &st);
f0c01ca67be18ed9c8011a094db2773f8795a1ebTimo Sirainen if (ret <= 0) {
f0c01ca67be18ed9c8011a094db2773f8795a1ebTimo Sirainen if (ret == 0)
f0c01ca67be18ed9c8011a094db2773f8795a1ebTimo Sirainen mail_set_expunged(_mail);
f0c01ca67be18ed9c8011a094db2773f8795a1ebTimo Sirainen return -1;
f0c01ca67be18ed9c8011a094db2773f8795a1ebTimo Sirainen }
f0c01ca67be18ed9c8011a094db2773f8795a1ebTimo Sirainen } else {
f0c01ca67be18ed9c8011a094db2773f8795a1ebTimo Sirainen /* saved mail which hasn't been committed yet */
f0c01ca67be18ed9c8011a094db2773f8795a1ebTimo Sirainen path = maildir_save_file_get_path(_mail->transaction,
f0c01ca67be18ed9c8011a094db2773f8795a1ebTimo Sirainen _mail->seq);
f0c01ca67be18ed9c8011a094db2773f8795a1ebTimo Sirainen if (stat(path, &st) < 0) {
f0c01ca67be18ed9c8011a094db2773f8795a1ebTimo Sirainen mail_storage_set_critical(_mail->box->storage,
f0c01ca67be18ed9c8011a094db2773f8795a1ebTimo Sirainen "stat(%s) failed: %m", path);
ce6b6093957885a74fd6e85c18801dbb727d61ecTimo Sirainen return -1;
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen }
31597236d79ac38a5cea7ab65a9d0a3df64ed201Timo Sirainen }
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen data->physical_size = st.st_size;
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen maildir_handle_size_caching(mail, FALSE, FALSE);
f0c01ca67be18ed9c8011a094db2773f8795a1ebTimo Sirainen *size_r = st.st_size;
e9503210d3521a6833ed62dc332fc42ffb0e7a13Timo Sirainen return 0;
31597236d79ac38a5cea7ab65a9d0a3df64ed201Timo Sirainen}
31597236d79ac38a5cea7ab65a9d0a3df64ed201Timo Sirainen
e9503210d3521a6833ed62dc332fc42ffb0e7a13Timo Sirainenstatic int
31597236d79ac38a5cea7ab65a9d0a3df64ed201Timo Sirainenmaildir_mail_get_special(struct mail *_mail, enum mail_fetch_field field,
70c181da837ed85fc5b0426c010b65609bda5329Timo Sirainen const char **value_r)
70c181da837ed85fc5b0426c010b65609bda5329Timo Sirainen{
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen struct index_mail *mail = (struct index_mail *)_mail;
ce6b6093957885a74fd6e85c18801dbb727d61ecTimo Sirainen struct maildir_mailbox *mbox = (struct maildir_mailbox *)mail->ibox;
70c181da837ed85fc5b0426c010b65609bda5329Timo Sirainen const char *path, *fname, *end, *uidl;
70c181da837ed85fc5b0426c010b65609bda5329Timo Sirainen
f0c01ca67be18ed9c8011a094db2773f8795a1ebTimo Sirainen switch (field) {
f0c01ca67be18ed9c8011a094db2773f8795a1ebTimo Sirainen case MAIL_FETCH_UIDL_FILE_NAME:
f0c01ca67be18ed9c8011a094db2773f8795a1ebTimo Sirainen case MAIL_FETCH_GUID:
f0c01ca67be18ed9c8011a094db2773f8795a1ebTimo Sirainen if (_mail->uid != 0) {
f0c01ca67be18ed9c8011a094db2773f8795a1ebTimo Sirainen if (!maildir_mail_get_fname(mbox, _mail, &fname))
f0c01ca67be18ed9c8011a094db2773f8795a1ebTimo Sirainen return -1;
e9503210d3521a6833ed62dc332fc42ffb0e7a13Timo Sirainen } else {
e9503210d3521a6833ed62dc332fc42ffb0e7a13Timo Sirainen path = maildir_save_file_get_path(_mail->transaction,
b42f37ae6f65ed986315b6885568d32115e589b1Timo Sirainen _mail->seq);
e9503210d3521a6833ed62dc332fc42ffb0e7a13Timo Sirainen fname = strrchr(path, '/');
ce6b6093957885a74fd6e85c18801dbb727d61ecTimo Sirainen fname = fname != NULL ? fname + 1 : path;
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen }
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen end = strchr(fname, MAILDIR_INFO_SEP);
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen *value_r = end == NULL ? fname : t_strdup_until(fname, end);
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen return 0;
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen case MAIL_FETCH_UIDL_BACKEND:
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen uidl = maildir_uidlist_lookup_ext(mbox->uidlist, _mail->uid,
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen MAILDIR_UIDLIST_REC_EXT_POP3_UIDL);
7cba14a4c3beb026a2862ee50d24c554fa713329Timo Sirainen if (uidl == NULL) {
7cba14a4c3beb026a2862ee50d24c554fa713329Timo Sirainen /* use the default */
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen *value_r = "";
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen } else if (*uidl == '\0') {
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen /* special optimization case: use the base file name */
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen return maildir_mail_get_special(_mail,
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen MAIL_FETCH_UIDL_FILE_NAME, value_r);
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen } else {
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen *value_r = uidl;
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen }
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen return 0;
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen default:
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen return index_mail_get_special(_mail, field, value_r);
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen }
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen}
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainenstatic int maildir_mail_get_stream(struct mail *_mail,
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen struct message_size *hdr_size,
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen struct message_size *body_size,
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen struct istream **stream_r)
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen{
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen struct index_mail *mail = (struct index_mail *)_mail;
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen struct maildir_mailbox *mbox = (struct maildir_mailbox *)mail->ibox;
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen struct index_mail_data *data = &mail->data;
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen bool deleted;
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen if (data->stream == NULL) {
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen data->stream = maildir_open_mail(mbox, _mail, &deleted);
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen if (data->stream == NULL) {
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen if (deleted)
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen mail_set_expunged(_mail);
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen return -1;
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen }
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen }
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen return index_mail_init_stream(mail, hdr_size, body_size, stream_r);
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen}
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainenstatic void maildir_mail_set_cache_corrupted(struct mail *_mail,
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen enum mail_fetch_field field)
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen{
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen struct index_mail *mail = (struct index_mail *)_mail;
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen struct maildir_mailbox *mbox = (struct maildir_mailbox *)mail->ibox;
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen enum maildir_uidlist_rec_flag flags;
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen const char *fname;
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen uoff_t size;
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen if (field == MAIL_FETCH_VIRTUAL_SIZE) {
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen /* make sure it gets removed from uidlist.
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen if it's in file name, we can't really do more than log it. */
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen fname = maildir_uidlist_lookup(mbox->uidlist,
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen _mail->uid, &flags);
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen if (maildir_filename_get_size(fname, MAILDIR_EXTRA_VIRTUAL_SIZE,
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen &size)) {
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen const char *subdir =
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen (flags & MAILDIR_UIDLIST_REC_FLAG_NEW_DIR) != 0 ?
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen "new" : "cur";
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen mail_storage_set_critical(_mail->box->storage,
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen "Maildir filename has wrong W value: %s/%s/%s",
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen mbox->path, subdir, fname);
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen } else if (maildir_uidlist_lookup_ext(mbox->uidlist, _mail->uid,
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen MAILDIR_UIDLIST_REC_EXT_VSIZE) != NULL) {
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen maildir_uidlist_set_ext(mbox->uidlist, _mail->uid,
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen MAILDIR_UIDLIST_REC_EXT_VSIZE,
ce6b6093957885a74fd6e85c18801dbb727d61ecTimo Sirainen NULL);
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen }
31597236d79ac38a5cea7ab65a9d0a3df64ed201Timo Sirainen }
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen index_mail_set_cache_corrupted(_mail, field);
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen}
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainenstruct mail_vfuncs maildir_mail_vfuncs = {
31597236d79ac38a5cea7ab65a9d0a3df64ed201Timo Sirainen index_mail_close,
f0c01ca67be18ed9c8011a094db2773f8795a1ebTimo Sirainen index_mail_free,
f0c01ca67be18ed9c8011a094db2773f8795a1ebTimo Sirainen index_mail_set_seq,
f0c01ca67be18ed9c8011a094db2773f8795a1ebTimo Sirainen index_mail_set_uid,
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen index_mail_get_flags,
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen index_mail_get_keywords,
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen index_mail_get_keyword_indexes,
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen index_mail_get_modseq,
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen index_mail_get_parts,
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen index_mail_get_date,
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen maildir_mail_get_received_date,
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen maildir_mail_get_save_date,
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen maildir_mail_get_virtual_size,
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen maildir_mail_get_physical_size,
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen index_mail_get_first_header,
849969f639a00eab26791db3cb1b66430420c0cdTimo Sirainen index_mail_get_headers,
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen index_mail_get_header_stream,
ce6b6093957885a74fd6e85c18801dbb727d61ecTimo Sirainen maildir_mail_get_stream,
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen maildir_mail_get_special,
43d3ea2780b5f8557ede7b4c039e8f56cb8d357dTimo Sirainen index_mail_update_flags,
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainen index_mail_update_keywords,
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen index_mail_expunge,
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen maildir_mail_set_cache_corrupted,
31597236d79ac38a5cea7ab65a9d0a3df64ed201Timo Sirainen index_mail_get_index_mail
2e29e4797a48d78d669821722bdb54fd0a1d3b94Timo Sirainen};
459b483806babd159daa8b461377281d89bb3bdcTimo Sirainen