mail-cache-lookup.c revision fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen/* Copyright (C) 2003-2004 Timo Sirainen */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "lib.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "buffer.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "byteorder.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "mail-cache-private.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
56f45b3f3ae20e5c933701f4657dda5ef1916855Timo Sirainen#define CACHE_PREFETCH 1024
56f45b3f3ae20e5c933701f4657dda5ef1916855Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenconst char *
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenmail_cache_get_header_fields_str(struct mail_cache *cache, unsigned int idx)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen uint32_t offset, data_size;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen unsigned char *buf;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen if (MAIL_CACHE_IS_UNUSABLE(cache))
ae4a7e6f1b097004f2bb62dd43f14db3f78ada0fTimo Sirainen return NULL;
ae4a7e6f1b097004f2bb62dd43f14db3f78ada0fTimo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen offset = mail_cache_offset_to_uint32(cache->hdr->header_offsets[idx]);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (offset == 0)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return NULL;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen if (mail_cache_map(cache, offset, CACHE_PREFETCH) < 0)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return NULL;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (offset + sizeof(data_size) > cache->mmap_length) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen mail_cache_set_corrupted(cache, "Header %u points outside file",
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen idx);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return NULL;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen buf = cache->mmap_base;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen memcpy(&data_size, buf + offset, sizeof(data_size));
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen data_size = nbo_to_uint32(data_size);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen offset += sizeof(data_size);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (data_size == 0) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen mail_cache_set_corrupted(cache,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen "Header %u points to empty string", idx);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return NULL;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
56f45b3f3ae20e5c933701f4657dda5ef1916855Timo Sirainen if (data_size + sizeof(data_size) > CACHE_PREFETCH) {
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen if (mail_cache_map(cache, offset, data_size) < 0)
56f45b3f3ae20e5c933701f4657dda5ef1916855Timo Sirainen return NULL;
56f45b3f3ae20e5c933701f4657dda5ef1916855Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (offset + data_size > cache->mmap_length) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen mail_cache_set_corrupted(cache, "Header %u points outside file",
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen idx);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return NULL;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen buf = cache->mmap_base;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (buf[offset + data_size - 1] != '\0') {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen mail_cache_set_corrupted(cache,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen "Header %u points to invalid string", idx);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return NULL;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return buf + offset;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenconst char *const *
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenmail_cache_split_header(struct mail_cache *cache, const char *header)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen const char *const *arr, *const *tmp;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen const char *null = NULL;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen char *str;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen buffer_t *buf;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (header == NULL)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return NULL;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen arr = t_strsplit(header, "\n");
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen buf = buffer_create_dynamic(cache->split_header_pool, 32, (size_t)-1);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen for (tmp = arr; *tmp != NULL; tmp++) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen str = p_strdup(cache->split_header_pool, *tmp);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen buffer_append(buf, &str, sizeof(str));
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen buffer_append(buf, &null, sizeof(null));
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return buffer_get_data(buf, NULL);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenconst char *const *mail_cache_get_header_fields(struct mail_cache_view *view,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen unsigned int idx)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen struct mail_cache *cache = view->cache;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen const char *str;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen int i;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen i_assert(idx < MAIL_CACHE_HEADERS_COUNT);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen if (MAIL_CACHE_IS_UNUSABLE(view->cache))
ae4a7e6f1b097004f2bb62dd43f14db3f78ada0fTimo Sirainen return NULL;
ae4a7e6f1b097004f2bb62dd43f14db3f78ada0fTimo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen /* t_strsplit() is a bit slow, so we cache it */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (cache->hdr->header_offsets[idx] != cache->split_offsets[idx]) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen p_clear(cache->split_header_pool);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen t_push();
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen for (i = 0; i < MAIL_CACHE_HEADERS_COUNT; i++) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen cache->split_offsets[i] =
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen cache->hdr->header_offsets[i];
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen str = mail_cache_get_header_fields_str(cache, i);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen cache->split_headers[i] =
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen mail_cache_split_header(cache, str);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen t_pop();
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return cache->split_headers[idx];
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstruct mail_cache_record *
da5d50534cfca45d0aaaf0bdac17b287b4588809Timo Sirainenmail_cache_get_record(struct mail_cache *cache, uint32_t offset,
da5d50534cfca45d0aaaf0bdac17b287b4588809Timo Sirainen int index_offset)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen struct mail_cache_record *cache_rec;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen size_t size;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
da5d50534cfca45d0aaaf0bdac17b287b4588809Timo Sirainen if (!index_offset)
da5d50534cfca45d0aaaf0bdac17b287b4588809Timo Sirainen offset = mail_cache_offset_to_uint32(offset);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (offset == 0)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return NULL;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen if (mail_cache_map(cache, offset,
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen sizeof(*cache_rec) + CACHE_PREFETCH) < 0)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return NULL;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (offset + sizeof(*cache_rec) > cache->mmap_length) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen mail_cache_set_corrupted(cache, "record points outside file");
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return NULL;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen cache_rec = CACHE_RECORD(cache, offset);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen size = nbo_to_uint32(cache_rec->size);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (size < sizeof(*cache_rec)) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen mail_cache_set_corrupted(cache, "invalid record size");
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return NULL;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (size > CACHE_PREFETCH) {
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen if (mail_cache_map(cache, offset, size) < 0)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return NULL;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (offset + size > cache->mmap_length) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen mail_cache_set_corrupted(cache, "record points outside file");
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return NULL;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return cache_rec;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainenint mail_cache_lookup_offset(struct mail_cache_view *view, uint32_t seq,
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen uint32_t *offset_r, int skip_expunged)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen const struct mail_index_record *rec;
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen struct mail_index_map *map;
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen int i, ret;
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen for (i = 0; i < 2; i++) {
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen ret = mail_index_lookup_full(view->view, seq, &map, &rec);
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen if (ret < 0)
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen return -1;
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen if (ret == 0 && skip_expunged)
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen return 0;
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen if (map->hdr->cache_file_seq == view->cache->hdr->file_seq) {
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen *offset_r = rec->cache_offset;
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen return 1;
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen if ((ret = mail_cache_reopen(view->cache)) <= 0)
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen return ret;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen return 0;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstruct mail_cache_record *
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenmail_cache_lookup(struct mail_cache_view *view, uint32_t seq,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen enum mail_cache_field fields)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen uint32_t offset;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (mail_cache_transaction_autocommit(view, seq, fields) < 0)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return NULL;
56f45b3f3ae20e5c933701f4657dda5ef1916855Timo Sirainen
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen if (MAIL_CACHE_IS_UNUSABLE(view->cache))
56f45b3f3ae20e5c933701f4657dda5ef1916855Timo Sirainen return NULL;
56f45b3f3ae20e5c933701f4657dda5ef1916855Timo Sirainen
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen if (mail_cache_lookup_offset(view, seq, &offset, FALSE) <= 0)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return NULL;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen return mail_cache_get_record(view->cache, offset, TRUE);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenenum mail_cache_field
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenmail_cache_get_fields(struct mail_cache_view *view, uint32_t seq)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen struct mail_cache_record *cache_rec;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen enum mail_cache_field fields = 0;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen cache_rec = mail_cache_lookup(view, seq, 0);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen while (cache_rec != NULL) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen fields |= cache_rec->fields;
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen cache_rec = mail_cache_get_record(view->cache,
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen cache_rec->next_offset,
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen FALSE);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return fields;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstatic int cache_get_field(struct mail_cache *cache,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen struct mail_cache_record *cache_rec,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen enum mail_cache_field field,
8aacc9e7c84f8376822823ec98c2f551d4919b2eTimo Sirainen const void **data_r, size_t *size_r)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen unsigned char *buf;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen unsigned int mask;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen uint32_t rec_size, data_size;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen size_t offset, next_offset;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen int i;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen rec_size = nbo_to_uint32(cache_rec->size);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen buf = (unsigned char *) cache_rec;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen offset = sizeof(*cache_rec);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen for (i = 0, mask = 1; i < 31; i++, mask <<= 1) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if ((cache_rec->fields & mask) == 0)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen continue;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen /* all records are at least 32bit. we have to check this
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen before getting data_size. */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (offset + sizeof(uint32_t) > rec_size) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen mail_cache_set_corrupted(cache,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen "Record continues outside it's allocated size");
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return FALSE;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if ((mask & MAIL_CACHE_FIXED_MASK) != 0)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen data_size = mail_cache_field_sizes[i];
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen else {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen memcpy(&data_size, buf + offset, sizeof(data_size));
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen data_size = nbo_to_uint32(data_size);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen offset += sizeof(data_size);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen next_offset = offset + ((data_size + 3) & ~3);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (next_offset > rec_size) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen mail_cache_set_corrupted(cache,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen "Record continues outside it's allocated size");
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return FALSE;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (field == mask) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (data_size == 0) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen mail_cache_set_corrupted(cache,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen "Field size is 0");
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return FALSE;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen *data_r = buf + offset;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen *size_r = data_size;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return TRUE;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen offset = next_offset;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen i_unreached();
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return FALSE;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
8aacc9e7c84f8376822823ec98c2f551d4919b2eTimo Sirainenint mail_cache_lookup_field(struct mail_cache_view *view, uint32_t seq,
8aacc9e7c84f8376822823ec98c2f551d4919b2eTimo Sirainen enum mail_cache_field field,
8aacc9e7c84f8376822823ec98c2f551d4919b2eTimo Sirainen const void **data_r, size_t *size_r)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen struct mail_cache_record *cache_rec;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
8aacc9e7c84f8376822823ec98c2f551d4919b2eTimo Sirainen mail_cache_handle_decisions(view, seq, field);
8aacc9e7c84f8376822823ec98c2f551d4919b2eTimo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen cache_rec = mail_cache_lookup(view, seq, field);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen while (cache_rec != NULL) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if ((cache_rec->fields & field) != 0) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return cache_get_field(view->cache, cache_rec, field,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen data_r, size_r);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen cache_rec = mail_cache_get_record(view->cache,
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen cache_rec->next_offset,
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen FALSE);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return FALSE;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenconst char *
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenmail_cache_lookup_string_field(struct mail_cache_view *view, uint32_t seq,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen enum mail_cache_field field)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen const void *data;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen size_t size;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen i_assert((field & MAIL_CACHE_STRING_MASK) != 0);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (!mail_cache_lookup_field(view, seq, field, &data, &size))
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return NULL;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (((const char *) data)[size-1] != '\0') {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen mail_cache_set_corrupted(view->cache,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen "String field %x doesn't end with NUL", field);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return NULL;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return data;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenint mail_cache_copy_fixed_field(struct mail_cache_view *view, uint32_t seq,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen enum mail_cache_field field,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen void *buffer, size_t buffer_size)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen const void *data;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen size_t size;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen i_assert((field & MAIL_CACHE_FIXED_MASK) != 0);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (!mail_cache_lookup_field(view, seq, field, &data, &size))
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return FALSE;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (buffer_size != size) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen i_panic("cache: fixed field %x wrong size "
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen "(%"PRIuSIZE_T" vs %"PRIuSIZE_T")",
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen field, size, buffer_size);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen memcpy(buffer, data, buffer_size);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return TRUE;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen}
da5d50534cfca45d0aaaf0bdac17b287b4588809Timo Sirainen
da5d50534cfca45d0aaaf0bdac17b287b4588809Timo Sirainenenum mail_cache_record_flag
da5d50534cfca45d0aaaf0bdac17b287b4588809Timo Sirainenmail_cache_get_record_flags(struct mail_cache_view *view, uint32_t seq)
da5d50534cfca45d0aaaf0bdac17b287b4588809Timo Sirainen{
da5d50534cfca45d0aaaf0bdac17b287b4588809Timo Sirainen // FIXME:
da5d50534cfca45d0aaaf0bdac17b287b4588809Timo Sirainen return 0;
da5d50534cfca45d0aaaf0bdac17b287b4588809Timo Sirainen}