/* Copyright (c) 2003-2018 Dovecot authors, see the included COPYING file */
#include "lib.h"
#include "array.h"
#include "buffer.h"
#include "str.h"
#include "mail-cache-private.h"
const struct mail_cache_record **rec_r)
{
const void *data;
int ret;
/* records are always 32-bit aligned */
return -1;
}
/* we don't know yet how large the record is, so just guess */
&data) < 0)
return -1;
return -1;
}
return -1;
}
/* larger than we guessed. map the rest of the record. */
return -1;
if (ret == 0) {
return -1;
}
}
return 0;
}
{
const void *data;
/* no cache offsets */
return 0;
}
if (offset == 0)
return 0;
i_unreached();
return offset;
}
static int
{
int i, ret;
if (offset == 0)
return 0;
/* reset_id must match file_seq or the offset is for a different cache
file. if this happens, try if reopening the cache helps. if not,
it was probably for an old cache file that's already lost by now. */
i = 0;
return 0;
/* we're probably compressing */
return 0;
}
/* error / we already have the latest file open */
return ret;
}
}
return 1;
}
{
/* looping happens only in rare error conditions, so it's enough if we
just catch it eventually. we do this by checking if we've seen
more record data than possible in the accessed file area. */
if (loop_track->size_sum == 0) {
/* first call */
} else {
}
return loop_track->size_sum >
}
struct mail_cache_lookup_iterate_ctx *ctx_r)
{
int ret;
/* look up the first offset */
if (ret <= 0) {
}
}
}
static bool
{
&ctx->trans_next_idx);
return FALSE;
return TRUE;
}
static int
{
return -1;
/* end of this record list. check newly appended data. */
return 0;
/* check data still in memory. this works for recent mails
even with INDEX=MEMORY */
if (!ctx->memory_appends_checked) {
return 1;
}
return 0;
/* check data already written to cache file */
if (ctx->disk_appends_checked ||
return 0;
}
return 0;
/* look up the next record */
return -1;
"record list is circular");
return -1;
}
return 1;
}
struct mail_cache_iterate_field *field_r)
{
unsigned int field_idx;
unsigned int data_size;
int ret;
"record has invalid size");
return -1;
}
return ret;
}
/* return the next field */
/* new field, have to re-read fields header to figure
out its size. don't do this if we're compressing. */
if (mail_cache_header_fields_read(cache) < 0)
return -1;
}
"field index too large (%u >= %u)",
return -1;
}
/* field reading might have re-mmaped the file and
caused rec pointer to break. need to get it again. */
return -1;
}
/* variable size field. get its size from the file. */
}
"record continues outside its allocated size");
return -1;
}
/* each record begins from 32bit aligned position */
return 1;
}
{
int ret;
if (++view->cached_exists_value == 0) {
/* wrapped, we'll have to clear the buffer */
}
}
return ret;
}
static bool
{
}
unsigned int field)
{
return 0;
/* FIXME: we should discard the cache if view has been synced */
return -1;
}
}
{
}
{
}
static int
unsigned int field_idx, unsigned int field_size,
{
const unsigned char *src;
unsigned char *dest;
unsigned int i;
int ret;
/* make sure all bits are cleared first */
continue;
/* merge all bits */
}
}
{
int ret;
if (ret <= 0)
return ret;
/* the field should exist */
dest_buf);
}
/* return the first one that's found. if there are multiple
they're all identical. */
break;
}
}
return ret;
}
struct header_lookup_data {
const unsigned char *data;
};
struct header_lookup_line {
};
struct header_lookup_context {
};
enum {
};
const struct mail_cache_iterate_field *field)
{
void *data_dup;
/* data = { line_nums[], 0, "headers" } */
if (lines[i] == 0)
break;
}
lines_count = i;
if (data_size > 0) {
}
for (i = 0; i < lines_count; i++) {
}
}
const struct header_lookup_line *l2)
{
}
static int
{
int ret;
if (fields_count == 0)
return 1;
/* update the decision state regardless of whether the fields
actually exist or not. */
for (i = 0; i < fields_count; i++)
/* mark all the fields we want to find. */
for (i = 0; i < fields_count; i++) {
return 0;
if (field_idxs[i] > max_field)
max_field = field_idxs[i];
}
/* lookup the fields */
/* a) don't want it, b) duplicate */
} else {
}
}
if (ret < 0)
return -1;
/* check that all fields were found */
for (i = 0; i <= max_field; i++) {
if (field_state[i] == HDR_FIELD_STATE_WANT)
return 0;
}
/* we need to return headers in the order they existed originally.
we can do this by sorting the messages by their line numbers. */
/* then start filling dest buffer from the headers */
for (i = 0; i < count; i++) {
/* find the end of the (multiline) header */
if (*p == '\n' &&
p++;
break;
}
}
/* if there are more lines for this header, the following lines
continue after this one. so skip this line. */
}
return 1;
}
unsigned int fields_count)
{
int ret;
T_BEGIN {
&pool);
pool_unref(&pool);
} T_END;
return ret;
}
static uint32_t
{
/* find the newest mail that has anything in cache */
/* reason_cache matches the current view - we can use it */
} else {
}
/* first check anything not already in reason_cache */
return seq;
}
}
if (seq == 0)
return 0;
/* then return the result from cache */
return rc->highest_seq_with_cache;
}
const char *
{
return "Cache file is unusable";
if (offset != 0) {
return t_strdup_printf(
"Index reset_id=%u doesn't match cache reset_id=%u",
}
return t_strdup_printf(
"Mail has other cached fields, reset_id=%u", reset_id);
}
if (seq == 0) {
return t_strdup_printf("Cache file is empty, reset_id=%u",
}
return t_strdup_printf(
"Mail not cached, highest cached seq=%u uid=%u: "
"Index reset_id=%u doesn't match cache reset_id=%u",
}
return t_strdup_printf(
"Mail not cached, highest cached seq=%u uid=%u: reset_id=%u",
}