mail-cache-lookup.c revision 1171f0abf442638bac1827bb24a0b6b8eb682a82
5a580c3a38ced62d4bcc95b8ac7c4f2935b5d294Timo Sirainen/* Copyright (C) 2003-2004 Timo Sirainen */
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen#include "lib.h"
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen#include "buffer.h"
78fa3c578c14ee8a612f86cf73b6181c7f16463fTimo Sirainen#include "str.h"
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen#include "mail-cache-private.h"
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen#define CACHE_PREFETCH 1024
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainenconst char *
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainenmail_cache_get_header_fields_str(struct mail_cache *cache, unsigned int idx)
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen{
f7423cbbd9dea363a5df18ebb96da055a977ae79Timo Sirainen uint32_t offset, data_size;
2cd2518bab14292a67cf8a490b58ab9ef89879daTimo Sirainen const unsigned char *buf;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if (MAIL_CACHE_IS_UNUSABLE(cache))
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen return NULL;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
6ec925f52d04ec8700e47cb005bd7ddc65ac5614Timo Sirainen offset = mail_cache_offset_to_uint32(cache->hdr->header_offsets[idx]);
c60178b2610a9b193ff72aa18448398ef72529a1Timo Sirainen
4d4d6d4745682790c20d759ba93dbea46b812c5dTimo Sirainen if (offset == 0)
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen return NULL;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if (mail_cache_map(cache, offset, CACHE_PREFETCH) < 0)
cf2e6953d03a1c22f272ec19432fc03c136ac1bbTimo Sirainen return NULL;
5d4c793b4e3dbc07f08daa4465594b1857f80725Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if (offset + sizeof(data_size) > cache->mmap_length) {
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen mail_cache_set_corrupted(cache, "Header %u points outside file",
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen idx);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen return NULL;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen }
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
617e13833c798435e2be425b99c27ecaad1b8393Timo Sirainen buf = cache->mmap_base;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen memcpy(&data_size, buf + offset, sizeof(data_size));
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen offset += sizeof(data_size);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if (data_size == 0) {
5d4c793b4e3dbc07f08daa4465594b1857f80725Timo Sirainen mail_cache_set_corrupted(cache,
5d4c793b4e3dbc07f08daa4465594b1857f80725Timo Sirainen "Header %u points to empty string", idx);
5d4c793b4e3dbc07f08daa4465594b1857f80725Timo Sirainen return NULL;
5d4c793b4e3dbc07f08daa4465594b1857f80725Timo Sirainen }
5d4c793b4e3dbc07f08daa4465594b1857f80725Timo Sirainen
5d4c793b4e3dbc07f08daa4465594b1857f80725Timo Sirainen if (data_size + sizeof(data_size) > CACHE_PREFETCH) {
5d4c793b4e3dbc07f08daa4465594b1857f80725Timo Sirainen if (mail_cache_map(cache, offset, data_size) < 0)
5d4c793b4e3dbc07f08daa4465594b1857f80725Timo Sirainen return NULL;
5d4c793b4e3dbc07f08daa4465594b1857f80725Timo Sirainen }
5d4c793b4e3dbc07f08daa4465594b1857f80725Timo Sirainen
5d4c793b4e3dbc07f08daa4465594b1857f80725Timo Sirainen if (offset + data_size > cache->mmap_length) {
5d4c793b4e3dbc07f08daa4465594b1857f80725Timo Sirainen mail_cache_set_corrupted(cache, "Header %u points outside file",
5d4c793b4e3dbc07f08daa4465594b1857f80725Timo Sirainen idx);
5d4c793b4e3dbc07f08daa4465594b1857f80725Timo Sirainen return NULL;
5d4c793b4e3dbc07f08daa4465594b1857f80725Timo Sirainen }
5d4c793b4e3dbc07f08daa4465594b1857f80725Timo Sirainen
5d4c793b4e3dbc07f08daa4465594b1857f80725Timo Sirainen buf = cache->mmap_base;
5d4c793b4e3dbc07f08daa4465594b1857f80725Timo Sirainen if (buf[offset + data_size - 1] != '\0') {
78fa3c578c14ee8a612f86cf73b6181c7f16463fTimo Sirainen mail_cache_set_corrupted(cache,
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen "Header %u points to invalid string", idx);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen return NULL;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen }
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
f7423cbbd9dea363a5df18ebb96da055a977ae79Timo Sirainen return buf + offset;
e9ac518aaf49a06d976bf7f24ab14a3e2d6d86abTimo Sirainen}
e9ac518aaf49a06d976bf7f24ab14a3e2d6d86abTimo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainenconst char *const *
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainenmail_cache_split_header(struct mail_cache *cache, const char *header)
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen{
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen const char *const *arr, *const *tmp;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen const char *null = NULL;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen char *str;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen buffer_t *buf;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if (header == NULL)
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen return NULL;
78fa3c578c14ee8a612f86cf73b6181c7f16463fTimo Sirainen
f7423cbbd9dea363a5df18ebb96da055a977ae79Timo Sirainen arr = t_strsplit(header, "\n");
78fa3c578c14ee8a612f86cf73b6181c7f16463fTimo Sirainen buf = buffer_create_dynamic(cache->split_header_pool, 32, (size_t)-1);
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen for (tmp = arr; *tmp != NULL; tmp++) {
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen str = p_strdup(cache->split_header_pool, *tmp);
e9ac518aaf49a06d976bf7f24ab14a3e2d6d86abTimo Sirainen buffer_append(buf, &str, sizeof(str));
e9ac518aaf49a06d976bf7f24ab14a3e2d6d86abTimo Sirainen }
78fa3c578c14ee8a612f86cf73b6181c7f16463fTimo Sirainen buffer_append(buf, &null, sizeof(null));
e9ac518aaf49a06d976bf7f24ab14a3e2d6d86abTimo Sirainen
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen return buffer_get_data(buf, NULL);
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen}
230ef558135f16a66b86cbe3762524eaa9ae9d81Timo Sirainen
230ef558135f16a66b86cbe3762524eaa9ae9d81Timo Sirainenconst char *const *mail_cache_get_header_fields(struct mail_cache_view *view,
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen unsigned int idx)
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen{
e9ac518aaf49a06d976bf7f24ab14a3e2d6d86abTimo Sirainen struct mail_cache *cache = view->cache;
e9ac518aaf49a06d976bf7f24ab14a3e2d6d86abTimo Sirainen const char *str;
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen int i;
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen i_assert(idx < MAIL_CACHE_HEADERS_COUNT);
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen
78fa3c578c14ee8a612f86cf73b6181c7f16463fTimo Sirainen if (MAIL_CACHE_IS_UNUSABLE(view->cache))
78fa3c578c14ee8a612f86cf73b6181c7f16463fTimo Sirainen return NULL;
f7423cbbd9dea363a5df18ebb96da055a977ae79Timo Sirainen
e9ac518aaf49a06d976bf7f24ab14a3e2d6d86abTimo Sirainen /* t_strsplit() is a bit slow, so we cache it */
f7423cbbd9dea363a5df18ebb96da055a977ae79Timo Sirainen if (cache->hdr->header_offsets[idx] != cache->split_offsets[idx]) {
f7423cbbd9dea363a5df18ebb96da055a977ae79Timo Sirainen p_clear(cache->split_header_pool);
7487ff578435377bbeefffdbfb78ca09ed1292dfTimo Sirainen
78fa3c578c14ee8a612f86cf73b6181c7f16463fTimo Sirainen t_push();
7487ff578435377bbeefffdbfb78ca09ed1292dfTimo Sirainen for (i = 0; i < MAIL_CACHE_HEADERS_COUNT; i++) {
617e13833c798435e2be425b99c27ecaad1b8393Timo Sirainen cache->split_offsets[i] =
617e13833c798435e2be425b99c27ecaad1b8393Timo Sirainen cache->hdr->header_offsets[i];
d03a871a77f8ec36f48f5fea98d810e51b186fdbTimo Sirainen
f7423cbbd9dea363a5df18ebb96da055a977ae79Timo Sirainen str = mail_cache_get_header_fields_str(cache, i);
e9ac518aaf49a06d976bf7f24ab14a3e2d6d86abTimo Sirainen cache->split_headers[i] =
e9ac518aaf49a06d976bf7f24ab14a3e2d6d86abTimo Sirainen mail_cache_split_header(cache, str);
7487ff578435377bbeefffdbfb78ca09ed1292dfTimo Sirainen }
7487ff578435377bbeefffdbfb78ca09ed1292dfTimo Sirainen t_pop();
7487ff578435377bbeefffdbfb78ca09ed1292dfTimo Sirainen }
7487ff578435377bbeefffdbfb78ca09ed1292dfTimo Sirainen
7487ff578435377bbeefffdbfb78ca09ed1292dfTimo Sirainen return cache->split_headers[idx];
7487ff578435377bbeefffdbfb78ca09ed1292dfTimo Sirainen}
617e13833c798435e2be425b99c27ecaad1b8393Timo Sirainen
7487ff578435377bbeefffdbfb78ca09ed1292dfTimo Sirainenstruct mail_cache_record *
d03a871a77f8ec36f48f5fea98d810e51b186fdbTimo Sirainenmail_cache_get_record(struct mail_cache *cache, uint32_t offset)
f7423cbbd9dea363a5df18ebb96da055a977ae79Timo Sirainen{
e9ac518aaf49a06d976bf7f24ab14a3e2d6d86abTimo Sirainen struct mail_cache_record *cache_rec;
e9ac518aaf49a06d976bf7f24ab14a3e2d6d86abTimo Sirainen
7487ff578435377bbeefffdbfb78ca09ed1292dfTimo Sirainen if (offset == 0)
7487ff578435377bbeefffdbfb78ca09ed1292dfTimo Sirainen return NULL;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if (mail_cache_map(cache, offset,
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen sizeof(*cache_rec) + CACHE_PREFETCH) < 0)
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen return NULL;
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen if (offset + sizeof(*cache_rec) > cache->mmap_length) {
efc5c69c572e83db7bf7eab5d4698c0ab0d3d886Timo Sirainen mail_cache_set_corrupted(cache, "record points outside file");
efc5c69c572e83db7bf7eab5d4698c0ab0d3d886Timo Sirainen return NULL;
efc5c69c572e83db7bf7eab5d4698c0ab0d3d886Timo Sirainen }
efc5c69c572e83db7bf7eab5d4698c0ab0d3d886Timo Sirainen cache_rec = CACHE_RECORD(cache, offset);
efc5c69c572e83db7bf7eab5d4698c0ab0d3d886Timo Sirainen
efc5c69c572e83db7bf7eab5d4698c0ab0d3d886Timo Sirainen if (cache_rec->size < sizeof(*cache_rec)) {
efc5c69c572e83db7bf7eab5d4698c0ab0d3d886Timo Sirainen mail_cache_set_corrupted(cache, "invalid record size");
efc5c69c572e83db7bf7eab5d4698c0ab0d3d886Timo Sirainen return NULL;
dc07b75b7ea83ff5f447970a20419032725271a7Timo Sirainen }
efc5c69c572e83db7bf7eab5d4698c0ab0d3d886Timo Sirainen if (cache_rec->size > CACHE_PREFETCH) {
efc5c69c572e83db7bf7eab5d4698c0ab0d3d886Timo Sirainen if (mail_cache_map(cache, offset, cache_rec->size) < 0)
efc5c69c572e83db7bf7eab5d4698c0ab0d3d886Timo Sirainen return NULL;
efc5c69c572e83db7bf7eab5d4698c0ab0d3d886Timo Sirainen }
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
29f32cdcf44cda9688576bfdc7450a8a15e90e86Timo Sirainen if (offset + cache_rec->size > cache->mmap_length) {
29f32cdcf44cda9688576bfdc7450a8a15e90e86Timo Sirainen mail_cache_set_corrupted(cache, "record points outside file");
29f32cdcf44cda9688576bfdc7450a8a15e90e86Timo Sirainen return NULL;
29f32cdcf44cda9688576bfdc7450a8a15e90e86Timo Sirainen }
29f32cdcf44cda9688576bfdc7450a8a15e90e86Timo Sirainen return cache_rec;
29f32cdcf44cda9688576bfdc7450a8a15e90e86Timo Sirainen}
29f32cdcf44cda9688576bfdc7450a8a15e90e86Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainenstatic int mail_cache_lookup_offset(struct mail_cache_view *view, uint32_t seq,
b955a1c1b6d466977d971c029a9305bee492f73cTimo Sirainen uint32_t *offset_r)
b955a1c1b6d466977d971c029a9305bee492f73cTimo Sirainen{
b955a1c1b6d466977d971c029a9305bee492f73cTimo Sirainen const struct mail_index_record *rec;
b955a1c1b6d466977d971c029a9305bee492f73cTimo Sirainen struct mail_index_map *map;
b955a1c1b6d466977d971c029a9305bee492f73cTimo Sirainen int i, ret;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen for (i = 0; i < 2; i++) {
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if (mail_index_lookup_full(view->view, seq, &map, &rec) < 0)
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen return -1;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if (map->hdr->cache_file_seq == view->cache->hdr->file_seq) {
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen *offset_r = rec->cache_offset;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen return 1;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen }
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if ((ret = mail_cache_reopen(view->cache)) <= 0)
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen return ret;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen }
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen return 0;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen}
601b455f4d5e780044b9e4fac5f687c1b07ae145Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainenstruct mail_cache_record *
e9ac518aaf49a06d976bf7f24ab14a3e2d6d86abTimo Sirainenmail_cache_lookup(struct mail_cache_view *view, uint32_t seq)
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen{
7487ff578435377bbeefffdbfb78ca09ed1292dfTimo Sirainen uint32_t offset;
f7423cbbd9dea363a5df18ebb96da055a977ae79Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen // FIXME: check transactions too
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
fb7ac3e31c92627efe076318319976ac1c27ae2aTimo Sirainen if (MAIL_CACHE_IS_UNUSABLE(view->cache))
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen return NULL;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if (mail_cache_lookup_offset(view, seq, &offset) <= 0)
72cc352b25ad401b923436c6ed0f1f3adaffa737Timo Sirainen return NULL;
e1f866daa1bd1a5cd7516f3b19c6f197bcf6cc8aTimo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen return mail_cache_get_record(view->cache, offset);
614529ee060755c0b282102b70daf56bcd64222dTimo Sirainen}
9ebd0c59de5f8240c0dbc58773fe5679391199dbTimo Sirainen
6ec925f52d04ec8700e47cb005bd7ddc65ac5614Timo Sirainenenum mail_cache_field
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainenmail_cache_get_fields(struct mail_cache_view *view, uint32_t seq)
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen{
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen struct mail_cache_record *cache_rec;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen enum mail_cache_field fields = 0;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen cache_rec = mail_cache_lookup(view, seq);
e1f866daa1bd1a5cd7516f3b19c6f197bcf6cc8aTimo Sirainen while (cache_rec != NULL) {
e1f866daa1bd1a5cd7516f3b19c6f197bcf6cc8aTimo Sirainen fields |= cache_rec->fields;
e1f866daa1bd1a5cd7516f3b19c6f197bcf6cc8aTimo Sirainen cache_rec = mail_cache_get_record(view->cache,
e1f866daa1bd1a5cd7516f3b19c6f197bcf6cc8aTimo Sirainen cache_rec->prev_offset);
e1f866daa1bd1a5cd7516f3b19c6f197bcf6cc8aTimo Sirainen }
e1f866daa1bd1a5cd7516f3b19c6f197bcf6cc8aTimo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen return fields;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen}
4b2a1030f9b51e90f6ff4cdbc115871a398c1e0fTimo Sirainen
72cc352b25ad401b923436c6ed0f1f3adaffa737Timo Sirainenstatic int cache_get_field(struct mail_cache *cache,
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen const struct mail_cache_record *cache_rec,
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen enum mail_cache_field field, buffer_t *dest_buf)
72cc352b25ad401b923436c6ed0f1f3adaffa737Timo Sirainen{
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen unsigned int mask;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen uint32_t data_size;
9e291f6a7ca67b86d1d65a730ffb71fb9a334fb0Timo Sirainen size_t offset, prev_offset;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen int i;
bad5fa318c6c1384ab83bd72d53ce06593274c18Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen offset = sizeof(*cache_rec);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen for (i = 0, mask = 1; i < 31; i++, mask <<= 1) {
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if ((cache_rec->fields & mask) == 0)
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen continue;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen /* all records are at least 32bit. we have to check this
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen before getting data_size. */
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if (offset + sizeof(uint32_t) > cache_rec->size) {
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen mail_cache_set_corrupted(cache,
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen "Record continues outside it's allocated size");
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen return FALSE;
f5e1d3d6b34ec152aa1ff15c7bd3d3552e9227eaTimo Sirainen }
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if ((mask & MAIL_CACHE_FIXED_MASK) != 0)
f29756821a4c6b12b73e4a2a3e1c230117a43773Timo Sirainen data_size = mail_cache_field_sizes[i];
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen else {
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen memcpy(&data_size, CONST_PTR_OFFSET(cache_rec, offset),
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen sizeof(data_size));
bad5fa318c6c1384ab83bd72d53ce06593274c18Timo Sirainen offset += sizeof(data_size);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen }
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
5d46f4d076fc13ae2779c365cf4bd9bda3a5bc69Timo Sirainen prev_offset = offset + ((data_size + 3) & ~3);
5d46f4d076fc13ae2779c365cf4bd9bda3a5bc69Timo Sirainen if (prev_offset > cache_rec->size) {
5d46f4d076fc13ae2779c365cf4bd9bda3a5bc69Timo Sirainen mail_cache_set_corrupted(cache,
28482afc8139462ff9bcc6cedc4936129e8763efTimo Sirainen "Record continues outside it's allocated size");
28482afc8139462ff9bcc6cedc4936129e8763efTimo Sirainen return FALSE;
5d46f4d076fc13ae2779c365cf4bd9bda3a5bc69Timo Sirainen }
5d46f4d076fc13ae2779c365cf4bd9bda3a5bc69Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if (field == mask) {
d482079eb385cd071bbc9637cacee225e4aff968Timo Sirainen if (data_size == 0) {
9e291f6a7ca67b86d1d65a730ffb71fb9a334fb0Timo Sirainen mail_cache_set_corrupted(cache,
3a0f9aa9504497e4e47f32df54fbf47fdc7423b6Timo Sirainen "Field size is 0");
3a0f9aa9504497e4e47f32df54fbf47fdc7423b6Timo Sirainen return FALSE;
1ffb2afe6d7e8860a2231a4827078cf2ef9c22cdTimo Sirainen }
1ffb2afe6d7e8860a2231a4827078cf2ef9c22cdTimo Sirainen buffer_append(dest_buf,
d4845c4245638fd6f02dc0cb92c3465fae763cbbTimo Sirainen CONST_PTR_OFFSET(cache_rec, offset),
d4845c4245638fd6f02dc0cb92c3465fae763cbbTimo Sirainen data_size);
0161376aac025266d8654577c4b9ce371ffc87eaTimo Sirainen return TRUE;
0161376aac025266d8654577c4b9ce371ffc87eaTimo Sirainen }
788f275469ad9ed530e440d6690d0e4381a323b2Timo Sirainen offset = prev_offset;
788f275469ad9ed530e440d6690d0e4381a323b2Timo Sirainen }
788f275469ad9ed530e440d6690d0e4381a323b2Timo Sirainen
788f275469ad9ed530e440d6690d0e4381a323b2Timo Sirainen i_unreached();
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen return FALSE;
a8aec60b5359e5ea7fc7a9464217ae3626df8785Timo Sirainen}
28482afc8139462ff9bcc6cedc4936129e8763efTimo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainenint mail_cache_lookup_field(struct mail_cache_view *view, buffer_t *dest_buf,
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen uint32_t seq, enum mail_cache_field field)
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen{
43d7e7ce608f5451e4907b5f5c48c00beb265802Timo Sirainen struct mail_cache_record *cache_rec;
0547a828ee9647fc5fd2e359b145774740a697feTimo Sirainen
43d7e7ce608f5451e4907b5f5c48c00beb265802Timo Sirainen mail_cache_handle_decisions(view, seq, field);
43d7e7ce608f5451e4907b5f5c48c00beb265802Timo Sirainen
43d7e7ce608f5451e4907b5f5c48c00beb265802Timo Sirainen cache_rec = mail_cache_lookup(view, seq);
43d7e7ce608f5451e4907b5f5c48c00beb265802Timo Sirainen while (cache_rec != NULL) {
43d7e7ce608f5451e4907b5f5c48c00beb265802Timo Sirainen if ((cache_rec->fields & field) != 0) {
5d46f4d076fc13ae2779c365cf4bd9bda3a5bc69Timo Sirainen return cache_get_field(view->cache, cache_rec, field,
5d46f4d076fc13ae2779c365cf4bd9bda3a5bc69Timo Sirainen dest_buf);
5d46f4d076fc13ae2779c365cf4bd9bda3a5bc69Timo Sirainen }
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen cache_rec = mail_cache_get_record(view->cache,
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen cache_rec->prev_offset);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen }
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
55bc6a7a0940ec48a68558ef70838991c5d301d2Timo Sirainen return FALSE;
55bc6a7a0940ec48a68558ef70838991c5d301d2Timo Sirainen}
55bc6a7a0940ec48a68558ef70838991c5d301d2Timo Sirainen
55bc6a7a0940ec48a68558ef70838991c5d301d2Timo Sirainenint mail_cache_lookup_string_field(struct mail_cache_view *view, string_t *dest,
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen uint32_t seq, enum mail_cache_field field)
55bc6a7a0940ec48a68558ef70838991c5d301d2Timo Sirainen{
55bc6a7a0940ec48a68558ef70838991c5d301d2Timo Sirainen size_t old_size, new_size;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen i_assert((field & MAIL_CACHE_STRING_MASK) != 0);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen old_size = str_len(dest);
cf0ad1a0bddb0787f3d7b408a96d721a8b2a98a3Timo Sirainen if (!mail_cache_lookup_field(view, dest, seq, field))
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen return FALSE;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen new_size = str_len(dest);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if (old_size == new_size ||
28482afc8139462ff9bcc6cedc4936129e8763efTimo Sirainen str_data(dest)[new_size-1] != '\0') {
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen mail_cache_set_corrupted(view->cache,
4f4943f6ef1bc45c23de73eebe83779712b3c8cbTimo Sirainen "String field %x doesn't end with NUL", field);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen return FALSE;
601b455f4d5e780044b9e4fac5f687c1b07ae145Timo Sirainen }
601b455f4d5e780044b9e4fac5f687c1b07ae145Timo Sirainen str_truncate(dest, new_size-1);
cdc8485491045d82bb98405d4b995f277d12838eTimo Sirainen return TRUE;
cdc8485491045d82bb98405d4b995f277d12838eTimo Sirainen}
b2ed2b25c4c457ec1c99ebe5e9bd66a2e2f89cfdTimo Sirainen
b2ed2b25c4c457ec1c99ebe5e9bd66a2e2f89cfdTimo Sirainenenum mail_cache_record_flag
e5097d2c8efecdd274272b222cf2b30a8ae4ca2aTimo Sirainenmail_cache_get_record_flags(struct mail_cache_view *view, uint32_t seq)
e5097d2c8efecdd274272b222cf2b30a8ae4ca2aTimo Sirainen{
e5097d2c8efecdd274272b222cf2b30a8ae4ca2aTimo Sirainen // FIXME:
e5097d2c8efecdd274272b222cf2b30a8ae4ca2aTimo Sirainen return 0;
e5097d2c8efecdd274272b222cf2b30a8ae4ca2aTimo Sirainen}
28482afc8139462ff9bcc6cedc4936129e8763efTimo Sirainen