mail-cache-fields.c revision 9c4c535b86e9473ad97c6e9242ed84f3d9d69d0d
02c335c23bf5fa225a467c19f2c063fb0dc7b8c3Timo Sirainen/* Copyright (c) 2004-2007 Dovecot authors, see the included COPYING file */
8a8a3b43987b5ade914f22765e51c9e3de8179d3Timo Sirainen#define CACHE_FIELD_IS_NEWLY_WANTED(cache, field_idx) \
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainen ((cache)->field_file_map[field_idx] == (uint32_t)-1 && \
baf346e71ebd7b44fcba4b48f4d39845453b778bTimo Sirainenstatic bool field_has_fixed_size(enum mail_cache_field_type type)
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainenstatic bool field_decision_is_valid(enum mail_cache_decision_type type)
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainenstatic int field_type_verify(struct mail_cache *cache, unsigned int idx,
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainen enum mail_cache_field_type type, unsigned int size)
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainen const struct mail_cache_field *field = &cache->fields[idx].field;
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainen "registered field %s type changed", field->name);
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainen if (field->field_size != size && field_has_fixed_size(type)) {
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainen "registered field %s size changed", field->name);
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainenvoid mail_cache_register_fields(struct mail_cache *cache,
e245fb1302121d2bc2580f61e040c2c8a558ee9eTimo Sirainen unsigned int new_idx;
d5e839aea288aceaddae28a1578cebda3c9e3b58Timo Sirainen unsigned int i, j;
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainen for (i = 0; i < fields_count; i++) {
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainen if (hash_lookup_full(cache->field_name_hash, fields[i].name,
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainen i_assert(fields[i].type < MAIL_CACHE_FIELD_COUNT);
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainen /* check if the same header is being registered in the
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainen same field array */
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainen for (j = 0; j < i; j++) {
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainen if (strcasecmp(fields[i].name, fields[j].name) == 0) {
baf346e71ebd7b44fcba4b48f4d39845453b778bTimo Sirainen /* @UNSAFE */
8a8a3b43987b5ade914f22765e51c9e3de8179d3Timo Sirainen cache->fields_count * sizeof(*cache->field_file_map),
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainen for (i = 0; i < fields_count; i++) {
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainen /* new index - save it */
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainen name = p_strdup(cache->field_pool, fields[i].name);
baf346e71ebd7b44fcba4b48f4d39845453b778bTimo Sirainen if (!field_has_fixed_size(cache->fields[idx].field.type))
baf346e71ebd7b44fcba4b48f4d39845453b778bTimo Sirainen cache->fields[idx].field.field_size = (unsigned int)-1;
baf346e71ebd7b44fcba4b48f4d39845453b778bTimo Sirainen hash_insert(cache->field_name_hash, name, POINTER_CAST(idx));
6adf683655750bcb809275cd65dc75fd12214198Timo Sirainenmail_cache_register_lookup(struct mail_cache *cache, const char *name)
baf346e71ebd7b44fcba4b48f4d39845453b778bTimo Sirainen if (hash_lookup_full(cache->field_name_hash, name,
baf346e71ebd7b44fcba4b48f4d39845453b778bTimo Sirainen return POINTER_CAST_TO(orig_value, unsigned int);
baf346e71ebd7b44fcba4b48f4d39845453b778bTimo Sirainen return (unsigned int)-1;
baf346e71ebd7b44fcba4b48f4d39845453b778bTimo Sirainenmail_cache_register_get_list(struct mail_cache *cache, pool_t pool,
baf346e71ebd7b44fcba4b48f4d39845453b778bTimo Sirainen unsigned int *count_r)
baf346e71ebd7b44fcba4b48f4d39845453b778bTimo Sirainen unsigned int i;
baf346e71ebd7b44fcba4b48f4d39845453b778bTimo Sirainen list = p_new(pool, struct mail_cache_field, cache->fields_count);
baf346e71ebd7b44fcba4b48f4d39845453b778bTimo Sirainenstatic int mail_cache_header_fields_get_offset(struct mail_cache *cache,
baf346e71ebd7b44fcba4b48f4d39845453b778bTimo Sirainen const struct mail_cache_header_fields *field_hdr;
baf346e71ebd7b44fcba4b48f4d39845453b778bTimo Sirainen struct mail_cache_header_fields tmp_field_hdr;
baf346e71ebd7b44fcba4b48f4d39845453b778bTimo Sirainen unsigned int next_count = 0;
baf346e71ebd7b44fcba4b48f4d39845453b778bTimo Sirainen /* find the latest header */
baf346e71ebd7b44fcba4b48f4d39845453b778bTimo Sirainen next_offset = cache->last_field_header_offset != 0 ?
6adf683655750bcb809275cd65dc75fd12214198Timo Sirainen mail_index_offset_to_uint32(cache->hdr->field_header_offset);
baf346e71ebd7b44fcba4b48f4d39845453b778bTimo Sirainen while (next_offset != 0) {
baf346e71ebd7b44fcba4b48f4d39845453b778bTimo Sirainen "next_offset in field header loops");
fb176cdc122707cda985ab3c09c02ccf3cec0af1Timo Sirainen sizeof(*field_hdr)) < 0)
fb176cdc122707cda985ab3c09c02ccf3cec0af1Timo Sirainen field_hdr = CONST_PTR_OFFSET(cache->data, offset);
d5e839aea288aceaddae28a1578cebda3c9e3b58Timo Sirainen /* if we need to follow multiple offsets to get to
d5e839aea288aceaddae28a1578cebda3c9e3b58Timo Sirainen the last one, it's faster to just pread() the file
d5e839aea288aceaddae28a1578cebda3c9e3b58Timo Sirainen instead of going through cache */
d5e839aea288aceaddae28a1578cebda3c9e3b58Timo Sirainen mail_cache_set_syscall_error(cache, "pread()");
fb176cdc122707cda985ab3c09c02ccf3cec0af1Timo Sirainen "next_offset points outside file");
baf346e71ebd7b44fcba4b48f4d39845453b778bTimo Sirainen mail_index_offset_to_uint32(field_hdr->next_offset);
2f4f603d4cebab2cc956c72164efb02da83515c5Timo Sirainen mail_cache_set_corrupted(cache, "missing header fields");
8a8a3b43987b5ade914f22765e51c9e3de8179d3Timo Sirainen if (next_count > MAIL_CACHE_HEADER_FIELD_CONTINUE_COUNT)
8a8a3b43987b5ade914f22765e51c9e3de8179d3Timo Sirainen cache->need_compress_file_seq = cache->hdr->file_seq;
8a8a3b43987b5ade914f22765e51c9e3de8179d3Timo Sirainen /* we can't trust that the cached data is valid */
8a8a3b43987b5ade914f22765e51c9e3de8179d3Timo Sirainen file_cache_invalidate(cache->file_cache, offset,
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainen if (mail_cache_map(cache, offset, field_hdr->size) < 0)
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainenint mail_cache_header_fields_read(struct mail_cache *cache)
baf346e71ebd7b44fcba4b48f4d39845453b778bTimo Sirainen const struct mail_cache_header_fields *field_hdr = NULL;
2f4f603d4cebab2cc956c72164efb02da83515c5Timo Sirainen if (mail_cache_header_fields_get_offset(cache, &offset, TRUE) < 0)
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainen /* no fields - the file is empty */
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainen field_hdr = CONST_PTR_OFFSET(cache->data, offset);
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainen if (offset + field_hdr->size > cache->mmap_length) {
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainen "field header points outside file");
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainen /* check the fixed size of the header. name[] has to be checked
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainen separately */
baf346e71ebd7b44fcba4b48f4d39845453b778bTimo Sirainen field_hdr->fields_count * (sizeof(uint32_t)*2 + 1 + 2)) {
2f4f603d4cebab2cc956c72164efb02da83515c5Timo Sirainen mail_cache_set_corrupted(cache, "invalid field header size");
2f4f603d4cebab2cc956c72164efb02da83515c5Timo Sirainen field_hdr = CONST_PTR_OFFSET(cache->data, offset);
baf346e71ebd7b44fcba4b48f4d39845453b778bTimo Sirainen sizeof(unsigned int),
baf346e71ebd7b44fcba4b48f4d39845453b778bTimo Sirainen new_fields_count * sizeof(unsigned int));
baf346e71ebd7b44fcba4b48f4d39845453b778bTimo Sirainen last_used = CONST_PTR_OFFSET(field_hdr, MAIL_CACHE_FIELD_LAST_USED());
baf346e71ebd7b44fcba4b48f4d39845453b778bTimo Sirainen MAIL_CACHE_FIELD_SIZE(field_hdr->fields_count));
c096257fbdaf4b9fcf8eb97aae94afdbb4e71ed4Timo Sirainen MAIL_CACHE_FIELD_TYPE(field_hdr->fields_count));
2f4f603d4cebab2cc956c72164efb02da83515c5Timo Sirainen MAIL_CACHE_FIELD_DECISION(field_hdr->fields_count));
e44028b5df7045dd9e7f324175e73e3ff490cb5dTimo Sirainen MAIL_CACHE_FIELD_NAMES(field_hdr->fields_count));
e44028b5df7045dd9e7f324175e73e3ff490cb5dTimo Sirainen end = CONST_PTR_OFFSET(field_hdr, field_hdr->size);
baf346e71ebd7b44fcba4b48f4d39845453b778bTimo Sirainen /* clear the old mapping */
2f4f603d4cebab2cc956c72164efb02da83515c5Timo Sirainen max_drop_time = cache->index->map->hdr.day_stamp -
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainen for (i = 0; i < field_hdr->fields_count; i++) {
c096257fbdaf4b9fcf8eb97aae94afdbb4e71ed4Timo Sirainen for (p = names; p != end && *p != '\0'; p++) ;
1a0ece3e873e3864269ed7eaed957dc10c56d25fTimo Sirainen "field header names corrupted");
cf636afb3826f0d8e15c248aa1fc04ce72820e08Timo Sirainen mail_cache_set_corrupted(cache, "field type corrupted");
decisions[i];
const void *data;
unsigned int i, field;
if (!add_new)
const int *data;
unsigned int i, field;
if (!add_new)
int ret = 0;
t_push();
sizeof(uint32_t));
if (ret == 0) {
if (ret == 0) {
t_pop();
if (ret == 0)
return ret;
int ret;
return ret;
unsigned int field;
const char *name;
uint32_t i;
sizeof(uint32_t));
sizeof(uint32_t));
if (*offset_r == 0) {