maildir-mail.c revision b19a1420da0618a10edf67c2cfd13c8c8633057a
c25356d5978632df6203437e1953bcb29e0c736fTimo Sirainen/* Copyright (c) 2003-2008 Dovecot authors, see the included COPYING file */
c25356d5978632df6203437e1953bcb29e0c736fTimo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "lib.h"
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen#include "istream.h"
d9076f5939edf5d20a261494b1a861dcbb0d32e2Timo Sirainen#include "index-mail.h"
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen#include "maildir-storage.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "maildir-filename.h"
5666a3d6a7ea89362b8d9e8b39b15424cd9d6388Timo Sirainen#include "maildir-uidlist.h"
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen#include "maildir-sync.h"
146f9076cd456ea1e9b3f8536456d9d3c962fadbStephan Bosch
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen#include <stdlib.h>
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include <fcntl.h>
2039bdca260cd123832ddda9b2b6862a4abc53aaTimo Sirainen#include <unistd.h>
2039bdca260cd123832ddda9b2b6862a4abc53aaTimo Sirainen#include <sys/stat.h>
2039bdca260cd123832ddda9b2b6862a4abc53aaTimo Sirainen
8c909e451d14075c05d90382cf8eebc4e354f569Timo Sirainenstatic int
8c909e451d14075c05d90382cf8eebc4e354f569Timo Sirainendo_open(struct maildir_mailbox *mbox, const char *path, int *fd)
8c909e451d14075c05d90382cf8eebc4e354f569Timo Sirainen{
573f0491a5733fe21fa062a455acb4790b4e0499Timo Sirainen *fd = open(path, O_RDONLY);
573f0491a5733fe21fa062a455acb4790b4e0499Timo Sirainen if (*fd != -1)
573f0491a5733fe21fa062a455acb4790b4e0499Timo Sirainen return 1;
3ed2d0f6b5e67e2663d44489d9da3176823789a8Timo Sirainen if (errno == ENOENT)
65f8fb656051f1059f7b5a2da9c5555adcc30439Timo Sirainen return 0;
1a5573ebc32fae2fe576ec544e1781323c1db609Timo Sirainen
1a5573ebc32fae2fe576ec544e1781323c1db609Timo Sirainen mail_storage_set_critical(&mbox->storage->storage,
82d1fe3d5d04fb11e3e89cce03dc4de191e58f75Timo Sirainen "open(%s) failed: %m", path);
82d1fe3d5d04fb11e3e89cce03dc4de191e58f75Timo Sirainen return -1;
82d1fe3d5d04fb11e3e89cce03dc4de191e58f75Timo Sirainen}
8049d5792631981b50b0ad226a03298445e305c7Timo Sirainen
8049d5792631981b50b0ad226a03298445e305c7Timo Sirainenstatic int
8049d5792631981b50b0ad226a03298445e305c7Timo Sirainendo_stat(struct maildir_mailbox *mbox, const char *path, struct stat *st)
8049d5792631981b50b0ad226a03298445e305c7Timo Sirainen{
8049d5792631981b50b0ad226a03298445e305c7Timo Sirainen if (stat(path, st) == 0)
8049d5792631981b50b0ad226a03298445e305c7Timo Sirainen return 1;
b42817ce16a8660cbcc4adfc8bccc3db1c6d00c7Timo Sirainen if (errno == ENOENT)
b42817ce16a8660cbcc4adfc8bccc3db1c6d00c7Timo Sirainen return 0;
b42817ce16a8660cbcc4adfc8bccc3db1c6d00c7Timo Sirainen
b42817ce16a8660cbcc4adfc8bccc3db1c6d00c7Timo Sirainen mail_storage_set_critical(&mbox->storage->storage,
82d1fe3d5d04fb11e3e89cce03dc4de191e58f75Timo Sirainen "stat(%s) failed: %m", path);
82d1fe3d5d04fb11e3e89cce03dc4de191e58f75Timo Sirainen return -1;
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen}
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainenstatic struct istream *
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainenmaildir_open_mail(struct maildir_mailbox *mbox, struct mail *mail,
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen bool *deleted_r)
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen{
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen const char *path;
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen int fd = -1;
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen *deleted_r = FALSE;
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen
f7539a17ea306191b53b8f5e752e228937df9ec3Timo Sirainen if (mail->uid != 0) {
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen if (maildir_file_do(mbox, mail->uid, do_open, &fd) < 0)
2dd39e478269d6fb0bb26d12b394aa30ee965e38Timo Sirainen return NULL;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen } else {
563273bdac80393af63b9520cbf4d24cc0efd028Timo Sirainen path = maildir_save_file_get_path(mail->transaction, mail->seq);
563273bdac80393af63b9520cbf4d24cc0efd028Timo Sirainen if (do_open(mbox, path, &fd) <= 0)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return NULL;
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen }
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen if (fd == -1) {
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen *deleted_r = TRUE;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return NULL;
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen }
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen return i_stream_create_fd(fd, MAIL_READ_BLOCK_SIZE, TRUE);
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen}
3e564425db51f3921ce4de11859777135fdedd15Timo Sirainen
82d1fe3d5d04fb11e3e89cce03dc4de191e58f75Timo Sirainenstatic int maildir_mail_stat(struct mail *mail, struct stat *st)
857c471c13ca215f4be9dd4b336b742b8d434e31Timo Sirainen{
857c471c13ca215f4be9dd4b336b742b8d434e31Timo Sirainen struct maildir_mailbox *mbox = (struct maildir_mailbox *)mail->box;
82d1fe3d5d04fb11e3e89cce03dc4de191e58f75Timo Sirainen struct index_mail_data *data = &((struct index_mail *)mail)->data;
82d1fe3d5d04fb11e3e89cce03dc4de191e58f75Timo Sirainen const char *path;
82d1fe3d5d04fb11e3e89cce03dc4de191e58f75Timo Sirainen int fd, ret;
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen if (data->access_part != 0 && data->stream == NULL) {
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen /* we're going to open the mail anyway */
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen struct istream *input;
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen (void)mail_get_stream(mail, NULL, NULL, &input);
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen }
563273bdac80393af63b9520cbf4d24cc0efd028Timo Sirainen
563273bdac80393af63b9520cbf4d24cc0efd028Timo Sirainen if (data->stream != NULL) {
563273bdac80393af63b9520cbf4d24cc0efd028Timo Sirainen fd = i_stream_get_fd(data->stream);
563273bdac80393af63b9520cbf4d24cc0efd028Timo Sirainen i_assert(fd != -1);
e5fd6dfd0a492e4708d4dbb7971d7fc5d7b8fd85Timo Sirainen
e5fd6dfd0a492e4708d4dbb7971d7fc5d7b8fd85Timo Sirainen if (fstat(fd, st) < 0) {
4ba9a1d3facc515b3feb5238a16bcf91f76fac61Timo Sirainen mail_storage_set_critical(&mbox->storage->storage,
4ba9a1d3facc515b3feb5238a16bcf91f76fac61Timo Sirainen "fstat(maildir) failed: %m");
dfaefeabae939803ceb8c503101e86b5496541d1Timo Sirainen return -1;
dfaefeabae939803ceb8c503101e86b5496541d1Timo Sirainen }
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen } else if (mail->uid != 0) {
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen ret = maildir_file_do(mbox, mail->uid, do_stat, st);
8b31f966d9688e07672ef1958dcbdb7686523c04Timo Sirainen if (ret <= 0) {
8b31f966d9688e07672ef1958dcbdb7686523c04Timo Sirainen if (ret == 0)
9847ec56efa15fa063eea9988eee2d4ed9ec7d58Timo Sirainen mail_set_expunged(mail);
9847ec56efa15fa063eea9988eee2d4ed9ec7d58Timo Sirainen return -1;
9847ec56efa15fa063eea9988eee2d4ed9ec7d58Timo Sirainen }
d46a1e3f999dda802dc5137e883adcd7a6629cd3Timo Sirainen } else {
d46a1e3f999dda802dc5137e883adcd7a6629cd3Timo Sirainen path = maildir_save_file_get_path(mail->transaction, mail->seq);
d46a1e3f999dda802dc5137e883adcd7a6629cd3Timo Sirainen if (stat(path, st) < 0) {
d1e843e77f4760e303c53d9fce10123fc8d230a1Timo Sirainen mail_storage_set_critical(mail->box->storage,
d1e843e77f4760e303c53d9fce10123fc8d230a1Timo Sirainen "stat(%s) failed: %m", path);
d1e843e77f4760e303c53d9fce10123fc8d230a1Timo Sirainen return -1;
291ce16fffca75e8598a8c9dceb08613413dcb07Timo Sirainen }
291ce16fffca75e8598a8c9dceb08613413dcb07Timo Sirainen }
291ce16fffca75e8598a8c9dceb08613413dcb07Timo Sirainen return 0;
08e9fd42eb8007e1f9db62c088eef74f906114a5Josef 'Jeff' Sipek}
08e9fd42eb8007e1f9db62c088eef74f906114a5Josef 'Jeff' Sipek
08e9fd42eb8007e1f9db62c088eef74f906114a5Josef 'Jeff' Sipekstatic int maildir_mail_get_received_date(struct mail *_mail, time_t *date_r)
563273bdac80393af63b9520cbf4d24cc0efd028Timo Sirainen{
563273bdac80393af63b9520cbf4d24cc0efd028Timo Sirainen struct index_mail *mail = (struct index_mail *)_mail;
306b3f41b05da642d87e7ca7a1496efce9f5902fTimo Sirainen struct index_mail_data *data = &mail->data;
306b3f41b05da642d87e7ca7a1496efce9f5902fTimo Sirainen struct stat st;
306b3f41b05da642d87e7ca7a1496efce9f5902fTimo Sirainen
306b3f41b05da642d87e7ca7a1496efce9f5902fTimo Sirainen if (index_mail_get_received_date(_mail, date_r) == 0)
306b3f41b05da642d87e7ca7a1496efce9f5902fTimo Sirainen return 0;
306b3f41b05da642d87e7ca7a1496efce9f5902fTimo Sirainen
306b3f41b05da642d87e7ca7a1496efce9f5902fTimo Sirainen if (maildir_mail_stat(_mail, &st) < 0)
306b3f41b05da642d87e7ca7a1496efce9f5902fTimo Sirainen return -1;
306b3f41b05da642d87e7ca7a1496efce9f5902fTimo Sirainen
306b3f41b05da642d87e7ca7a1496efce9f5902fTimo Sirainen *date_r = data->received_date = st.st_mtime;
306b3f41b05da642d87e7ca7a1496efce9f5902fTimo Sirainen return 0;
97ae33602db7d5bc8eede82512a965d49ab8853bTimo Sirainen}
97ae33602db7d5bc8eede82512a965d49ab8853bTimo Sirainen
97ae33602db7d5bc8eede82512a965d49ab8853bTimo Sirainenstatic int maildir_mail_get_save_date(struct mail *_mail, time_t *date_r)
30d50c7e8706f2d750215e009504109ca19cd485Timo Sirainen{
30d50c7e8706f2d750215e009504109ca19cd485Timo Sirainen struct index_mail *mail = (struct index_mail *)_mail;
97ae33602db7d5bc8eede82512a965d49ab8853bTimo Sirainen struct index_mail_data *data = &mail->data;
97ae33602db7d5bc8eede82512a965d49ab8853bTimo Sirainen struct stat st;
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen
57a8c6a95e4bce3eeaba36985adb81c07dd683ffTimo Sirainen if (index_mail_get_save_date(_mail, date_r) == 0)
563273bdac80393af63b9520cbf4d24cc0efd028Timo Sirainen return 0;
afe1da042382720393eca6497253106e4eec75e0Timo Sirainen
afe1da042382720393eca6497253106e4eec75e0Timo Sirainen if (maildir_mail_stat(_mail, &st) < 0)
afe1da042382720393eca6497253106e4eec75e0Timo Sirainen return -1;
afe1da042382720393eca6497253106e4eec75e0Timo Sirainen
afe1da042382720393eca6497253106e4eec75e0Timo Sirainen *date_r = data->save_date = st.st_ctime;
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen return data->save_date;
539977f9257bd8985be5a8093658da266ae9cd19Timo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstatic bool
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainenmaildir_mail_get_fname(struct maildir_mailbox *mbox, struct mail *mail,
563273bdac80393af63b9520cbf4d24cc0efd028Timo Sirainen const char **fname_r)
420040a5930a2b497e79ff0b5f59ba4b764a5b39Timo Sirainen{
420040a5930a2b497e79ff0b5f59ba4b764a5b39Timo Sirainen enum maildir_uidlist_rec_flag flags;
563273bdac80393af63b9520cbf4d24cc0efd028Timo Sirainen struct mail_index_view *view;
420040a5930a2b497e79ff0b5f59ba4b764a5b39Timo Sirainen uint32_t seq;
420040a5930a2b497e79ff0b5f59ba4b764a5b39Timo Sirainen bool exists;
420040a5930a2b497e79ff0b5f59ba4b764a5b39Timo Sirainen
eecb235c14b49c01774134ea593c266f2d2c2be1Timo Sirainen *fname_r = maildir_uidlist_lookup(mbox->uidlist, mail->uid, &flags);
eecb235c14b49c01774134ea593c266f2d2c2be1Timo Sirainen if (*fname_r != NULL)
7900eb30bac4a46b259522c58362884661483d7cJosef 'Jeff' Sipek return TRUE;
7900eb30bac4a46b259522c58362884661483d7cJosef 'Jeff' Sipek
563273bdac80393af63b9520cbf4d24cc0efd028Timo Sirainen /* file exists in index file, but not in dovecot-uidlist anymore. */
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen mail_set_expunged(mail);
98c217499d578495e982ea6010ebff831e9669aeMartti Rannanjärvi
98c217499d578495e982ea6010ebff831e9669aeMartti Rannanjärvi /* one reason this could happen is if we delayed opening
98c217499d578495e982ea6010ebff831e9669aeMartti Rannanjärvi dovecot-uidlist and we're trying to open a mail that got recently
ff7056842f14fd3b30a2d327dfab165b9d15dd30Timo Sirainen expunged. Let's test this theory first: */
ff7056842f14fd3b30a2d327dfab165b9d15dd30Timo Sirainen (void)mail_index_refresh(mbox->ibox.index);
97ae33602db7d5bc8eede82512a965d49ab8853bTimo Sirainen view = mail_index_view_open(mbox->ibox.index);
ff7056842f14fd3b30a2d327dfab165b9d15dd30Timo Sirainen exists = mail_index_lookup_seq(view, mail->uid, &seq);
f1743785713e7632459d623d5df2108f4b93accbTimo Sirainen mail_index_view_close(&view);
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen
70ead6466f9baa8294e71fc2fba0a4f54f488b5eTimo Sirainen if (exists) {
a64adf62fa33f2463a86f990217b0c9078531a40Timo Sirainen /* the message still exists in index. this means there's some
ccc895c0358108d2304239063e940b7d75f364abTimo Sirainen kind of a desync, which doesn't get fixed if cur/ mtime is
8d630c15a8ed6f85553467c3a231a273defca5f6Timo Sirainen the same as in index. fix this by forcing a resync. */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen (void)maildir_storage_sync_force(mbox, mail->uid);
ee116df08d0fdab703483e18fe8076b2ef9fd9d7Timo Sirainen }
c5ab90cfad9cc3e33bcb1baeb30ffc82a7b7053aTimo Sirainen return FALSE;
c5ab90cfad9cc3e33bcb1baeb30ffc82a7b7053aTimo Sirainen}
306b3f41b05da642d87e7ca7a1496efce9f5902fTimo Sirainen
9fd2181788a61500641c66aec0f8c746b19bf830Timo Sirainenstatic int maildir_get_pop3_state(struct index_mail *mail)
9fd2181788a61500641c66aec0f8c746b19bf830Timo Sirainen{
9fd2181788a61500641c66aec0f8c746b19bf830Timo Sirainen const struct mail_cache_field *fields;
306b3f41b05da642d87e7ca7a1496efce9f5902fTimo Sirainen unsigned int i, count, psize_idx, vsize_idx;
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen enum mail_cache_decision_type dec, vsize_dec;
4ee00532a265bdfb38539d811fcd12d51210ac35Timo Sirainen enum mail_fetch_field allowed_pop3_fields;
c6afd726060aae56b6622c6c52aec10231c4bf1cTimo Sirainen bool not_pop3_only = FALSE;
9fd2181788a61500641c66aec0f8c746b19bf830Timo Sirainen
0dffa25d211be541ee3c953b23566a1a990789dfTimo Sirainen if (mail->pop3_state_set)
98c217499d578495e982ea6010ebff831e9669aeMartti Rannanjärvi return mail->pop3_state;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen /* if this mail itself has non-pop3 fields we know we're not
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen pop3-only */
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen allowed_pop3_fields = MAIL_FETCH_FLAGS | MAIL_FETCH_STREAM_HEADER |
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen MAIL_FETCH_STREAM_BODY | MAIL_FETCH_UIDL_FILE_NAME |
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen MAIL_FETCH_VIRTUAL_SIZE;
b9f564d00b7a115f465ffd6840341c7b8f9bfc8aTimo Sirainen
aa41b2e17912d6cad3151babea6a85dd88539d28Timo Sirainen if (mail->wanted_headers != NULL ||
aa41b2e17912d6cad3151babea6a85dd88539d28Timo Sirainen (mail->wanted_fields & ~allowed_pop3_fields) != 0)
aa41b2e17912d6cad3151babea6a85dd88539d28Timo Sirainen not_pop3_only = TRUE;
aa41b2e17912d6cad3151babea6a85dd88539d28Timo Sirainen
aa41b2e17912d6cad3151babea6a85dd88539d28Timo Sirainen /* get vsize decisions */
aa41b2e17912d6cad3151babea6a85dd88539d28Timo Sirainen psize_idx = mail->ibox->cache_fields[MAIL_CACHE_PHYSICAL_FULL_SIZE].idx;
aa41b2e17912d6cad3151babea6a85dd88539d28Timo Sirainen vsize_idx = mail->ibox->cache_fields[MAIL_CACHE_VIRTUAL_FULL_SIZE].idx;
aa41b2e17912d6cad3151babea6a85dd88539d28Timo Sirainen if (not_pop3_only) {
aa41b2e17912d6cad3151babea6a85dd88539d28Timo Sirainen vsize_dec = mail_cache_field_get_decision(mail->ibox->cache,
aa41b2e17912d6cad3151babea6a85dd88539d28Timo Sirainen vsize_idx);
aa41b2e17912d6cad3151babea6a85dd88539d28Timo Sirainen vsize_dec &= ~MAIL_CACHE_DECISION_FORCED;
aa41b2e17912d6cad3151babea6a85dd88539d28Timo Sirainen } else {
aa41b2e17912d6cad3151babea6a85dd88539d28Timo Sirainen /* also check if there are any non-[pv]size cached fields */
aa41b2e17912d6cad3151babea6a85dd88539d28Timo Sirainen vsize_dec = MAIL_CACHE_DECISION_NO;
aa41b2e17912d6cad3151babea6a85dd88539d28Timo Sirainen fields = mail_cache_register_get_list(mail->ibox->cache,
aa41b2e17912d6cad3151babea6a85dd88539d28Timo Sirainen pool_datastack_create(),
aa41b2e17912d6cad3151babea6a85dd88539d28Timo Sirainen &count);
aa41b2e17912d6cad3151babea6a85dd88539d28Timo Sirainen for (i = 0; i < count; i++) {
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen dec = fields[i].decision & ~MAIL_CACHE_DECISION_FORCED;
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainen if (fields[i].idx == vsize_idx)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen vsize_dec = dec;
a2f250a332dfc1e6cd4ffd196c621eb9dbf7b8a1Timo Sirainen else if (dec != MAIL_CACHE_DECISION_NO &&
cff1f182205e674285cf3ff446a0dcf7afea277dTimo Sirainen fields[i].idx != psize_idx)
cff1f182205e674285cf3ff446a0dcf7afea277dTimo Sirainen not_pop3_only = TRUE;
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen }
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen }
e03d986a74128f5ba30fcfda9f6e36578f5d8decTimo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (!not_pop3_only) {
f318b3dbe2acc177b8ee1c160e4b5b14e7f2cd41Timo Sirainen /* either nothing is cached, or only vsize is cached. */
f318b3dbe2acc177b8ee1c160e4b5b14e7f2cd41Timo Sirainen mail->pop3_state = 1;
f318b3dbe2acc177b8ee1c160e4b5b14e7f2cd41Timo Sirainen } else if (vsize_dec != MAIL_CACHE_DECISION_YES) {
f318b3dbe2acc177b8ee1c160e4b5b14e7f2cd41Timo Sirainen /* if virtual size isn't cached permanently,
f318b3dbe2acc177b8ee1c160e4b5b14e7f2cd41Timo Sirainen POP3 isn't being used */
f318b3dbe2acc177b8ee1c160e4b5b14e7f2cd41Timo Sirainen mail->pop3_state = -1;
17ad2164c747cedbf81dae1893063e71a3df0356Timo Sirainen } else {
d3280fe317a4598c0868cc440e7a1191c06d0db3Timo Sirainen /* possibly a mixed pop3/imap */
d3280fe317a4598c0868cc440e7a1191c06d0db3Timo Sirainen mail->pop3_state = 0;
51327f2489a4e0e615eb9f7d921473cf8512bb79Timo Sirainen }
51327f2489a4e0e615eb9f7d921473cf8512bb79Timo Sirainen mail->pop3_state_set = TRUE;
51327f2489a4e0e615eb9f7d921473cf8512bb79Timo Sirainen return mail->pop3_state;
6469cf211a57433335641725dc236ebb2b9fdd3bTimo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
50c617761ee9653bd44646a95178773a3686d62eTimo Sirainenstatic int maildir_quick_size_lookup(struct index_mail *mail, bool vsize,
6cc4cce2078aca138fbce19305e69e77edcee614Timo Sirainen uoff_t *size_r)
bd6a8056771b6150685dea319ab5a94e021d17f1Josef 'Jeff' Sipek{
9f37ef2a9192e7d47e3d7ac959080fd01120f2e9Aki Tuomi struct mail *_mail = &mail->mail.mail;
50c617761ee9653bd44646a95178773a3686d62eTimo Sirainen struct maildir_mailbox *mbox = (struct maildir_mailbox *)mail->ibox;
bd6a8056771b6150685dea319ab5a94e021d17f1Josef 'Jeff' Sipek enum maildir_uidlist_rec_ext_key key;
62041dfb7d6ac6e9c633a557075999cdfcff7bd5Timo Sirainen const char *path, *fname, *value;
62041dfb7d6ac6e9c633a557075999cdfcff7bd5Timo Sirainen uoff_t size;
62041dfb7d6ac6e9c633a557075999cdfcff7bd5Timo Sirainen char *p;
62041dfb7d6ac6e9c633a557075999cdfcff7bd5Timo Sirainen
62041dfb7d6ac6e9c633a557075999cdfcff7bd5Timo Sirainen if (_mail->uid != 0) {
62041dfb7d6ac6e9c633a557075999cdfcff7bd5Timo Sirainen if (!maildir_mail_get_fname(mbox, _mail, &fname))
62041dfb7d6ac6e9c633a557075999cdfcff7bd5Timo Sirainen return -1;
d3442384ca53d4b18a493db7dd0b000f470419cfTimo Sirainen } else {
aa47c9bd1d1fc70cd699c49fd1ca92dbc7615953Timo Sirainen path = maildir_save_file_get_path(_mail->transaction,
aa47c9bd1d1fc70cd699c49fd1ca92dbc7615953Timo Sirainen _mail->seq);
d3442384ca53d4b18a493db7dd0b000f470419cfTimo Sirainen fname = strrchr(path, '/');
d3442384ca53d4b18a493db7dd0b000f470419cfTimo Sirainen fname = fname != NULL ? fname + 1 : path;
aa47c9bd1d1fc70cd699c49fd1ca92dbc7615953Timo Sirainen }
c0d069950af1dbc6a4e5c3de3bf2e437796e3ae0Timo Sirainen
c0d069950af1dbc6a4e5c3de3bf2e437796e3ae0Timo Sirainen /* size can be included in filename */
c0d069950af1dbc6a4e5c3de3bf2e437796e3ae0Timo Sirainen if (maildir_filename_get_size(fname,
c0d069950af1dbc6a4e5c3de3bf2e437796e3ae0Timo Sirainen vsize ? MAILDIR_EXTRA_VIRTUAL_SIZE :
d3442384ca53d4b18a493db7dd0b000f470419cfTimo Sirainen MAILDIR_EXTRA_FILE_SIZE,
d756ebcfa96bd7cff02097c8f26df9df368b81b1Timo Sirainen size_r))
d756ebcfa96bd7cff02097c8f26df9df368b81b1Timo Sirainen return 1;
d756ebcfa96bd7cff02097c8f26df9df368b81b1Timo Sirainen
c979eeda1f46483d9c963e265786b701d7683d77Timo Sirainen /* size can be included in uidlist entry */
c979eeda1f46483d9c963e265786b701d7683d77Timo Sirainen if (_mail->uid != 0) {
d756ebcfa96bd7cff02097c8f26df9df368b81b1Timo Sirainen key = vsize ? MAILDIR_UIDLIST_REC_EXT_VSIZE :
2584e86cc2d8c31ba30a4109cf4ba09d1e37e28aTimo Sirainen MAILDIR_UIDLIST_REC_EXT_PSIZE;
d756ebcfa96bd7cff02097c8f26df9df368b81b1Timo Sirainen value = maildir_uidlist_lookup_ext(mbox->uidlist, _mail->uid,
4b41116563110d00330896a568eff1078c382827Timo Sirainen key);
4b41116563110d00330896a568eff1078c382827Timo Sirainen if (value != NULL) {
4b41116563110d00330896a568eff1078c382827Timo Sirainen size = strtoull(value, &p, 10);
5137d2d80255938a0f5fb8f3c1a21b34cf11ada3Timo Sirainen if (*p == '\0') {
5137d2d80255938a0f5fb8f3c1a21b34cf11ada3Timo Sirainen *size_r = size;
5137d2d80255938a0f5fb8f3c1a21b34cf11ada3Timo Sirainen return 1;
f81f4bc282cd1944cec187bae89c0701a416ed2aTimo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen return 0;
c6ce2e251ac75fa650c7fbfa52150eae69386293Martti Rannanjärvi}
c6ce2e251ac75fa650c7fbfa52150eae69386293Martti Rannanjärvi
b2c1349cf07410aefab0f5b17153af9e5cfcf48fTimo Sirainenstatic void
96308127e006bb3b1108093bcf4cc1fd9481cb7aTimo Sirainenmaildir_handle_size_caching(struct index_mail *mail, bool quick_check,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen bool vsize)
dbe64f3893616a4005c8946be75d2dc8f6823d72Timo Sirainen{
8a13b020f90e080570658b18c042e7e352c8b14fTimo Sirainen struct maildir_mailbox *mbox = (struct maildir_mailbox *)mail->ibox;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen enum mail_fetch_field field;
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen uoff_t size;
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen int pop3_state;
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen field = vsize ? MAIL_FETCH_VIRTUAL_SIZE : MAIL_FETCH_PHYSICAL_SIZE;
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen if ((mail->data.dont_cache_fetch_fields & field) != 0)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return;
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen
c4b376dd6e0c423006d7ac83a39253bcaf8e7c47Timo Sirainen if (quick_check && maildir_quick_size_lookup(mail, vsize, &size) > 0) {
eef4ba0cc3e78f8c26804c1c9251a76580a41f0cTimo Sirainen /* already in filename / uidlist. don't add it anywhere,
eef4ba0cc3e78f8c26804c1c9251a76580a41f0cTimo Sirainen including to the uidlist if it's already in filename.
eef4ba0cc3e78f8c26804c1c9251a76580a41f0cTimo Sirainen do some extra checks here to catch potential cache bugs. */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (vsize && mail->data.virtual_size != size) {
f3bb2fbe87425dc89a839908985af496f7f65702Timo Sirainen mail_cache_set_corrupted(mail->ibox->cache,
eef4ba0cc3e78f8c26804c1c9251a76580a41f0cTimo Sirainen "Corrupted virtual size for uid=%u: "
a3ee5ce6ecc8e228ee69300fdd562d7ac8be89a7Timo Sirainen "%"PRIuUOFF_T" != %"PRIuUOFF_T,
bd1b2615928a1e8be190cb0405754f0aec8cac2fTimo Sirainen mail->mail.mail.uid,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen mail->data.virtual_size, size);
e3aeeb634245e80d4f643f8d2eea11d6b72336d8Timo Sirainen mail->data.virtual_size = size;
e3aeeb634245e80d4f643f8d2eea11d6b72336d8Timo Sirainen } else if (!vsize && mail->data.physical_size != size) {
e3aeeb634245e80d4f643f8d2eea11d6b72336d8Timo Sirainen mail_cache_set_corrupted(mail->ibox->cache,
a423d985ba7261661475811c22b21b80ec765a71Timo Sirainen "Corrupted physical size for uid=%u: "
2ebeb22b9a8a8bb7fbe2f2e2908478a220792b87Timo Sirainen "%"PRIuUOFF_T" != %"PRIuUOFF_T,
a423d985ba7261661475811c22b21b80ec765a71Timo Sirainen mail->mail.mail.uid,
bd4d0a1a7c0626452b8d82f37e3ec07267ac9896Timo Sirainen mail->data.physical_size, size);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen mail->data.physical_size = size;
1460ef7a18c53216ddb4a94bb62fba96076aae8eTimo Sirainen }
1460ef7a18c53216ddb4a94bb62fba96076aae8eTimo Sirainen mail->data.dont_cache_fetch_fields |= field;
1460ef7a18c53216ddb4a94bb62fba96076aae8eTimo Sirainen return;
1460ef7a18c53216ddb4a94bb62fba96076aae8eTimo Sirainen }
1460ef7a18c53216ddb4a94bb62fba96076aae8eTimo Sirainen
1460ef7a18c53216ddb4a94bb62fba96076aae8eTimo Sirainen /* 1 = pop3-only, 0 = mixed, -1 = no pop3 */
1460ef7a18c53216ddb4a94bb62fba96076aae8eTimo Sirainen pop3_state = maildir_get_pop3_state(mail);
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainen if (pop3_state >= 0 && mail->mail.mail.uid != 0) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen /* if size is wanted permanently, store it to uidlist
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen so that in case cache file gets lost we can get it quickly */
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen mail->data.dont_cache_fetch_fields |= field;
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen size = vsize ? mail->data.virtual_size :
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen mail->data.physical_size;
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen maildir_uidlist_set_ext(mbox->uidlist, mail->mail.mail.uid,
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen vsize ? MAILDIR_UIDLIST_REC_EXT_VSIZE :
0177594fa5217b02001f4ec8752154fd2b05c545Timo Sirainen MAILDIR_UIDLIST_REC_EXT_PSIZE,
0177594fa5217b02001f4ec8752154fd2b05c545Timo Sirainen dec2str(size));
0177594fa5217b02001f4ec8752154fd2b05c545Timo Sirainen }
0177594fa5217b02001f4ec8752154fd2b05c545Timo Sirainen}
0177594fa5217b02001f4ec8752154fd2b05c545Timo Sirainen
0177594fa5217b02001f4ec8752154fd2b05c545Timo Sirainenstatic int maildir_mail_get_virtual_size(struct mail *_mail, uoff_t *size_r)
2c70086138fe7ac9abf52cd4223c224fe0bbb488Timo Sirainen{
2c70086138fe7ac9abf52cd4223c224fe0bbb488Timo Sirainen struct index_mail *mail = (struct index_mail *)_mail;
2c70086138fe7ac9abf52cd4223c224fe0bbb488Timo Sirainen struct index_mail_data *data = &mail->data;
2c70086138fe7ac9abf52cd4223c224fe0bbb488Timo Sirainen struct message_size hdr_size, body_size;
2c70086138fe7ac9abf52cd4223c224fe0bbb488Timo Sirainen struct istream *input;
2c70086138fe7ac9abf52cd4223c224fe0bbb488Timo Sirainen uoff_t old_offset;
2b9dbb270ad82e58d5f3581436e6f143176d5819Timo Sirainen
2b9dbb270ad82e58d5f3581436e6f143176d5819Timo Sirainen if (index_mail_get_cached_virtual_size(mail, size_r)) {
2b9dbb270ad82e58d5f3581436e6f143176d5819Timo Sirainen i_assert(mail->data.virtual_size != (uoff_t)-1);
2b9dbb270ad82e58d5f3581436e6f143176d5819Timo Sirainen maildir_handle_size_caching(mail, TRUE, TRUE);
1ae5d61ec366fdb2f3c5b150ca378d6141b0f4bdTimo Sirainen return 0;
1ae5d61ec366fdb2f3c5b150ca378d6141b0f4bdTimo Sirainen }
1ae5d61ec366fdb2f3c5b150ca378d6141b0f4bdTimo Sirainen
1ae5d61ec366fdb2f3c5b150ca378d6141b0f4bdTimo Sirainen if (maildir_quick_size_lookup(mail, TRUE, &data->virtual_size) < 0)
1ae5d61ec366fdb2f3c5b150ca378d6141b0f4bdTimo Sirainen return -1;
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen if (data->virtual_size != (uoff_t)-1) {
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen data->dont_cache_fetch_fields |= MAIL_FETCH_VIRTUAL_SIZE;
df00412606a00714a6e85383fa87fbdc7cc1fb5bTimo Sirainen *size_r = data->virtual_size;
df00412606a00714a6e85383fa87fbdc7cc1fb5bTimo Sirainen return 0;
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen }
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen
b644a77b00ce21c67a7becda974a12dfe3a946e4Timo Sirainen /* fallback to reading the file */
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen old_offset = data->stream == NULL ? 0 : data->stream->v_offset;
aa41b2e17912d6cad3151babea6a85dd88539d28Timo Sirainen if (mail_get_stream(_mail, &hdr_size, &body_size, &input) < 0)
aa41b2e17912d6cad3151babea6a85dd88539d28Timo Sirainen return -1;
aa41b2e17912d6cad3151babea6a85dd88539d28Timo Sirainen i_stream_seek(data->stream, old_offset);
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen
d938e9e4ec4c0f326dffd5ebe42c1ad893ce7e52Timo Sirainen maildir_handle_size_caching(mail, FALSE, TRUE);
eecb235c14b49c01774134ea593c266f2d2c2be1Timo Sirainen *size_r = data->virtual_size;
eecb235c14b49c01774134ea593c266f2d2c2be1Timo Sirainen return 0;
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen}
ca98892a6b8a30ffc1fe26fcf02c7d59e3204e7eTimo Sirainen
ca98d6a1bbe73499da758a36bfab2963375c8d06Timo Sirainenstatic int maildir_mail_get_physical_size(struct mail *_mail, uoff_t *size_r)
ca98d6a1bbe73499da758a36bfab2963375c8d06Timo Sirainen{
ca98d6a1bbe73499da758a36bfab2963375c8d06Timo Sirainen struct index_mail *mail = (struct index_mail *)_mail;
5da1aa5197a43d83f0fb3eeb83125c7cd73d1b62Timo Sirainen struct maildir_mailbox *mbox = (struct maildir_mailbox *)mail->ibox;
5da1aa5197a43d83f0fb3eeb83125c7cd73d1b62Timo Sirainen struct index_mail_data *data = &mail->data;
5da1aa5197a43d83f0fb3eeb83125c7cd73d1b62Timo Sirainen struct stat st;
5da1aa5197a43d83f0fb3eeb83125c7cd73d1b62Timo Sirainen const char *path;
5da1aa5197a43d83f0fb3eeb83125c7cd73d1b62Timo Sirainen int ret;
ca98892a6b8a30ffc1fe26fcf02c7d59e3204e7eTimo Sirainen
ca98892a6b8a30ffc1fe26fcf02c7d59e3204e7eTimo Sirainen if (index_mail_get_physical_size(_mail, size_r) == 0) {
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen i_assert(mail->data.physical_size != (uoff_t)-1);
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen maildir_handle_size_caching(mail, TRUE, FALSE);
ca98892a6b8a30ffc1fe26fcf02c7d59e3204e7eTimo Sirainen return 0;
546335814920fb6b5b44c68c7803e654eefeae9dTimo Sirainen }
546335814920fb6b5b44c68c7803e654eefeae9dTimo Sirainen
546335814920fb6b5b44c68c7803e654eefeae9dTimo Sirainen if (maildir_quick_size_lookup(mail, FALSE, &data->physical_size) < 0)
4b41218f9e09386ad5d8f279355aad1dfb64392dTimo Sirainen return -1;
4b41218f9e09386ad5d8f279355aad1dfb64392dTimo Sirainen if (data->physical_size != (uoff_t)-1) {
ca98d6a1bbe73499da758a36bfab2963375c8d06Timo Sirainen data->dont_cache_fetch_fields |= MAIL_FETCH_PHYSICAL_SIZE;
ca98d6a1bbe73499da758a36bfab2963375c8d06Timo Sirainen *size_r = data->physical_size;
ca98d6a1bbe73499da758a36bfab2963375c8d06Timo Sirainen return 0;
eb1572d7c44ebc7b0b039d085c3dbab2ef7043ddTimo Sirainen }
eb1572d7c44ebc7b0b039d085c3dbab2ef7043ddTimo Sirainen
ca98d6a1bbe73499da758a36bfab2963375c8d06Timo Sirainen if (_mail->uid != 0) {
bd4e36a8cd7257cca7d1434c49a1e343ed7c5100Timo Sirainen ret = maildir_file_do(mbox, _mail->uid, do_stat, &st);
bd4e36a8cd7257cca7d1434c49a1e343ed7c5100Timo Sirainen if (ret <= 0) {
bd4e36a8cd7257cca7d1434c49a1e343ed7c5100Timo Sirainen if (ret == 0)
bd4e36a8cd7257cca7d1434c49a1e343ed7c5100Timo Sirainen mail_set_expunged(_mail);
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen return -1;
df00412606a00714a6e85383fa87fbdc7cc1fb5bTimo Sirainen }
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen } else {
42507d758b053bb483de58fba55c73a9eb5d3fbaTimo Sirainen /* saved mail which hasn't been committed yet */
c0c346d0e6a76137ba5006857ed03b1227804170Timo Sirainen path = maildir_save_file_get_path(_mail->transaction,
a2f250a332dfc1e6cd4ffd196c621eb9dbf7b8a1Timo Sirainen _mail->seq);
0177594fa5217b02001f4ec8752154fd2b05c545Timo Sirainen if (stat(path, &st) < 0) {
382f23541ce657be87b079abd6784d376fb4eb43Timo Sirainen mail_storage_set_critical(_mail->box->storage,
2b9dbb270ad82e58d5f3581436e6f143176d5819Timo Sirainen "stat(%s) failed: %m", path);
97a5e150cacf7da9dd200e317b75460352038d65Timo Sirainen return -1;
3743948b65bd079cd6f2502d35bd21666c1a2f5aAki Tuomi }
134987bc3b685d7ec71c04e9337f7125cff0698fTimo Sirainen }
42507d758b053bb483de58fba55c73a9eb5d3fbaTimo Sirainen
817d027593510c3ba70ad542ce0011f5f6916d1eTimo Sirainen data->physical_size = st.st_size;
817d027593510c3ba70ad542ce0011f5f6916d1eTimo Sirainen maildir_handle_size_caching(mail, FALSE, FALSE);
817d027593510c3ba70ad542ce0011f5f6916d1eTimo Sirainen *size_r = st.st_size;
817d027593510c3ba70ad542ce0011f5f6916d1eTimo Sirainen return 0;
817d027593510c3ba70ad542ce0011f5f6916d1eTimo Sirainen}
6ae329de09afb7214c906d762320847e05469d53Timo Sirainen
6ae329de09afb7214c906d762320847e05469d53Timo Sirainenstatic int
f81f4bc282cd1944cec187bae89c0701a416ed2aTimo Sirainenmaildir_mail_get_special(struct mail *_mail, enum mail_fetch_field field,
f81f4bc282cd1944cec187bae89c0701a416ed2aTimo Sirainen const char **value_r)
f81f4bc282cd1944cec187bae89c0701a416ed2aTimo Sirainen{
7e2671b295927b461adc8b6c4ed6a1c4761fb323Timo Sirainen struct index_mail *mail = (struct index_mail *)_mail;
7e2671b295927b461adc8b6c4ed6a1c4761fb323Timo Sirainen struct maildir_mailbox *mbox = (struct maildir_mailbox *)mail->ibox;
f81f4bc282cd1944cec187bae89c0701a416ed2aTimo Sirainen const char *path, *fname, *end, *uidl;
fcfe85637e1ee14a9fc39c41fd6ceca106301542Timo Sirainen
fcfe85637e1ee14a9fc39c41fd6ceca106301542Timo Sirainen switch (field) {
fcfe85637e1ee14a9fc39c41fd6ceca106301542Timo Sirainen case MAIL_FETCH_UIDL_FILE_NAME:
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen case MAIL_FETCH_GUID:
4ee00532a265bdfb38539d811fcd12d51210ac35Timo Sirainen if (_mail->uid != 0) {
3dd0679b6f24be0287cc42d7a60bbf59cdf8b637Timo Sirainen if (!maildir_mail_get_fname(mbox, _mail, &fname))
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen return -1;
4ee00532a265bdfb38539d811fcd12d51210ac35Timo Sirainen } else {
5fb3bff645380804c9db2510940c41db6b8fdb01Timo Sirainen path = maildir_save_file_get_path(_mail->transaction,
5fb3bff645380804c9db2510940c41db6b8fdb01Timo Sirainen _mail->seq);
5fb3bff645380804c9db2510940c41db6b8fdb01Timo Sirainen fname = strrchr(path, '/');
0dffa25d211be541ee3c953b23566a1a990789dfTimo Sirainen fname = fname != NULL ? fname + 1 : path;
4bbd396aa6198c84f3f7763b6e8a63a26e97e141Timo Sirainen }
0dffa25d211be541ee3c953b23566a1a990789dfTimo Sirainen end = strchr(fname, MAILDIR_INFO_SEP);
7baab0b0b60df7ce9093d0881cd322dff1e79491Timo Sirainen *value_r = end == NULL ? fname : t_strdup_until(fname, end);
0dffa25d211be541ee3c953b23566a1a990789dfTimo Sirainen return 0;
3f91e60401495a4046c73992fabaa5e77200a451Timo Sirainen case MAIL_FETCH_UIDL_BACKEND:
0dffa25d211be541ee3c953b23566a1a990789dfTimo Sirainen uidl = maildir_uidlist_lookup_ext(mbox->uidlist, _mail->uid,
3857e2945a3b6744d603f0f5a656849ed8436ba3Timo Sirainen MAILDIR_UIDLIST_REC_EXT_POP3_UIDL);
3857e2945a3b6744d603f0f5a656849ed8436ba3Timo Sirainen *value_r = uidl != NULL ? uidl : "";
f90cbe597c41d5cc91debd371f8648bd8e6ffbc2Timo Sirainen return 0;
0dffa25d211be541ee3c953b23566a1a990789dfTimo Sirainen default:
33b469d1ca66dd2cc496d2d990b8b98e72952a29Timo Sirainen return index_mail_get_special(_mail, field, value_r);
0dffa25d211be541ee3c953b23566a1a990789dfTimo Sirainen }
58ba0fe5a6904d3a65cfe268411f4cbb881234eeTimo Sirainen}
58ba0fe5a6904d3a65cfe268411f4cbb881234eeTimo Sirainen
0dffa25d211be541ee3c953b23566a1a990789dfTimo Sirainenstatic int maildir_mail_get_stream(struct mail *_mail,
6b0d8106ae51ffc6ce45636b34d2e21cbefca7fdTimo Sirainen struct message_size *hdr_size,
0dffa25d211be541ee3c953b23566a1a990789dfTimo Sirainen struct message_size *body_size,
eb64c3586d854cddd693f0b811d897399076a441Timo Sirainen struct istream **stream_r)
0dffa25d211be541ee3c953b23566a1a990789dfTimo Sirainen{
eb64c3586d854cddd693f0b811d897399076a441Timo Sirainen struct index_mail *mail = (struct index_mail *)_mail;
0dffa25d211be541ee3c953b23566a1a990789dfTimo Sirainen struct maildir_mailbox *mbox = (struct maildir_mailbox *)mail->ibox;
7f735cb86b2d8abd8f230089065eacfc24e9e5d6Timo Sirainen struct index_mail_data *data = &mail->data;
7f735cb86b2d8abd8f230089065eacfc24e9e5d6Timo Sirainen bool deleted;
7f735cb86b2d8abd8f230089065eacfc24e9e5d6Timo Sirainen
0dffa25d211be541ee3c953b23566a1a990789dfTimo Sirainen if (data->stream == NULL) {
b3484b5b1f47e4cf112f0e371478a2d7794b31bbTimo Sirainen data->stream = maildir_open_mail(mbox, _mail, &deleted);
0dffa25d211be541ee3c953b23566a1a990789dfTimo Sirainen if (data->stream == NULL) {
d81131d3bbb4f0befb62a661d1785cf8c84a17e2Timo Sirainen if (deleted)
0dffa25d211be541ee3c953b23566a1a990789dfTimo Sirainen mail_set_expunged(_mail);
9456a4a3e74929f9d3d5b00b93be6d8eb69bc52aTimo Sirainen return -1;
0dffa25d211be541ee3c953b23566a1a990789dfTimo Sirainen }
4e3bcf7fdaeef92dd07a2acb1ded58422a907e87Timo Sirainen }
0dffa25d211be541ee3c953b23566a1a990789dfTimo Sirainen
19e161dd9e2c3a2ffc96ee8852bec0720cb30d1cTimo Sirainen return index_mail_init_stream(mail, hdr_size, body_size, stream_r);
0dffa25d211be541ee3c953b23566a1a990789dfTimo Sirainen}
540555c5b435203e1c26c8e7b924b2643ae07ae3Timo Sirainen
540555c5b435203e1c26c8e7b924b2643ae07ae3Timo Sirainenstatic void maildir_mail_set_cache_corrupted(struct mail *_mail,
540555c5b435203e1c26c8e7b924b2643ae07ae3Timo Sirainen enum mail_fetch_field field)
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen{
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen struct index_mail *mail = (struct index_mail *)_mail;
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen struct maildir_mailbox *mbox = (struct maildir_mailbox *)mail->ibox;
0d86aa0d47f7393c669c084b34c0537b193688adTimo Sirainen enum maildir_uidlist_rec_flag flags;
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen const char *fname;
7631f16156aca373004953fe6b01a7f343fb47e0Timo Sirainen uoff_t size;
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen
aa247243412a49f9bdebf7255e131dc6ece4ed46Timo Sirainen if (field == MAIL_FETCH_VIRTUAL_SIZE) {
e15b305e90c9834734ccf35ed78f0ad29d570ee9Timo Sirainen /* make sure it gets removed from uidlist.
421d30619384e72a27e2a5d13ff6525aff4d17feTimo Sirainen if it's in file name, we can't really do more than log it. */
ecd69c4e8371853667e01b0c16d436ef7f7393e2Timo Sirainen fname = maildir_uidlist_lookup(mbox->uidlist,
ecd69c4e8371853667e01b0c16d436ef7f7393e2Timo Sirainen _mail->uid, &flags);
ecd69c4e8371853667e01b0c16d436ef7f7393e2Timo Sirainen if (maildir_filename_get_size(fname, MAILDIR_EXTRA_VIRTUAL_SIZE,
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen &size)) {
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen i_error("Maildir filename has wrong W value: %s/%s",
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen mbox->path, fname);
a757f31393b9d6fc7760a9dec8363404ab3ae576Timo Sirainen } else if (maildir_uidlist_lookup_ext(mbox->uidlist, _mail->uid,
a757f31393b9d6fc7760a9dec8363404ab3ae576Timo Sirainen MAILDIR_UIDLIST_REC_EXT_VSIZE) != NULL) {
a2f250a332dfc1e6cd4ffd196c621eb9dbf7b8a1Timo Sirainen maildir_uidlist_set_ext(mbox->uidlist, _mail->uid,
f46885a5b78b15a8d2419f6e5d13b643bd85e41fTimo Sirainen MAILDIR_UIDLIST_REC_EXT_VSIZE,
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen NULL);
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen }
c0225f7f6b43d34dc58c17d3304f0fd60ab89894Timo Sirainen }
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen index_mail_set_cache_corrupted(_mail, field);
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen}
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainenstruct mail_vfuncs maildir_mail_vfuncs = {
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen index_mail_close,
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen index_mail_free,
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen index_mail_set_seq,
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen index_mail_set_uid,
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen index_mail_get_flags,
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen index_mail_get_keywords,
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen index_mail_get_keyword_indexes,
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen index_mail_get_modseq,
6df0ab0c1ab91f06b6418cb30eff44405a1b8f02Timo Sirainen index_mail_get_parts,
6df0ab0c1ab91f06b6418cb30eff44405a1b8f02Timo Sirainen index_mail_get_date,
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen maildir_mail_get_received_date,
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen maildir_mail_get_save_date,
306b3f41b05da642d87e7ca7a1496efce9f5902fTimo Sirainen maildir_mail_get_virtual_size,
306b3f41b05da642d87e7ca7a1496efce9f5902fTimo Sirainen maildir_mail_get_physical_size,
306b3f41b05da642d87e7ca7a1496efce9f5902fTimo Sirainen index_mail_get_first_header,
e53ab6c7081246c865917f9aa0eff031a08ad1e7Timo Sirainen index_mail_get_headers,
e53ab6c7081246c865917f9aa0eff031a08ad1e7Timo Sirainen index_mail_get_header_stream,
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen maildir_mail_get_stream,
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen maildir_mail_get_special,
83bb013a99f0936995f9c7a1077822662d8fefdbTimo Sirainen index_mail_update_flags,
21aaa6affb9f134112b75b5db737309fc35ef1cfMartti Rannanjärvi index_mail_update_keywords,
fdc557286bc9f92c5f3bb49096ff6e2bcec0ea79Timo Sirainen index_mail_expunge,
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen maildir_mail_set_cache_corrupted,
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen index_mail_get_index_mail
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen};
73b50eecfc31750a312e2f940023f522eb07178cTimo Sirainen