mail-cache-fields.c revision df6478c4cf605bd81b3891c148b84c14eb6c4035
8900b9eb2514c07047541833286428572493a9fdStéphane Graber/* Copyright (C) 2004 Timo Sirainen */
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumistatic bool field_has_fixed_size(enum mail_cache_field_type type)
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumistatic bool field_decision_is_valid(enum mail_cache_decision_type type)
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi switch (type & ~MAIL_CACHE_DECISION_FORCED) {
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumistatic int field_type_verify(struct mail_cache *cache, unsigned int idx,
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi enum mail_cache_field_type type, unsigned int size)
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi const struct mail_cache_field *field = &cache->fields[idx].field;
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi "registered field %s type changed", field->name);
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi if (field->field_size != size && field_has_fixed_size(type)) {
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi "registered field %s size changed", field->name);
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumivoid mail_cache_register_fields(struct mail_cache *cache,
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi unsigned int i, j;
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi for (i = 0; i < fields_count; i++) {
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi if (hash_lookup_full(cache->field_name_hash, fields[i].name,
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi i_assert(fields[i].type < MAIL_CACHE_FIELD_COUNT);
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi (void)field_type_verify(cache, fields[i].idx,
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi /* check if the same header is being registered in the
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi same field array */
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi for (j = 0; j < i; j++) {
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi if (strcasecmp(fields[i].name, fields[j].name) == 0) {
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi /* @UNSAFE */
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi cache->fields_count * sizeof(*cache->fields),
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi cache->fields_count * sizeof(*cache->field_file_map),
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi for (i = 0; i < fields_count; i++) {
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi /* new index - save it */
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi name = p_strdup(cache->field_pool, fields[i].name);
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi if (!field_has_fixed_size(cache->fields[idx].field.type))
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi cache->fields[idx].field.field_size = (unsigned int)-1;
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi hash_insert(cache->field_name_hash, name, POINTER_CAST(idx));
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumimail_cache_register_lookup(struct mail_cache *cache, const char *name)
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi if (hash_lookup_full(cache->field_name_hash, name,
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi return POINTER_CAST_TO(orig_value, unsigned int);
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi return (unsigned int)-1;
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumimail_cache_register_get_list(struct mail_cache *cache, pool_t pool,
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi unsigned int *count_r)
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi unsigned int i;
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi list = p_new(pool, struct mail_cache_field, cache->fields_count);
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumistatic int mail_cache_header_fields_get_offset(struct mail_cache *cache,
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi const struct mail_cache_header_fields *field_hdr;
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi /* find the latest header */
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi mail_index_offset_to_uint32(cache->hdr->field_header_offset);
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi "next_offset in field header loops");
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi /* we can't trust that the cached data is valid */
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi file_cache_invalidate(cache->file_cache, offset,
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi sizeof(*field_hdr) + CACHE_HDR_PREFETCH) < 0)
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi field_hdr = CONST_PTR_OFFSET(cache->data, offset);
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi mail_index_offset_to_uint32(field_hdr->next_offset);
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumiint mail_cache_header_fields_read(struct mail_cache *cache)
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi const struct mail_cache_header_fields *field_hdr = NULL;
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi if (mail_cache_header_fields_get_offset(cache, &offset) < 0)
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi /* no fields - the file is empty */
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi field_hdr = CONST_PTR_OFFSET(cache->data, offset);
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi if (offset + field_hdr->size > cache->mmap_length) {
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi "field header points outside file");
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi /* check the fixed size of the header. name[] has to be checked
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi separately */
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi field_hdr->fields_count * (sizeof(uint32_t)*2 + 1 + 2)) {
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi mail_cache_set_corrupted(cache, "invalid field header size");
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi if (field_hdr->size > sizeof(*field_hdr) + CACHE_HDR_PREFETCH) {
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi /* we can't trust that the cached data is valid */
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi file_cache_invalidate(cache->file_cache, offset,
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi if (mail_cache_map(cache, offset, field_hdr->size) < 0)
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi field_hdr = CONST_PTR_OFFSET(cache->data, offset);
8900b9eb2514c07047541833286428572493a9fdStéphane Graber sizeof(unsigned int),
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi sizeof(unsigned int));
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi cache->file_fields_count = field_hdr->fields_count;
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi last_used = CONST_PTR_OFFSET(field_hdr, MAIL_CACHE_FIELD_LAST_USED());
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi MAIL_CACHE_FIELD_SIZE(field_hdr->fields_count));
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi MAIL_CACHE_FIELD_TYPE(field_hdr->fields_count));
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi MAIL_CACHE_FIELD_DECISION(field_hdr->fields_count));
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi MAIL_CACHE_FIELD_NAMES(field_hdr->fields_count));
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi end = CONST_PTR_OFFSET(field_hdr, field_hdr->size);
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi /* clear the old mapping */
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi for (i = 0; i < field_hdr->fields_count; i++) {
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi for (p = names; p != end && *p != '\0'; p++) ;
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi "field header names corrupted");
57da8c32f85c0255efa61ee32e260068afdaa565KATOH Yasufumi mail_cache_set_corrupted(cache, "field type corrupted");
decisions[i];
const void *data;
unsigned int i, field;
const int *data;
unsigned int i, field;
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) {