mail-index-map.c revision d051664df497582e1eb75a9f238d04b65e858db8
772199031f0ec687fa1fefd939206858c440e5a1Pavel Březina/* Copyright (C) 2003-2007 Timo Sirainen */
772199031f0ec687fa1fefd939206858c440e5a1Pavel Březinastatic void mail_index_map_init_extbufs(struct mail_index_map *map,
772199031f0ec687fa1fefd939206858c440e5a1Pavel Březina ((sizeof(map->extensions) + BUFFER_APPROX_SIZE) * 2)
772199031f0ec687fa1fefd939206858c440e5a1Pavel Březina sizeof(struct mail_index_ext) + sizeof(uint32_t))
772199031f0ec687fa1fefd939206858c440e5a1Pavel Březina /* try to use the existing pool's size for initial_count so
772199031f0ec687fa1fefd939206858c440e5a1Pavel Březina we don't grow it unneededly */
772199031f0ec687fa1fefd939206858c440e5a1Pavel Březina size = p_get_max_easy_alloc_size(map->extension_pool);
772199031f0ec687fa1fefd939206858c440e5a1Pavel Březina if (size > EXT_GLOBAL_ALLOC_SIZE + EXT_PER_ALLOC_SIZE) {
772199031f0ec687fa1fefd939206858c440e5a1Pavel Březina initial_count = (size - EXT_GLOBAL_ALLOC_SIZE) /
772199031f0ec687fa1fefd939206858c440e5a1Pavel Březina p_array_init(&map->extensions, map->extension_pool, initial_count);
772199031f0ec687fa1fefd939206858c440e5a1Pavel Březina p_array_init(&map->ext_id_map, map->extension_pool, initial_count);
772199031f0ec687fa1fefd939206858c440e5a1Pavel Březinabool mail_index_map_lookup_ext(struct mail_index_map *map, const char *name,
beeef7f627a5ed9264de25ee4c76eb9620c1c984Pavel Březina unsigned int i, size;
4e5d19f659d8c545c4ed3c307c95cfe4f2ca33cbPavel Březina extensions = array_get(&map->extensions, &size);
4e5d19f659d8c545c4ed3c307c95cfe4f2ca33cbPavel Březina for (i = 0; i < size; i++) {
4e5d19f659d8c545c4ed3c307c95cfe4f2ca33cbPavel Březina size_t size = sizeof(struct mail_index_ext_header) + name_len;
4e5d19f659d8c545c4ed3c307c95cfe4f2ca33cbPavel Březinamail_index_map_register_ext(struct mail_index_map *map, const char *name,
9e9ad4cb181c6c0ec70caacfb31319753f889e98Pavel Březina i_assert(!mail_index_map_lookup_ext(map, name, NULL));
c747b0c875785ce693f70b50bdda0237c4b04e35Pavel Březina ext->name = p_strdup(map->extension_pool, name);
827a016a07d5f911cc4195be89896a376fd71f59Sumit Bose ext->hdr_offset = ext_offset + get_ext_size(strlen(name));
a1e4113a5388e34c08459c5b69679c82ac2bddc9Pavel Březina ext->index_idx = mail_index_ext_register(map->index, name, hdr_size,
a1e4113a5388e34c08459c5b69679c82ac2bddc9Pavel Březina /* Update index ext_id -> map ext_id mapping. Fill non-used
a1e4113a5388e34c08459c5b69679c82ac2bddc9Pavel Březina ext_ids with (uint32_t)-1 */
a1e4113a5388e34c08459c5b69679c82ac2bddc9Pavel Březina while (array_count(&map->ext_id_map) < ext->index_idx)
a1e4113a5388e34c08459c5b69679c82ac2bddc9Pavel Březina array_append(&map->ext_id_map, &empty_idx, 1);
a1e4113a5388e34c08459c5b69679c82ac2bddc9Pavel Březina array_idx_set(&map->ext_id_map, ext->index_idx, &idx);
37d2194cc9ea4d0254c88a3419e2376572562babPavel Březinastatic int mail_index_parse_extensions(struct mail_index_map *map)
a1e4113a5388e34c08459c5b69679c82ac2bddc9Pavel Březina unsigned int i, old_count;
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina uint32_t ext_id, ext_offset, offset, name_offset;
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina /* extension headers always start from 64bit offsets, so if base header
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina doesn't happen to be 64bit aligned we'll skip some bytes */
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina offset = MAIL_INDEX_HEADER_SIZE_ALIGN(map->hdr.base_header_size);
132e477d69e07e02fe6e4d668c0bb6226206474aPavel Březina if (offset >= map->hdr.header_size && map->extension_pool == NULL) {
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina /* nothing to do, skip allocatations and all */
e9a2e7afbd09c23dd8748246e09831ed7b17d7c5Thomas Equeter mail_index_map_init_extbufs(map, old_count + 5);
8fe171bf5a7a570591418e6548105f1d5a0097b3Pavel Březina for (i = 0; i < old_count; i++)
d3c82d0170d6d7407549afdadd08aa7e11aeb9a2Pavel Březina for (i = 0; offset < map->hdr.header_size; i++) {
d3c82d0170d6d7407549afdadd08aa7e11aeb9a2Pavel Březina ext_hdr = CONST_PTR_OFFSET(map->hdr_base, offset);
d3c82d0170d6d7407549afdadd08aa7e11aeb9a2Pavel Březina /* Extension header contains:
d3c82d0170d6d7407549afdadd08aa7e11aeb9a2Pavel Březina - struct mail_index_ext_header
d3c82d0170d6d7407549afdadd08aa7e11aeb9a2Pavel Březina - name (not 0-terminated)
d3c82d0170d6d7407549afdadd08aa7e11aeb9a2Pavel Březina - 64bit alignment padding
d3c82d0170d6d7407549afdadd08aa7e11aeb9a2Pavel Březina - extension header contents
d3c82d0170d6d7407549afdadd08aa7e11aeb9a2Pavel Březina - 64bit alignment padding
d3c82d0170d6d7407549afdadd08aa7e11aeb9a2Pavel Březina size_left < get_ext_size(ext_hdr->name_size) +
d3c82d0170d6d7407549afdadd08aa7e11aeb9a2Pavel Březina mail_index_set_error(index, "Corrupted index file %s: "
d3c82d0170d6d7407549afdadd08aa7e11aeb9a2Pavel Březina "Header extension goes outside header",
b420aae3becdbf501deb2637e2a06636bd6ce1fePavel Březina name = t_strndup(CONST_PTR_OFFSET(map->hdr_base, name_offset),
62ebed8582285bd24efba92b9a06366511507946Pavel Březina if (mail_index_map_lookup_ext(map, name, NULL)) {
c747b0c875785ce693f70b50bdda0237c4b04e35Pavel Březina mail_index_set_error(index, "Corrupted index file %s: "
d3c82d0170d6d7407549afdadd08aa7e11aeb9a2Pavel Březina "Duplicate header extension %s",
d3c82d0170d6d7407549afdadd08aa7e11aeb9a2Pavel Březina if ((ext_hdr->record_size == 0 && ext_hdr->hdr_size == 0) ||
772199031f0ec687fa1fefd939206858c440e5a1Pavel Březina (ext_hdr->record_align == 0 && ext_hdr->record_size != 0) ||
772199031f0ec687fa1fefd939206858c440e5a1Pavel Březina mail_index_set_error(index, "Corrupted index file %s: "
772199031f0ec687fa1fefd939206858c440e5a1Pavel Březina "Broken header extension %s",
t_pop();
t_pop();
t_pop();
#ifndef WORDS_BIGENDIAN
return FALSE;
return FALSE;
return FALSE;
return FALSE;
return FALSE;
return TRUE;
sizeof(struct mail_index_record));
unsigned int records_count;
int ret;
pos = 0;
if (ret > 0)
return ret;
const void *buf;
pos);
if (ret > 0) {
extra = 0;
extra);
if (ret < 0) {
if (ret == 0) {
unsigned int i, count;
int ret;
for (i = 0; i < count; i++)
ret = 0;
if (ret <= 0) {
if (ret == 0) {
return ret;
#ifndef WORDS_BIGENDIAN
unsigned int lock_id;
bool use_mmap;
int ret;
if (ret <= 0) {
if (ret < 0)
if (use_mmap) {
if (ret > 0) {
if (ret >= 0) {
if (ret > 0) {
if (ret == 0)
else if (ret < 0)
ret = 0;
if (ret <= 0) {
return ret;
int ret;
ret = 0;
if (ret == 0) {
return ret;
unsigned int i, count;
for (i = 0; i < count; i++) {
i_unreached();
unsigned int record_size)
static struct mail_index_record_map *
return rec_map;
unsigned int i, count;
for (i = 0; i < count; i++) {
return mem_map;
return FALSE;