maildir-mail.c revision ad48319996942463675b53877092ab7e13a7a75a
2454dfa32c93c20a8522c6ed42fe057baaac9f9aStephan Bosch/* Copyright (c) 2003-2009 Dovecot authors, see the included COPYING file */
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen#include "lib.h"
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen#include "istream.h"
0536ccb51d41e3078c3a9fa33e509fb4b2420f95Timo Sirainen#include "index-mail.h"
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen#include "maildir-storage.h"
8cb72c59d5ea4e9e5f638d7ec840bb853f5a188eTimo Sirainen#include "maildir-filename.h"
8cb72c59d5ea4e9e5f638d7ec840bb853f5a188eTimo Sirainen#include "maildir-uidlist.h"
8cb72c59d5ea4e9e5f638d7ec840bb853f5a188eTimo Sirainen#include "maildir-sync.h"
8cb72c59d5ea4e9e5f638d7ec840bb853f5a188eTimo Sirainen
8cb72c59d5ea4e9e5f638d7ec840bb853f5a188eTimo Sirainen#include <stdlib.h>
8cb72c59d5ea4e9e5f638d7ec840bb853f5a188eTimo Sirainen#include <fcntl.h>
8cb72c59d5ea4e9e5f638d7ec840bb853f5a188eTimo Sirainen#include <unistd.h>
8cb72c59d5ea4e9e5f638d7ec840bb853f5a188eTimo Sirainen#include <sys/stat.h>
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainenstatic int
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainendo_open(struct maildir_mailbox *mbox, const char *path, int *fd)
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen{
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen *fd = open(path, O_RDONLY);
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen if (*fd != -1)
8cb72c59d5ea4e9e5f638d7ec840bb853f5a188eTimo Sirainen return 1;
8cb72c59d5ea4e9e5f638d7ec840bb853f5a188eTimo Sirainen if (errno == ENOENT)
8b247780e911909a9fdc47f69ce6d1478902ad98Timo Sirainen return 0;
8b247780e911909a9fdc47f69ce6d1478902ad98Timo Sirainen
8b247780e911909a9fdc47f69ce6d1478902ad98Timo Sirainen mail_storage_set_critical(&mbox->storage->storage,
8b247780e911909a9fdc47f69ce6d1478902ad98Timo Sirainen "open(%s) failed: %m", path);
8b247780e911909a9fdc47f69ce6d1478902ad98Timo Sirainen return -1;
862ec874f9373e3e499e237d3b9f71fdf1413feeTimo Sirainen}
862ec874f9373e3e499e237d3b9f71fdf1413feeTimo Sirainen
862ec874f9373e3e499e237d3b9f71fdf1413feeTimo Sirainenstatic int
862ec874f9373e3e499e237d3b9f71fdf1413feeTimo Sirainendo_stat(struct maildir_mailbox *mbox, const char *path, struct stat *st)
862ec874f9373e3e499e237d3b9f71fdf1413feeTimo Sirainen{
862ec874f9373e3e499e237d3b9f71fdf1413feeTimo Sirainen if (stat(path, st) == 0)
862ec874f9373e3e499e237d3b9f71fdf1413feeTimo Sirainen return 1;
862ec874f9373e3e499e237d3b9f71fdf1413feeTimo Sirainen if (errno == ENOENT)
862ec874f9373e3e499e237d3b9f71fdf1413feeTimo Sirainen return 0;
862ec874f9373e3e499e237d3b9f71fdf1413feeTimo Sirainen
862ec874f9373e3e499e237d3b9f71fdf1413feeTimo Sirainen mail_storage_set_critical(&mbox->storage->storage,
862ec874f9373e3e499e237d3b9f71fdf1413feeTimo Sirainen "stat(%s) failed: %m", path);
862ec874f9373e3e499e237d3b9f71fdf1413feeTimo Sirainen return -1;
862ec874f9373e3e499e237d3b9f71fdf1413feeTimo Sirainen}
862ec874f9373e3e499e237d3b9f71fdf1413feeTimo Sirainen
862ec874f9373e3e499e237d3b9f71fdf1413feeTimo Sirainenstatic struct istream *
862ec874f9373e3e499e237d3b9f71fdf1413feeTimo Sirainenmaildir_open_mail(struct maildir_mailbox *mbox, struct mail *mail,
862ec874f9373e3e499e237d3b9f71fdf1413feeTimo Sirainen bool *deleted_r)
e2ce8d4a6ac5d82a906178148453e7613fab9ba0Timo Sirainen{
e2ce8d4a6ac5d82a906178148453e7613fab9ba0Timo Sirainen struct mail_private *p = (struct mail_private *)mail;
9a48c2243fe98ca8393be7908f84d20c634bcdf9Timo Sirainen const char *path;
9a48c2243fe98ca8393be7908f84d20c634bcdf9Timo Sirainen int fd = -1;
9a48c2243fe98ca8393be7908f84d20c634bcdf9Timo Sirainen
9a48c2243fe98ca8393be7908f84d20c634bcdf9Timo Sirainen *deleted_r = FALSE;
9a48c2243fe98ca8393be7908f84d20c634bcdf9Timo Sirainen
9a48c2243fe98ca8393be7908f84d20c634bcdf9Timo Sirainen p->stats_open_lookup_count++;
59e26ff34b05cd971a111f8a42fc60c13d9f688bTimo Sirainen if (mail->uid != 0) {
9a48c2243fe98ca8393be7908f84d20c634bcdf9Timo Sirainen if (maildir_file_do(mbox, mail->uid, do_open, &fd) < 0)
2d2ebe91d56e9a158de000c9d0026f65600fbcfaTimo Sirainen return NULL;
e2ce8d4a6ac5d82a906178148453e7613fab9ba0Timo Sirainen } else {
f988b93c2ef773987bcdcbfb4cca39b955e3a392Timo Sirainen path = maildir_save_file_get_path(mail->transaction, mail->seq);
e2ce8d4a6ac5d82a906178148453e7613fab9ba0Timo Sirainen if (do_open(mbox, path, &fd) <= 0)
e2ce8d4a6ac5d82a906178148453e7613fab9ba0Timo Sirainen return NULL;
e2ce8d4a6ac5d82a906178148453e7613fab9ba0Timo Sirainen }
cd56a23e21f1df3f79648cf07e2f4385e2fadebbTimo Sirainen
cd56a23e21f1df3f79648cf07e2f4385e2fadebbTimo Sirainen if (fd == -1) {
d6684856fb99e51bc22a6346e08b2d81c996f963Josef 'Jeff' Sipek *deleted_r = TRUE;
d6684856fb99e51bc22a6346e08b2d81c996f963Josef 'Jeff' Sipek return NULL;
d6684856fb99e51bc22a6346e08b2d81c996f963Josef 'Jeff' Sipek }
e2ce8d4a6ac5d82a906178148453e7613fab9ba0Timo Sirainen
cd56a23e21f1df3f79648cf07e2f4385e2fadebbTimo Sirainen return i_stream_create_fd(fd, MAIL_READ_BLOCK_SIZE, TRUE);
cd56a23e21f1df3f79648cf07e2f4385e2fadebbTimo Sirainen}
cd56a23e21f1df3f79648cf07e2f4385e2fadebbTimo Sirainen
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainenstatic int maildir_mail_stat(struct mail *mail, struct stat *st)
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen{
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainen struct maildir_mailbox *mbox = (struct maildir_mailbox *)mail->box;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen struct index_mail *imail = (struct index_mail *)mail;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen const struct stat *stp;
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen const char *path;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen int ret;
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen if (mail->lookup_abort == MAIL_LOOKUP_ABORT_NOT_IN_CACHE)
571fd6ff94570ee11a72a20b649acfdac2495919Timo Sirainen return mail_set_aborted(mail);
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen if (imail->data.access_part != 0 && imail->data.stream == NULL) {
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen /* we're going to open the mail anyway */
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen struct istream *input;
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen (void)mail_get_stream(mail, NULL, NULL, &input);
5a1b498b646b5c5dbd1b3f3861df766f560578c5Timo Sirainen }
5a1b498b646b5c5dbd1b3f3861df766f560578c5Timo Sirainen
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen if (imail->data.stream != NULL) {
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen imail->mail.stats_fstat_lookup_count++;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen stp = i_stream_stat(imail->data.stream, FALSE);
eb98a038ca8b0ef33d1d11794803ce09547496faTimo Sirainen if (stp == NULL)
eb98a038ca8b0ef33d1d11794803ce09547496faTimo Sirainen return -1;
eb98a038ca8b0ef33d1d11794803ce09547496faTimo Sirainen *st = *stp;
eb98a038ca8b0ef33d1d11794803ce09547496faTimo Sirainen } else if (mail->uid != 0) {
eb98a038ca8b0ef33d1d11794803ce09547496faTimo Sirainen imail->mail.stats_stat_lookup_count++;
eb98a038ca8b0ef33d1d11794803ce09547496faTimo Sirainen ret = maildir_file_do(mbox, mail->uid, do_stat, st);
eb98a038ca8b0ef33d1d11794803ce09547496faTimo Sirainen if (ret <= 0) {
eb98a038ca8b0ef33d1d11794803ce09547496faTimo Sirainen if (ret == 0)
eb98a038ca8b0ef33d1d11794803ce09547496faTimo Sirainen mail_set_expunged(mail);
eb98a038ca8b0ef33d1d11794803ce09547496faTimo Sirainen return -1;
eb98a038ca8b0ef33d1d11794803ce09547496faTimo Sirainen }
eb98a038ca8b0ef33d1d11794803ce09547496faTimo Sirainen } else {
eb98a038ca8b0ef33d1d11794803ce09547496faTimo Sirainen imail->mail.stats_stat_lookup_count++;
eb98a038ca8b0ef33d1d11794803ce09547496faTimo Sirainen path = maildir_save_file_get_path(mail->transaction, mail->seq);
eb98a038ca8b0ef33d1d11794803ce09547496faTimo Sirainen if (stat(path, st) < 0) {
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainen mail_storage_set_critical(mail->box->storage,
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen "stat(%s) failed: %m", path);
e2ce8d4a6ac5d82a906178148453e7613fab9ba0Timo Sirainen return -1;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen }
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen }
59151b71059df1190acd75d8717ed04a7920c862Timo Sirainen return 0;
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen}
211ed7806d8715ec2280ffbf5d10f0d6e4f1beb2Timo Sirainen
211ed7806d8715ec2280ffbf5d10f0d6e4f1beb2Timo Sirainenstatic int maildir_mail_get_received_date(struct mail *_mail, time_t *date_r)
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen{
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainen struct index_mail *mail = (struct index_mail *)_mail;
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen struct index_mail_data *data = &mail->data;
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen struct stat st;
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen if (index_mail_get_received_date(_mail, date_r) == 0)
59151b71059df1190acd75d8717ed04a7920c862Timo Sirainen return 0;
59151b71059df1190acd75d8717ed04a7920c862Timo Sirainen
a10ed8c47534b4c6b6bf2711ccfe577e720a47b4Timo Sirainen if (maildir_mail_stat(_mail, &st) < 0)
a10ed8c47534b4c6b6bf2711ccfe577e720a47b4Timo Sirainen return -1;
a10ed8c47534b4c6b6bf2711ccfe577e720a47b4Timo Sirainen
59151b71059df1190acd75d8717ed04a7920c862Timo Sirainen *date_r = data->received_date = st.st_mtime;
59151b71059df1190acd75d8717ed04a7920c862Timo Sirainen return 0;
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainen}
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainenstatic int maildir_mail_get_save_date(struct mail *_mail, time_t *date_r)
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen{
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen struct index_mail *mail = (struct index_mail *)_mail;
556f95092c3bc850517d5ab2bb502024a55645f1Timo Sirainen struct index_mail_data *data = &mail->data;
556f95092c3bc850517d5ab2bb502024a55645f1Timo Sirainen struct stat st;
556f95092c3bc850517d5ab2bb502024a55645f1Timo Sirainen
556f95092c3bc850517d5ab2bb502024a55645f1Timo Sirainen if (index_mail_get_save_date(_mail, date_r) == 0)
556f95092c3bc850517d5ab2bb502024a55645f1Timo Sirainen return 0;
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen if (maildir_mail_stat(_mail, &st) < 0)
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainen return -1;
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen
3d77cc0d502dc69ffe2afe318605964dd40b7b20Timo Sirainen *date_r = data->save_date = st.st_ctime;
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen return data->save_date;
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen}
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainenstatic int
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainenmaildir_mail_get_fname(struct maildir_mailbox *mbox, struct mail *mail,
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen const char **fname_r)
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen{
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainen enum maildir_uidlist_rec_flag flags;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen struct mail_index_view *view;
3d77cc0d502dc69ffe2afe318605964dd40b7b20Timo Sirainen uint32_t seq;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen bool exists;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen int ret;
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen ret = maildir_uidlist_lookup(mbox->uidlist, mail->uid, &flags, fname_r);
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen if (ret != 0)
10ff47d5d6146995e16da00d36eca7d162064a7bTimo Sirainen return ret;
10ff47d5d6146995e16da00d36eca7d162064a7bTimo Sirainen
10ff47d5d6146995e16da00d36eca7d162064a7bTimo Sirainen /* file exists in index file, but not in dovecot-uidlist anymore. */
10ff47d5d6146995e16da00d36eca7d162064a7bTimo Sirainen mail_set_expunged(mail);
10ff47d5d6146995e16da00d36eca7d162064a7bTimo Sirainen
10ff47d5d6146995e16da00d36eca7d162064a7bTimo Sirainen /* one reason this could happen is if we delayed opening
10ff47d5d6146995e16da00d36eca7d162064a7bTimo Sirainen dovecot-uidlist and we're trying to open a mail that got recently
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainen expunged. Let's test this theory first: */
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen (void)mail_index_refresh(mbox->ibox.index);
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainen view = mail_index_view_open(mbox->ibox.index);
8f32e59200da904613506f5649ffa4d9f5989cebTimo Sirainen exists = mail_index_lookup_seq(view, mail->uid, &seq);
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen mail_index_view_close(&view);
3d77cc0d502dc69ffe2afe318605964dd40b7b20Timo Sirainen
d66ef20c30fee728899ee168c75fcc5ff8fbdac1Timo Sirainen if (exists) {
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen /* the message still exists in index. this means there's some
d66ef20c30fee728899ee168c75fcc5ff8fbdac1Timo Sirainen kind of a desync, which doesn't get fixed if cur/ mtime is
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen the same as in index. fix this by forcing a resync. */
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen (void)maildir_storage_sync_force(mbox, mail->uid);
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen }
d66ef20c30fee728899ee168c75fcc5ff8fbdac1Timo Sirainen return 0;
6cc0546c058f3e6253c6f99727b28dd602712974Timo Sirainen}
6cc0546c058f3e6253c6f99727b28dd602712974Timo Sirainen
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainenstatic int maildir_get_pop3_state(struct index_mail *mail)
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen{
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainen const struct mail_cache_field *fields;
5238111c460098d9cc8cc22527026138a278b9a4Timo Sirainen unsigned int i, count, psize_idx, vsize_idx;
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainen enum mail_cache_decision_type dec, vsize_dec;
5238111c460098d9cc8cc22527026138a278b9a4Timo Sirainen enum mail_fetch_field allowed_pop3_fields;
3d77cc0d502dc69ffe2afe318605964dd40b7b20Timo Sirainen bool not_pop3_only = FALSE;
c9bf63e9094761767a63ac6b189bcf60bcffdc44Timo Sirainen
c9bf63e9094761767a63ac6b189bcf60bcffdc44Timo Sirainen if (mail->pop3_state_set)
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen return mail->pop3_state;
5238111c460098d9cc8cc22527026138a278b9a4Timo Sirainen
5238111c460098d9cc8cc22527026138a278b9a4Timo Sirainen /* if this mail itself has non-pop3 fields we know we're not
68a4946b12583b88fa802e52ebee45cd96056772Timo Sirainen pop3-only */
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen allowed_pop3_fields = MAIL_FETCH_FLAGS | MAIL_FETCH_STREAM_HEADER |
68a4946b12583b88fa802e52ebee45cd96056772Timo Sirainen MAIL_FETCH_STREAM_BODY | MAIL_FETCH_UIDL_FILE_NAME |
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen MAIL_FETCH_VIRTUAL_SIZE;
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen if (mail->wanted_headers != NULL ||
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen (mail->wanted_fields & ~allowed_pop3_fields) != 0)
de954ff15b495be13007a8aca2c09fd1d356a283Timo Sirainen not_pop3_only = TRUE;
de954ff15b495be13007a8aca2c09fd1d356a283Timo Sirainen
de954ff15b495be13007a8aca2c09fd1d356a283Timo Sirainen /* get vsize decisions */
de954ff15b495be13007a8aca2c09fd1d356a283Timo Sirainen psize_idx = mail->ibox->cache_fields[MAIL_CACHE_PHYSICAL_FULL_SIZE].idx;
de954ff15b495be13007a8aca2c09fd1d356a283Timo Sirainen vsize_idx = mail->ibox->cache_fields[MAIL_CACHE_VIRTUAL_FULL_SIZE].idx;
de954ff15b495be13007a8aca2c09fd1d356a283Timo Sirainen if (not_pop3_only) {
de954ff15b495be13007a8aca2c09fd1d356a283Timo Sirainen vsize_dec = mail_cache_field_get_decision(mail->ibox->cache,
de954ff15b495be13007a8aca2c09fd1d356a283Timo Sirainen vsize_idx);
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainen vsize_dec &= ~MAIL_CACHE_DECISION_FORCED;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen } else {
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainen /* also check if there are any non-[pv]size cached fields */
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen vsize_dec = MAIL_CACHE_DECISION_NO;
3d77cc0d502dc69ffe2afe318605964dd40b7b20Timo Sirainen fields = mail_cache_register_get_list(mail->ibox->cache,
d66ef20c30fee728899ee168c75fcc5ff8fbdac1Timo Sirainen pool_datastack_create(),
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen &count);
d66ef20c30fee728899ee168c75fcc5ff8fbdac1Timo Sirainen for (i = 0; i < count; i++) {
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen dec = fields[i].decision & ~MAIL_CACHE_DECISION_FORCED;
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen if (fields[i].idx == vsize_idx)
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen vsize_dec = dec;
d66ef20c30fee728899ee168c75fcc5ff8fbdac1Timo Sirainen else if (dec != MAIL_CACHE_DECISION_NO &&
8f32e59200da904613506f5649ffa4d9f5989cebTimo Sirainen fields[i].idx != psize_idx)
6cc0546c058f3e6253c6f99727b28dd602712974Timo Sirainen not_pop3_only = TRUE;
6cc0546c058f3e6253c6f99727b28dd602712974Timo Sirainen }
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen }
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
b92e979748a22925b0770d3004eaab043ed69574Timo Sirainen if (!not_pop3_only) {
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen /* either nothing is cached, or only vsize is cached. */
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen mail->pop3_state = 1;
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen } else if (vsize_dec != MAIL_CACHE_DECISION_YES &&
efe78d3ba24fc866af1c79b9223dc0809ba26cadStephan Bosch (mail->ibox->box.flags & MAILBOX_FLAG_POP3_SESSION) == 0) {
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen /* if virtual size isn't cached permanently,
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen POP3 isn't being used */
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen mail->pop3_state = -1;
35283613d4c04ce18836e9fc431582c87b3710a0Timo Sirainen } else {
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen /* possibly a mixed pop3/imap */
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen mail->pop3_state = 0;
9de176ef7f3d28ff486c2a8805110b84389e4f19Timo Sirainen }
9de176ef7f3d28ff486c2a8805110b84389e4f19Timo Sirainen mail->pop3_state_set = TRUE;
9de176ef7f3d28ff486c2a8805110b84389e4f19Timo Sirainen return mail->pop3_state;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen}
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainen
0ce5f96804e81cb0f857e7df32c0272f1eed9377Timo Sirainenstatic int maildir_quick_size_lookup(struct index_mail *mail, bool vsize,
0ce5f96804e81cb0f857e7df32c0272f1eed9377Timo Sirainen uoff_t *size_r)
0ce5f96804e81cb0f857e7df32c0272f1eed9377Timo Sirainen{
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen struct mail *_mail = &mail->mail.mail;
9de176ef7f3d28ff486c2a8805110b84389e4f19Timo Sirainen struct maildir_mailbox *mbox = (struct maildir_mailbox *)mail->ibox;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen enum maildir_uidlist_rec_ext_key key;
0ce5f96804e81cb0f857e7df32c0272f1eed9377Timo Sirainen const char *path, *fname, *value;
0ce5f96804e81cb0f857e7df32c0272f1eed9377Timo Sirainen uoff_t size;
0dbcf4026ff8471b4d6d2e14f7e52321396bf087Timo Sirainen char *p;
0dbcf4026ff8471b4d6d2e14f7e52321396bf087Timo Sirainen
0ce5f96804e81cb0f857e7df32c0272f1eed9377Timo Sirainen if (_mail->uid != 0) {
0ce5f96804e81cb0f857e7df32c0272f1eed9377Timo Sirainen if (maildir_mail_get_fname(mbox, _mail, &fname) <= 0)
6cc0546c058f3e6253c6f99727b28dd602712974Timo Sirainen return -1;
6cc0546c058f3e6253c6f99727b28dd602712974Timo Sirainen } else {
6cc0546c058f3e6253c6f99727b28dd602712974Timo Sirainen path = maildir_save_file_get_path(_mail->transaction,
d66ef20c30fee728899ee168c75fcc5ff8fbdac1Timo Sirainen _mail->seq);
6cc0546c058f3e6253c6f99727b28dd602712974Timo Sirainen fname = strrchr(path, '/');
8b2cf1c1bd8ddcea0525b62fd35ba76e136828a1Timo Sirainen fname = fname != NULL ? fname + 1 : path;
6cc0546c058f3e6253c6f99727b28dd602712974Timo Sirainen }
9de176ef7f3d28ff486c2a8805110b84389e4f19Timo Sirainen
6cc0546c058f3e6253c6f99727b28dd602712974Timo Sirainen /* size can be included in filename */
6cc0546c058f3e6253c6f99727b28dd602712974Timo Sirainen if (maildir_filename_get_size(fname,
0ce5f96804e81cb0f857e7df32c0272f1eed9377Timo Sirainen vsize ? MAILDIR_EXTRA_VIRTUAL_SIZE :
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen MAILDIR_EXTRA_FILE_SIZE,
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen size_r))
9de176ef7f3d28ff486c2a8805110b84389e4f19Timo Sirainen return 1;
9de176ef7f3d28ff486c2a8805110b84389e4f19Timo Sirainen
9de176ef7f3d28ff486c2a8805110b84389e4f19Timo Sirainen /* size can be included in uidlist entry */
9de176ef7f3d28ff486c2a8805110b84389e4f19Timo Sirainen if (_mail->uid != 0) {
9de176ef7f3d28ff486c2a8805110b84389e4f19Timo Sirainen key = vsize ? MAILDIR_UIDLIST_REC_EXT_VSIZE :
9de176ef7f3d28ff486c2a8805110b84389e4f19Timo Sirainen MAILDIR_UIDLIST_REC_EXT_PSIZE;
9de176ef7f3d28ff486c2a8805110b84389e4f19Timo Sirainen value = maildir_uidlist_lookup_ext(mbox->uidlist, _mail->uid,
9de176ef7f3d28ff486c2a8805110b84389e4f19Timo Sirainen key);
9de176ef7f3d28ff486c2a8805110b84389e4f19Timo Sirainen if (value != NULL) {
9de176ef7f3d28ff486c2a8805110b84389e4f19Timo Sirainen size = strtoull(value, &p, 10);
9de176ef7f3d28ff486c2a8805110b84389e4f19Timo Sirainen if (*p == '\0') {
9de176ef7f3d28ff486c2a8805110b84389e4f19Timo Sirainen *size_r = size;
b92e979748a22925b0770d3004eaab043ed69574Timo Sirainen return 1;
555ebb032f9b8f0cdb66f27ce7374734833e7cacTimo Sirainen }
555ebb032f9b8f0cdb66f27ce7374734833e7cacTimo Sirainen }
555ebb032f9b8f0cdb66f27ce7374734833e7cacTimo Sirainen }
555ebb032f9b8f0cdb66f27ce7374734833e7cacTimo Sirainen return 0;
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen}
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainenstatic void
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainenmaildir_handle_size_caching(struct index_mail *mail, bool quick_check,
efe78d3ba24fc866af1c79b9223dc0809ba26cadStephan Bosch bool vsize)
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen{
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen struct maildir_mailbox *mbox = (struct maildir_mailbox *)mail->ibox;
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen enum mail_fetch_field field;
4e8d6d03c2ff85448df79b181a2ea850fb5d4199Timo Sirainen uoff_t size;
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen int pop3_state;
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen field = vsize ? MAIL_FETCH_VIRTUAL_SIZE : MAIL_FETCH_PHYSICAL_SIZE;
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen if ((mail->data.dont_cache_fetch_fields & field) != 0)
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen return;
9de176ef7f3d28ff486c2a8805110b84389e4f19Timo Sirainen
9de176ef7f3d28ff486c2a8805110b84389e4f19Timo Sirainen if (quick_check && maildir_quick_size_lookup(mail, vsize, &size) > 0) {
9de176ef7f3d28ff486c2a8805110b84389e4f19Timo Sirainen /* already in filename / uidlist. don't add it anywhere,
9de176ef7f3d28ff486c2a8805110b84389e4f19Timo Sirainen including to the uidlist if it's already in filename.
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen do some extra checks here to catch potential cache bugs. */
9de176ef7f3d28ff486c2a8805110b84389e4f19Timo Sirainen if (vsize && mail->data.virtual_size != size) {
9de176ef7f3d28ff486c2a8805110b84389e4f19Timo Sirainen mail_cache_set_corrupted(mail->ibox->cache,
9de176ef7f3d28ff486c2a8805110b84389e4f19Timo Sirainen "Corrupted virtual size for uid=%u: "
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen "%"PRIuUOFF_T" != %"PRIuUOFF_T,
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen mail->mail.mail.uid,
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen mail->data.virtual_size, size);
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen mail->data.virtual_size = size;
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen } else if (!vsize && mail->data.physical_size != size) {
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen mail_cache_set_corrupted(mail->ibox->cache,
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen "Corrupted physical size for uid=%u: "
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen "%"PRIuUOFF_T" != %"PRIuUOFF_T,
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen mail->mail.mail.uid,
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen mail->data.physical_size, size);
3d77cc0d502dc69ffe2afe318605964dd40b7b20Timo Sirainen mail->data.physical_size = size;
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen }
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen mail->data.dont_cache_fetch_fields |= field;
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen return;
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen }
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen /* 1 = pop3-only, 0 = mixed, -1 = no pop3 */
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen pop3_state = maildir_get_pop3_state(mail);
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen if (pop3_state >= 0 && mail->mail.mail.uid != 0) {
98a73e104c7b9c3747053e63113451e24daf7f36Timo Sirainen /* if size is wanted permanently, store it to uidlist
9de176ef7f3d28ff486c2a8805110b84389e4f19Timo Sirainen so that in case cache file gets lost we can get it quickly */
9de176ef7f3d28ff486c2a8805110b84389e4f19Timo Sirainen mail->data.dont_cache_fetch_fields |= field;
9de176ef7f3d28ff486c2a8805110b84389e4f19Timo Sirainen size = vsize ? mail->data.virtual_size :
9de176ef7f3d28ff486c2a8805110b84389e4f19Timo Sirainen mail->data.physical_size;
9de176ef7f3d28ff486c2a8805110b84389e4f19Timo Sirainen maildir_uidlist_set_ext(mbox->uidlist, mail->mail.mail.uid,
9de176ef7f3d28ff486c2a8805110b84389e4f19Timo Sirainen vsize ? MAILDIR_UIDLIST_REC_EXT_VSIZE :
f988b93c2ef773987bcdcbfb4cca39b955e3a392Timo Sirainen MAILDIR_UIDLIST_REC_EXT_PSIZE,
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen dec2str(size));
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen }
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen}
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen
98a73e104c7b9c3747053e63113451e24daf7f36Timo Sirainenstatic int maildir_mail_get_virtual_size(struct mail *_mail, uoff_t *size_r)
98a73e104c7b9c3747053e63113451e24daf7f36Timo Sirainen{
98a73e104c7b9c3747053e63113451e24daf7f36Timo Sirainen struct index_mail *mail = (struct index_mail *)_mail;
98a73e104c7b9c3747053e63113451e24daf7f36Timo Sirainen struct index_mail_data *data = &mail->data;
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen struct message_size hdr_size, body_size;
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen struct istream *input;
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen uoff_t old_offset;
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen if (index_mail_get_cached_virtual_size(mail, size_r)) {
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen i_assert(mail->data.virtual_size != (uoff_t)-1);
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen maildir_handle_size_caching(mail, TRUE, TRUE);
378e6cb162b355d6f103526505bc00b9a78962e7Timo Sirainen return 0;
378e6cb162b355d6f103526505bc00b9a78962e7Timo Sirainen }
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainen if (maildir_quick_size_lookup(mail, TRUE, &data->virtual_size) < 0)
6adf683655750bcb809275cd65dc75fd12214198Timo Sirainen return -1;
6adf683655750bcb809275cd65dc75fd12214198Timo Sirainen if (data->virtual_size != (uoff_t)-1) {
378e6cb162b355d6f103526505bc00b9a78962e7Timo Sirainen data->dont_cache_fetch_fields |= MAIL_FETCH_VIRTUAL_SIZE;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen *size_r = data->virtual_size;
378e6cb162b355d6f103526505bc00b9a78962e7Timo Sirainen return 0;
6adf683655750bcb809275cd65dc75fd12214198Timo Sirainen }
378e6cb162b355d6f103526505bc00b9a78962e7Timo Sirainen
378e6cb162b355d6f103526505bc00b9a78962e7Timo Sirainen /* fallback to reading the file */
378e6cb162b355d6f103526505bc00b9a78962e7Timo Sirainen old_offset = data->stream == NULL ? 0 : data->stream->v_offset;
6adf683655750bcb809275cd65dc75fd12214198Timo Sirainen if (mail_get_stream(_mail, &hdr_size, &body_size, &input) < 0)
378e6cb162b355d6f103526505bc00b9a78962e7Timo Sirainen return -1;
6adf683655750bcb809275cd65dc75fd12214198Timo Sirainen i_stream_seek(data->stream, old_offset);
378e6cb162b355d6f103526505bc00b9a78962e7Timo Sirainen
378e6cb162b355d6f103526505bc00b9a78962e7Timo Sirainen maildir_handle_size_caching(mail, FALSE, TRUE);
378e6cb162b355d6f103526505bc00b9a78962e7Timo Sirainen *size_r = data->virtual_size;
378e6cb162b355d6f103526505bc00b9a78962e7Timo Sirainen return 0;
378e6cb162b355d6f103526505bc00b9a78962e7Timo Sirainen}
378e6cb162b355d6f103526505bc00b9a78962e7Timo Sirainen
6adf683655750bcb809275cd65dc75fd12214198Timo Sirainenstatic int maildir_mail_get_physical_size(struct mail *_mail, uoff_t *size_r)
378e6cb162b355d6f103526505bc00b9a78962e7Timo Sirainen{
378e6cb162b355d6f103526505bc00b9a78962e7Timo Sirainen struct index_mail *mail = (struct index_mail *)_mail;
378e6cb162b355d6f103526505bc00b9a78962e7Timo Sirainen struct maildir_mailbox *mbox = (struct maildir_mailbox *)mail->ibox;
378e6cb162b355d6f103526505bc00b9a78962e7Timo Sirainen struct index_mail_data *data = &mail->data;
378e6cb162b355d6f103526505bc00b9a78962e7Timo Sirainen struct stat st;
378e6cb162b355d6f103526505bc00b9a78962e7Timo Sirainen const char *path;
378e6cb162b355d6f103526505bc00b9a78962e7Timo Sirainen int ret;
378e6cb162b355d6f103526505bc00b9a78962e7Timo Sirainen
378e6cb162b355d6f103526505bc00b9a78962e7Timo Sirainen if (index_mail_get_physical_size(_mail, size_r) == 0) {
378e6cb162b355d6f103526505bc00b9a78962e7Timo Sirainen i_assert(mail->data.physical_size != (uoff_t)-1);
378e6cb162b355d6f103526505bc00b9a78962e7Timo Sirainen maildir_handle_size_caching(mail, TRUE, FALSE);
378e6cb162b355d6f103526505bc00b9a78962e7Timo Sirainen return 0;
378e6cb162b355d6f103526505bc00b9a78962e7Timo Sirainen }
378e6cb162b355d6f103526505bc00b9a78962e7Timo Sirainen
d66ef20c30fee728899ee168c75fcc5ff8fbdac1Timo Sirainen if (maildir_quick_size_lookup(mail, FALSE, &data->physical_size) < 0)
378e6cb162b355d6f103526505bc00b9a78962e7Timo Sirainen return -1;
6adf683655750bcb809275cd65dc75fd12214198Timo Sirainen if (data->physical_size != (uoff_t)-1) {
6adf683655750bcb809275cd65dc75fd12214198Timo Sirainen data->dont_cache_fetch_fields |= MAIL_FETCH_PHYSICAL_SIZE;
378e6cb162b355d6f103526505bc00b9a78962e7Timo Sirainen *size_r = data->physical_size;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen return 0;
ecc81625167ed96c04c02aa190a1ea5baa65b474Timo Sirainen }
b90fb7f78aca271243c26074ddd6587cce112a1eTimo Sirainen
b90fb7f78aca271243c26074ddd6587cce112a1eTimo Sirainen if (_mail->uid != 0) {
378e6cb162b355d6f103526505bc00b9a78962e7Timo Sirainen ret = maildir_file_do(mbox, _mail->uid, do_stat, &st);
378e6cb162b355d6f103526505bc00b9a78962e7Timo Sirainen if (ret <= 0) {
b90fb7f78aca271243c26074ddd6587cce112a1eTimo Sirainen if (ret == 0)
378e6cb162b355d6f103526505bc00b9a78962e7Timo Sirainen mail_set_expunged(_mail);
b90fb7f78aca271243c26074ddd6587cce112a1eTimo Sirainen return -1;
378e6cb162b355d6f103526505bc00b9a78962e7Timo Sirainen }
378e6cb162b355d6f103526505bc00b9a78962e7Timo Sirainen } else {
378e6cb162b355d6f103526505bc00b9a78962e7Timo Sirainen /* saved mail which hasn't been committed yet */
b90fb7f78aca271243c26074ddd6587cce112a1eTimo Sirainen path = maildir_save_file_get_path(_mail->transaction,
b90fb7f78aca271243c26074ddd6587cce112a1eTimo Sirainen _mail->seq);
378e6cb162b355d6f103526505bc00b9a78962e7Timo Sirainen if (stat(path, &st) < 0) {
b90fb7f78aca271243c26074ddd6587cce112a1eTimo Sirainen mail_storage_set_critical(_mail->box->storage,
b90fb7f78aca271243c26074ddd6587cce112a1eTimo Sirainen "stat(%s) failed: %m", path);
b90fb7f78aca271243c26074ddd6587cce112a1eTimo Sirainen return -1;
b90fb7f78aca271243c26074ddd6587cce112a1eTimo Sirainen }
378e6cb162b355d6f103526505bc00b9a78962e7Timo Sirainen }
378e6cb162b355d6f103526505bc00b9a78962e7Timo Sirainen
378e6cb162b355d6f103526505bc00b9a78962e7Timo Sirainen data->physical_size = st.st_size;
378e6cb162b355d6f103526505bc00b9a78962e7Timo Sirainen maildir_handle_size_caching(mail, FALSE, FALSE);
b90fb7f78aca271243c26074ddd6587cce112a1eTimo Sirainen *size_r = st.st_size;
b90fb7f78aca271243c26074ddd6587cce112a1eTimo Sirainen return 0;
b90fb7f78aca271243c26074ddd6587cce112a1eTimo Sirainen}
b90fb7f78aca271243c26074ddd6587cce112a1eTimo Sirainen
8cdb3234fe3c77e477c7a0e6934678f58fc54d4dTimo Sirainenstatic int
8cdb3234fe3c77e477c7a0e6934678f58fc54d4dTimo Sirainenmaildir_mail_get_special(struct mail *_mail, enum mail_fetch_field field,
8cdb3234fe3c77e477c7a0e6934678f58fc54d4dTimo Sirainen const char **value_r)
8cdb3234fe3c77e477c7a0e6934678f58fc54d4dTimo Sirainen{
8cdb3234fe3c77e477c7a0e6934678f58fc54d4dTimo Sirainen struct index_mail *mail = (struct index_mail *)_mail;
3d77cc0d502dc69ffe2afe318605964dd40b7b20Timo Sirainen struct maildir_mailbox *mbox = (struct maildir_mailbox *)mail->ibox;
d66ef20c30fee728899ee168c75fcc5ff8fbdac1Timo Sirainen const char *path, *fname, *end, *uidl;
8cdb3234fe3c77e477c7a0e6934678f58fc54d4dTimo Sirainen
d66ef20c30fee728899ee168c75fcc5ff8fbdac1Timo Sirainen switch (field) {
8cdb3234fe3c77e477c7a0e6934678f58fc54d4dTimo Sirainen case MAIL_FETCH_UIDL_FILE_NAME:
8cdb3234fe3c77e477c7a0e6934678f58fc54d4dTimo Sirainen case MAIL_FETCH_GUID:
8cdb3234fe3c77e477c7a0e6934678f58fc54d4dTimo Sirainen if (_mail->uid != 0) {
8cdb3234fe3c77e477c7a0e6934678f58fc54d4dTimo Sirainen if (maildir_mail_get_fname(mbox, _mail, &fname) <= 0)
8cdb3234fe3c77e477c7a0e6934678f58fc54d4dTimo Sirainen return -1;
d66ef20c30fee728899ee168c75fcc5ff8fbdac1Timo Sirainen } else {
8cdb3234fe3c77e477c7a0e6934678f58fc54d4dTimo Sirainen path = maildir_save_file_get_path(_mail->transaction,
8cdb3234fe3c77e477c7a0e6934678f58fc54d4dTimo Sirainen _mail->seq);
8cdb3234fe3c77e477c7a0e6934678f58fc54d4dTimo Sirainen fname = strrchr(path, '/');
8cdb3234fe3c77e477c7a0e6934678f58fc54d4dTimo Sirainen fname = fname != NULL ? fname + 1 : path;
378e6cb162b355d6f103526505bc00b9a78962e7Timo Sirainen }
378e6cb162b355d6f103526505bc00b9a78962e7Timo Sirainen end = strchr(fname, MAILDIR_INFO_SEP);
8ab3d88c56dff2f567193f80cc29821a64e576d1Timo Sirainen *value_r = end == NULL ? fname : t_strdup_until(fname, end);
8ab3d88c56dff2f567193f80cc29821a64e576d1Timo Sirainen return 0;
8ab3d88c56dff2f567193f80cc29821a64e576d1Timo Sirainen case MAIL_FETCH_UIDL_BACKEND:
8ab3d88c56dff2f567193f80cc29821a64e576d1Timo Sirainen uidl = maildir_uidlist_lookup_ext(mbox->uidlist, _mail->uid,
8ab3d88c56dff2f567193f80cc29821a64e576d1Timo Sirainen MAILDIR_UIDLIST_REC_EXT_POP3_UIDL);
6adf683655750bcb809275cd65dc75fd12214198Timo Sirainen if (uidl == NULL) {
8ab3d88c56dff2f567193f80cc29821a64e576d1Timo Sirainen /* use the default */
378e6cb162b355d6f103526505bc00b9a78962e7Timo Sirainen *value_r = "";
378e6cb162b355d6f103526505bc00b9a78962e7Timo Sirainen } else if (*uidl == '\0') {
378e6cb162b355d6f103526505bc00b9a78962e7Timo Sirainen /* special optimization case: use the base file name */
378e6cb162b355d6f103526505bc00b9a78962e7Timo Sirainen return maildir_mail_get_special(_mail,
8ab3d88c56dff2f567193f80cc29821a64e576d1Timo Sirainen MAIL_FETCH_UIDL_FILE_NAME, value_r);
6adf683655750bcb809275cd65dc75fd12214198Timo Sirainen } else {
8ab3d88c56dff2f567193f80cc29821a64e576d1Timo Sirainen *value_r = uidl;
6adf683655750bcb809275cd65dc75fd12214198Timo Sirainen }
378e6cb162b355d6f103526505bc00b9a78962e7Timo Sirainen return 0;
378e6cb162b355d6f103526505bc00b9a78962e7Timo Sirainen default:
378e6cb162b355d6f103526505bc00b9a78962e7Timo Sirainen return index_mail_get_special(_mail, field, value_r);
378e6cb162b355d6f103526505bc00b9a78962e7Timo Sirainen }
8ab3d88c56dff2f567193f80cc29821a64e576d1Timo Sirainen}
71da447014454c84828d9dface77219875554d7dTimo Sirainen
71da447014454c84828d9dface77219875554d7dTimo Sirainenstatic int maildir_mail_get_stream(struct mail *_mail,
71da447014454c84828d9dface77219875554d7dTimo Sirainen struct message_size *hdr_size,
71da447014454c84828d9dface77219875554d7dTimo Sirainen struct message_size *body_size,
71da447014454c84828d9dface77219875554d7dTimo Sirainen struct istream **stream_r)
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen{
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen struct index_mail *mail = (struct index_mail *)_mail;
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen struct maildir_mailbox *mbox = (struct maildir_mailbox *)mail->ibox;
e2ce8d4a6ac5d82a906178148453e7613fab9ba0Timo Sirainen struct index_mail_data *data = &mail->data;
e2ce8d4a6ac5d82a906178148453e7613fab9ba0Timo Sirainen bool deleted;
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen if (data->stream == NULL) {
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen data->stream = maildir_open_mail(mbox, _mail, &deleted);
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen if (data->stream == NULL) {
e2ce8d4a6ac5d82a906178148453e7613fab9ba0Timo Sirainen if (deleted)
e2ce8d4a6ac5d82a906178148453e7613fab9ba0Timo Sirainen mail_set_expunged(_mail);
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen return -1;
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen }
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen }
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen return index_mail_init_stream(mail, hdr_size, body_size, stream_r);
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen}
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainenstatic void maildir_mail_set_cache_corrupted(struct mail *_mail,
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen enum mail_fetch_field field)
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen{
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen struct index_mail *mail = (struct index_mail *)_mail;
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen struct maildir_mailbox *mbox = (struct maildir_mailbox *)mail->ibox;
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen enum maildir_uidlist_rec_flag flags;
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen const char *fname;
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen uoff_t size;
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen int ret;
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen if (field == MAIL_FETCH_VIRTUAL_SIZE) {
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen /* make sure it gets removed from uidlist.
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen if it's in file name, we can't really do more than log it. */
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen ret = maildir_uidlist_lookup(mbox->uidlist, _mail->uid,
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen &flags, &fname);
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen if (ret <= 0)
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen return;
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen if (maildir_filename_get_size(fname, MAILDIR_EXTRA_VIRTUAL_SIZE,
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen &size)) {
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen const char *subdir =
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen (flags & MAILDIR_UIDLIST_REC_FLAG_NEW_DIR) != 0 ?
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen "new" : "cur";
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen mail_storage_set_critical(_mail->box->storage,
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen "Maildir filename has wrong W value: %s/%s/%s",
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen mbox->ibox.box.path, subdir, fname);
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen } else if (maildir_uidlist_lookup_ext(mbox->uidlist, _mail->uid,
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen MAILDIR_UIDLIST_REC_EXT_VSIZE) != NULL) {
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen maildir_uidlist_set_ext(mbox->uidlist, _mail->uid,
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen MAILDIR_UIDLIST_REC_EXT_VSIZE,
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen NULL);
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen }
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen }
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen index_mail_set_cache_corrupted(_mail, field);
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen}
2d2ebe91d56e9a158de000c9d0026f65600fbcfaTimo Sirainen
2d2ebe91d56e9a158de000c9d0026f65600fbcfaTimo Sirainenstruct mail_vfuncs maildir_mail_vfuncs = {
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen index_mail_close,
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen index_mail_free,
d691782ae9eb4f6ab06bc42f1617e889e7c18a3bTimo Sirainen index_mail_set_seq,
d691782ae9eb4f6ab06bc42f1617e889e7c18a3bTimo Sirainen index_mail_set_uid,
d691782ae9eb4f6ab06bc42f1617e889e7c18a3bTimo Sirainen index_mail_set_uid_cache_updates,
d691782ae9eb4f6ab06bc42f1617e889e7c18a3bTimo Sirainen
d691782ae9eb4f6ab06bc42f1617e889e7c18a3bTimo Sirainen index_mail_get_flags,
d691782ae9eb4f6ab06bc42f1617e889e7c18a3bTimo Sirainen index_mail_get_keywords,
d691782ae9eb4f6ab06bc42f1617e889e7c18a3bTimo Sirainen index_mail_get_keyword_indexes,
d691782ae9eb4f6ab06bc42f1617e889e7c18a3bTimo Sirainen index_mail_get_modseq,
d691782ae9eb4f6ab06bc42f1617e889e7c18a3bTimo Sirainen index_mail_get_parts,
d691782ae9eb4f6ab06bc42f1617e889e7c18a3bTimo Sirainen index_mail_get_date,
d691782ae9eb4f6ab06bc42f1617e889e7c18a3bTimo Sirainen maildir_mail_get_received_date,
d691782ae9eb4f6ab06bc42f1617e889e7c18a3bTimo Sirainen maildir_mail_get_save_date,
d691782ae9eb4f6ab06bc42f1617e889e7c18a3bTimo Sirainen maildir_mail_get_virtual_size,
d691782ae9eb4f6ab06bc42f1617e889e7c18a3bTimo Sirainen maildir_mail_get_physical_size,
d691782ae9eb4f6ab06bc42f1617e889e7c18a3bTimo Sirainen index_mail_get_first_header,
d691782ae9eb4f6ab06bc42f1617e889e7c18a3bTimo Sirainen index_mail_get_headers,
d691782ae9eb4f6ab06bc42f1617e889e7c18a3bTimo Sirainen index_mail_get_header_stream,
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen maildir_mail_get_stream,
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen maildir_mail_get_special,
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen index_mail_update_flags,
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen index_mail_update_keywords,
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen index_mail_update_modseq,
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen index_mail_update_uid,
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen index_mail_expunge,
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen maildir_mail_set_cache_corrupted,
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen index_mail_get_index_mail
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen};
e3678f7bfba87b5aa1446a1a7b9928272b4f72a3Timo Sirainen