maildir-mail.c revision 236bedf76e31651ea9fca63fbdc25be673819526
2454dfa32c93c20a8522c6ed42fe057baaac9f9aStephan Bosch/* Copyright (c) 2003-2008 Dovecot authors, see the included COPYING file */
5ce2084ada06ade9f44fc2914c34658e9a842dc1Timo Sirainen
08d6658a4e2ec8104cd1307f6baa75fdb07a24f8Mark Washenberger#include "lib.h"
16f816d3f3c32ae3351834253f52ddd0212bcbf3Timo Sirainen#include "istream.h"
6789ed17e7ca4021713507baf0dcf6979bb42e0cTimo Sirainen#include "index-mail.h"
5ce2084ada06ade9f44fc2914c34658e9a842dc1Timo Sirainen#include "maildir-storage.h"
5ce2084ada06ade9f44fc2914c34658e9a842dc1Timo Sirainen#include "maildir-filename.h"
5ce2084ada06ade9f44fc2914c34658e9a842dc1Timo Sirainen#include "maildir-uidlist.h"
5ce2084ada06ade9f44fc2914c34658e9a842dc1Timo Sirainen#include "maildir-sync.h"
5ce2084ada06ade9f44fc2914c34658e9a842dc1Timo Sirainen
636f017be100bce67d66fd3ae1544a47681efd33Timo Sirainen#include <stdlib.h>
923eb3dde28e4d8841c14fd6b4a69635b7070c3eTimo Sirainen#include <fcntl.h>
08d6658a4e2ec8104cd1307f6baa75fdb07a24f8Mark Washenberger#include <unistd.h>
06ff2a72c39cb34cc6425f17fc82c5e93fef2018Timo Sirainen#include <sys/stat.h>
5ce2084ada06ade9f44fc2914c34658e9a842dc1Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstatic int
5ce2084ada06ade9f44fc2914c34658e9a842dc1Timo Sirainendo_open(struct maildir_mailbox *mbox, const char *path, int *fd)
de76b960297406115cf6bae473f004c08174b16aTimo Sirainen{
5ce2084ada06ade9f44fc2914c34658e9a842dc1Timo Sirainen *fd = open(path, O_RDONLY);
3ddbbe03fe74b3ee7b1dff4e08ec706d7880d052Timo Sirainen if (*fd != -1)
c519de264df14a9d525e2604671c332590ce54e3Timo Sirainen return 1;
61530b48694398df42744204e35535dbe3f745c4Timo Sirainen if (errno == ENOENT)
61530b48694398df42744204e35535dbe3f745c4Timo Sirainen return 0;
3ddbbe03fe74b3ee7b1dff4e08ec706d7880d052Timo Sirainen
4ee00532a265bdfb38539d811fcd12d51210ac35Timo Sirainen mail_storage_set_critical(&mbox->storage->storage,
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen "open(%s) failed: %m", path);
c9dea5c23355dea35c6fa423de69f6507852efe4Timo Sirainen return -1;
c9dea5c23355dea35c6fa423de69f6507852efe4Timo Sirainen}
6789ed17e7ca4021713507baf0dcf6979bb42e0cTimo Sirainen
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainenstatic int
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainendo_stat(struct maildir_mailbox *mbox, const char *path, struct stat *st)
6789ed17e7ca4021713507baf0dcf6979bb42e0cTimo Sirainen{
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen if (stat(path, st) == 0)
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen return 1;
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen if (errno == ENOENT)
2b3b0df76184799317584b596af8df5afec3ebddTimo Sirainen return 0;
c9dea5c23355dea35c6fa423de69f6507852efe4Timo Sirainen
6789ed17e7ca4021713507baf0dcf6979bb42e0cTimo Sirainen mail_storage_set_critical(&mbox->storage->storage,
6789ed17e7ca4021713507baf0dcf6979bb42e0cTimo Sirainen "stat(%s) failed: %m", path);
67c25cb4af273aff7384d5028d459cc9afdf8712Timo Sirainen return -1;
67c25cb4af273aff7384d5028d459cc9afdf8712Timo Sirainen}
67c25cb4af273aff7384d5028d459cc9afdf8712Timo Sirainen
67c25cb4af273aff7384d5028d459cc9afdf8712Timo Sirainenstatic struct istream *
67c25cb4af273aff7384d5028d459cc9afdf8712Timo Sirainenmaildir_open_mail(struct maildir_mailbox *mbox, struct mail *mail,
67c25cb4af273aff7384d5028d459cc9afdf8712Timo Sirainen bool *deleted_r)
67c25cb4af273aff7384d5028d459cc9afdf8712Timo Sirainen{
67c25cb4af273aff7384d5028d459cc9afdf8712Timo Sirainen const char *path;
67c25cb4af273aff7384d5028d459cc9afdf8712Timo Sirainen int fd = -1;
67c25cb4af273aff7384d5028d459cc9afdf8712Timo Sirainen
fde0b1793a2842da00eaa105d5e13fec465f0443Timo Sirainen *deleted_r = FALSE;
fde0b1793a2842da00eaa105d5e13fec465f0443Timo Sirainen
5ce2084ada06ade9f44fc2914c34658e9a842dc1Timo Sirainen if (mail->uid != 0) {
d244c6cadd5f077f5d0f1e00c3652d0108a2d908Timo Sirainen if (maildir_file_do(mbox, mail->uid, do_open, &fd) < 0)
5ce2084ada06ade9f44fc2914c34658e9a842dc1Timo Sirainen return NULL;
5ce2084ada06ade9f44fc2914c34658e9a842dc1Timo Sirainen } else {
67c25cb4af273aff7384d5028d459cc9afdf8712Timo Sirainen path = maildir_save_file_get_path(mail->transaction, mail->seq);
67c25cb4af273aff7384d5028d459cc9afdf8712Timo Sirainen if (do_open(mbox, path, &fd) <= 0)
67c25cb4af273aff7384d5028d459cc9afdf8712Timo Sirainen return NULL;
67c25cb4af273aff7384d5028d459cc9afdf8712Timo Sirainen }
67c25cb4af273aff7384d5028d459cc9afdf8712Timo Sirainen
d6c5ceea8521b92d10e51a59da00c792f6140b1dTimo Sirainen if (fd == -1) {
5ce2084ada06ade9f44fc2914c34658e9a842dc1Timo Sirainen *deleted_r = TRUE;
fde0b1793a2842da00eaa105d5e13fec465f0443Timo Sirainen return NULL;
d244c6cadd5f077f5d0f1e00c3652d0108a2d908Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
d6c5ceea8521b92d10e51a59da00c792f6140b1dTimo Sirainen return i_stream_create_fd(fd, MAIL_READ_BLOCK_SIZE, TRUE);
d6c5ceea8521b92d10e51a59da00c792f6140b1dTimo Sirainen}
d244c6cadd5f077f5d0f1e00c3652d0108a2d908Timo Sirainen
fde0b1793a2842da00eaa105d5e13fec465f0443Timo Sirainenstatic int maildir_mail_stat(struct mail *mail, struct stat *st)
fde0b1793a2842da00eaa105d5e13fec465f0443Timo Sirainen{
baf1148108b7d9739626b47cc57298c36929586aTimo Sirainen struct maildir_mailbox *mbox = (struct maildir_mailbox *)mail->box;
d6c5ceea8521b92d10e51a59da00c792f6140b1dTimo Sirainen struct index_mail_data *data = &((struct index_mail *)mail)->data;
d6c5ceea8521b92d10e51a59da00c792f6140b1dTimo Sirainen const char *path;
baf1148108b7d9739626b47cc57298c36929586aTimo Sirainen int fd, ret;
baf1148108b7d9739626b47cc57298c36929586aTimo Sirainen
e82e363e7a6917f470412d629db6c5b1f5891a35Timo Sirainen if (data->access_part != 0 && data->stream == NULL) {
e82e363e7a6917f470412d629db6c5b1f5891a35Timo Sirainen /* we're going to open the mail anyway */
e82e363e7a6917f470412d629db6c5b1f5891a35Timo Sirainen struct istream *input;
e82e363e7a6917f470412d629db6c5b1f5891a35Timo Sirainen
e82e363e7a6917f470412d629db6c5b1f5891a35Timo Sirainen (void)mail_get_stream(mail, NULL, NULL, &input);
d6c5ceea8521b92d10e51a59da00c792f6140b1dTimo Sirainen }
d6c5ceea8521b92d10e51a59da00c792f6140b1dTimo Sirainen
d6c5ceea8521b92d10e51a59da00c792f6140b1dTimo Sirainen if (data->stream != NULL) {
d6c5ceea8521b92d10e51a59da00c792f6140b1dTimo Sirainen fd = i_stream_get_fd(data->stream);
d6c5ceea8521b92d10e51a59da00c792f6140b1dTimo Sirainen i_assert(fd != -1);
d6c5ceea8521b92d10e51a59da00c792f6140b1dTimo Sirainen
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen if (fstat(fd, st) < 0) {
efe78d3ba24fc866af1c79b9223dc0809ba26cadStephan Bosch mail_storage_set_critical(&mbox->storage->storage,
d6c5ceea8521b92d10e51a59da00c792f6140b1dTimo Sirainen "fstat(maildir) failed: %m");
e82e363e7a6917f470412d629db6c5b1f5891a35Timo Sirainen return -1;
e82e363e7a6917f470412d629db6c5b1f5891a35Timo Sirainen }
d6c5ceea8521b92d10e51a59da00c792f6140b1dTimo Sirainen } else if (mail->uid != 0) {
d6c5ceea8521b92d10e51a59da00c792f6140b1dTimo Sirainen ret = maildir_file_do(mbox, mail->uid, do_stat, st);
d6c5ceea8521b92d10e51a59da00c792f6140b1dTimo Sirainen if (ret <= 0) {
d6c5ceea8521b92d10e51a59da00c792f6140b1dTimo Sirainen if (ret == 0)
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen mail_set_expunged(mail);
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen return -1;
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen }
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen } else {
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen path = maildir_save_file_get_path(mail->transaction, mail->seq);
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen if (stat(path, st) < 0) {
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen mail_storage_set_critical(mail->box->storage,
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen "stat(%s) failed: %m", path);
efe78d3ba24fc866af1c79b9223dc0809ba26cadStephan Bosch return -1;
cddfd1355db6b60c71d7ee3c0b4f23b3efcc9ad1Timo Sirainen }
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen }
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen return 0;
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen}
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainenstatic int maildir_mail_get_received_date(struct mail *_mail, time_t *date_r)
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen{
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen struct index_mail *mail = (struct index_mail *)_mail;
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen struct index_mail_data *data = &mail->data;
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen struct stat st;
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen if (index_mail_get_received_date(_mail, date_r) == 0)
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen return 0;
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen if (maildir_mail_stat(_mail, &st) < 0)
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen return -1;
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen *date_r = data->received_date = st.st_mtime;
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen return 0;
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen}
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainenstatic int maildir_mail_get_save_date(struct mail *_mail, time_t *date_r)
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen{
923eb3dde28e4d8841c14fd6b4a69635b7070c3eTimo Sirainen struct index_mail *mail = (struct index_mail *)_mail;
cddfd1355db6b60c71d7ee3c0b4f23b3efcc9ad1Timo Sirainen struct index_mail_data *data = &mail->data;
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen struct stat st;
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen if (index_mail_get_save_date(_mail, date_r) == 0)
e82e363e7a6917f470412d629db6c5b1f5891a35Timo Sirainen return 0;
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen
e82e363e7a6917f470412d629db6c5b1f5891a35Timo Sirainen if (maildir_mail_stat(_mail, &st) < 0)
cddfd1355db6b60c71d7ee3c0b4f23b3efcc9ad1Timo Sirainen return -1;
e82e363e7a6917f470412d629db6c5b1f5891a35Timo Sirainen
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen *date_r = data->save_date = st.st_ctime;
e82e363e7a6917f470412d629db6c5b1f5891a35Timo Sirainen return data->save_date;
e82e363e7a6917f470412d629db6c5b1f5891a35Timo Sirainen}
e82e363e7a6917f470412d629db6c5b1f5891a35Timo Sirainen
8039af9679af6fb56116b353fe44f7dd4c08f031Timo Sirainenstatic bool
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainenmaildir_mail_get_fname(struct maildir_mailbox *mbox, struct mail *mail,
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen const char **fname_r)
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen{
2cfe9983ce7a6280636ee12beccc2e865111967bTimo Sirainen enum maildir_uidlist_rec_flag flags;
d6c5ceea8521b92d10e51a59da00c792f6140b1dTimo Sirainen struct mail_index_view *view;
d6c5ceea8521b92d10e51a59da00c792f6140b1dTimo Sirainen uint32_t seq;
d6c5ceea8521b92d10e51a59da00c792f6140b1dTimo Sirainen bool exists;
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen *fname_r = maildir_uidlist_lookup(mbox->uidlist, mail->uid, &flags);
88ea893b45d3ed8d68000921db9156c03cbe1b00Timo Sirainen if (*fname_r != NULL)
88ea893b45d3ed8d68000921db9156c03cbe1b00Timo Sirainen return TRUE;
88ea893b45d3ed8d68000921db9156c03cbe1b00Timo Sirainen
d10a370b2614712d9cb6a1dd8625f62a071b6377Timo Sirainen /* file exists in index file, but not in dovecot-uidlist anymore. */
d10a370b2614712d9cb6a1dd8625f62a071b6377Timo Sirainen mail_set_expunged(mail);
88ea893b45d3ed8d68000921db9156c03cbe1b00Timo Sirainen
88ea893b45d3ed8d68000921db9156c03cbe1b00Timo Sirainen /* one reason this could happen is if we delayed opening
88ea893b45d3ed8d68000921db9156c03cbe1b00Timo Sirainen dovecot-uidlist and we're trying to open a mail that got recently
88ea893b45d3ed8d68000921db9156c03cbe1b00Timo Sirainen expunged. Let's test this theory first: */
88ea893b45d3ed8d68000921db9156c03cbe1b00Timo Sirainen (void)mail_index_refresh(mbox->ibox.index);
e20e638805c4bd54e039891a3e92760b1dfa189aTimo Sirainen view = mail_index_view_open(mbox->ibox.index);
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen exists = mail_index_lookup_seq(view, mail->uid, &seq);
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen mail_index_view_close(&view);
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen if (exists) {
d6c5ceea8521b92d10e51a59da00c792f6140b1dTimo Sirainen /* the message still exists in index. this means there's some
e20e638805c4bd54e039891a3e92760b1dfa189aTimo Sirainen kind of a desync, which doesn't get fixed if cur/ mtime is
e20e638805c4bd54e039891a3e92760b1dfa189aTimo Sirainen the same as in index. fix this by forcing a resync. */
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen (void)maildir_storage_sync_force(mbox, mail->uid);
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return FALSE;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
efe78d3ba24fc866af1c79b9223dc0809ba26cadStephan Bosch
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainenstatic int maildir_get_pop3_state(struct index_mail *mail)
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen{
d6c5ceea8521b92d10e51a59da00c792f6140b1dTimo Sirainen const struct mail_cache_field *fields;
d6c5ceea8521b92d10e51a59da00c792f6140b1dTimo Sirainen unsigned int i, count, psize_idx, vsize_idx;
e82e363e7a6917f470412d629db6c5b1f5891a35Timo Sirainen enum mail_cache_decision_type dec, vsize_dec;
e82e363e7a6917f470412d629db6c5b1f5891a35Timo Sirainen enum mail_fetch_field allowed_pop3_fields;
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen bool not_pop3_only = FALSE;
d6c5ceea8521b92d10e51a59da00c792f6140b1dTimo Sirainen
d6c5ceea8521b92d10e51a59da00c792f6140b1dTimo Sirainen if (mail->pop3_state_set)
88ea893b45d3ed8d68000921db9156c03cbe1b00Timo Sirainen return mail->pop3_state;
d6c5ceea8521b92d10e51a59da00c792f6140b1dTimo Sirainen
d6c5ceea8521b92d10e51a59da00c792f6140b1dTimo Sirainen /* if this mail itself has non-pop3 fields we know we're not
d6c5ceea8521b92d10e51a59da00c792f6140b1dTimo Sirainen pop3-only */
88ea893b45d3ed8d68000921db9156c03cbe1b00Timo Sirainen allowed_pop3_fields = MAIL_FETCH_FLAGS | MAIL_FETCH_STREAM_HEADER |
5ce2084ada06ade9f44fc2914c34658e9a842dc1Timo Sirainen MAIL_FETCH_STREAM_BODY | MAIL_FETCH_UIDL_FILE_NAME |
5ce2084ada06ade9f44fc2914c34658e9a842dc1Timo Sirainen MAIL_FETCH_VIRTUAL_SIZE;
923eb3dde28e4d8841c14fd6b4a69635b7070c3eTimo Sirainen
e82e363e7a6917f470412d629db6c5b1f5891a35Timo Sirainen if (mail->wanted_headers != NULL ||
e82e363e7a6917f470412d629db6c5b1f5891a35Timo Sirainen (mail->wanted_fields & ~allowed_pop3_fields) != 0)
eef4ba0cc3e78f8c26804c1c9251a76580a41f0cTimo Sirainen not_pop3_only = TRUE;
4145aa5025b57ec64418e503c2a5a6bf5a02aec5Timo Sirainen
923eb3dde28e4d8841c14fd6b4a69635b7070c3eTimo Sirainen /* get vsize decisions */
905951e448e0d0f0778f43ce7673d0cac60b9b61Timo Sirainen psize_idx = mail->ibox->cache_fields[MAIL_CACHE_PHYSICAL_FULL_SIZE].idx;
eef4ba0cc3e78f8c26804c1c9251a76580a41f0cTimo Sirainen vsize_idx = mail->ibox->cache_fields[MAIL_CACHE_VIRTUAL_FULL_SIZE].idx;
923eb3dde28e4d8841c14fd6b4a69635b7070c3eTimo Sirainen if (not_pop3_only) {
923eb3dde28e4d8841c14fd6b4a69635b7070c3eTimo Sirainen vsize_dec = mail_cache_field_get_decision(mail->ibox->cache,
923eb3dde28e4d8841c14fd6b4a69635b7070c3eTimo Sirainen vsize_idx);
e82e363e7a6917f470412d629db6c5b1f5891a35Timo Sirainen vsize_dec &= ~MAIL_CACHE_DECISION_FORCED;
e82e363e7a6917f470412d629db6c5b1f5891a35Timo Sirainen } else {
e82e363e7a6917f470412d629db6c5b1f5891a35Timo Sirainen /* also check if there are any non-[pv]size cached fields */
923eb3dde28e4d8841c14fd6b4a69635b7070c3eTimo Sirainen vsize_dec = MAIL_CACHE_DECISION_NO;
923eb3dde28e4d8841c14fd6b4a69635b7070c3eTimo Sirainen fields = mail_cache_register_get_list(mail->ibox->cache,
e82e363e7a6917f470412d629db6c5b1f5891a35Timo Sirainen pool_datastack_create(),
eef4ba0cc3e78f8c26804c1c9251a76580a41f0cTimo Sirainen &count);
905951e448e0d0f0778f43ce7673d0cac60b9b61Timo Sirainen for (i = 0; i < count; i++) {
923eb3dde28e4d8841c14fd6b4a69635b7070c3eTimo Sirainen dec = fields[i].decision & ~MAIL_CACHE_DECISION_FORCED;
905951e448e0d0f0778f43ce7673d0cac60b9b61Timo Sirainen if (fields[i].idx == vsize_idx)
923eb3dde28e4d8841c14fd6b4a69635b7070c3eTimo Sirainen vsize_dec = dec;
923eb3dde28e4d8841c14fd6b4a69635b7070c3eTimo Sirainen else if (dec != MAIL_CACHE_DECISION_NO &&
923eb3dde28e4d8841c14fd6b4a69635b7070c3eTimo Sirainen fields[i].idx != psize_idx)
923eb3dde28e4d8841c14fd6b4a69635b7070c3eTimo Sirainen not_pop3_only = TRUE;
923eb3dde28e4d8841c14fd6b4a69635b7070c3eTimo Sirainen }
4145aa5025b57ec64418e503c2a5a6bf5a02aec5Timo Sirainen }
eef4ba0cc3e78f8c26804c1c9251a76580a41f0cTimo Sirainen
923eb3dde28e4d8841c14fd6b4a69635b7070c3eTimo Sirainen if (!not_pop3_only) {
923eb3dde28e4d8841c14fd6b4a69635b7070c3eTimo Sirainen /* either nothing is cached, or only vsize is cached. */
e82e363e7a6917f470412d629db6c5b1f5891a35Timo Sirainen mail->pop3_state = 1;
e82e363e7a6917f470412d629db6c5b1f5891a35Timo Sirainen } else if (vsize_dec != MAIL_CACHE_DECISION_YES &&
e82e363e7a6917f470412d629db6c5b1f5891a35Timo Sirainen (mail->ibox->open_flags & MAILBOX_OPEN_POP3_SESSION) == 0) {
e82e363e7a6917f470412d629db6c5b1f5891a35Timo Sirainen /* if virtual size isn't cached permanently,
e82e363e7a6917f470412d629db6c5b1f5891a35Timo Sirainen POP3 isn't being used */
923eb3dde28e4d8841c14fd6b4a69635b7070c3eTimo Sirainen mail->pop3_state = -1;
923eb3dde28e4d8841c14fd6b4a69635b7070c3eTimo Sirainen } else {
c4b376dd6e0c423006d7ac83a39253bcaf8e7c47Timo Sirainen /* possibly a mixed pop3/imap */
923eb3dde28e4d8841c14fd6b4a69635b7070c3eTimo Sirainen mail->pop3_state = 0;
923eb3dde28e4d8841c14fd6b4a69635b7070c3eTimo Sirainen }
4145aa5025b57ec64418e503c2a5a6bf5a02aec5Timo Sirainen mail->pop3_state_set = TRUE;
923eb3dde28e4d8841c14fd6b4a69635b7070c3eTimo Sirainen return mail->pop3_state;
923eb3dde28e4d8841c14fd6b4a69635b7070c3eTimo Sirainen}
923eb3dde28e4d8841c14fd6b4a69635b7070c3eTimo Sirainen
923eb3dde28e4d8841c14fd6b4a69635b7070c3eTimo Sirainenstatic int maildir_quick_size_lookup(struct index_mail *mail, bool vsize,
923eb3dde28e4d8841c14fd6b4a69635b7070c3eTimo Sirainen uoff_t *size_r)
4145aa5025b57ec64418e503c2a5a6bf5a02aec5Timo Sirainen{
923eb3dde28e4d8841c14fd6b4a69635b7070c3eTimo Sirainen struct mail *_mail = &mail->mail.mail;
923eb3dde28e4d8841c14fd6b4a69635b7070c3eTimo Sirainen struct maildir_mailbox *mbox = (struct maildir_mailbox *)mail->ibox;
4145aa5025b57ec64418e503c2a5a6bf5a02aec5Timo Sirainen enum maildir_uidlist_rec_ext_key key;
923eb3dde28e4d8841c14fd6b4a69635b7070c3eTimo Sirainen const char *path, *fname, *value;
4145aa5025b57ec64418e503c2a5a6bf5a02aec5Timo Sirainen uoff_t size;
c4b376dd6e0c423006d7ac83a39253bcaf8e7c47Timo Sirainen char *p;
c4b376dd6e0c423006d7ac83a39253bcaf8e7c47Timo Sirainen
c4b376dd6e0c423006d7ac83a39253bcaf8e7c47Timo Sirainen if (_mail->uid != 0) {
4145aa5025b57ec64418e503c2a5a6bf5a02aec5Timo Sirainen if (!maildir_mail_get_fname(mbox, _mail, &fname))
4145aa5025b57ec64418e503c2a5a6bf5a02aec5Timo Sirainen return -1;
923eb3dde28e4d8841c14fd6b4a69635b7070c3eTimo Sirainen } else {
0dab9cb35a976c49b28a11e28d5570f5191f1a7aMartti Rannanjärvi path = maildir_save_file_get_path(_mail->transaction,
eef4ba0cc3e78f8c26804c1c9251a76580a41f0cTimo Sirainen _mail->seq);
c4b376dd6e0c423006d7ac83a39253bcaf8e7c47Timo Sirainen fname = strrchr(path, '/');
c4b376dd6e0c423006d7ac83a39253bcaf8e7c47Timo Sirainen fname = fname != NULL ? fname + 1 : path;
eef4ba0cc3e78f8c26804c1c9251a76580a41f0cTimo Sirainen }
923eb3dde28e4d8841c14fd6b4a69635b7070c3eTimo Sirainen
4145aa5025b57ec64418e503c2a5a6bf5a02aec5Timo Sirainen /* size can be included in filename */
923eb3dde28e4d8841c14fd6b4a69635b7070c3eTimo Sirainen if (maildir_filename_get_size(fname,
923eb3dde28e4d8841c14fd6b4a69635b7070c3eTimo Sirainen vsize ? MAILDIR_EXTRA_VIRTUAL_SIZE :
217cdf98fe6f3e5a9a932e41fa2e956c153a6947Timo Sirainen MAILDIR_EXTRA_FILE_SIZE,
923eb3dde28e4d8841c14fd6b4a69635b7070c3eTimo Sirainen size_r))
923eb3dde28e4d8841c14fd6b4a69635b7070c3eTimo Sirainen return 1;
923eb3dde28e4d8841c14fd6b4a69635b7070c3eTimo Sirainen
923eb3dde28e4d8841c14fd6b4a69635b7070c3eTimo Sirainen /* size can be included in uidlist entry */
923eb3dde28e4d8841c14fd6b4a69635b7070c3eTimo Sirainen if (_mail->uid != 0) {
4145aa5025b57ec64418e503c2a5a6bf5a02aec5Timo Sirainen key = vsize ? MAILDIR_UIDLIST_REC_EXT_VSIZE :
4145aa5025b57ec64418e503c2a5a6bf5a02aec5Timo Sirainen MAILDIR_UIDLIST_REC_EXT_PSIZE;
4145aa5025b57ec64418e503c2a5a6bf5a02aec5Timo Sirainen value = maildir_uidlist_lookup_ext(mbox->uidlist, _mail->uid,
4145aa5025b57ec64418e503c2a5a6bf5a02aec5Timo Sirainen key);
923eb3dde28e4d8841c14fd6b4a69635b7070c3eTimo Sirainen if (value != NULL) {
923eb3dde28e4d8841c14fd6b4a69635b7070c3eTimo Sirainen size = strtoull(value, &p, 10);
4145aa5025b57ec64418e503c2a5a6bf5a02aec5Timo Sirainen if (*p == '\0') {
923eb3dde28e4d8841c14fd6b4a69635b7070c3eTimo Sirainen *size_r = size;
923eb3dde28e4d8841c14fd6b4a69635b7070c3eTimo Sirainen return 1;
4145aa5025b57ec64418e503c2a5a6bf5a02aec5Timo Sirainen }
4145aa5025b57ec64418e503c2a5a6bf5a02aec5Timo Sirainen }
923eb3dde28e4d8841c14fd6b4a69635b7070c3eTimo Sirainen }
923eb3dde28e4d8841c14fd6b4a69635b7070c3eTimo Sirainen return 0;
cdc5c81463995a153c57c68c299e98cc3de0b287Timo Sirainen}
923eb3dde28e4d8841c14fd6b4a69635b7070c3eTimo Sirainen
cdc5c81463995a153c57c68c299e98cc3de0b287Timo Sirainenstatic void
cdc5c81463995a153c57c68c299e98cc3de0b287Timo Sirainenmaildir_handle_size_caching(struct index_mail *mail, bool quick_check,
cdc5c81463995a153c57c68c299e98cc3de0b287Timo Sirainen bool vsize)
cdc5c81463995a153c57c68c299e98cc3de0b287Timo Sirainen{
923eb3dde28e4d8841c14fd6b4a69635b7070c3eTimo Sirainen struct maildir_mailbox *mbox = (struct maildir_mailbox *)mail->ibox;
923eb3dde28e4d8841c14fd6b4a69635b7070c3eTimo Sirainen enum mail_fetch_field field;
923eb3dde28e4d8841c14fd6b4a69635b7070c3eTimo Sirainen uoff_t size;
4145aa5025b57ec64418e503c2a5a6bf5a02aec5Timo Sirainen int pop3_state;
4145aa5025b57ec64418e503c2a5a6bf5a02aec5Timo Sirainen
4145aa5025b57ec64418e503c2a5a6bf5a02aec5Timo Sirainen field = vsize ? MAIL_FETCH_VIRTUAL_SIZE : MAIL_FETCH_PHYSICAL_SIZE;
923eb3dde28e4d8841c14fd6b4a69635b7070c3eTimo Sirainen if ((mail->data.dont_cache_fetch_fields & field) != 0)
923eb3dde28e4d8841c14fd6b4a69635b7070c3eTimo Sirainen return;
923eb3dde28e4d8841c14fd6b4a69635b7070c3eTimo Sirainen
4145aa5025b57ec64418e503c2a5a6bf5a02aec5Timo Sirainen if (quick_check && maildir_quick_size_lookup(mail, vsize, &size) > 0) {
4145aa5025b57ec64418e503c2a5a6bf5a02aec5Timo Sirainen /* already in filename / uidlist. don't add it anywhere,
923eb3dde28e4d8841c14fd6b4a69635b7070c3eTimo Sirainen including to the uidlist if it's already in filename.
923eb3dde28e4d8841c14fd6b4a69635b7070c3eTimo Sirainen do some extra checks here to catch potential cache bugs. */
e82e363e7a6917f470412d629db6c5b1f5891a35Timo Sirainen if (vsize && mail->data.virtual_size != size) {
4145aa5025b57ec64418e503c2a5a6bf5a02aec5Timo Sirainen mail_cache_set_corrupted(mail->ibox->cache,
4145aa5025b57ec64418e503c2a5a6bf5a02aec5Timo Sirainen "Corrupted virtual size for uid=%u: "
923eb3dde28e4d8841c14fd6b4a69635b7070c3eTimo Sirainen "%"PRIuUOFF_T" != %"PRIuUOFF_T,
923eb3dde28e4d8841c14fd6b4a69635b7070c3eTimo Sirainen mail->mail.mail.uid,
923eb3dde28e4d8841c14fd6b4a69635b7070c3eTimo Sirainen mail->data.virtual_size, size);
923eb3dde28e4d8841c14fd6b4a69635b7070c3eTimo Sirainen mail->data.virtual_size = size;
e82e363e7a6917f470412d629db6c5b1f5891a35Timo Sirainen } else if (!vsize && mail->data.physical_size != size) {
e82e363e7a6917f470412d629db6c5b1f5891a35Timo Sirainen mail_cache_set_corrupted(mail->ibox->cache,
e82e363e7a6917f470412d629db6c5b1f5891a35Timo Sirainen "Corrupted physical size for uid=%u: "
923eb3dde28e4d8841c14fd6b4a69635b7070c3eTimo Sirainen "%"PRIuUOFF_T" != %"PRIuUOFF_T,
923eb3dde28e4d8841c14fd6b4a69635b7070c3eTimo Sirainen mail->mail.mail.uid,
923eb3dde28e4d8841c14fd6b4a69635b7070c3eTimo Sirainen mail->data.physical_size, size);
923eb3dde28e4d8841c14fd6b4a69635b7070c3eTimo Sirainen mail->data.physical_size = size;
923eb3dde28e4d8841c14fd6b4a69635b7070c3eTimo Sirainen }
e82e363e7a6917f470412d629db6c5b1f5891a35Timo Sirainen mail->data.dont_cache_fetch_fields |= field;
e82e363e7a6917f470412d629db6c5b1f5891a35Timo Sirainen return;
e82e363e7a6917f470412d629db6c5b1f5891a35Timo Sirainen }
923eb3dde28e4d8841c14fd6b4a69635b7070c3eTimo Sirainen
e82e363e7a6917f470412d629db6c5b1f5891a35Timo Sirainen /* 1 = pop3-only, 0 = mixed, -1 = no pop3 */
923eb3dde28e4d8841c14fd6b4a69635b7070c3eTimo Sirainen pop3_state = maildir_get_pop3_state(mail);
e82e363e7a6917f470412d629db6c5b1f5891a35Timo Sirainen if (pop3_state >= 0 && mail->mail.mail.uid != 0) {
e82e363e7a6917f470412d629db6c5b1f5891a35Timo Sirainen /* if size is wanted permanently, store it to uidlist
4145aa5025b57ec64418e503c2a5a6bf5a02aec5Timo Sirainen so that in case cache file gets lost we can get it quickly */
923eb3dde28e4d8841c14fd6b4a69635b7070c3eTimo Sirainen mail->data.dont_cache_fetch_fields |= field;
923eb3dde28e4d8841c14fd6b4a69635b7070c3eTimo Sirainen size = vsize ? mail->data.virtual_size :
923eb3dde28e4d8841c14fd6b4a69635b7070c3eTimo Sirainen mail->data.physical_size;
e82e363e7a6917f470412d629db6c5b1f5891a35Timo Sirainen maildir_uidlist_set_ext(mbox->uidlist, mail->mail.mail.uid,
e82e363e7a6917f470412d629db6c5b1f5891a35Timo Sirainen vsize ? MAILDIR_UIDLIST_REC_EXT_VSIZE :
e82e363e7a6917f470412d629db6c5b1f5891a35Timo Sirainen MAILDIR_UIDLIST_REC_EXT_PSIZE,
e82e363e7a6917f470412d629db6c5b1f5891a35Timo Sirainen dec2str(size));
e82e363e7a6917f470412d629db6c5b1f5891a35Timo Sirainen }
e82e363e7a6917f470412d629db6c5b1f5891a35Timo Sirainen}
4145aa5025b57ec64418e503c2a5a6bf5a02aec5Timo Sirainen
e82e363e7a6917f470412d629db6c5b1f5891a35Timo Sirainenstatic int maildir_mail_get_virtual_size(struct mail *_mail, uoff_t *size_r)
923eb3dde28e4d8841c14fd6b4a69635b7070c3eTimo Sirainen{
e82e363e7a6917f470412d629db6c5b1f5891a35Timo Sirainen struct index_mail *mail = (struct index_mail *)_mail;
4145aa5025b57ec64418e503c2a5a6bf5a02aec5Timo Sirainen struct index_mail_data *data = &mail->data;
4145aa5025b57ec64418e503c2a5a6bf5a02aec5Timo Sirainen struct message_size hdr_size, body_size;
923eb3dde28e4d8841c14fd6b4a69635b7070c3eTimo Sirainen struct istream *input;
923eb3dde28e4d8841c14fd6b4a69635b7070c3eTimo Sirainen uoff_t old_offset;
923eb3dde28e4d8841c14fd6b4a69635b7070c3eTimo Sirainen
4145aa5025b57ec64418e503c2a5a6bf5a02aec5Timo Sirainen if (index_mail_get_cached_virtual_size(mail, size_r)) {
923eb3dde28e4d8841c14fd6b4a69635b7070c3eTimo Sirainen i_assert(mail->data.virtual_size != (uoff_t)-1);
923eb3dde28e4d8841c14fd6b4a69635b7070c3eTimo Sirainen maildir_handle_size_caching(mail, TRUE, TRUE);
4145aa5025b57ec64418e503c2a5a6bf5a02aec5Timo Sirainen return 0;
923eb3dde28e4d8841c14fd6b4a69635b7070c3eTimo Sirainen }
e82e363e7a6917f470412d629db6c5b1f5891a35Timo Sirainen
923eb3dde28e4d8841c14fd6b4a69635b7070c3eTimo Sirainen if (maildir_quick_size_lookup(mail, TRUE, &data->virtual_size) < 0)
923eb3dde28e4d8841c14fd6b4a69635b7070c3eTimo Sirainen return -1;
4145aa5025b57ec64418e503c2a5a6bf5a02aec5Timo Sirainen if (data->virtual_size != (uoff_t)-1) {
923eb3dde28e4d8841c14fd6b4a69635b7070c3eTimo Sirainen data->dont_cache_fetch_fields |= MAIL_FETCH_VIRTUAL_SIZE;
923eb3dde28e4d8841c14fd6b4a69635b7070c3eTimo Sirainen *size_r = data->virtual_size;
923eb3dde28e4d8841c14fd6b4a69635b7070c3eTimo Sirainen return 0;
e82e363e7a6917f470412d629db6c5b1f5891a35Timo Sirainen }
5ce2084ada06ade9f44fc2914c34658e9a842dc1Timo Sirainen
e82e363e7a6917f470412d629db6c5b1f5891a35Timo Sirainen /* fallback to reading the file */
e82e363e7a6917f470412d629db6c5b1f5891a35Timo Sirainen old_offset = data->stream == NULL ? 0 : data->stream->v_offset;
e82e363e7a6917f470412d629db6c5b1f5891a35Timo Sirainen if (mail_get_stream(_mail, &hdr_size, &body_size, &input) < 0)
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen return -1;
e82e363e7a6917f470412d629db6c5b1f5891a35Timo Sirainen i_stream_seek(data->stream, old_offset);
e82e363e7a6917f470412d629db6c5b1f5891a35Timo Sirainen
e82e363e7a6917f470412d629db6c5b1f5891a35Timo Sirainen maildir_handle_size_caching(mail, FALSE, TRUE);
923eb3dde28e4d8841c14fd6b4a69635b7070c3eTimo Sirainen *size_r = data->virtual_size;
e82e363e7a6917f470412d629db6c5b1f5891a35Timo Sirainen return 0;
e82e363e7a6917f470412d629db6c5b1f5891a35Timo Sirainen}
e82e363e7a6917f470412d629db6c5b1f5891a35Timo Sirainen
e82e363e7a6917f470412d629db6c5b1f5891a35Timo Sirainenstatic int maildir_mail_get_physical_size(struct mail *_mail, uoff_t *size_r)
923eb3dde28e4d8841c14fd6b4a69635b7070c3eTimo Sirainen{
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen struct index_mail *mail = (struct index_mail *)_mail;
51cbc45fc1ac5dde29bc2adbb175945df1b4f7d4Timo Sirainen struct maildir_mailbox *mbox = (struct maildir_mailbox *)mail->ibox;
e82e363e7a6917f470412d629db6c5b1f5891a35Timo Sirainen struct index_mail_data *data = &mail->data;
cee926660616568927461f1349420e41aa9e89e1Timo Sirainen struct stat st;
cee926660616568927461f1349420e41aa9e89e1Timo Sirainen const char *path;
e82e363e7a6917f470412d629db6c5b1f5891a35Timo Sirainen int ret;
e82e363e7a6917f470412d629db6c5b1f5891a35Timo Sirainen
e82e363e7a6917f470412d629db6c5b1f5891a35Timo Sirainen if (index_mail_get_physical_size(_mail, size_r) == 0) {
e82e363e7a6917f470412d629db6c5b1f5891a35Timo Sirainen i_assert(mail->data.physical_size != (uoff_t)-1);
e82e363e7a6917f470412d629db6c5b1f5891a35Timo Sirainen maildir_handle_size_caching(mail, TRUE, FALSE);
e82e363e7a6917f470412d629db6c5b1f5891a35Timo Sirainen return 0;
efe78d3ba24fc866af1c79b9223dc0809ba26cadStephan Bosch }
5ce2084ada06ade9f44fc2914c34658e9a842dc1Timo Sirainen
a342a31752dd71ac444259ca57ad33ea6b79a572Timo Sirainen if (maildir_quick_size_lookup(mail, FALSE, &data->physical_size) < 0)
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen return -1;
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen if (data->physical_size != (uoff_t)-1) {
31a574fda352ef4f71dbff9c30e15e4744e132c0Timo Sirainen data->dont_cache_fetch_fields |= MAIL_FETCH_PHYSICAL_SIZE;
5ce2084ada06ade9f44fc2914c34658e9a842dc1Timo Sirainen *size_r = data->physical_size;
e82e363e7a6917f470412d629db6c5b1f5891a35Timo Sirainen return 0;
e82e363e7a6917f470412d629db6c5b1f5891a35Timo Sirainen }
e82e363e7a6917f470412d629db6c5b1f5891a35Timo Sirainen
e82e363e7a6917f470412d629db6c5b1f5891a35Timo Sirainen if (_mail->uid != 0) {
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen ret = maildir_file_do(mbox, _mail->uid, do_stat, &st);
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen if (ret <= 0) {
cee926660616568927461f1349420e41aa9e89e1Timo Sirainen if (ret == 0)
cee926660616568927461f1349420e41aa9e89e1Timo Sirainen mail_set_expunged(_mail);
cee926660616568927461f1349420e41aa9e89e1Timo Sirainen return -1;
cee926660616568927461f1349420e41aa9e89e1Timo Sirainen }
cee926660616568927461f1349420e41aa9e89e1Timo Sirainen } else {
cee926660616568927461f1349420e41aa9e89e1Timo Sirainen /* saved mail which hasn't been committed yet */
cee926660616568927461f1349420e41aa9e89e1Timo Sirainen path = maildir_save_file_get_path(_mail->transaction,
cee926660616568927461f1349420e41aa9e89e1Timo Sirainen _mail->seq);
cee926660616568927461f1349420e41aa9e89e1Timo Sirainen if (stat(path, &st) < 0) {
cee926660616568927461f1349420e41aa9e89e1Timo Sirainen mail_storage_set_critical(_mail->box->storage,
cee926660616568927461f1349420e41aa9e89e1Timo Sirainen "stat(%s) failed: %m", path);
0dab9cb35a976c49b28a11e28d5570f5191f1a7aMartti Rannanjärvi return -1;
0dab9cb35a976c49b28a11e28d5570f5191f1a7aMartti Rannanjärvi }
923eb3dde28e4d8841c14fd6b4a69635b7070c3eTimo Sirainen }
e82e363e7a6917f470412d629db6c5b1f5891a35Timo Sirainen
d6c5ceea8521b92d10e51a59da00c792f6140b1dTimo Sirainen data->physical_size = st.st_size;
d10a370b2614712d9cb6a1dd8625f62a071b6377Timo Sirainen maildir_handle_size_caching(mail, FALSE, FALSE);
e82e363e7a6917f470412d629db6c5b1f5891a35Timo Sirainen *size_r = st.st_size;
d10a370b2614712d9cb6a1dd8625f62a071b6377Timo Sirainen return 0;
e82e363e7a6917f470412d629db6c5b1f5891a35Timo Sirainen}
e82e363e7a6917f470412d629db6c5b1f5891a35Timo Sirainen
e82e363e7a6917f470412d629db6c5b1f5891a35Timo Sirainenstatic int
d10a370b2614712d9cb6a1dd8625f62a071b6377Timo Sirainenmaildir_mail_get_special(struct mail *_mail, enum mail_fetch_field field,
d10a370b2614712d9cb6a1dd8625f62a071b6377Timo Sirainen const char **value_r)
5ce2084ada06ade9f44fc2914c34658e9a842dc1Timo Sirainen{
5ce2084ada06ade9f44fc2914c34658e9a842dc1Timo Sirainen struct index_mail *mail = (struct index_mail *)_mail;
88ea893b45d3ed8d68000921db9156c03cbe1b00Timo Sirainen struct maildir_mailbox *mbox = (struct maildir_mailbox *)mail->ibox;
88ea893b45d3ed8d68000921db9156c03cbe1b00Timo Sirainen const char *path, *fname, *end, *uidl;
88ea893b45d3ed8d68000921db9156c03cbe1b00Timo Sirainen
88ea893b45d3ed8d68000921db9156c03cbe1b00Timo Sirainen switch (field) {
88ea893b45d3ed8d68000921db9156c03cbe1b00Timo Sirainen case MAIL_FETCH_UIDL_FILE_NAME:
d10a370b2614712d9cb6a1dd8625f62a071b6377Timo Sirainen case MAIL_FETCH_GUID:
d10a370b2614712d9cb6a1dd8625f62a071b6377Timo Sirainen if (_mail->uid != 0) {
88ea893b45d3ed8d68000921db9156c03cbe1b00Timo Sirainen if (!maildir_mail_get_fname(mbox, _mail, &fname))
2412873209ff658bc4bd20123af2d6162464c4ffTimo Sirainen return -1;
2412873209ff658bc4bd20123af2d6162464c4ffTimo Sirainen } else {
2412873209ff658bc4bd20123af2d6162464c4ffTimo Sirainen path = maildir_save_file_get_path(_mail->transaction,
88ea893b45d3ed8d68000921db9156c03cbe1b00Timo Sirainen _mail->seq);
88ea893b45d3ed8d68000921db9156c03cbe1b00Timo Sirainen fname = strrchr(path, '/');
88ea893b45d3ed8d68000921db9156c03cbe1b00Timo Sirainen fname = fname != NULL ? fname + 1 : path;
88ea893b45d3ed8d68000921db9156c03cbe1b00Timo Sirainen }
d10a370b2614712d9cb6a1dd8625f62a071b6377Timo Sirainen end = strchr(fname, MAILDIR_INFO_SEP);
88ea893b45d3ed8d68000921db9156c03cbe1b00Timo Sirainen *value_r = end == NULL ? fname : t_strdup_until(fname, end);
46e17407ed48155ac7290a992216a11b2b2b3cf4Timo Sirainen return 0;
88ea893b45d3ed8d68000921db9156c03cbe1b00Timo Sirainen case MAIL_FETCH_UIDL_BACKEND:
88ea893b45d3ed8d68000921db9156c03cbe1b00Timo Sirainen uidl = maildir_uidlist_lookup_ext(mbox->uidlist, _mail->uid,
88ea893b45d3ed8d68000921db9156c03cbe1b00Timo Sirainen MAILDIR_UIDLIST_REC_EXT_POP3_UIDL);
88ea893b45d3ed8d68000921db9156c03cbe1b00Timo Sirainen *value_r = uidl != NULL ? uidl : "";
d10a370b2614712d9cb6a1dd8625f62a071b6377Timo Sirainen return 0;
88ea893b45d3ed8d68000921db9156c03cbe1b00Timo Sirainen default:
88ea893b45d3ed8d68000921db9156c03cbe1b00Timo Sirainen return index_mail_get_special(_mail, field, value_r);
88ea893b45d3ed8d68000921db9156c03cbe1b00Timo Sirainen }
3ddbbe03fe74b3ee7b1dff4e08ec706d7880d052Timo Sirainen}
3ddbbe03fe74b3ee7b1dff4e08ec706d7880d052Timo Sirainen
3ddbbe03fe74b3ee7b1dff4e08ec706d7880d052Timo Sirainenstatic int maildir_mail_get_stream(struct mail *_mail,
3ddbbe03fe74b3ee7b1dff4e08ec706d7880d052Timo Sirainen struct message_size *hdr_size,
d10a370b2614712d9cb6a1dd8625f62a071b6377Timo Sirainen struct message_size *body_size,
d10a370b2614712d9cb6a1dd8625f62a071b6377Timo Sirainen struct istream **stream_r)
3ddbbe03fe74b3ee7b1dff4e08ec706d7880d052Timo Sirainen{
d10a370b2614712d9cb6a1dd8625f62a071b6377Timo Sirainen struct index_mail *mail = (struct index_mail *)_mail;
d10a370b2614712d9cb6a1dd8625f62a071b6377Timo Sirainen struct maildir_mailbox *mbox = (struct maildir_mailbox *)mail->ibox;
3ddbbe03fe74b3ee7b1dff4e08ec706d7880d052Timo Sirainen struct index_mail_data *data = &mail->data;
3ddbbe03fe74b3ee7b1dff4e08ec706d7880d052Timo Sirainen bool deleted;
3ddbbe03fe74b3ee7b1dff4e08ec706d7880d052Timo Sirainen
3ddbbe03fe74b3ee7b1dff4e08ec706d7880d052Timo Sirainen if (data->stream == NULL) {
3ddbbe03fe74b3ee7b1dff4e08ec706d7880d052Timo Sirainen data->stream = maildir_open_mail(mbox, _mail, &deleted);
3ddbbe03fe74b3ee7b1dff4e08ec706d7880d052Timo Sirainen if (data->stream == NULL) {
3ddbbe03fe74b3ee7b1dff4e08ec706d7880d052Timo Sirainen if (deleted)
3ddbbe03fe74b3ee7b1dff4e08ec706d7880d052Timo Sirainen mail_set_expunged(_mail);
3ddbbe03fe74b3ee7b1dff4e08ec706d7880d052Timo Sirainen return -1;
905627a760ce8bf4141b361f72858a99975ded3cTimo Sirainen }
905627a760ce8bf4141b361f72858a99975ded3cTimo Sirainen }
46e17407ed48155ac7290a992216a11b2b2b3cf4Timo Sirainen
905627a760ce8bf4141b361f72858a99975ded3cTimo Sirainen return index_mail_init_stream(mail, hdr_size, body_size, stream_r);
905627a760ce8bf4141b361f72858a99975ded3cTimo Sirainen}
905627a760ce8bf4141b361f72858a99975ded3cTimo Sirainen
905627a760ce8bf4141b361f72858a99975ded3cTimo Sirainenstatic void maildir_mail_set_cache_corrupted(struct mail *_mail,
905627a760ce8bf4141b361f72858a99975ded3cTimo Sirainen enum mail_fetch_field field)
905627a760ce8bf4141b361f72858a99975ded3cTimo Sirainen{
905627a760ce8bf4141b361f72858a99975ded3cTimo Sirainen struct index_mail *mail = (struct index_mail *)_mail;
905627a760ce8bf4141b361f72858a99975ded3cTimo Sirainen struct maildir_mailbox *mbox = (struct maildir_mailbox *)mail->ibox;
905627a760ce8bf4141b361f72858a99975ded3cTimo Sirainen enum maildir_uidlist_rec_flag flags;
905627a760ce8bf4141b361f72858a99975ded3cTimo Sirainen const char *fname;
704a96fa677763eef7ae62466e14e83a2f535427Timo Sirainen uoff_t size;
704a96fa677763eef7ae62466e14e83a2f535427Timo Sirainen
704a96fa677763eef7ae62466e14e83a2f535427Timo Sirainen if (field == MAIL_FETCH_VIRTUAL_SIZE) {
704a96fa677763eef7ae62466e14e83a2f535427Timo Sirainen /* make sure it gets removed from uidlist.
704a96fa677763eef7ae62466e14e83a2f535427Timo Sirainen if it's in file name, we can't really do more than log it. */
704a96fa677763eef7ae62466e14e83a2f535427Timo Sirainen fname = maildir_uidlist_lookup(mbox->uidlist,
704a96fa677763eef7ae62466e14e83a2f535427Timo Sirainen _mail->uid, &flags);
704a96fa677763eef7ae62466e14e83a2f535427Timo Sirainen if (maildir_filename_get_size(fname, MAILDIR_EXTRA_VIRTUAL_SIZE,
704a96fa677763eef7ae62466e14e83a2f535427Timo Sirainen &size)) {
704a96fa677763eef7ae62466e14e83a2f535427Timo Sirainen i_error("Maildir filename has wrong W value: %s/%s",
289bd999f282a307b05e6f8beef33155a50fb837Timo Sirainen mbox->path, fname);
289bd999f282a307b05e6f8beef33155a50fb837Timo Sirainen } else if (maildir_uidlist_lookup_ext(mbox->uidlist, _mail->uid,
289bd999f282a307b05e6f8beef33155a50fb837Timo Sirainen MAILDIR_UIDLIST_REC_EXT_VSIZE) != NULL) {
289bd999f282a307b05e6f8beef33155a50fb837Timo Sirainen maildir_uidlist_set_ext(mbox->uidlist, _mail->uid,
289bd999f282a307b05e6f8beef33155a50fb837Timo Sirainen MAILDIR_UIDLIST_REC_EXT_VSIZE,
289bd999f282a307b05e6f8beef33155a50fb837Timo Sirainen NULL);
704a96fa677763eef7ae62466e14e83a2f535427Timo Sirainen }
704a96fa677763eef7ae62466e14e83a2f535427Timo Sirainen }
704a96fa677763eef7ae62466e14e83a2f535427Timo Sirainen index_mail_set_cache_corrupted(_mail, field);
e82e363e7a6917f470412d629db6c5b1f5891a35Timo Sirainen}
5ce2084ada06ade9f44fc2914c34658e9a842dc1Timo Sirainen
d10a370b2614712d9cb6a1dd8625f62a071b6377Timo Sirainenstruct mail_vfuncs maildir_mail_vfuncs = {
42507d758b053bb483de58fba55c73a9eb5d3fbaTimo Sirainen index_mail_close,
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen index_mail_free,
3ddbbe03fe74b3ee7b1dff4e08ec706d7880d052Timo Sirainen index_mail_set_seq,
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen index_mail_set_uid,
2767104d81e97a109f0aa9758792bfa1da325a97Timo Sirainen
d10a370b2614712d9cb6a1dd8625f62a071b6377Timo Sirainen index_mail_get_flags,
d10a370b2614712d9cb6a1dd8625f62a071b6377Timo Sirainen index_mail_get_keywords,
d21f14c01d5546f4bf1b2cbb28ac1f00c24d952aTimo Sirainen index_mail_get_keyword_indexes,
d21f14c01d5546f4bf1b2cbb28ac1f00c24d952aTimo Sirainen index_mail_get_modseq,
d21f14c01d5546f4bf1b2cbb28ac1f00c24d952aTimo Sirainen index_mail_get_parts,
d21f14c01d5546f4bf1b2cbb28ac1f00c24d952aTimo Sirainen index_mail_get_date,
16a815d92a3202e3a66fd7f8e3478664b852bf1eTimo Sirainen maildir_mail_get_received_date,
3ddbbe03fe74b3ee7b1dff4e08ec706d7880d052Timo Sirainen maildir_mail_get_save_date,
3ddbbe03fe74b3ee7b1dff4e08ec706d7880d052Timo Sirainen maildir_mail_get_virtual_size,
d10a370b2614712d9cb6a1dd8625f62a071b6377Timo Sirainen maildir_mail_get_physical_size,
d21f14c01d5546f4bf1b2cbb28ac1f00c24d952aTimo Sirainen index_mail_get_first_header,
d10a370b2614712d9cb6a1dd8625f62a071b6377Timo Sirainen index_mail_get_headers,
3ddbbe03fe74b3ee7b1dff4e08ec706d7880d052Timo Sirainen index_mail_get_header_stream,
3ddbbe03fe74b3ee7b1dff4e08ec706d7880d052Timo Sirainen maildir_mail_get_stream,
d21f14c01d5546f4bf1b2cbb28ac1f00c24d952aTimo Sirainen maildir_mail_get_special,
704a96fa677763eef7ae62466e14e83a2f535427Timo Sirainen index_mail_update_flags,
704a96fa677763eef7ae62466e14e83a2f535427Timo Sirainen index_mail_update_keywords,
d21f14c01d5546f4bf1b2cbb28ac1f00c24d952aTimo Sirainen index_mail_expunge,
d21f14c01d5546f4bf1b2cbb28ac1f00c24d952aTimo Sirainen maildir_mail_set_cache_corrupted,
5ce2084ada06ade9f44fc2914c34658e9a842dc1Timo Sirainen index_mail_get_index_mail
d10a370b2614712d9cb6a1dd8625f62a071b6377Timo Sirainen};
d10a370b2614712d9cb6a1dd8625f62a071b6377Timo Sirainen