mail-cache-fields.c revision 44ff75ca53188056ff5a3e50428e3f2078800b3c
7cb128dc4cae2a03a742f63ba7afee23c78e3af0Phil Carmody/* Copyright (C) 2004 Timo Sirainen */
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen#include "lib.h"
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen#include "buffer.h"
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen#include "hash.h"
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen#include "write-full.h"
212e9e43a7d49242446331fd43ba519eda936d60Timo Sirainen#include "mail-cache-private.h"
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen#include <stddef.h>
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen#define CACHE_HDR_PREFETCH 1024
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
7a7d2aa11e46195e2d92d6c337d7e78052a5ce67Timo Sirainenstatic const unsigned char *null4[] = { 0, 0, 0, 0 };
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
c115c742f730e312d6b6ab5064595cd0d8b4e26eTimo Sirainenvoid mail_cache_register_fields(struct mail_cache *cache,
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen struct mail_cache_field *fields,
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen size_t fields_count)
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen{
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen void *orig_key, *orig_value;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen unsigned int new_idx;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen size_t i;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
212e9e43a7d49242446331fd43ba519eda936d60Timo Sirainen new_idx = cache->fields_count;
212e9e43a7d49242446331fd43ba519eda936d60Timo Sirainen for (i = 0; i < fields_count; i++) {
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen if (hash_lookup_full(cache->field_name_hash, fields[i].name,
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen &orig_key, &orig_value)) {
499fec3443374cc89fb8c83b8027c1614097d7a3Timo Sirainen fields[i].idx =
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen POINTER_CAST_TO(orig_value, unsigned int);
f5a7396b31762a1f876517e13ce9065820139f7cTimo Sirainen continue;
f5a7396b31762a1f876517e13ce9065820139f7cTimo Sirainen }
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
132487b9a47c2eb6fc80cfa2b0aaf82c6dc3af56Timo Sirainen fields[i].idx = new_idx++;
132487b9a47c2eb6fc80cfa2b0aaf82c6dc3af56Timo Sirainen }
132487b9a47c2eb6fc80cfa2b0aaf82c6dc3af56Timo Sirainen
132487b9a47c2eb6fc80cfa2b0aaf82c6dc3af56Timo Sirainen if (new_idx == cache->fields_count)
132487b9a47c2eb6fc80cfa2b0aaf82c6dc3af56Timo Sirainen return;
132487b9a47c2eb6fc80cfa2b0aaf82c6dc3af56Timo Sirainen
132487b9a47c2eb6fc80cfa2b0aaf82c6dc3af56Timo Sirainen /* @UNSAFE */
132487b9a47c2eb6fc80cfa2b0aaf82c6dc3af56Timo Sirainen cache->fields = i_realloc(cache->fields,
132487b9a47c2eb6fc80cfa2b0aaf82c6dc3af56Timo Sirainen cache->fields_count * sizeof(*cache->fields),
132487b9a47c2eb6fc80cfa2b0aaf82c6dc3af56Timo Sirainen new_idx * sizeof(*cache->fields));
132487b9a47c2eb6fc80cfa2b0aaf82c6dc3af56Timo Sirainen cache->field_file_map =
132487b9a47c2eb6fc80cfa2b0aaf82c6dc3af56Timo Sirainen i_realloc(cache->field_file_map,
132487b9a47c2eb6fc80cfa2b0aaf82c6dc3af56Timo Sirainen cache->fields_count * sizeof(*cache->field_file_map),
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen new_idx * sizeof(*cache->field_file_map));
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen
132487b9a47c2eb6fc80cfa2b0aaf82c6dc3af56Timo Sirainen for (i = 0; i < fields_count; i++) {
132487b9a47c2eb6fc80cfa2b0aaf82c6dc3af56Timo Sirainen unsigned int idx = fields[i].idx;
132487b9a47c2eb6fc80cfa2b0aaf82c6dc3af56Timo Sirainen
942302b0247403645394d848b3c620ead262a2a5Timo Sirainen if (idx < cache->fields_count)
942302b0247403645394d848b3c620ead262a2a5Timo Sirainen continue;
132487b9a47c2eb6fc80cfa2b0aaf82c6dc3af56Timo Sirainen
942302b0247403645394d848b3c620ead262a2a5Timo Sirainen /* new index - save it */
942302b0247403645394d848b3c620ead262a2a5Timo Sirainen cache->fields[idx].field = fields[i];
132487b9a47c2eb6fc80cfa2b0aaf82c6dc3af56Timo Sirainen cache->fields[idx].field.name =
11352dc3e4b29f3d2763c82f8ea4f99e8daf4fa3Timo Sirainen p_strdup(cache->field_pool, fields[i].name);
132487b9a47c2eb6fc80cfa2b0aaf82c6dc3af56Timo Sirainen cache->field_file_map[idx] = (uint32_t)-1;
132487b9a47c2eb6fc80cfa2b0aaf82c6dc3af56Timo Sirainen
942302b0247403645394d848b3c620ead262a2a5Timo Sirainen switch (cache->fields[idx].field.type) {
942302b0247403645394d848b3c620ead262a2a5Timo Sirainen case MAIL_CACHE_FIELD_FIXED_SIZE:
942302b0247403645394d848b3c620ead262a2a5Timo Sirainen case MAIL_CACHE_FIELD_BITMASK:
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen break;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen case MAIL_CACHE_FIELD_VARIABLE_SIZE:
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen case MAIL_CACHE_FIELD_STRING:
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen case MAIL_CACHE_FIELD_HEADER:
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen cache->fields[idx].field.field_size = (unsigned int)-1;
cd8507179823de33d6e8242e10dbc15d136245b5Timo Sirainen break;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen }
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen hash_insert(cache->field_name_hash,
c93ff0433cc3d348116f75a64f9988fedb86fd18Timo Sirainen (char *)cache->fields[idx].field.name,
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen POINTER_CAST(idx));
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen }
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen cache->fields_count = new_idx;
212e9e43a7d49242446331fd43ba519eda936d60Timo Sirainen}
212e9e43a7d49242446331fd43ba519eda936d60Timo Sirainen
212e9e43a7d49242446331fd43ba519eda936d60Timo Sirainenunsigned int
212e9e43a7d49242446331fd43ba519eda936d60Timo Sirainenmail_cache_register_lookup(struct mail_cache *cache, const char *name)
212e9e43a7d49242446331fd43ba519eda936d60Timo Sirainen{
212e9e43a7d49242446331fd43ba519eda936d60Timo Sirainen void *orig_key, *orig_value;
212e9e43a7d49242446331fd43ba519eda936d60Timo Sirainen
212e9e43a7d49242446331fd43ba519eda936d60Timo Sirainen if (hash_lookup_full(cache->field_name_hash, name,
212e9e43a7d49242446331fd43ba519eda936d60Timo Sirainen &orig_key, &orig_value))
212e9e43a7d49242446331fd43ba519eda936d60Timo Sirainen return POINTER_CAST_TO(orig_value, unsigned int);
212e9e43a7d49242446331fd43ba519eda936d60Timo Sirainen else
212e9e43a7d49242446331fd43ba519eda936d60Timo Sirainen return (unsigned int)-1;
212e9e43a7d49242446331fd43ba519eda936d60Timo Sirainen}
212e9e43a7d49242446331fd43ba519eda936d60Timo Sirainen
212e9e43a7d49242446331fd43ba519eda936d60Timo Sirainenstatic int mail_cache_header_fields_get_offset(struct mail_cache *cache,
212e9e43a7d49242446331fd43ba519eda936d60Timo Sirainen uint32_t *offset_r)
212e9e43a7d49242446331fd43ba519eda936d60Timo Sirainen{
212e9e43a7d49242446331fd43ba519eda936d60Timo Sirainen const struct mail_cache_header_fields *field_hdr;
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen uint32_t offset, next_offset;
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen if (MAIL_CACHE_IS_UNUSABLE(cache)) {
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen *offset_r = 0;
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen return 0;
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen }
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen /* find the latest header */
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen offset = 0;
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen next_offset =
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen mail_index_offset_to_uint32(cache->hdr->field_header_offset);
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen while (next_offset != 0) {
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen if (next_offset == offset) {
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen mail_cache_set_corrupted(cache,
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen "next_offset in field header loops");
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen return -1;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen }
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen offset = next_offset;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen if (mail_cache_map(cache, offset,
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen sizeof(*field_hdr) + CACHE_HDR_PREFETCH) < 0)
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen return -1;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen field_hdr = CONST_PTR_OFFSET(cache->mmap_base, offset);
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen next_offset =
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen mail_index_offset_to_uint32(field_hdr->next_offset);
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen }
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen *offset_r = offset;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen return 0;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen}
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainenint mail_cache_header_fields_read(struct mail_cache *cache)
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen{
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen const struct mail_cache_header_fields *field_hdr = NULL;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen struct mail_cache_field field;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen const uint32_t *last_used, *sizes;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen const uint8_t *types, *decisions;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen const char *p, *names, *end;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen void *orig_key, *orig_value;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen uint32_t offset, i;
c93ff0433cc3d348116f75a64f9988fedb86fd18Timo Sirainen
c93ff0433cc3d348116f75a64f9988fedb86fd18Timo Sirainen if (mail_cache_header_fields_get_offset(cache, &offset) < 0)
c93ff0433cc3d348116f75a64f9988fedb86fd18Timo Sirainen return -1;
c93ff0433cc3d348116f75a64f9988fedb86fd18Timo Sirainen
c93ff0433cc3d348116f75a64f9988fedb86fd18Timo Sirainen if (offset == 0) {
c93ff0433cc3d348116f75a64f9988fedb86fd18Timo Sirainen /* no fields - the file is empty */
c93ff0433cc3d348116f75a64f9988fedb86fd18Timo Sirainen return 0;
c93ff0433cc3d348116f75a64f9988fedb86fd18Timo Sirainen }
c93ff0433cc3d348116f75a64f9988fedb86fd18Timo Sirainen
c93ff0433cc3d348116f75a64f9988fedb86fd18Timo Sirainen field_hdr = CONST_PTR_OFFSET(cache->mmap_base, offset);
c93ff0433cc3d348116f75a64f9988fedb86fd18Timo Sirainen if (offset + field_hdr->size > cache->mmap_length) {
c93ff0433cc3d348116f75a64f9988fedb86fd18Timo Sirainen mail_cache_set_corrupted(cache,
c93ff0433cc3d348116f75a64f9988fedb86fd18Timo Sirainen "field header points outside file");
c93ff0433cc3d348116f75a64f9988fedb86fd18Timo Sirainen return -1;
132487b9a47c2eb6fc80cfa2b0aaf82c6dc3af56Timo Sirainen }
132487b9a47c2eb6fc80cfa2b0aaf82c6dc3af56Timo Sirainen
132487b9a47c2eb6fc80cfa2b0aaf82c6dc3af56Timo Sirainen /* check the fixed size of the header. name[] has to be checked
132487b9a47c2eb6fc80cfa2b0aaf82c6dc3af56Timo Sirainen separately */
18a41cbd38f83429b790414c1159c097af4a59b8Timo Sirainen if (field_hdr->size < sizeof(*field_hdr) +
132487b9a47c2eb6fc80cfa2b0aaf82c6dc3af56Timo Sirainen field_hdr->fields_count * (sizeof(uint32_t)*2 + 1 + 2)) {
18a41cbd38f83429b790414c1159c097af4a59b8Timo Sirainen mail_cache_set_corrupted(cache, "invalid field header size");
18a41cbd38f83429b790414c1159c097af4a59b8Timo Sirainen return -1;
18a41cbd38f83429b790414c1159c097af4a59b8Timo Sirainen }
18a41cbd38f83429b790414c1159c097af4a59b8Timo Sirainen
18a41cbd38f83429b790414c1159c097af4a59b8Timo Sirainen if (field_hdr->size > sizeof(*field_hdr) + CACHE_HDR_PREFETCH) {
132487b9a47c2eb6fc80cfa2b0aaf82c6dc3af56Timo Sirainen if (mail_cache_map(cache, offset, field_hdr->size) < 0)
132487b9a47c2eb6fc80cfa2b0aaf82c6dc3af56Timo Sirainen return -1;
755aea84bbe2b15ed7fe991f6462a93333ff571fTimo Sirainen }
755aea84bbe2b15ed7fe991f6462a93333ff571fTimo Sirainen field_hdr = CONST_PTR_OFFSET(cache->mmap_base, offset);
755aea84bbe2b15ed7fe991f6462a93333ff571fTimo Sirainen
8305127d1074cf9a1e25dec9be2735276462079dTimo Sirainen cache->file_field_map =
132487b9a47c2eb6fc80cfa2b0aaf82c6dc3af56Timo Sirainen i_realloc(cache->file_field_map,
132487b9a47c2eb6fc80cfa2b0aaf82c6dc3af56Timo Sirainen cache->file_fields_count * sizeof(unsigned int),
132487b9a47c2eb6fc80cfa2b0aaf82c6dc3af56Timo Sirainen field_hdr->fields_count * sizeof(unsigned int));
212e9e43a7d49242446331fd43ba519eda936d60Timo Sirainen cache->file_fields_count = field_hdr->fields_count;
212e9e43a7d49242446331fd43ba519eda936d60Timo Sirainen
212e9e43a7d49242446331fd43ba519eda936d60Timo Sirainen last_used = CONST_PTR_OFFSET(field_hdr, MAIL_CACHE_FIELD_LAST_USED());
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen sizes = CONST_PTR_OFFSET(field_hdr,
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen MAIL_CACHE_FIELD_SIZE(field_hdr->fields_count));
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen types = CONST_PTR_OFFSET(field_hdr,
132487b9a47c2eb6fc80cfa2b0aaf82c6dc3af56Timo Sirainen MAIL_CACHE_FIELD_TYPE(field_hdr->fields_count));
18a41cbd38f83429b790414c1159c097af4a59b8Timo Sirainen decisions = CONST_PTR_OFFSET(field_hdr,
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen MAIL_CACHE_FIELD_DECISION(field_hdr->fields_count));
596433ccbca59ce2328dc1d029586154cd937155Timo Sirainen names = CONST_PTR_OFFSET(field_hdr,
596433ccbca59ce2328dc1d029586154cd937155Timo Sirainen MAIL_CACHE_FIELD_NAMES(field_hdr->fields_count));
15b5076a239682277b44880e33ea23b55fff7e71Timo Sirainen end = CONST_PTR_OFFSET(field_hdr, field_hdr->size);
15b5076a239682277b44880e33ea23b55fff7e71Timo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen /* clear the old mapping */
6b399f555c9c5c722d4cd5eab8faa02b2a4731d3Timo Sirainen for (i = 0; i < cache->fields_count; i++)
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen cache->field_file_map[i] = (uint32_t)-1;
e5fd6dfd0a492e4708d4dbb7971d7fc5d7b8fd85Timo Sirainen
dd37e2ff291fbebac1b94e8aad50f3bdf7531049Timo Sirainen memset(&field, 0, sizeof(field));
6b399f555c9c5c722d4cd5eab8faa02b2a4731d3Timo Sirainen for (i = 0; i < field_hdr->fields_count; i++) {
18a41cbd38f83429b790414c1159c097af4a59b8Timo Sirainen for (p = names; p != end && *p != '\0'; p++) ;
132487b9a47c2eb6fc80cfa2b0aaf82c6dc3af56Timo Sirainen if (p == end || *names == '\0') {
18a41cbd38f83429b790414c1159c097af4a59b8Timo Sirainen mail_cache_set_corrupted(cache,
18a41cbd38f83429b790414c1159c097af4a59b8Timo Sirainen "field header names corrupted");
18a41cbd38f83429b790414c1159c097af4a59b8Timo Sirainen return -1;
18a41cbd38f83429b790414c1159c097af4a59b8Timo Sirainen }
18a41cbd38f83429b790414c1159c097af4a59b8Timo Sirainen
18a41cbd38f83429b790414c1159c097af4a59b8Timo Sirainen if (hash_lookup_full(cache->field_name_hash, names,
18a41cbd38f83429b790414c1159c097af4a59b8Timo Sirainen &orig_key, &orig_value)) {
18a41cbd38f83429b790414c1159c097af4a59b8Timo Sirainen /* already exists, see if decision can be updated */
18a41cbd38f83429b790414c1159c097af4a59b8Timo Sirainen field.idx = POINTER_CAST_TO(orig_value, unsigned int);
18a41cbd38f83429b790414c1159c097af4a59b8Timo Sirainen if (!cache->fields[field.idx].decision_dirty) {
18a41cbd38f83429b790414c1159c097af4a59b8Timo Sirainen cache->fields[field.idx].field.decision =
6b399f555c9c5c722d4cd5eab8faa02b2a4731d3Timo Sirainen decisions[i];
6b399f555c9c5c722d4cd5eab8faa02b2a4731d3Timo Sirainen }
074055dadbca01626437cc4724853a374acab6a8Timo Sirainen if (cache->fields[field.idx].field.type != types[i]) {
074055dadbca01626437cc4724853a374acab6a8Timo Sirainen mail_cache_set_corrupted(cache,
074055dadbca01626437cc4724853a374acab6a8Timo Sirainen "registered field type changed");
6b399f555c9c5c722d4cd5eab8faa02b2a4731d3Timo Sirainen return -1;
6b399f555c9c5c722d4cd5eab8faa02b2a4731d3Timo Sirainen }
6b399f555c9c5c722d4cd5eab8faa02b2a4731d3Timo Sirainen } else {
6b399f555c9c5c722d4cd5eab8faa02b2a4731d3Timo Sirainen field.name = names;
6b399f555c9c5c722d4cd5eab8faa02b2a4731d3Timo Sirainen field.type = types[i];
6b399f555c9c5c722d4cd5eab8faa02b2a4731d3Timo Sirainen field.field_size = sizes[i];
6b399f555c9c5c722d4cd5eab8faa02b2a4731d3Timo Sirainen field.decision = decisions[i];
6b399f555c9c5c722d4cd5eab8faa02b2a4731d3Timo Sirainen mail_cache_register_fields(cache, &field, 1);
6b399f555c9c5c722d4cd5eab8faa02b2a4731d3Timo Sirainen }
6b399f555c9c5c722d4cd5eab8faa02b2a4731d3Timo Sirainen cache->field_file_map[field.idx] = i;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen cache->file_field_map[i] = field.idx;
7f3b826a89bcb7a72759912e99f574b28309fe1bTimo Sirainen
212e9e43a7d49242446331fd43ba519eda936d60Timo Sirainen /* update last_used if it's newer than ours */
6b399f555c9c5c722d4cd5eab8faa02b2a4731d3Timo Sirainen if (last_used[i] > cache->fields[field.idx].last_used)
6b399f555c9c5c722d4cd5eab8faa02b2a4731d3Timo Sirainen cache->fields[field.idx].last_used = last_used[i];
6b399f555c9c5c722d4cd5eab8faa02b2a4731d3Timo Sirainen
6b399f555c9c5c722d4cd5eab8faa02b2a4731d3Timo Sirainen names = p + 1;
6b399f555c9c5c722d4cd5eab8faa02b2a4731d3Timo Sirainen }
6b399f555c9c5c722d4cd5eab8faa02b2a4731d3Timo Sirainen return 0;
6b399f555c9c5c722d4cd5eab8faa02b2a4731d3Timo Sirainen}
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainenstatic void copy_to_buf(struct mail_cache *cache, buffer_t *dest,
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen size_t offset, size_t size)
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen{
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen const void *data;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen unsigned int i, field;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
e10d8b1291090c26b9ef499637e6e632485ca5beTimo Sirainen for (i = 0; i < cache->file_fields_count; i++) {
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen field = cache->file_field_map[i];
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen data = CONST_PTR_OFFSET(&cache->fields[field], offset);
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen buffer_append(dest, data, size);
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen }
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen for (i = 0; i < cache->fields_count; i++) {
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen if (cache->field_file_map[i] != (uint32_t)-1)
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen continue;
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen data = CONST_PTR_OFFSET(&cache->fields[i], offset);
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen buffer_append(dest, data, size);
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen }
18ccd19c244f49665fe03cda785efa066d2c38dfTimo Sirainen}
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainenstatic void copy_to_buf_byte(struct mail_cache *cache, buffer_t *dest,
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen size_t offset)
c529313e1cbc22244d4528e80aa3e485f8806cd3Timo Sirainen{
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen const int *data;
d22301419109ed4a38351715e6760011421dadecTimo Sirainen unsigned int i, field;
d22301419109ed4a38351715e6760011421dadecTimo Sirainen uint8_t byte;
d22301419109ed4a38351715e6760011421dadecTimo Sirainen
d22301419109ed4a38351715e6760011421dadecTimo Sirainen for (i = 0; i < cache->file_fields_count; i++) {
d22301419109ed4a38351715e6760011421dadecTimo Sirainen field = cache->file_field_map[i];
499fec3443374cc89fb8c83b8027c1614097d7a3Timo Sirainen data = CONST_PTR_OFFSET(&cache->fields[field], offset);
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen byte = (uint8_t)*data;
8c909e451d14075c05d90382cf8eebc4e354f569Timo Sirainen buffer_append(dest, &byte, 1);
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen }
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen for (i = 0; i < cache->fields_count; i++) {
8d587838c414c48a331f0b54cd7ffd97e5024abdTimo Sirainen if (cache->field_file_map[i] != (uint32_t)-1)
d22301419109ed4a38351715e6760011421dadecTimo Sirainen continue;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen data = CONST_PTR_OFFSET(&cache->fields[i], offset);
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen byte = (uint8_t)*data;
212e9e43a7d49242446331fd43ba519eda936d60Timo Sirainen buffer_append(dest, &byte, 1);
212e9e43a7d49242446331fd43ba519eda936d60Timo Sirainen }
212e9e43a7d49242446331fd43ba519eda936d60Timo Sirainen}
212e9e43a7d49242446331fd43ba519eda936d60Timo Sirainen
212e9e43a7d49242446331fd43ba519eda936d60Timo Sirainenint mail_cache_header_fields_update(struct mail_cache *cache)
212e9e43a7d49242446331fd43ba519eda936d60Timo Sirainen{
212e9e43a7d49242446331fd43ba519eda936d60Timo Sirainen int locked = cache->locked;
212e9e43a7d49242446331fd43ba519eda936d60Timo Sirainen buffer_t *buffer;
212e9e43a7d49242446331fd43ba519eda936d60Timo Sirainen uint32_t i, offset;
212e9e43a7d49242446331fd43ba519eda936d60Timo Sirainen int ret = 0;
212e9e43a7d49242446331fd43ba519eda936d60Timo Sirainen
ce930f99c6a78f2c74b00df1ad2337095978a9dbTimo Sirainen if (!locked) {
ce930f99c6a78f2c74b00df1ad2337095978a9dbTimo Sirainen if (mail_cache_lock(cache) <= 0)
ce930f99c6a78f2c74b00df1ad2337095978a9dbTimo Sirainen return -1;
ce930f99c6a78f2c74b00df1ad2337095978a9dbTimo Sirainen }
ce930f99c6a78f2c74b00df1ad2337095978a9dbTimo Sirainen
ce930f99c6a78f2c74b00df1ad2337095978a9dbTimo Sirainen if (mail_cache_header_fields_read(cache) < 0 ||
ce930f99c6a78f2c74b00df1ad2337095978a9dbTimo Sirainen mail_cache_header_fields_get_offset(cache, &offset) < 0) {
ce930f99c6a78f2c74b00df1ad2337095978a9dbTimo Sirainen mail_cache_unlock(cache);
ce930f99c6a78f2c74b00df1ad2337095978a9dbTimo Sirainen return -1;
ce930f99c6a78f2c74b00df1ad2337095978a9dbTimo Sirainen }
ce930f99c6a78f2c74b00df1ad2337095978a9dbTimo Sirainen
ce930f99c6a78f2c74b00df1ad2337095978a9dbTimo Sirainen t_push();
ce930f99c6a78f2c74b00df1ad2337095978a9dbTimo Sirainen buffer = buffer_create_dynamic(pool_datastack_create(),
ce930f99c6a78f2c74b00df1ad2337095978a9dbTimo Sirainen 256, (size_t)-1);
ce930f99c6a78f2c74b00df1ad2337095978a9dbTimo Sirainen
212e9e43a7d49242446331fd43ba519eda936d60Timo Sirainen copy_to_buf(cache, buffer,
212e9e43a7d49242446331fd43ba519eda936d60Timo Sirainen offsetof(struct mail_cache_field_private, last_used),
212e9e43a7d49242446331fd43ba519eda936d60Timo Sirainen sizeof(uint32_t));
212e9e43a7d49242446331fd43ba519eda936d60Timo Sirainen ret = pwrite_full(cache->fd, buffer_get_data(buffer, NULL),
212e9e43a7d49242446331fd43ba519eda936d60Timo Sirainen sizeof(uint32_t) * cache->file_fields_count,
212e9e43a7d49242446331fd43ba519eda936d60Timo Sirainen offset + MAIL_CACHE_FIELD_LAST_USED());
212e9e43a7d49242446331fd43ba519eda936d60Timo Sirainen if (ret == 0) {
212e9e43a7d49242446331fd43ba519eda936d60Timo Sirainen buffer_set_used_size(buffer, 0);
212e9e43a7d49242446331fd43ba519eda936d60Timo Sirainen copy_to_buf_byte(cache, buffer,
212e9e43a7d49242446331fd43ba519eda936d60Timo Sirainen offsetof(struct mail_cache_field, decision));
212e9e43a7d49242446331fd43ba519eda936d60Timo Sirainen
212e9e43a7d49242446331fd43ba519eda936d60Timo Sirainen ret = pwrite_full(cache->fd, buffer_get_data(buffer, NULL),
212e9e43a7d49242446331fd43ba519eda936d60Timo Sirainen sizeof(uint8_t) * cache->file_fields_count, offset +
212e9e43a7d49242446331fd43ba519eda936d60Timo Sirainen MAIL_CACHE_FIELD_DECISION(cache->file_fields_count));
ce930f99c6a78f2c74b00df1ad2337095978a9dbTimo Sirainen
212e9e43a7d49242446331fd43ba519eda936d60Timo Sirainen if (ret == 0) {
212e9e43a7d49242446331fd43ba519eda936d60Timo Sirainen for (i = 0; i < cache->fields_count; i++)
212e9e43a7d49242446331fd43ba519eda936d60Timo Sirainen cache->fields[i].decision_dirty = FALSE;
212e9e43a7d49242446331fd43ba519eda936d60Timo Sirainen }
212e9e43a7d49242446331fd43ba519eda936d60Timo Sirainen }
212e9e43a7d49242446331fd43ba519eda936d60Timo Sirainen t_pop();
212e9e43a7d49242446331fd43ba519eda936d60Timo Sirainen
212e9e43a7d49242446331fd43ba519eda936d60Timo Sirainen if (ret == 0)
212e9e43a7d49242446331fd43ba519eda936d60Timo Sirainen cache->field_header_write_pending = FALSE;
212e9e43a7d49242446331fd43ba519eda936d60Timo Sirainen
212e9e43a7d49242446331fd43ba519eda936d60Timo Sirainen if (!locked)
212e9e43a7d49242446331fd43ba519eda936d60Timo Sirainen mail_cache_unlock(cache);
ce930f99c6a78f2c74b00df1ad2337095978a9dbTimo Sirainen return ret;
212e9e43a7d49242446331fd43ba519eda936d60Timo Sirainen}
212e9e43a7d49242446331fd43ba519eda936d60Timo Sirainen
212e9e43a7d49242446331fd43ba519eda936d60Timo Sirainenvoid mail_cache_header_fields_get(struct mail_cache *cache, buffer_t *dest)
212e9e43a7d49242446331fd43ba519eda936d60Timo Sirainen{
212e9e43a7d49242446331fd43ba519eda936d60Timo Sirainen struct mail_cache_header_fields hdr;
212e9e43a7d49242446331fd43ba519eda936d60Timo Sirainen unsigned int field;
212e9e43a7d49242446331fd43ba519eda936d60Timo Sirainen const char *name;
212e9e43a7d49242446331fd43ba519eda936d60Timo Sirainen uint32_t i;
212e9e43a7d49242446331fd43ba519eda936d60Timo Sirainen
dd37e2ff291fbebac1b94e8aad50f3bdf7531049Timo Sirainen memset(&hdr, 0, sizeof(hdr));
212e9e43a7d49242446331fd43ba519eda936d60Timo Sirainen hdr.fields_count = cache->fields_count;
dd37e2ff291fbebac1b94e8aad50f3bdf7531049Timo Sirainen buffer_append(dest, &hdr, sizeof(hdr));
dd37e2ff291fbebac1b94e8aad50f3bdf7531049Timo Sirainen
dd37e2ff291fbebac1b94e8aad50f3bdf7531049Timo Sirainen /* we have to keep the field order for the existing fields. */
dd37e2ff291fbebac1b94e8aad50f3bdf7531049Timo Sirainen copy_to_buf(cache, dest,
dd37e2ff291fbebac1b94e8aad50f3bdf7531049Timo Sirainen offsetof(struct mail_cache_field_private, last_used),
dd37e2ff291fbebac1b94e8aad50f3bdf7531049Timo Sirainen sizeof(uint32_t));
dd37e2ff291fbebac1b94e8aad50f3bdf7531049Timo Sirainen copy_to_buf(cache, dest, offsetof(struct mail_cache_field, field_size),
9cb0fe28ae6f59b9f075e1edfc30f417e846c4a2Timo Sirainen sizeof(uint32_t));
dd37e2ff291fbebac1b94e8aad50f3bdf7531049Timo Sirainen copy_to_buf_byte(cache, dest, offsetof(struct mail_cache_field, type));
9cb0fe28ae6f59b9f075e1edfc30f417e846c4a2Timo Sirainen copy_to_buf_byte(cache, dest,
212e9e43a7d49242446331fd43ba519eda936d60Timo Sirainen offsetof(struct mail_cache_field, decision));
212e9e43a7d49242446331fd43ba519eda936d60Timo Sirainen
212e9e43a7d49242446331fd43ba519eda936d60Timo Sirainen i_assert(buffer_get_used_size(dest) == sizeof(hdr) +
212e9e43a7d49242446331fd43ba519eda936d60Timo Sirainen (sizeof(uint32_t)*2 + 2) * hdr.fields_count);
212e9e43a7d49242446331fd43ba519eda936d60Timo Sirainen
212e9e43a7d49242446331fd43ba519eda936d60Timo Sirainen for (i = 0; i < cache->file_fields_count; i++) {
9cb0fe28ae6f59b9f075e1edfc30f417e846c4a2Timo Sirainen field = cache->file_field_map[i];
212e9e43a7d49242446331fd43ba519eda936d60Timo Sirainen name = cache->fields[field].field.name;
212e9e43a7d49242446331fd43ba519eda936d60Timo Sirainen buffer_append(dest, name, strlen(name)+1);
212e9e43a7d49242446331fd43ba519eda936d60Timo Sirainen }
212e9e43a7d49242446331fd43ba519eda936d60Timo Sirainen for (i = 0; i < cache->fields_count; i++) {
212e9e43a7d49242446331fd43ba519eda936d60Timo Sirainen if (cache->field_file_map[i] != (uint32_t)-1)
212e9e43a7d49242446331fd43ba519eda936d60Timo Sirainen continue;
212e9e43a7d49242446331fd43ba519eda936d60Timo Sirainen name = cache->fields[i].field.name;
212e9e43a7d49242446331fd43ba519eda936d60Timo Sirainen buffer_append(dest, name, strlen(name)+1);
212e9e43a7d49242446331fd43ba519eda936d60Timo Sirainen }
212e9e43a7d49242446331fd43ba519eda936d60Timo Sirainen
212e9e43a7d49242446331fd43ba519eda936d60Timo Sirainen hdr.size = buffer_get_used_size(dest);
212e9e43a7d49242446331fd43ba519eda936d60Timo Sirainen buffer_write(dest, 0, &hdr, sizeof(hdr));
212e9e43a7d49242446331fd43ba519eda936d60Timo Sirainen
212e9e43a7d49242446331fd43ba519eda936d60Timo Sirainen if ((hdr.size & 3) != 0)
212e9e43a7d49242446331fd43ba519eda936d60Timo Sirainen buffer_append(dest, null4, 4 - (hdr.size & 3));
212e9e43a7d49242446331fd43ba519eda936d60Timo Sirainen}
212e9e43a7d49242446331fd43ba519eda936d60Timo Sirainen
dd37e2ff291fbebac1b94e8aad50f3bdf7531049Timo Sirainenint mail_cache_header_fields_get_next_offset(struct mail_cache *cache,
212e9e43a7d49242446331fd43ba519eda936d60Timo Sirainen uint32_t *offset_r)
212e9e43a7d49242446331fd43ba519eda936d60Timo Sirainen{
212e9e43a7d49242446331fd43ba519eda936d60Timo Sirainen if (mail_cache_header_fields_get_offset(cache, offset_r) < 0)
212e9e43a7d49242446331fd43ba519eda936d60Timo Sirainen return -1;
212e9e43a7d49242446331fd43ba519eda936d60Timo Sirainen
212e9e43a7d49242446331fd43ba519eda936d60Timo Sirainen if (*offset_r == 0) {
dd37e2ff291fbebac1b94e8aad50f3bdf7531049Timo Sirainen *offset_r = offsetof(struct mail_cache_header,
212e9e43a7d49242446331fd43ba519eda936d60Timo Sirainen field_header_offset);
212e9e43a7d49242446331fd43ba519eda936d60Timo Sirainen } else {
212e9e43a7d49242446331fd43ba519eda936d60Timo Sirainen *offset_r += offsetof(struct mail_cache_header_fields,
212e9e43a7d49242446331fd43ba519eda936d60Timo Sirainen next_offset);
212e9e43a7d49242446331fd43ba519eda936d60Timo Sirainen }
212e9e43a7d49242446331fd43ba519eda936d60Timo Sirainen return 0;
212e9e43a7d49242446331fd43ba519eda936d60Timo Sirainen}
212e9e43a7d49242446331fd43ba519eda936d60Timo Sirainen