maildir-mail.c revision e4e7475f646d66a257d682738fbff1f206ce4924
/* Copyright (c) 2003-2010 Dovecot authors, see the included COPYING file */
#include "lib.h"
#include "istream.h"
#include "index-mail.h"
#include "maildir-storage.h"
#include "maildir-filename.h"
#include "maildir-uidlist.h"
#include "maildir-sync.h"
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
struct maildir_open_context {
int fd;
char *path;
};
static int
struct maildir_open_context *ctx)
{
return 1;
}
return 0;
} else {
"open(%s) failed: %m", path);
}
return -1;
}
static int
{
return 1;
return 0;
} else {
"stat(%s) failed: %m", path);
}
return -1;
}
static int
{
"Maildir: rmdir()ed unwanted empty directory: %s",
path);
return 0;
} else {
"Maildir: Found unwanted directory %s, "
"but rmdir() failed: %m", path);
return -1;
}
}
static struct istream *
bool *deleted_r)
{
const char *path;
struct maildir_open_context ctx;
p->stats_open_lookup_count++;
return NULL;
} else {
return NULL;
}
return NULL;
}
/* there's a directory in maildir. many installations seem to
have messed up something and causing "cur", "new" and "tmp"
directories to be created under the "cur" directory.
if the directory is empty, just get rid of it and log an
error */
} else {
}
return input;
}
{
const char *path;
int ret;
return mail_set_aborted(mail);
/* we're going to open the mail anyway */
}
return -1;
if (ret <= 0) {
if (ret == 0)
return -1;
}
} else {
"stat(%s) failed: %m", path);
return -1;
}
}
return 0;
}
{
return 0;
return -1;
return 0;
}
{
return 0;
return -1;
return 0;
}
static int
const char **fname_r)
{
struct mail_index_view *view;
bool exists;
int ret;
if (ret != 0)
return ret;
/* file exists in index file, but not in dovecot-uidlist anymore. */
/* one reason this could happen is if we delayed opening
dovecot-uidlist and we're trying to open a mail that got recently
expunged. Let's test this theory first: */
if (exists) {
/* the message still exists in index. this means there's some
kind of a desync, which doesn't get fixed if cur/ mtime is
the same as in index. fix this by forcing a resync. */
}
return 0;
}
{
const struct mail_cache_field *fields;
bool not_pop3_only = FALSE;
if (mail->pop3_state_set)
return mail->pop3_state;
/* if this mail itself has non-pop3 fields we know we're not
pop3-only */
/* get vsize decisions */
if (not_pop3_only) {
} else {
/* also check if there are any non-[pv]size cached fields */
&count);
for (i = 0; i < count; i++) {
else if (dec != MAIL_CACHE_DECISION_NO &&
}
}
if (!not_pop3_only) {
/* either nothing is cached, or only vsize is cached. */
} else if (vsize_dec != MAIL_CACHE_DECISION_YES &&
/* if virtual size isn't cached permanently,
POP3 isn't being used */
} else {
mail->pop3_state = 0;
}
return mail->pop3_state;
}
{
return -1;
} else {
}
/* size can be included in filename */
size_r))
return 1;
/* size can be included in uidlist entry */
key);
return 1;
}
return 0;
}
static void
bool vsize)
{
enum mail_fetch_field field;
int pop3_state;
return;
/* already in filename / uidlist. don't add it anywhere,
including to the uidlist if it's already in filename.
do some extra checks here to catch potential cache bugs. */
"Corrupted virtual size for uid=%u: "
"Corrupted physical size for uid=%u: "
}
return;
}
/* 1 = pop3-only, 0 = mixed, -1 = no pop3 */
/* if size is wanted permanently, store it to uidlist
so that in case cache file gets lost we can get it quickly */
}
}
{
return 0;
}
return -1;
return 0;
}
/* fallback to reading the file */
return -1;
return 0;
}
{
const char *path;
int ret;
return 0;
}
return -1;
return 0;
}
if (ret <= 0) {
if (ret == 0)
return -1;
}
} else {
/* saved mail which hasn't been committed yet */
"stat(%s) failed: %m", path);
return -1;
}
}
return 0;
}
static int
const char **value_r)
{
switch (field) {
case MAIL_FETCH_GUID:
/* use GUID from uidlist if it exists */
return 0;
}
/* default to base filename: */
return 0;
}
return -1;
} else {
}
return 0;
case MAIL_FETCH_UIDL_BACKEND:
/* use the default */
*value_r = "";
} else if (*uidl == '\0') {
/* special optimization case: use the base file name */
return maildir_mail_get_special(_mail,
} else {
}
return 0;
default:
}
}
struct message_size *hdr_size,
struct message_size *body_size,
{
bool deleted;
if (deleted)
return -1;
}
}
}
{
const char *fname;
&fname) == 0 &&
/* special case optimization: empty UIDL means the same
as base filename */
uidl = "";
}
}
enum mail_fetch_field field)
{
const char *fname;
int ret;
if (field == MAIL_FETCH_VIRTUAL_SIZE) {
/* make sure it gets removed from uidlist.
if it's in file name, we can't really do more than log it. */
if (ret <= 0)
return;
&size)) {
const char *subdir =
(flags & MAILDIR_UIDLIST_REC_FLAG_NEW_DIR) != 0 ?
"new" : "cur";
"Maildir filename has wrong W value: %s/%s/%s",
NULL);
}
}
}
struct mail_vfuncs maildir_mail_vfuncs = {
};