mail-cache-fields.c revision 4bbee99b3aef449a9a2a11a5b5cf1ca486915c49
02c335c23bf5fa225a467c19f2c063fb0dc7b8c3Timo Sirainen/* Copyright (C) 2004 Timo Sirainen */
94ba4820927b906b333e39445c1508a29387c3aaTimo Sirainen
94ba4820927b906b333e39445c1508a29387c3aaTimo Sirainen#include "lib.h"
cdf294e5cceee81d58c8477c7c28d9ad6b55c36aTimo Sirainen#include "buffer.h"
94ba4820927b906b333e39445c1508a29387c3aaTimo Sirainen#include "hash.h"
94ba4820927b906b333e39445c1508a29387c3aaTimo Sirainen#include "write-full.h"
94ba4820927b906b333e39445c1508a29387c3aaTimo Sirainen#include "mail-cache-private.h"
cf1c3e6833fc5031d89db48dad46ed025beda4e7Timo Sirainen
cdf294e5cceee81d58c8477c7c28d9ad6b55c36aTimo Sirainen#include <stddef.h>
46d283ef537885386ab3fc72d1831054ea5f986bTimo Sirainen
c4ac0f222613903b7f8c9e0825198396e6bf793eTimo Sirainen#define CACHE_HDR_PREFETCH 1024
46d283ef537885386ab3fc72d1831054ea5f986bTimo Sirainen
cdf294e5cceee81d58c8477c7c28d9ad6b55c36aTimo Sirainenstatic const unsigned char *null4[] = { 0, 0, 0, 0 };
1631885636d15abaf0375304a17928c8c23782cdTimo Sirainen
94ba4820927b906b333e39445c1508a29387c3aaTimo Sirainenvoid mail_cache_register_fields(struct mail_cache *cache,
f330fcc3307d48954b6f8909349546773368a041Timo Sirainen struct mail_cache_field *fields,
d389c93ada174a8fc6edf995b4f829d38e8fe567Timo Sirainen size_t fields_count)
f24b245f49b030d7dba3bcb2463cbc05b98c9d1dTimo Sirainen{
c154a05c76d4d83de1cdf9746ce4e2da0869705dTimo Sirainen void *orig_key, *orig_value;
94ba4820927b906b333e39445c1508a29387c3aaTimo Sirainen unsigned int new_idx;
5fbccc935e3f7b916aa7c6e302a212821072e83aTimo Sirainen size_t i;
f23baa3b53b1dd4eb19729e99a43937fa3c7f309Timo Sirainen
8732bdd21579472feb40da8ffc99b8fd3b341417Timo Sirainen new_idx = cache->fields_count;
7f098e28ddad259d9fbe76e18347c722bb005189Timo Sirainen for (i = 0; i < fields_count; i++) {
7f098e28ddad259d9fbe76e18347c722bb005189Timo Sirainen if (hash_lookup_full(cache->field_name_hash, fields[i].name,
cf63dc8723b971cc80638fccbf494d961cbafc7fTimo Sirainen &orig_key, &orig_value)) {
cf63dc8723b971cc80638fccbf494d961cbafc7fTimo Sirainen fields[i].idx =
cf63dc8723b971cc80638fccbf494d961cbafc7fTimo Sirainen POINTER_CAST_TO(orig_value, unsigned int);
cdf294e5cceee81d58c8477c7c28d9ad6b55c36aTimo Sirainen continue;
cdf294e5cceee81d58c8477c7c28d9ad6b55c36aTimo Sirainen }
71fbc9af425dc9afc2fb58f911bfe4c5b4edba9bTimo Sirainen
d38ca817bdcec666a3b91efb917064ab844c36a2Timo Sirainen fields[i].idx = new_idx++;
cdf294e5cceee81d58c8477c7c28d9ad6b55c36aTimo Sirainen }
8732bdd21579472feb40da8ffc99b8fd3b341417Timo Sirainen
d38ca817bdcec666a3b91efb917064ab844c36a2Timo Sirainen if (new_idx == cache->fields_count)
2d7da70c0e6768afeb1200c95f3e1293f2e502c6Timo Sirainen return;
2d7da70c0e6768afeb1200c95f3e1293f2e502c6Timo Sirainen
2d7da70c0e6768afeb1200c95f3e1293f2e502c6Timo Sirainen /* @UNSAFE */
cdf294e5cceee81d58c8477c7c28d9ad6b55c36aTimo Sirainen cache->fields = p_realloc(cache->field_pool, cache->fields,
cdf294e5cceee81d58c8477c7c28d9ad6b55c36aTimo Sirainen cache->fields_count * sizeof(*cache->fields),
d38ca817bdcec666a3b91efb917064ab844c36a2Timo Sirainen new_idx * sizeof(*cache->fields));
d38ca817bdcec666a3b91efb917064ab844c36a2Timo Sirainen cache->field_file_map =
d38ca817bdcec666a3b91efb917064ab844c36a2Timo Sirainen p_realloc(cache->field_pool, cache->field_file_map,
d38ca817bdcec666a3b91efb917064ab844c36a2Timo Sirainen cache->fields_count * sizeof(*cache->field_file_map),
d38ca817bdcec666a3b91efb917064ab844c36a2Timo Sirainen new_idx * sizeof(*cache->field_file_map));
d38ca817bdcec666a3b91efb917064ab844c36a2Timo Sirainen
1631885636d15abaf0375304a17928c8c23782cdTimo Sirainen for (i = 0; i < fields_count; i++) {
1631885636d15abaf0375304a17928c8c23782cdTimo Sirainen unsigned int idx = fields[i].idx;
c154a05c76d4d83de1cdf9746ce4e2da0869705dTimo Sirainen
1631885636d15abaf0375304a17928c8c23782cdTimo Sirainen if (idx < cache->fields_count)
1631885636d15abaf0375304a17928c8c23782cdTimo Sirainen continue;
1631885636d15abaf0375304a17928c8c23782cdTimo Sirainen
cf63dc8723b971cc80638fccbf494d961cbafc7fTimo Sirainen /* new index - save it */
cdf294e5cceee81d58c8477c7c28d9ad6b55c36aTimo Sirainen cache->fields[idx].field = fields[i];
cdf294e5cceee81d58c8477c7c28d9ad6b55c36aTimo Sirainen cache->fields[idx].field.name =
cdf294e5cceee81d58c8477c7c28d9ad6b55c36aTimo Sirainen p_strdup(cache->field_pool, fields[i].name);
cdf294e5cceee81d58c8477c7c28d9ad6b55c36aTimo Sirainen cache->field_file_map[idx] = (uint32_t)-1;
cdf294e5cceee81d58c8477c7c28d9ad6b55c36aTimo Sirainen
ea1ae54fcfbd8e911978c149f9e7265a45b6380aTimo Sirainen switch (cache->fields[idx].field.type) {
636f017be100bce67d66fd3ae1544a47681efd33Timo Sirainen case MAIL_CACHE_FIELD_FIXED_SIZE:
cdf294e5cceee81d58c8477c7c28d9ad6b55c36aTimo Sirainen case MAIL_CACHE_FIELD_BITMASK:
cdf294e5cceee81d58c8477c7c28d9ad6b55c36aTimo Sirainen break;
cdf294e5cceee81d58c8477c7c28d9ad6b55c36aTimo Sirainen case MAIL_CACHE_FIELD_VARIABLE_SIZE:
cf63dc8723b971cc80638fccbf494d961cbafc7fTimo Sirainen case MAIL_CACHE_FIELD_STRING:
f77da594de6318312a7f31589c9e4c38e2b74c73Timo Sirainen case MAIL_CACHE_FIELD_HEADER:
51327f2489a4e0e615eb9f7d921473cf8512bb79Timo Sirainen cache->fields[idx].field.field_size = (unsigned int)-1;
f77da594de6318312a7f31589c9e4c38e2b74c73Timo Sirainen break;
51327f2489a4e0e615eb9f7d921473cf8512bb79Timo Sirainen }
51327f2489a4e0e615eb9f7d921473cf8512bb79Timo Sirainen
f77da594de6318312a7f31589c9e4c38e2b74c73Timo Sirainen hash_insert(cache->field_name_hash,
de62ce819d59a529530da4b57be1b8d6dad13d6bTimo Sirainen (char *)cache->fields[idx].field.name,
f77da594de6318312a7f31589c9e4c38e2b74c73Timo Sirainen POINTER_CAST(idx));
f77da594de6318312a7f31589c9e4c38e2b74c73Timo Sirainen }
f77da594de6318312a7f31589c9e4c38e2b74c73Timo Sirainen cache->fields_count = new_idx;
cf63dc8723b971cc80638fccbf494d961cbafc7fTimo Sirainen}
cdf294e5cceee81d58c8477c7c28d9ad6b55c36aTimo Sirainen
c154a05c76d4d83de1cdf9746ce4e2da0869705dTimo Sirainenunsigned int
cdf294e5cceee81d58c8477c7c28d9ad6b55c36aTimo Sirainenmail_cache_register_lookup(struct mail_cache *cache, const char *name)
cdf294e5cceee81d58c8477c7c28d9ad6b55c36aTimo Sirainen{
cdf294e5cceee81d58c8477c7c28d9ad6b55c36aTimo Sirainen void *orig_key, *orig_value;
cf63dc8723b971cc80638fccbf494d961cbafc7fTimo Sirainen
cdf294e5cceee81d58c8477c7c28d9ad6b55c36aTimo Sirainen if (hash_lookup_full(cache->field_name_hash, name,
1f792fb84e8fdfd2a9b65100ce1c31d0212fa3b0Timo Sirainen &orig_key, &orig_value))
cdf294e5cceee81d58c8477c7c28d9ad6b55c36aTimo Sirainen return POINTER_CAST_TO(orig_value, unsigned int);
cdf294e5cceee81d58c8477c7c28d9ad6b55c36aTimo Sirainen else
cdf294e5cceee81d58c8477c7c28d9ad6b55c36aTimo Sirainen return (unsigned int)-1;
cf63dc8723b971cc80638fccbf494d961cbafc7fTimo Sirainen}
cdf294e5cceee81d58c8477c7c28d9ad6b55c36aTimo Sirainen
cdf294e5cceee81d58c8477c7c28d9ad6b55c36aTimo Sirainenstatic int mail_cache_header_fields_get_offset(struct mail_cache *cache,
cdf294e5cceee81d58c8477c7c28d9ad6b55c36aTimo Sirainen uint32_t *offset_r)
cdf294e5cceee81d58c8477c7c28d9ad6b55c36aTimo Sirainen{
cdf294e5cceee81d58c8477c7c28d9ad6b55c36aTimo Sirainen const struct mail_cache_header_fields *field_hdr;
c154a05c76d4d83de1cdf9746ce4e2da0869705dTimo Sirainen uint32_t offset, next_offset;
cdf294e5cceee81d58c8477c7c28d9ad6b55c36aTimo Sirainen
cdf294e5cceee81d58c8477c7c28d9ad6b55c36aTimo Sirainen if (MAIL_CACHE_IS_UNUSABLE(cache)) {
cdf294e5cceee81d58c8477c7c28d9ad6b55c36aTimo Sirainen *offset_r = 0;
cf63dc8723b971cc80638fccbf494d961cbafc7fTimo Sirainen return 0;
cdf294e5cceee81d58c8477c7c28d9ad6b55c36aTimo Sirainen }
c154a05c76d4d83de1cdf9746ce4e2da0869705dTimo Sirainen
c154a05c76d4d83de1cdf9746ce4e2da0869705dTimo Sirainen /* find the latest header */
c154a05c76d4d83de1cdf9746ce4e2da0869705dTimo Sirainen offset = 0;
cdf294e5cceee81d58c8477c7c28d9ad6b55c36aTimo Sirainen next_offset =
c154a05c76d4d83de1cdf9746ce4e2da0869705dTimo Sirainen mail_cache_offset_to_uint32(cache->hdr->field_header_offset);
cdf294e5cceee81d58c8477c7c28d9ad6b55c36aTimo Sirainen while (next_offset != 0) {
cdf294e5cceee81d58c8477c7c28d9ad6b55c36aTimo Sirainen if (next_offset == offset) {
cdf294e5cceee81d58c8477c7c28d9ad6b55c36aTimo Sirainen mail_cache_set_corrupted(cache,
5e46f82843a13cc590900352d34c899cd5967de0Timo Sirainen "next_offset in field header loops");
5e46f82843a13cc590900352d34c899cd5967de0Timo Sirainen return -1;
5e46f82843a13cc590900352d34c899cd5967de0Timo Sirainen }
5e46f82843a13cc590900352d34c899cd5967de0Timo Sirainen offset = next_offset;
5e46f82843a13cc590900352d34c899cd5967de0Timo Sirainen
5e46f82843a13cc590900352d34c899cd5967de0Timo Sirainen if (mail_cache_map(cache, offset,
2d7da70c0e6768afeb1200c95f3e1293f2e502c6Timo Sirainen sizeof(*field_hdr) + CACHE_HDR_PREFETCH) < 0)
2d7da70c0e6768afeb1200c95f3e1293f2e502c6Timo Sirainen return -1;
2d7da70c0e6768afeb1200c95f3e1293f2e502c6Timo Sirainen
2d7da70c0e6768afeb1200c95f3e1293f2e502c6Timo Sirainen field_hdr = CONST_PTR_OFFSET(cache->mmap_base, offset);
2d7da70c0e6768afeb1200c95f3e1293f2e502c6Timo Sirainen next_offset =
2d7da70c0e6768afeb1200c95f3e1293f2e502c6Timo Sirainen mail_cache_offset_to_uint32(field_hdr->next_offset);
2d7da70c0e6768afeb1200c95f3e1293f2e502c6Timo Sirainen }
cf63dc8723b971cc80638fccbf494d961cbafc7fTimo Sirainen
cdf294e5cceee81d58c8477c7c28d9ad6b55c36aTimo Sirainen *offset_r = offset;
cdf294e5cceee81d58c8477c7c28d9ad6b55c36aTimo Sirainen return 0;
cdf294e5cceee81d58c8477c7c28d9ad6b55c36aTimo Sirainen}
7fbd5e7ceedb73996290c5358f5243d7d22b4d49Timo Sirainen
cdf294e5cceee81d58c8477c7c28d9ad6b55c36aTimo Sirainenint mail_cache_header_fields_read(struct mail_cache *cache)
6df0ab0c1ab91f06b6418cb30eff44405a1b8f02Timo Sirainen{
cdf294e5cceee81d58c8477c7c28d9ad6b55c36aTimo Sirainen const struct mail_cache_header_fields *field_hdr = NULL;
cdf294e5cceee81d58c8477c7c28d9ad6b55c36aTimo Sirainen struct mail_cache_field field;
cdf294e5cceee81d58c8477c7c28d9ad6b55c36aTimo Sirainen const uint32_t *last_used, *sizes;
d9a7e950a9cd21f2b4a90ec7759fca9e8fcc7995Timo Sirainen const uint8_t *types, *decisions;
2d7da70c0e6768afeb1200c95f3e1293f2e502c6Timo Sirainen const char *p, *names, *end;
cdf294e5cceee81d58c8477c7c28d9ad6b55c36aTimo Sirainen void *orig_key, *orig_value;
cdf294e5cceee81d58c8477c7c28d9ad6b55c36aTimo Sirainen uint32_t offset, i;
cdf294e5cceee81d58c8477c7c28d9ad6b55c36aTimo Sirainen
cdf294e5cceee81d58c8477c7c28d9ad6b55c36aTimo Sirainen if (mail_cache_header_fields_get_offset(cache, &offset) < 0)
d38ca817bdcec666a3b91efb917064ab844c36a2Timo Sirainen return -1;
d38ca817bdcec666a3b91efb917064ab844c36a2Timo Sirainen
cf1c3e6833fc5031d89db48dad46ed025beda4e7Timo Sirainen if (offset == 0) {
c154a05c76d4d83de1cdf9746ce4e2da0869705dTimo Sirainen /* no fields - the file is empty */
d38ca817bdcec666a3b91efb917064ab844c36a2Timo Sirainen return 0;
d38ca817bdcec666a3b91efb917064ab844c36a2Timo Sirainen }
cf1c3e6833fc5031d89db48dad46ed025beda4e7Timo Sirainen
cf1c3e6833fc5031d89db48dad46ed025beda4e7Timo Sirainen field_hdr = CONST_PTR_OFFSET(cache->mmap_base, offset);
cf1c3e6833fc5031d89db48dad46ed025beda4e7Timo Sirainen if (offset + field_hdr->size > cache->mmap_length) {
cf1c3e6833fc5031d89db48dad46ed025beda4e7Timo Sirainen mail_cache_set_corrupted(cache,
b5ad250aeacc094b84cce08eeab227d0ec14fb14Timo Sirainen "field header points outside file");
b5ad250aeacc094b84cce08eeab227d0ec14fb14Timo Sirainen return -1;
b5ad250aeacc094b84cce08eeab227d0ec14fb14Timo Sirainen }
b5ad250aeacc094b84cce08eeab227d0ec14fb14Timo Sirainen
b5ad250aeacc094b84cce08eeab227d0ec14fb14Timo Sirainen /* check the fixed size of the header. name[] has to be checked
b5ad250aeacc094b84cce08eeab227d0ec14fb14Timo Sirainen separately */
b5ad250aeacc094b84cce08eeab227d0ec14fb14Timo Sirainen if (field_hdr->size < sizeof(*field_hdr) +
d38ca817bdcec666a3b91efb917064ab844c36a2Timo Sirainen field_hdr->fields_count * (sizeof(uint32_t)*2 + 1 + 2)) {
d38ca817bdcec666a3b91efb917064ab844c36a2Timo Sirainen mail_cache_set_corrupted(cache, "invalid field header size");
d38ca817bdcec666a3b91efb917064ab844c36a2Timo Sirainen return -1;
c154a05c76d4d83de1cdf9746ce4e2da0869705dTimo Sirainen }
c154a05c76d4d83de1cdf9746ce4e2da0869705dTimo Sirainen
d38ca817bdcec666a3b91efb917064ab844c36a2Timo Sirainen if (field_hdr->size > sizeof(*field_hdr) + CACHE_HDR_PREFETCH) {
d38ca817bdcec666a3b91efb917064ab844c36a2Timo Sirainen if (mail_cache_map(cache, offset, field_hdr->size) < 0)
cf1c3e6833fc5031d89db48dad46ed025beda4e7Timo Sirainen return -1;
b5ad250aeacc094b84cce08eeab227d0ec14fb14Timo Sirainen }
cf1c3e6833fc5031d89db48dad46ed025beda4e7Timo Sirainen field_hdr = CONST_PTR_OFFSET(cache->mmap_base, offset);
cf1c3e6833fc5031d89db48dad46ed025beda4e7Timo Sirainen
c4ac0f222613903b7f8c9e0825198396e6bf793eTimo Sirainen cache->file_field_map =
c4ac0f222613903b7f8c9e0825198396e6bf793eTimo Sirainen i_realloc(cache->file_field_map,
cf1c3e6833fc5031d89db48dad46ed025beda4e7Timo Sirainen cache->file_fields_count * sizeof(unsigned int),
cf1c3e6833fc5031d89db48dad46ed025beda4e7Timo Sirainen field_hdr->fields_count * sizeof(unsigned int));
cf1c3e6833fc5031d89db48dad46ed025beda4e7Timo Sirainen cache->file_fields_count = field_hdr->fields_count;
8ae72ad7d0c69e972cfa65d1e2ce4e3e9a8b765cTimo Sirainen
8ae72ad7d0c69e972cfa65d1e2ce4e3e9a8b765cTimo Sirainen last_used = CONST_PTR_OFFSET(field_hdr, MAIL_CACHE_FIELD_LAST_USED());
cf1c3e6833fc5031d89db48dad46ed025beda4e7Timo Sirainen sizes = CONST_PTR_OFFSET(field_hdr,
cf1c3e6833fc5031d89db48dad46ed025beda4e7Timo Sirainen MAIL_CACHE_FIELD_SIZE(field_hdr->fields_count));
cf1c3e6833fc5031d89db48dad46ed025beda4e7Timo Sirainen types = CONST_PTR_OFFSET(field_hdr,
cf1c3e6833fc5031d89db48dad46ed025beda4e7Timo Sirainen MAIL_CACHE_FIELD_TYPE(field_hdr->fields_count));
cf1c3e6833fc5031d89db48dad46ed025beda4e7Timo Sirainen decisions = CONST_PTR_OFFSET(field_hdr,
cf1c3e6833fc5031d89db48dad46ed025beda4e7Timo Sirainen MAIL_CACHE_FIELD_DECISION(field_hdr->fields_count));
f33d37b678b5a14c8fb058a8f723e9b65f0b2043Timo Sirainen names = CONST_PTR_OFFSET(field_hdr,
f33d37b678b5a14c8fb058a8f723e9b65f0b2043Timo Sirainen MAIL_CACHE_FIELD_NAMES(field_hdr->fields_count));
f33d37b678b5a14c8fb058a8f723e9b65f0b2043Timo Sirainen end = CONST_PTR_OFFSET(field_hdr, field_hdr->size);
f33d37b678b5a14c8fb058a8f723e9b65f0b2043Timo Sirainen
f33d37b678b5a14c8fb058a8f723e9b65f0b2043Timo Sirainen /* clear the old mapping */
f33d37b678b5a14c8fb058a8f723e9b65f0b2043Timo Sirainen for (i = 0; i < cache->fields_count; i++)
c4ac0f222613903b7f8c9e0825198396e6bf793eTimo Sirainen cache->field_file_map[i] = (uint32_t)-1;
c4ac0f222613903b7f8c9e0825198396e6bf793eTimo Sirainen
f33d37b678b5a14c8fb058a8f723e9b65f0b2043Timo Sirainen memset(&field, 0, sizeof(field));
c4ac0f222613903b7f8c9e0825198396e6bf793eTimo Sirainen for (i = 0; i < field_hdr->fields_count; i++) {
c4ac0f222613903b7f8c9e0825198396e6bf793eTimo Sirainen for (p = names; p != end && *p != '\0'; p++) ;
c4ac0f222613903b7f8c9e0825198396e6bf793eTimo Sirainen if (p == end || *names == '\0') {
edd3573b249c7cc824d55897b77a768be3a2e13eTimo Sirainen mail_cache_set_corrupted(cache,
c4ac0f222613903b7f8c9e0825198396e6bf793eTimo Sirainen "field header names corrupted");
cf1c3e6833fc5031d89db48dad46ed025beda4e7Timo Sirainen return -1;
cf1c3e6833fc5031d89db48dad46ed025beda4e7Timo Sirainen }
cf1c3e6833fc5031d89db48dad46ed025beda4e7Timo Sirainen
cf1c3e6833fc5031d89db48dad46ed025beda4e7Timo Sirainen if (hash_lookup_full(cache->field_name_hash, names,
cf1c3e6833fc5031d89db48dad46ed025beda4e7Timo Sirainen &orig_key, &orig_value)) {
cf1c3e6833fc5031d89db48dad46ed025beda4e7Timo Sirainen /* already exists, see if decision can be updated */
c154a05c76d4d83de1cdf9746ce4e2da0869705dTimo Sirainen field.idx = POINTER_CAST_TO(orig_value, unsigned int);
d38ca817bdcec666a3b91efb917064ab844c36a2Timo Sirainen if (!cache->fields[field.idx].decision_dirty) {
d38ca817bdcec666a3b91efb917064ab844c36a2Timo Sirainen cache->fields[field.idx].field.decision =
d38ca817bdcec666a3b91efb917064ab844c36a2Timo Sirainen decisions[i];
f24b245f49b030d7dba3bcb2463cbc05b98c9d1dTimo Sirainen }
f24b245f49b030d7dba3bcb2463cbc05b98c9d1dTimo Sirainen if (cache->fields[field.idx].field.type != types[i]) {
f24b245f49b030d7dba3bcb2463cbc05b98c9d1dTimo Sirainen mail_cache_set_corrupted(cache,
f24b245f49b030d7dba3bcb2463cbc05b98c9d1dTimo Sirainen "registered field type changed");
f24b245f49b030d7dba3bcb2463cbc05b98c9d1dTimo Sirainen return -1;
f24b245f49b030d7dba3bcb2463cbc05b98c9d1dTimo Sirainen }
f24b245f49b030d7dba3bcb2463cbc05b98c9d1dTimo Sirainen } else {
f24b245f49b030d7dba3bcb2463cbc05b98c9d1dTimo Sirainen field.name = names;
f24b245f49b030d7dba3bcb2463cbc05b98c9d1dTimo Sirainen field.type = types[i];
f24b245f49b030d7dba3bcb2463cbc05b98c9d1dTimo Sirainen field.field_size = sizes[i];
f24b245f49b030d7dba3bcb2463cbc05b98c9d1dTimo Sirainen field.decision = decisions[i];
f24b245f49b030d7dba3bcb2463cbc05b98c9d1dTimo Sirainen mail_cache_register_fields(cache, &field, 1);
f24b245f49b030d7dba3bcb2463cbc05b98c9d1dTimo Sirainen }
f24b245f49b030d7dba3bcb2463cbc05b98c9d1dTimo Sirainen cache->field_file_map[field.idx] = i;
f24b245f49b030d7dba3bcb2463cbc05b98c9d1dTimo Sirainen cache->file_field_map[i] = field.idx;
f24b245f49b030d7dba3bcb2463cbc05b98c9d1dTimo Sirainen
f24b245f49b030d7dba3bcb2463cbc05b98c9d1dTimo Sirainen /* update last_used if it's newer than ours */
f24b245f49b030d7dba3bcb2463cbc05b98c9d1dTimo Sirainen if ((time_t)last_used[i] > cache->fields[field.idx].last_used) {
f24b245f49b030d7dba3bcb2463cbc05b98c9d1dTimo Sirainen cache->fields[field.idx].last_used =
d9a7e950a9cd21f2b4a90ec7759fca9e8fcc7995Timo Sirainen (time_t)last_used[i];
2d7da70c0e6768afeb1200c95f3e1293f2e502c6Timo Sirainen }
f24b245f49b030d7dba3bcb2463cbc05b98c9d1dTimo Sirainen
f24b245f49b030d7dba3bcb2463cbc05b98c9d1dTimo Sirainen names = p + 1;
f24b245f49b030d7dba3bcb2463cbc05b98c9d1dTimo Sirainen }
f24b245f49b030d7dba3bcb2463cbc05b98c9d1dTimo Sirainen return 0;
f24b245f49b030d7dba3bcb2463cbc05b98c9d1dTimo Sirainen}
cf63dc8723b971cc80638fccbf494d961cbafc7fTimo Sirainen
cdf294e5cceee81d58c8477c7c28d9ad6b55c36aTimo Sirainenstatic void copy_to_buf(struct mail_cache *cache, buffer_t *dest,
cdf294e5cceee81d58c8477c7c28d9ad6b55c36aTimo Sirainen size_t offset, size_t size)
cdf294e5cceee81d58c8477c7c28d9ad6b55c36aTimo Sirainen{
2d7da70c0e6768afeb1200c95f3e1293f2e502c6Timo Sirainen const void *data;
cdf294e5cceee81d58c8477c7c28d9ad6b55c36aTimo Sirainen unsigned int i, field;
cdf294e5cceee81d58c8477c7c28d9ad6b55c36aTimo Sirainen
cdf294e5cceee81d58c8477c7c28d9ad6b55c36aTimo Sirainen for (i = 0; i < cache->file_fields_count; i++) {
cdf294e5cceee81d58c8477c7c28d9ad6b55c36aTimo Sirainen field = cache->file_field_map[i];
cdf294e5cceee81d58c8477c7c28d9ad6b55c36aTimo Sirainen data = CONST_PTR_OFFSET(&cache->fields[field], offset);
d9a7e950a9cd21f2b4a90ec7759fca9e8fcc7995Timo Sirainen buffer_append(dest, data, size);
2d7da70c0e6768afeb1200c95f3e1293f2e502c6Timo Sirainen }
2d7da70c0e6768afeb1200c95f3e1293f2e502c6Timo Sirainen for (i = 0; i < cache->fields_count; i++) {
cdf294e5cceee81d58c8477c7c28d9ad6b55c36aTimo Sirainen if (cache->field_file_map[i] != (uint32_t)-1)
cdf294e5cceee81d58c8477c7c28d9ad6b55c36aTimo Sirainen continue;
ed897f9e09ae8ad86a88955420bd275b46ee8231Timo Sirainen data = CONST_PTR_OFFSET(&cache->fields[i], offset);
ed897f9e09ae8ad86a88955420bd275b46ee8231Timo Sirainen buffer_append(dest, data, size);
ed897f9e09ae8ad86a88955420bd275b46ee8231Timo Sirainen }
ed897f9e09ae8ad86a88955420bd275b46ee8231Timo Sirainen}
ed897f9e09ae8ad86a88955420bd275b46ee8231Timo Sirainen
ed897f9e09ae8ad86a88955420bd275b46ee8231Timo Sirainenint mail_cache_header_fields_update(struct mail_cache *cache)
ed897f9e09ae8ad86a88955420bd275b46ee8231Timo Sirainen{
ed897f9e09ae8ad86a88955420bd275b46ee8231Timo Sirainen int locked = cache->locked;
ed897f9e09ae8ad86a88955420bd275b46ee8231Timo Sirainen buffer_t *buffer;
ed897f9e09ae8ad86a88955420bd275b46ee8231Timo Sirainen uint32_t i, offset;
ed897f9e09ae8ad86a88955420bd275b46ee8231Timo Sirainen int ret = 0;
ed897f9e09ae8ad86a88955420bd275b46ee8231Timo Sirainen
cf63dc8723b971cc80638fccbf494d961cbafc7fTimo Sirainen if (!locked) {
cdf294e5cceee81d58c8477c7c28d9ad6b55c36aTimo Sirainen if (mail_cache_lock(cache) <= 0)
cdf294e5cceee81d58c8477c7c28d9ad6b55c36aTimo Sirainen return -1;
2d7da70c0e6768afeb1200c95f3e1293f2e502c6Timo Sirainen }
cdf294e5cceee81d58c8477c7c28d9ad6b55c36aTimo Sirainen
cdf294e5cceee81d58c8477c7c28d9ad6b55c36aTimo Sirainen if (mail_cache_header_fields_read(cache) < 0 ||
cdf294e5cceee81d58c8477c7c28d9ad6b55c36aTimo Sirainen mail_cache_header_fields_get_offset(cache, &offset) < 0) {
d9a7e950a9cd21f2b4a90ec7759fca9e8fcc7995Timo Sirainen mail_cache_unlock(cache);
2d7da70c0e6768afeb1200c95f3e1293f2e502c6Timo Sirainen return -1;
2d7da70c0e6768afeb1200c95f3e1293f2e502c6Timo Sirainen }
cdf294e5cceee81d58c8477c7c28d9ad6b55c36aTimo Sirainen
cdf294e5cceee81d58c8477c7c28d9ad6b55c36aTimo Sirainen t_push();
46d283ef537885386ab3fc72d1831054ea5f986bTimo Sirainen buffer = buffer_create_dynamic(pool_datastack_create(),
46d283ef537885386ab3fc72d1831054ea5f986bTimo Sirainen 256, (size_t)-1);
46d283ef537885386ab3fc72d1831054ea5f986bTimo Sirainen
46d283ef537885386ab3fc72d1831054ea5f986bTimo Sirainen copy_to_buf(cache, buffer,
46d283ef537885386ab3fc72d1831054ea5f986bTimo Sirainen offsetof(struct mail_cache_field_private, last_used),
46d283ef537885386ab3fc72d1831054ea5f986bTimo Sirainen sizeof(uint32_t));
46d283ef537885386ab3fc72d1831054ea5f986bTimo Sirainen ret = pwrite_full(cache->fd, buffer_get_data(buffer, NULL),
46d283ef537885386ab3fc72d1831054ea5f986bTimo Sirainen sizeof(uint32_t) * cache->file_fields_count,
46d283ef537885386ab3fc72d1831054ea5f986bTimo Sirainen offset + MAIL_CACHE_FIELD_LAST_USED());
46d283ef537885386ab3fc72d1831054ea5f986bTimo Sirainen if (ret == 0) {
46d283ef537885386ab3fc72d1831054ea5f986bTimo Sirainen buffer_set_used_size(buffer, 0);
46d283ef537885386ab3fc72d1831054ea5f986bTimo Sirainen copy_to_buf(cache, buffer,
46d283ef537885386ab3fc72d1831054ea5f986bTimo Sirainen offsetof(struct mail_cache_field, decision),
46d283ef537885386ab3fc72d1831054ea5f986bTimo Sirainen sizeof(uint8_t));
46d283ef537885386ab3fc72d1831054ea5f986bTimo Sirainen
d9076f5939edf5d20a261494b1a861dcbb0d32e2Timo Sirainen ret = pwrite_full(cache->fd, buffer_get_data(buffer, NULL),
46d283ef537885386ab3fc72d1831054ea5f986bTimo Sirainen sizeof(uint8_t) * cache->file_fields_count, offset +
46d283ef537885386ab3fc72d1831054ea5f986bTimo Sirainen MAIL_CACHE_FIELD_DECISION(cache->file_fields_count));
46d283ef537885386ab3fc72d1831054ea5f986bTimo Sirainen
46d283ef537885386ab3fc72d1831054ea5f986bTimo Sirainen if (ret == 0) {
46d283ef537885386ab3fc72d1831054ea5f986bTimo Sirainen for (i = 0; i < cache->fields_count; i++)
46d283ef537885386ab3fc72d1831054ea5f986bTimo Sirainen cache->fields[i].decision_dirty = FALSE;
46d283ef537885386ab3fc72d1831054ea5f986bTimo Sirainen }
46d283ef537885386ab3fc72d1831054ea5f986bTimo Sirainen }
46d283ef537885386ab3fc72d1831054ea5f986bTimo Sirainen t_pop();
46d283ef537885386ab3fc72d1831054ea5f986bTimo Sirainen
46d283ef537885386ab3fc72d1831054ea5f986bTimo Sirainen if (ret == 0)
46d283ef537885386ab3fc72d1831054ea5f986bTimo Sirainen cache->field_header_write_pending = FALSE;
46d283ef537885386ab3fc72d1831054ea5f986bTimo Sirainen
46d283ef537885386ab3fc72d1831054ea5f986bTimo Sirainen if (!locked)
46d283ef537885386ab3fc72d1831054ea5f986bTimo Sirainen mail_cache_unlock(cache);
46d283ef537885386ab3fc72d1831054ea5f986bTimo Sirainen return ret;
46d283ef537885386ab3fc72d1831054ea5f986bTimo Sirainen}
46d283ef537885386ab3fc72d1831054ea5f986bTimo Sirainen
46d283ef537885386ab3fc72d1831054ea5f986bTimo Sirainenvoid mail_cache_header_fields_get(struct mail_cache *cache, buffer_t *dest)
46d283ef537885386ab3fc72d1831054ea5f986bTimo Sirainen{
46d283ef537885386ab3fc72d1831054ea5f986bTimo Sirainen struct mail_cache_header_fields hdr;
46d283ef537885386ab3fc72d1831054ea5f986bTimo Sirainen unsigned int field;
46d283ef537885386ab3fc72d1831054ea5f986bTimo Sirainen const char *name;
46d283ef537885386ab3fc72d1831054ea5f986bTimo Sirainen uint32_t i;
46d283ef537885386ab3fc72d1831054ea5f986bTimo Sirainen
12e5ac049bd74f8b98d9dc62adcb0bf3217beef6Martti Rannanjärvi memset(&hdr, 0, sizeof(hdr));
46d283ef537885386ab3fc72d1831054ea5f986bTimo Sirainen hdr.fields_count = cache->fields_count;
a10ed8c47534b4c6b6bf2711ccfe577e720a47b4Timo Sirainen buffer_append(dest, &hdr, sizeof(hdr));
46d283ef537885386ab3fc72d1831054ea5f986bTimo Sirainen
9f7a3d6bbc4601e293656295f2aa44dc67e1cb16Timo Sirainen /* we have to keep the field order for the existing fields. */
9f7a3d6bbc4601e293656295f2aa44dc67e1cb16Timo Sirainen copy_to_buf(cache, dest,
9e952e5d80c17d2b47d2383dfc0c955292bb5c38Timo Sirainen offsetof(struct mail_cache_field_private, last_used),
46d283ef537885386ab3fc72d1831054ea5f986bTimo Sirainen sizeof(uint32_t));
9e952e5d80c17d2b47d2383dfc0c955292bb5c38Timo Sirainen copy_to_buf(cache, dest, offsetof(struct mail_cache_field, field_size),
46d283ef537885386ab3fc72d1831054ea5f986bTimo Sirainen sizeof(uint32_t));
46d283ef537885386ab3fc72d1831054ea5f986bTimo Sirainen copy_to_buf(cache, dest, offsetof(struct mail_cache_field, type),
cf63dc8723b971cc80638fccbf494d961cbafc7fTimo Sirainen sizeof(uint8_t));
cdf294e5cceee81d58c8477c7c28d9ad6b55c36aTimo Sirainen copy_to_buf(cache, dest, offsetof(struct mail_cache_field, decision),
cdf294e5cceee81d58c8477c7c28d9ad6b55c36aTimo Sirainen sizeof(uint8_t));
cdf294e5cceee81d58c8477c7c28d9ad6b55c36aTimo Sirainen
cdf294e5cceee81d58c8477c7c28d9ad6b55c36aTimo Sirainen i_assert(buffer_get_used_size(dest) == sizeof(hdr) +
cdf294e5cceee81d58c8477c7c28d9ad6b55c36aTimo Sirainen (sizeof(uint32_t)*2 + 2) * hdr.fields_count);
c154a05c76d4d83de1cdf9746ce4e2da0869705dTimo Sirainen
cdf294e5cceee81d58c8477c7c28d9ad6b55c36aTimo Sirainen for (i = 0; i < cache->file_fields_count; i++) {
cdf294e5cceee81d58c8477c7c28d9ad6b55c36aTimo Sirainen field = cache->file_field_map[i];
cdf294e5cceee81d58c8477c7c28d9ad6b55c36aTimo Sirainen name = cache->fields[field].field.name;
cf63dc8723b971cc80638fccbf494d961cbafc7fTimo Sirainen buffer_append(dest, name, strlen(name)+1);
cdf294e5cceee81d58c8477c7c28d9ad6b55c36aTimo Sirainen }
cdf294e5cceee81d58c8477c7c28d9ad6b55c36aTimo Sirainen for (i = 0; i < cache->fields_count; i++) {
cdf294e5cceee81d58c8477c7c28d9ad6b55c36aTimo Sirainen if (cache->field_file_map[i] != (uint32_t)-1)
cdf294e5cceee81d58c8477c7c28d9ad6b55c36aTimo Sirainen continue;
cdf294e5cceee81d58c8477c7c28d9ad6b55c36aTimo Sirainen name = cache->fields[i].field.name;
c154a05c76d4d83de1cdf9746ce4e2da0869705dTimo Sirainen buffer_append(dest, name, strlen(name)+1);
cdf294e5cceee81d58c8477c7c28d9ad6b55c36aTimo Sirainen }
cdf294e5cceee81d58c8477c7c28d9ad6b55c36aTimo Sirainen
cdf294e5cceee81d58c8477c7c28d9ad6b55c36aTimo Sirainen hdr.size = buffer_get_used_size(dest);
cf63dc8723b971cc80638fccbf494d961cbafc7fTimo Sirainen buffer_write(dest, 0, &hdr, sizeof(hdr));
cdf294e5cceee81d58c8477c7c28d9ad6b55c36aTimo Sirainen
cdf294e5cceee81d58c8477c7c28d9ad6b55c36aTimo Sirainen if ((hdr.size & 3) != 0)
cdf294e5cceee81d58c8477c7c28d9ad6b55c36aTimo Sirainen buffer_append(dest, null4, 4 - (hdr.size & 3));
cdf294e5cceee81d58c8477c7c28d9ad6b55c36aTimo Sirainen}
cdf294e5cceee81d58c8477c7c28d9ad6b55c36aTimo Sirainen
c154a05c76d4d83de1cdf9746ce4e2da0869705dTimo Sirainenint mail_cache_header_fields_get_next_offset(struct mail_cache *cache,
cdf294e5cceee81d58c8477c7c28d9ad6b55c36aTimo Sirainen uint32_t *offset_r)
cdf294e5cceee81d58c8477c7c28d9ad6b55c36aTimo Sirainen{
cdf294e5cceee81d58c8477c7c28d9ad6b55c36aTimo Sirainen if (mail_cache_header_fields_get_offset(cache, offset_r) < 0)
cf63dc8723b971cc80638fccbf494d961cbafc7fTimo Sirainen return -1;
cdf294e5cceee81d58c8477c7c28d9ad6b55c36aTimo Sirainen
cdf294e5cceee81d58c8477c7c28d9ad6b55c36aTimo Sirainen if (*offset_r == 0) {
cdf294e5cceee81d58c8477c7c28d9ad6b55c36aTimo Sirainen *offset_r = offsetof(struct mail_cache_header,
cdf294e5cceee81d58c8477c7c28d9ad6b55c36aTimo Sirainen field_header_offset);
cdf294e5cceee81d58c8477c7c28d9ad6b55c36aTimo Sirainen } else {
cdf294e5cceee81d58c8477c7c28d9ad6b55c36aTimo Sirainen *offset_r += offsetof(struct mail_cache_header_fields,
cdf294e5cceee81d58c8477c7c28d9ad6b55c36aTimo Sirainen next_offset);
cdf294e5cceee81d58c8477c7c28d9ad6b55c36aTimo Sirainen }
cdf294e5cceee81d58c8477c7c28d9ad6b55c36aTimo Sirainen return 0;
cdf294e5cceee81d58c8477c7c28d9ad6b55c36aTimo Sirainen}
c154a05c76d4d83de1cdf9746ce4e2da0869705dTimo Sirainen