mail-index-map.c revision 19779377be72c9fe8365bb9ba7a2e0d06dc99c3b
e59faf65ce864fe95dc00f5d52b8323cdbd0608aTimo Sirainen/* Copyright (C) 2003-2007 Timo Sirainen */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "lib.h"
8aacc9e7c84f8376822823ec98c2f551d4919b2eTimo Sirainen#include "array.h"
16f816d3f3c32ae3351834253f52ddd0212bcbf3Timo Sirainen#include "nfs-workarounds.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "mmap-util.h"
a2f250a332dfc1e6cd4ffd196c621eb9dbf7b8a1Timo Sirainen#include "read-full.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "mail-index-private.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "mail-index-sync-private.h"
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen#include "mail-transaction-log-private.h"
463e82bdf0e990f4f2252d2b53ea23a5abe5883cTimo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstatic void mail_index_map_init_extbufs(struct mail_index_map *map,
d41573018e85896ec836d897fd554e87126147f5Timo Sirainen unsigned int initial_count)
d41573018e85896ec836d897fd554e87126147f5Timo Sirainen{
d41573018e85896ec836d897fd554e87126147f5Timo Sirainen#define EXTENSION_NAME_APPROX_LEN 20
d41573018e85896ec836d897fd554e87126147f5Timo Sirainen#define EXT_GLOBAL_ALLOC_SIZE \
945631faab2bf1aed8d95a1fd0c317a9ce153725Timo Sirainen ((sizeof(map->extensions) + BUFFER_APPROX_SIZE) * 2)
945631faab2bf1aed8d95a1fd0c317a9ce153725Timo Sirainen#define EXT_PER_ALLOC_SIZE \
2c677e9d339bc91d5b54376ba2986f71476c06abTimo Sirainen (EXTENSION_NAME_APPROX_LEN + \
945631faab2bf1aed8d95a1fd0c317a9ce153725Timo Sirainen sizeof(struct mail_index_ext) + sizeof(uint32_t))
945631faab2bf1aed8d95a1fd0c317a9ce153725Timo Sirainen size_t size;
945631faab2bf1aed8d95a1fd0c317a9ce153725Timo Sirainen
945631faab2bf1aed8d95a1fd0c317a9ce153725Timo Sirainen if (map->extension_pool == NULL) {
945631faab2bf1aed8d95a1fd0c317a9ce153725Timo Sirainen size = EXT_GLOBAL_ALLOC_SIZE +
945631faab2bf1aed8d95a1fd0c317a9ce153725Timo Sirainen initial_count * EXT_PER_ALLOC_SIZE;
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen map->extension_pool =
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen pool_alloconly_create("map extensions",
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen nearest_power(size));
20c892309312df8f4f73cfcaf8acd2ededda8b05Timo Sirainen } else {
945631faab2bf1aed8d95a1fd0c317a9ce153725Timo Sirainen p_clear(map->extension_pool);
f81a4d2002da0db33d11ca694d3a91b3ee2a0fdbTimo Sirainen
f81a4d2002da0db33d11ca694d3a91b3ee2a0fdbTimo Sirainen /* try to use the existing pool's size for initial_count so
f81a4d2002da0db33d11ca694d3a91b3ee2a0fdbTimo Sirainen we don't grow it unneededly */
f81a4d2002da0db33d11ca694d3a91b3ee2a0fdbTimo Sirainen size = p_get_max_easy_alloc_size(map->extension_pool);
f81a4d2002da0db33d11ca694d3a91b3ee2a0fdbTimo Sirainen if (size > EXT_GLOBAL_ALLOC_SIZE + EXT_PER_ALLOC_SIZE) {
f81a4d2002da0db33d11ca694d3a91b3ee2a0fdbTimo Sirainen initial_count = (size - EXT_GLOBAL_ALLOC_SIZE) /
f81a4d2002da0db33d11ca694d3a91b3ee2a0fdbTimo Sirainen EXT_PER_ALLOC_SIZE;
f81a4d2002da0db33d11ca694d3a91b3ee2a0fdbTimo Sirainen }
f81a4d2002da0db33d11ca694d3a91b3ee2a0fdbTimo Sirainen }
f81a4d2002da0db33d11ca694d3a91b3ee2a0fdbTimo Sirainen
f81a4d2002da0db33d11ca694d3a91b3ee2a0fdbTimo Sirainen p_array_init(&map->extensions, map->extension_pool, initial_count);
f81a4d2002da0db33d11ca694d3a91b3ee2a0fdbTimo Sirainen p_array_init(&map->ext_id_map, map->extension_pool, initial_count);
f81a4d2002da0db33d11ca694d3a91b3ee2a0fdbTimo Sirainen}
f81a4d2002da0db33d11ca694d3a91b3ee2a0fdbTimo Sirainen
c21c33a8c98972c45349066fc76ac9e2c05013c1Timo Sirainenuint32_t mail_index_map_lookup_ext(struct mail_index_map *map, const char *name)
f81a4d2002da0db33d11ca694d3a91b3ee2a0fdbTimo Sirainen{
f81a4d2002da0db33d11ca694d3a91b3ee2a0fdbTimo Sirainen const struct mail_index_ext *extensions;
7bd3f5614e0dd2324dd1015f084de72c0b069a1aTimo Sirainen unsigned int i, size;
7bd3f5614e0dd2324dd1015f084de72c0b069a1aTimo Sirainen
7bd3f5614e0dd2324dd1015f084de72c0b069a1aTimo Sirainen if (!array_is_created(&map->extensions))
7bd3f5614e0dd2324dd1015f084de72c0b069a1aTimo Sirainen return (uint32_t)-1;
2c677e9d339bc91d5b54376ba2986f71476c06abTimo Sirainen
51795bfe9d05d92fe942cb451aec2b9d16d32a11Timo Sirainen extensions = array_get(&map->extensions, &size);
945631faab2bf1aed8d95a1fd0c317a9ce153725Timo Sirainen for (i = 0; i < size; i++) {
945631faab2bf1aed8d95a1fd0c317a9ce153725Timo Sirainen if (strcmp(extensions[i].name, name) == 0)
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen return i;
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen }
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen return (uint32_t)-1;
e6d7d19c328e7043ad35d5a52c1617bde915a16fTimo Sirainen}
d7095f3a4466fbb78b2d5eb3d322bc15a5b0ab1fTimo Sirainen
153de7823e64c67678b3fc95719c41a8ec5b864dTimo Sirainenuint32_t
153de7823e64c67678b3fc95719c41a8ec5b864dTimo Sirainenmail_index_map_register_ext(struct mail_index_map *map, const char *name,
f81a4d2002da0db33d11ca694d3a91b3ee2a0fdbTimo Sirainen uint32_t hdr_offset, uint32_t hdr_size,
b0be0bead3d6963149f7f2a9504b8ab5aced9af5Timo Sirainen uint32_t record_offset, uint32_t record_size,
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen uint32_t record_align, uint32_t reset_id)
e6d7d19c328e7043ad35d5a52c1617bde915a16fTimo Sirainen{
8d131435ba4648c8821160ec38d508c97177c715Timo Sirainen struct mail_index_ext *ext;
9315dd69233d554452df0c12bc57002d2042a8f4Timo Sirainen uint32_t idx, empty_idx = (uint32_t)-1;
7de1c472fd23ddac6b4dc5cbeee6fa6a8418b071Timo Sirainen
7de1c472fd23ddac6b4dc5cbeee6fa6a8418b071Timo Sirainen if (!array_is_created(&map->extensions)) {
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen mail_index_map_init_extbufs(map, 5);
538c58fc95200fcc5e91abdda8b912b574a2f968Timo Sirainen idx = 0;
a28a6267f48971117dec958b160deefd14ebb7a6Timo Sirainen } else {
a28a6267f48971117dec958b160deefd14ebb7a6Timo Sirainen idx = array_count(&map->extensions);
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen }
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen i_assert(mail_index_map_lookup_ext(map, name) == (uint32_t)-1);
945631faab2bf1aed8d95a1fd0c317a9ce153725Timo Sirainen
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen ext = array_append_space(&map->extensions);
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen ext->name = p_strdup(map->extension_pool, name);
bf91bed88d4e294b4577ba2a3b14d87cf35ae135Timo Sirainen ext->hdr_offset = hdr_offset;
bf91bed88d4e294b4577ba2a3b14d87cf35ae135Timo Sirainen ext->hdr_size = hdr_size;
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen ext->record_offset = record_offset;
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen ext->record_size = record_size;
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen ext->record_align = record_align;
bf91bed88d4e294b4577ba2a3b14d87cf35ae135Timo Sirainen ext->reset_id = reset_id;
bf91bed88d4e294b4577ba2a3b14d87cf35ae135Timo Sirainen
bf91bed88d4e294b4577ba2a3b14d87cf35ae135Timo Sirainen ext->index_idx = mail_index_ext_register(map->index, name, hdr_size,
7de1c472fd23ddac6b4dc5cbeee6fa6a8418b071Timo Sirainen record_size, record_align);
bf91bed88d4e294b4577ba2a3b14d87cf35ae135Timo Sirainen
bf91bed88d4e294b4577ba2a3b14d87cf35ae135Timo Sirainen /* Update index ext_id -> map ext_id mapping. Fill non-used
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen ext_ids with (uint32_t)-1 */
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen while (array_count(&map->ext_id_map) < ext->index_idx)
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen array_append(&map->ext_id_map, &empty_idx, 1);
bf91bed88d4e294b4577ba2a3b14d87cf35ae135Timo Sirainen array_idx_set(&map->ext_id_map, ext->index_idx, &idx);
a28a6267f48971117dec958b160deefd14ebb7a6Timo Sirainen return idx;
7de1c472fd23ddac6b4dc5cbeee6fa6a8418b071Timo Sirainen}
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainenstatic bool size_check(size_t *size_left, size_t size)
bbf796c17f02538058d7559bfe96d677e5b55015Timo Sirainen{
8aacc9e7c84f8376822823ec98c2f551d4919b2eTimo Sirainen if (size > *size_left)
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen return FALSE;
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen *size_left -= size;
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen return TRUE;
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstatic size_t get_align(size_t name_len)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen size_t size = sizeof(struct mail_index_ext_header) + name_len;
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen return MAIL_INDEX_HEADER_SIZE_ALIGN(size) - size;
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen}
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainenstatic int mail_index_parse_extensions(struct mail_index_map *map)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen{
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen struct mail_index *index = map->index;
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen const struct mail_index_ext_header *ext_hdr;
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen unsigned int i, old_count;
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen const char *name;
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen uint32_t ext_id, offset, name_offset;
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen size_t size_left;
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen /* extension headers always start from 64bit offsets, so if base header
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen doesn't happen to be 64bit aligned we'll skip some bytes */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen offset = MAIL_INDEX_HEADER_SIZE_ALIGN(map->hdr.base_header_size);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (offset >= map->hdr.header_size && map->extension_pool == NULL) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen /* nothing to do, skip allocatations and all */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return 1;
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen old_count = array_count(&index->extensions);
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen mail_index_map_init_extbufs(map, old_count + 5);
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen ext_id = (uint32_t)-1;
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen for (i = 0; i < old_count; i++)
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen array_append(&map->ext_id_map, &ext_id, 1);
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen for (i = 0; offset < map->hdr.header_size; i++) {
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen ext_hdr = CONST_PTR_OFFSET(map->hdr_base, offset);
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen /* Extension header contains:
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen - struct mail_index_ext_header
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen - name (not 0-terminated)
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen - 64bit alignment padding
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen - extension header contents
1cad0dd34667548ba39f794ddeb9fc486cf4c666Timo Sirainen - 64bit alignment padding
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen size_left = map->hdr.header_size - offset;
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen if (!size_check(&size_left, sizeof(*ext_hdr)) ||
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen !size_check(&size_left, ext_hdr->name_size) ||
a28a6267f48971117dec958b160deefd14ebb7a6Timo Sirainen !size_check(&size_left, get_align(ext_hdr->name_size)) ||
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen !size_check(&size_left, ext_hdr->hdr_size)) {
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen mail_index_set_error(index, "Corrupted index file %s: "
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen "Header extension goes outside header",
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen index->filepath);
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen return -1;
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen }
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen offset += sizeof(*ext_hdr);
a28a6267f48971117dec958b160deefd14ebb7a6Timo Sirainen name_offset = offset;
a28a6267f48971117dec958b160deefd14ebb7a6Timo Sirainen offset += ext_hdr->name_size + get_align(ext_hdr->name_size);
a28a6267f48971117dec958b160deefd14ebb7a6Timo Sirainen
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen t_push();
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen name = t_strndup(CONST_PTR_OFFSET(map->hdr_base, name_offset),
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen ext_hdr->name_size);
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen if (mail_index_map_lookup_ext(map, name) != (uint32_t)-1) {
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen mail_index_set_error(index, "Corrupted index file %s: "
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen "Duplicate header extension %s",
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen index->filepath, name);
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen t_pop();
a28a6267f48971117dec958b160deefd14ebb7a6Timo Sirainen return -1;
a28a6267f48971117dec958b160deefd14ebb7a6Timo Sirainen }
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen if ((ext_hdr->record_size == 0 && ext_hdr->hdr_size == 0) ||
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen ext_hdr->record_align == 0 || *name == '\0') {
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen mail_index_set_error(index, "Corrupted index file %s: "
a28a6267f48971117dec958b160deefd14ebb7a6Timo Sirainen "Broken header extension %s",
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen index->filepath, *name == '\0' ?
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen t_strdup_printf("#%d", i) : name);
a28a6267f48971117dec958b160deefd14ebb7a6Timo Sirainen t_pop();
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen return -1;
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen }
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen if (map->hdr.record_size <
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen ext_hdr->record_offset + ext_hdr->record_size) {
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen mail_index_set_error(index, "Corrupted index file %s: "
fa5957ffc9b676bfd649fa9953e63e72ee4ebeb4Timo Sirainen "Record field %s points outside record size "
fa5957ffc9b676bfd649fa9953e63e72ee4ebeb4Timo Sirainen "(%u < %u+%u)", index->filepath, name,
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen map->hdr.record_size,
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen ext_hdr->record_offset, ext_hdr->record_size);
3342badd8c69adff34db589fb0a221ace5996212Timo Sirainen t_pop();
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return -1;
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen }
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen if ((ext_hdr->record_offset % ext_hdr->record_align) != 0 ||
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen (map->hdr.record_size % ext_hdr->record_align) != 0) {
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen mail_index_set_error(index, "Corrupted index file %s: "
3342badd8c69adff34db589fb0a221ace5996212Timo Sirainen "Record field %s alignmentation %u not used",
3342badd8c69adff34db589fb0a221ace5996212Timo Sirainen index->filepath, name, ext_hdr->record_align);
3342badd8c69adff34db589fb0a221ace5996212Timo Sirainen t_pop();
3342badd8c69adff34db589fb0a221ace5996212Timo Sirainen return -1;
3342badd8c69adff34db589fb0a221ace5996212Timo Sirainen }
3342badd8c69adff34db589fb0a221ace5996212Timo Sirainen
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen mail_index_map_register_ext(map, name,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen offset, ext_hdr->hdr_size,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen ext_hdr->record_offset,
31050c3df6cbe403e8ced8ef11b5c4e12124d354Timo Sirainen ext_hdr->record_size,
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen ext_hdr->record_align,
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen ext_hdr->reset_id);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen t_pop();
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen offset += MAIL_INDEX_HEADER_SIZE_ALIGN(ext_hdr->hdr_size);
68b3667c9ee95951d7c3e03b19b2d37abbaa5736Timo Sirainen }
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen return 1;
9315dd69233d554452df0c12bc57002d2042a8f4Timo Sirainen}
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen
31050c3df6cbe403e8ced8ef11b5c4e12124d354Timo Sirainenstatic bool mail_index_check_header_compat(struct mail_index *index,
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen const struct mail_index_header *hdr,
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen uoff_t file_size)
7889c9f65e23c83fc31cecf304cab4ab070d6aa1Timo Sirainen{
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen enum mail_index_header_compat_flags compat_flags = 0;
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen
31050c3df6cbe403e8ced8ef11b5c4e12124d354Timo Sirainen#ifndef WORDS_BIGENDIAN
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen compat_flags |= MAIL_INDEX_COMPAT_LITTLE_ENDIAN;
e20e638805c4bd54e039891a3e92760b1dfa189aTimo Sirainen#endif
68b3667c9ee95951d7c3e03b19b2d37abbaa5736Timo Sirainen
68b3667c9ee95951d7c3e03b19b2d37abbaa5736Timo Sirainen if (hdr->major_version != MAIL_INDEX_MAJOR_VERSION) {
31050c3df6cbe403e8ced8ef11b5c4e12124d354Timo Sirainen /* major version change - handle silently(?) */
31050c3df6cbe403e8ced8ef11b5c4e12124d354Timo Sirainen return FALSE;
31050c3df6cbe403e8ced8ef11b5c4e12124d354Timo Sirainen }
31050c3df6cbe403e8ced8ef11b5c4e12124d354Timo Sirainen if ((hdr->flags & MAIL_INDEX_HDR_FLAG_CORRUPTED) != 0) {
68b3667c9ee95951d7c3e03b19b2d37abbaa5736Timo Sirainen /* we've already complained about it */
31050c3df6cbe403e8ced8ef11b5c4e12124d354Timo Sirainen return FALSE;
31050c3df6cbe403e8ced8ef11b5c4e12124d354Timo Sirainen }
fa5957ffc9b676bfd649fa9953e63e72ee4ebeb4Timo Sirainen
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen if (hdr->compat_flags != compat_flags) {
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen /* architecture change */
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen mail_index_set_error(index, "Rebuilding index file %s: "
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen "CPU architecture changed",
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen index->filepath);
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen return FALSE;
8bb360f9e5de1c25e4f875205bb06e8bf15dae14Timo Sirainen }
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen if (hdr->base_header_size < MAIL_INDEX_HEADER_MIN_SIZE ||
31050c3df6cbe403e8ced8ef11b5c4e12124d354Timo Sirainen hdr->header_size < hdr->base_header_size) {
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen mail_index_set_error(index, "Corrupted index file %s: "
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen "Corrupted header sizes (base %u, full %u)",
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen index->filepath, hdr->base_header_size,
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen hdr->header_size);
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen return FALSE;
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen }
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen if (hdr->header_size > file_size) {
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen mail_index_set_error(index, "Corrupted index file %s: "
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen "Corrupted header size (%u > %"PRIuUOFF_T")",
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen index->filepath, hdr->header_size,
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen file_size);
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen return FALSE;
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen }
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen if (hdr->indexid != index->indexid) {
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen if (index->indexid != 0) {
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen mail_index_set_error(index, "Index file %s: "
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen "indexid changed: %u -> %u",
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen index->filepath, index->indexid,
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen hdr->indexid);
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen }
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen index->indexid = hdr->indexid;
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen mail_transaction_log_indexid_changed(index->log);
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
bddd52cb7f3e5a894c080f60750aa76b5aeaf103Timo Sirainen return TRUE;
bddd52cb7f3e5a894c080f60750aa76b5aeaf103Timo Sirainen}
bddd52cb7f3e5a894c080f60750aa76b5aeaf103Timo Sirainen
bddd52cb7f3e5a894c080f60750aa76b5aeaf103Timo Sirainenstatic int mail_index_check_header(struct mail_index_map *map)
bddd52cb7f3e5a894c080f60750aa76b5aeaf103Timo Sirainen{
bddd52cb7f3e5a894c080f60750aa76b5aeaf103Timo Sirainen struct mail_index *index = map->index;
bddd52cb7f3e5a894c080f60750aa76b5aeaf103Timo Sirainen const struct mail_index_header *hdr = &map->hdr;
bddd52cb7f3e5a894c080f60750aa76b5aeaf103Timo Sirainen
bddd52cb7f3e5a894c080f60750aa76b5aeaf103Timo Sirainen if (!mail_index_check_header_compat(index, hdr, (uoff_t)-1))
bddd52cb7f3e5a894c080f60750aa76b5aeaf103Timo Sirainen return -1;
bddd52cb7f3e5a894c080f60750aa76b5aeaf103Timo Sirainen
bddd52cb7f3e5a894c080f60750aa76b5aeaf103Timo Sirainen /* following some extra checks that only take a bit of CPU */
bddd52cb7f3e5a894c080f60750aa76b5aeaf103Timo Sirainen if (hdr->uid_validity == 0 && hdr->next_uid != 1) {
9f19a50d5966643c4d1c5ca06868ac2ad31bc4d5Timo Sirainen mail_index_set_error(index, "Corrupted index file %s: "
9f19a50d5966643c4d1c5ca06868ac2ad31bc4d5Timo Sirainen "uid_validity = 0, next_uid = %u",
9f19a50d5966643c4d1c5ca06868ac2ad31bc4d5Timo Sirainen index->filepath, hdr->next_uid);
9f19a50d5966643c4d1c5ca06868ac2ad31bc4d5Timo Sirainen return -1;
9f19a50d5966643c4d1c5ca06868ac2ad31bc4d5Timo Sirainen }
9f19a50d5966643c4d1c5ca06868ac2ad31bc4d5Timo Sirainen
9f19a50d5966643c4d1c5ca06868ac2ad31bc4d5Timo Sirainen if (hdr->record_size < sizeof(struct mail_index_record)) {
9f19a50d5966643c4d1c5ca06868ac2ad31bc4d5Timo Sirainen mail_index_set_error(index, "Corrupted index file %s: "
9f19a50d5966643c4d1c5ca06868ac2ad31bc4d5Timo Sirainen "record_size too small: %u < %"PRIuSIZE_T,
9f19a50d5966643c4d1c5ca06868ac2ad31bc4d5Timo Sirainen index->filepath, hdr->record_size,
9f19a50d5966643c4d1c5ca06868ac2ad31bc4d5Timo Sirainen sizeof(struct mail_index_record));
9f19a50d5966643c4d1c5ca06868ac2ad31bc4d5Timo Sirainen return -1;
9f19a50d5966643c4d1c5ca06868ac2ad31bc4d5Timo Sirainen }
9f19a50d5966643c4d1c5ca06868ac2ad31bc4d5Timo Sirainen
9f19a50d5966643c4d1c5ca06868ac2ad31bc4d5Timo Sirainen if ((hdr->flags & MAIL_INDEX_HDR_FLAG_FSCK) != 0)
9f19a50d5966643c4d1c5ca06868ac2ad31bc4d5Timo Sirainen return 0;
9f19a50d5966643c4d1c5ca06868ac2ad31bc4d5Timo Sirainen
9f19a50d5966643c4d1c5ca06868ac2ad31bc4d5Timo Sirainen if (hdr->next_uid == 0)
9f19a50d5966643c4d1c5ca06868ac2ad31bc4d5Timo Sirainen return 0;
9f19a50d5966643c4d1c5ca06868ac2ad31bc4d5Timo Sirainen
9f19a50d5966643c4d1c5ca06868ac2ad31bc4d5Timo Sirainen if (hdr->recent_messages_count > hdr->messages_count ||
9f19a50d5966643c4d1c5ca06868ac2ad31bc4d5Timo Sirainen hdr->seen_messages_count > hdr->messages_count ||
bddd52cb7f3e5a894c080f60750aa76b5aeaf103Timo Sirainen hdr->deleted_messages_count > hdr->messages_count)
bddd52cb7f3e5a894c080f60750aa76b5aeaf103Timo Sirainen return 0;
bddd52cb7f3e5a894c080f60750aa76b5aeaf103Timo Sirainen if (hdr->first_recent_uid_lowwater > hdr->next_uid ||
9f19a50d5966643c4d1c5ca06868ac2ad31bc4d5Timo Sirainen hdr->first_unseen_uid_lowwater > hdr->next_uid ||
bddd52cb7f3e5a894c080f60750aa76b5aeaf103Timo Sirainen hdr->first_deleted_uid_lowwater > hdr->next_uid)
bddd52cb7f3e5a894c080f60750aa76b5aeaf103Timo Sirainen return 0;
bddd52cb7f3e5a894c080f60750aa76b5aeaf103Timo Sirainen
bddd52cb7f3e5a894c080f60750aa76b5aeaf103Timo Sirainen if (map->records_count > 0) {
bddd52cb7f3e5a894c080f60750aa76b5aeaf103Timo Sirainen /* last message's UID must be smaller than next_uid.
bddd52cb7f3e5a894c080f60750aa76b5aeaf103Timo Sirainen also make sure it's not zero. */
bddd52cb7f3e5a894c080f60750aa76b5aeaf103Timo Sirainen const struct mail_index_record *rec;
9f19a50d5966643c4d1c5ca06868ac2ad31bc4d5Timo Sirainen
9f19a50d5966643c4d1c5ca06868ac2ad31bc4d5Timo Sirainen rec = MAIL_INDEX_MAP_IDX(map, map->records_count-1);
bddd52cb7f3e5a894c080f60750aa76b5aeaf103Timo Sirainen if (rec->uid == 0 || rec->uid >= hdr->next_uid)
bddd52cb7f3e5a894c080f60750aa76b5aeaf103Timo Sirainen return 0;
bddd52cb7f3e5a894c080f60750aa76b5aeaf103Timo Sirainen }
9f19a50d5966643c4d1c5ca06868ac2ad31bc4d5Timo Sirainen
bddd52cb7f3e5a894c080f60750aa76b5aeaf103Timo Sirainen return 1;
bddd52cb7f3e5a894c080f60750aa76b5aeaf103Timo Sirainen}
bddd52cb7f3e5a894c080f60750aa76b5aeaf103Timo Sirainen
bddd52cb7f3e5a894c080f60750aa76b5aeaf103Timo Sirainenstatic void mail_index_map_clear(struct mail_index_map *map)
bddd52cb7f3e5a894c080f60750aa76b5aeaf103Timo Sirainen{
bddd52cb7f3e5a894c080f60750aa76b5aeaf103Timo Sirainen if (map->buffer != NULL) {
bddd52cb7f3e5a894c080f60750aa76b5aeaf103Timo Sirainen i_assert(map->mmap_base == NULL);
bddd52cb7f3e5a894c080f60750aa76b5aeaf103Timo Sirainen buffer_free(map->buffer);
d1baa8c6f97cdb1b3c2c44a73cc21f9dfc7a963fTimo Sirainen map->buffer = NULL;
d1baa8c6f97cdb1b3c2c44a73cc21f9dfc7a963fTimo Sirainen } else if (map->mmap_base != NULL) {
bddd52cb7f3e5a894c080f60750aa76b5aeaf103Timo Sirainen i_assert(map->buffer == NULL);
bddd52cb7f3e5a894c080f60750aa76b5aeaf103Timo Sirainen if (munmap(map->mmap_base, map->mmap_size) < 0)
bddd52cb7f3e5a894c080f60750aa76b5aeaf103Timo Sirainen mail_index_set_syscall_error(map->index, "munmap()");
bddd52cb7f3e5a894c080f60750aa76b5aeaf103Timo Sirainen map->mmap_base = NULL;
bddd52cb7f3e5a894c080f60750aa76b5aeaf103Timo Sirainen }
bddd52cb7f3e5a894c080f60750aa76b5aeaf103Timo Sirainen
bddd52cb7f3e5a894c080f60750aa76b5aeaf103Timo Sirainen if (map->refcount > 0) {
bddd52cb7f3e5a894c080f60750aa76b5aeaf103Timo Sirainen memset(&map->hdr, 0, sizeof(map->hdr));
ad48319996942463675b53877092ab7e13a7a75aTimo Sirainen map->mmap_size = 0;
ad48319996942463675b53877092ab7e13a7a75aTimo Sirainen map->mmap_used_size = 0;
ad48319996942463675b53877092ab7e13a7a75aTimo Sirainen map->records = NULL;
ad48319996942463675b53877092ab7e13a7a75aTimo Sirainen map->records_count = 0;
ad48319996942463675b53877092ab7e13a7a75aTimo Sirainen }
ad48319996942463675b53877092ab7e13a7a75aTimo Sirainen}
ad48319996942463675b53877092ab7e13a7a75aTimo Sirainen
ad48319996942463675b53877092ab7e13a7a75aTimo Sirainenstatic void mail_index_map_copy_hdr(struct mail_index_map *map,
ad48319996942463675b53877092ab7e13a7a75aTimo Sirainen const struct mail_index_header *hdr)
9f19a50d5966643c4d1c5ca06868ac2ad31bc4d5Timo Sirainen{
ad48319996942463675b53877092ab7e13a7a75aTimo Sirainen if (hdr->base_header_size < sizeof(map->hdr)) {
ad48319996942463675b53877092ab7e13a7a75aTimo Sirainen /* header smaller than ours, make a copy so our newer headers
ad48319996942463675b53877092ab7e13a7a75aTimo Sirainen won't have garbage in them */
4b89231f4ec9cc69f4aea715e1d34f405c7e317dTimo Sirainen memset(&map->hdr, 0, sizeof(map->hdr));
4b89231f4ec9cc69f4aea715e1d34f405c7e317dTimo Sirainen memcpy(&map->hdr, hdr, hdr->base_header_size);
4b89231f4ec9cc69f4aea715e1d34f405c7e317dTimo Sirainen } else {
ad48319996942463675b53877092ab7e13a7a75aTimo Sirainen map->hdr = *hdr;
ad48319996942463675b53877092ab7e13a7a75aTimo Sirainen }
ad48319996942463675b53877092ab7e13a7a75aTimo Sirainen}
ad48319996942463675b53877092ab7e13a7a75aTimo Sirainen
ad48319996942463675b53877092ab7e13a7a75aTimo Sirainenstatic int mail_index_mmap(struct mail_index_map *map, uoff_t file_size)
ad48319996942463675b53877092ab7e13a7a75aTimo Sirainen{
9f19a50d5966643c4d1c5ca06868ac2ad31bc4d5Timo Sirainen struct mail_index *index = map->index;
9f19a50d5966643c4d1c5ca06868ac2ad31bc4d5Timo Sirainen const struct mail_index_header *hdr;
9f19a50d5966643c4d1c5ca06868ac2ad31bc4d5Timo Sirainen unsigned int records_count;
9f19a50d5966643c4d1c5ca06868ac2ad31bc4d5Timo Sirainen
ad48319996942463675b53877092ab7e13a7a75aTimo Sirainen if (map->buffer != NULL) {
ad48319996942463675b53877092ab7e13a7a75aTimo Sirainen /* we had temporarily used a buffer, eg. for updating index */
ad48319996942463675b53877092ab7e13a7a75aTimo Sirainen buffer_free(map->buffer);
ad48319996942463675b53877092ab7e13a7a75aTimo Sirainen map->buffer = NULL;
9f19a50d5966643c4d1c5ca06868ac2ad31bc4d5Timo Sirainen }
9f19a50d5966643c4d1c5ca06868ac2ad31bc4d5Timo Sirainen
ad48319996942463675b53877092ab7e13a7a75aTimo Sirainen if (file_size > SSIZE_T_MAX) {
ad48319996942463675b53877092ab7e13a7a75aTimo Sirainen /* too large file to map into memory */
ad48319996942463675b53877092ab7e13a7a75aTimo Sirainen mail_index_set_error(index, "Index file too large: %s",
ad48319996942463675b53877092ab7e13a7a75aTimo Sirainen index->filepath);
ad48319996942463675b53877092ab7e13a7a75aTimo Sirainen return -1;
ad48319996942463675b53877092ab7e13a7a75aTimo Sirainen }
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen map->mmap_base =
abfcd9f73b9ad1eeef4fe6e9940383defabf68c3Timo Sirainen mmap(NULL, file_size, PROT_READ, MAP_SHARED, index->fd, 0);
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen if (map->mmap_base == MAP_FAILED) {
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen map->mmap_base = NULL;
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen mail_index_set_syscall_error(index, "mmap()");
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen return -1;
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen }
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen map->mmap_size = file_size;
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen
abfcd9f73b9ad1eeef4fe6e9940383defabf68c3Timo Sirainen hdr = map->mmap_base;
abfcd9f73b9ad1eeef4fe6e9940383defabf68c3Timo Sirainen if (map->mmap_size >
cd5ee8630497fdbd853ef588a858b4ef619a5e03Timo Sirainen offsetof(struct mail_index_header, major_version) &&
cd5ee8630497fdbd853ef588a858b4ef619a5e03Timo Sirainen hdr->major_version != MAIL_INDEX_MAJOR_VERSION) {
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen /* major version change - handle silently */
7394389230750c45b105cdefb5850c81cae8cdc0Timo Sirainen return 0;
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen }
1032e5427bf10566098f3b3bb9110e2bc1227e85Timo Sirainen
3342badd8c69adff34db589fb0a221ace5996212Timo Sirainen if (map->mmap_size < MAIL_INDEX_HEADER_MIN_SIZE) {
7e94cf9d70ce9fdeccb7a85ff400b899e6386f36Timo Sirainen mail_index_set_error(index, "Corrupted index file %s: "
7e94cf9d70ce9fdeccb7a85ff400b899e6386f36Timo Sirainen "File too small (%"PRIuSIZE_T")",
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen index->filepath, map->mmap_size);
9887c39c5ba429169389153ca99de49e084a73f0Timo Sirainen return 0;
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen }
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen if (!mail_index_check_header_compat(index, hdr, map->mmap_size)) {
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen /* Can't use this file */
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen return 0;
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen }
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen map->mmap_used_size = hdr->header_size +
bf91bed88d4e294b4577ba2a3b14d87cf35ae135Timo Sirainen hdr->messages_count * hdr->record_size;
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen if (map->mmap_used_size > map->mmap_size) {
a28a6267f48971117dec958b160deefd14ebb7a6Timo Sirainen records_count = (map->mmap_size - hdr->header_size) /
a28a6267f48971117dec958b160deefd14ebb7a6Timo Sirainen hdr->record_size;
3342badd8c69adff34db589fb0a221ace5996212Timo Sirainen mail_index_set_error(index, "Corrupted index file %s: "
3342badd8c69adff34db589fb0a221ace5996212Timo Sirainen "messages_count too large (%u > %u)",
3342badd8c69adff34db589fb0a221ace5996212Timo Sirainen index->filepath, hdr->messages_count,
1032e5427bf10566098f3b3bb9110e2bc1227e85Timo Sirainen records_count);
1032e5427bf10566098f3b3bb9110e2bc1227e85Timo Sirainen return 0;
1032e5427bf10566098f3b3bb9110e2bc1227e85Timo Sirainen }
a28a6267f48971117dec958b160deefd14ebb7a6Timo Sirainen
a28a6267f48971117dec958b160deefd14ebb7a6Timo Sirainen mail_index_map_copy_hdr(map, hdr);
a28a6267f48971117dec958b160deefd14ebb7a6Timo Sirainen
bddd52cb7f3e5a894c080f60750aa76b5aeaf103Timo Sirainen map->hdr_base = map->mmap_base;
a28a6267f48971117dec958b160deefd14ebb7a6Timo Sirainen map->records = PTR_OFFSET(map->mmap_base, map->hdr.header_size);
a28a6267f48971117dec958b160deefd14ebb7a6Timo Sirainen map->records_count = map->hdr.messages_count;
a28a6267f48971117dec958b160deefd14ebb7a6Timo Sirainen return 1;
a28a6267f48971117dec958b160deefd14ebb7a6Timo Sirainen}
a28a6267f48971117dec958b160deefd14ebb7a6Timo Sirainen
3342badd8c69adff34db589fb0a221ace5996212Timo Sirainenstatic int mail_index_read_header(struct mail_index *index,
a28a6267f48971117dec958b160deefd14ebb7a6Timo Sirainen void *buf, size_t buf_size, size_t *pos_r)
2ebfb5c0608e2323b73271208f4036a7ea7d7f3aTimo Sirainen{
2ebfb5c0608e2323b73271208f4036a7ea7d7f3aTimo Sirainen size_t pos;
2ebfb5c0608e2323b73271208f4036a7ea7d7f3aTimo Sirainen int ret;
a2f250a332dfc1e6cd4ffd196c621eb9dbf7b8a1Timo Sirainen
a2f250a332dfc1e6cd4ffd196c621eb9dbf7b8a1Timo Sirainen memset(buf, 0, sizeof(struct mail_index_header));
a28a6267f48971117dec958b160deefd14ebb7a6Timo Sirainen
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen /* try to read the whole header, but it's not necessarily an error to
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen read less since the older versions of the index format could be
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen smaller. Request reading up to buf_size, but accept if we only got
41bb0aa8e357876bc9a1916a37c9e3e78e5f8185Timo Sirainen the header. */
3342badd8c69adff34db589fb0a221ace5996212Timo Sirainen pos = 0;
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen do {
dd8de60250511cc729b67249e61dfc6b4debff11Timo Sirainen ret = pread(index->fd, PTR_OFFSET(buf, pos),
3342badd8c69adff34db589fb0a221ace5996212Timo Sirainen buf_size - pos, pos);
a28a6267f48971117dec958b160deefd14ebb7a6Timo Sirainen if (ret > 0)
3342badd8c69adff34db589fb0a221ace5996212Timo Sirainen pos += ret;
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen } while (ret > 0 && pos < sizeof(struct mail_index_header));
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen *pos_r = pos;
20b9283d4af31e45e588014da427fb2dbcd3227aTimo Sirainen return ret;
20b9283d4af31e45e588014da427fb2dbcd3227aTimo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
7394389230750c45b105cdefb5850c81cae8cdc0Timo Sirainenstatic int
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainenmail_index_try_read_map(struct mail_index_map *map,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen uoff_t file_size, bool *retry_r, bool try_retry)
20b9283d4af31e45e588014da427fb2dbcd3227aTimo Sirainen{
20b9283d4af31e45e588014da427fb2dbcd3227aTimo Sirainen struct mail_index *index = map->index;
20b9283d4af31e45e588014da427fb2dbcd3227aTimo Sirainen const struct mail_index_header *hdr;
20b9283d4af31e45e588014da427fb2dbcd3227aTimo Sirainen unsigned char read_buf[4096];
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen const void *buf;
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen void *data = NULL;
95a1a5195d56f3cf5d1e529aad668f87ad3b979bTimo Sirainen ssize_t ret;
95a1a5195d56f3cf5d1e529aad668f87ad3b979bTimo Sirainen size_t pos, records_size, initial_buf_pos = 0;
95a1a5195d56f3cf5d1e529aad668f87ad3b979bTimo Sirainen unsigned int records_count, extra;
95a1a5195d56f3cf5d1e529aad668f87ad3b979bTimo Sirainen
95a1a5195d56f3cf5d1e529aad668f87ad3b979bTimo Sirainen i_assert(map->mmap_base == NULL);
41bb0aa8e357876bc9a1916a37c9e3e78e5f8185Timo Sirainen
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen *retry_r = FALSE;
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen ret = mail_index_read_header(index, read_buf, sizeof(read_buf), &pos);
b35f7104715edee0cfac6d46ab0b342033867eb7Timo Sirainen buf = read_buf; hdr = buf;
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (pos > (ssize_t)offsetof(struct mail_index_header, major_version) &&
51920d00fa50edf7b2e9b1019288d64b7abee7f3Timo Sirainen hdr->major_version != MAIL_INDEX_MAJOR_VERSION) {
1d3f7c1278168d5b1cbfa9a2cc9929a0909056b4Timo Sirainen /* major version change - handle silently */
51920d00fa50edf7b2e9b1019288d64b7abee7f3Timo Sirainen return 0;
21ec6628c567eeff025af35d8027be01044b0b1aTimo Sirainen }
21ec6628c567eeff025af35d8027be01044b0b1aTimo Sirainen
21ec6628c567eeff025af35d8027be01044b0b1aTimo Sirainen if (ret >= 0 && pos >= MAIL_INDEX_HEADER_MIN_SIZE &&
21ec6628c567eeff025af35d8027be01044b0b1aTimo Sirainen (ret > 0 || pos >= hdr->base_header_size)) {
fa5957ffc9b676bfd649fa9953e63e72ee4ebeb4Timo Sirainen if (!mail_index_check_header_compat(index, hdr, file_size)) {
fa5957ffc9b676bfd649fa9953e63e72ee4ebeb4Timo Sirainen /* Can't use this file */
fa5957ffc9b676bfd649fa9953e63e72ee4ebeb4Timo Sirainen return 0;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen }
fa5957ffc9b676bfd649fa9953e63e72ee4ebeb4Timo Sirainen
fa5957ffc9b676bfd649fa9953e63e72ee4ebeb4Timo Sirainen initial_buf_pos = pos;
fa5957ffc9b676bfd649fa9953e63e72ee4ebeb4Timo Sirainen if (pos > hdr->header_size)
3342badd8c69adff34db589fb0a221ace5996212Timo Sirainen pos = hdr->header_size;
3342badd8c69adff34db589fb0a221ace5996212Timo Sirainen
a28a6267f48971117dec958b160deefd14ebb7a6Timo Sirainen /* place the base header into memory. */
a28a6267f48971117dec958b160deefd14ebb7a6Timo Sirainen buffer_reset(map->hdr_copy_buf);
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen buffer_append(map->hdr_copy_buf, buf, pos);
fa5957ffc9b676bfd649fa9953e63e72ee4ebeb4Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (pos != hdr->header_size) {
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen /* @UNSAFE: read the rest of the header into memory */
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen data = buffer_append_space_unsafe(map->hdr_copy_buf,
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen hdr->header_size -
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen pos);
cd5ee8630497fdbd853ef588a858b4ef619a5e03Timo Sirainen ret = pread_full(index->fd, data,
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen hdr->header_size - pos, pos);
fd2118e34f4d1d65cffdccc40d74dda931fae81eTimo Sirainen }
fd2118e34f4d1d65cffdccc40d74dda931fae81eTimo Sirainen }
fd2118e34f4d1d65cffdccc40d74dda931fae81eTimo Sirainen
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen if (ret > 0) {
5a7b52012bf77132bb8f466d07e0e88c63fdba42Timo Sirainen /* header read, read the records now. */
d647e72663b52cb2301df5eaf93e67ee873a41f8Timo Sirainen records_size = (size_t)hdr->messages_count * hdr->record_size;
d647e72663b52cb2301df5eaf93e67ee873a41f8Timo Sirainen
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen if (file_size - hdr->header_size < records_size ||
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen (hdr->record_size != 0 &&
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen records_size / hdr->record_size != hdr->messages_count)) {
9887c39c5ba429169389153ca99de49e084a73f0Timo Sirainen records_count = (file_size - hdr->header_size) /
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen hdr->record_size;
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen mail_index_set_error(index, "Corrupted index file %s: "
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen "messages_count too large (%u > %u)",
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen index->filepath, hdr->messages_count,
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen records_count);
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen return 0;
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen }
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen if (map->buffer == NULL) {
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen map->buffer = buffer_create_dynamic(default_pool,
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen records_size);
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen }
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen /* @UNSAFE */
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen buffer_set_used_size(map->buffer, 0);
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen if (initial_buf_pos <= hdr->header_size)
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen extra = 0;
5a7b52012bf77132bb8f466d07e0e88c63fdba42Timo Sirainen else {
d647e72663b52cb2301df5eaf93e67ee873a41f8Timo Sirainen extra = initial_buf_pos - hdr->header_size;
d647e72663b52cb2301df5eaf93e67ee873a41f8Timo Sirainen buffer_append(map->buffer,
d647e72663b52cb2301df5eaf93e67ee873a41f8Timo Sirainen CONST_PTR_OFFSET(buf, hdr->header_size),
d647e72663b52cb2301df5eaf93e67ee873a41f8Timo Sirainen extra);
d647e72663b52cb2301df5eaf93e67ee873a41f8Timo Sirainen }
d647e72663b52cb2301df5eaf93e67ee873a41f8Timo Sirainen if (records_size > extra) {
d647e72663b52cb2301df5eaf93e67ee873a41f8Timo Sirainen data = buffer_append_space_unsafe(map->buffer,
d647e72663b52cb2301df5eaf93e67ee873a41f8Timo Sirainen records_size - extra);
d647e72663b52cb2301df5eaf93e67ee873a41f8Timo Sirainen ret = pread_full(index->fd, data, records_size - extra,
d647e72663b52cb2301df5eaf93e67ee873a41f8Timo Sirainen hdr->header_size + extra);
d647e72663b52cb2301df5eaf93e67ee873a41f8Timo Sirainen }
d647e72663b52cb2301df5eaf93e67ee873a41f8Timo Sirainen }
d647e72663b52cb2301df5eaf93e67ee873a41f8Timo Sirainen
d647e72663b52cb2301df5eaf93e67ee873a41f8Timo Sirainen if (ret < 0) {
d647e72663b52cb2301df5eaf93e67ee873a41f8Timo Sirainen if (errno == ESTALE && try_retry) {
d647e72663b52cb2301df5eaf93e67ee873a41f8Timo Sirainen /* a new index file was renamed over this one. */
d647e72663b52cb2301df5eaf93e67ee873a41f8Timo Sirainen *retry_r = TRUE;
5a7b52012bf77132bb8f466d07e0e88c63fdba42Timo Sirainen return 0;
5a7b52012bf77132bb8f466d07e0e88c63fdba42Timo Sirainen }
5a7b52012bf77132bb8f466d07e0e88c63fdba42Timo Sirainen mail_index_set_syscall_error(index, "pread_full()");
5a7b52012bf77132bb8f466d07e0e88c63fdba42Timo Sirainen return -1;
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen }
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen if (ret == 0) {
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainen mail_index_set_error(index,
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen "Corrupted index file %s: File too small",
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen index->filepath);
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen return 0;
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen }
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen map->records = buffer_get_modifiable_data(map->buffer, NULL);
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen map->records_count = hdr->messages_count;
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen mail_index_map_copy_hdr(map, hdr);
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen map->hdr_base = map->hdr_copy_buf->data;
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen return 1;
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen}
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen
d143077bd518de129b8d446fb58e003903e50867Timo Sirainenstatic int mail_index_read_map(struct mail_index_map *map, uoff_t file_size)
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen{
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen struct mail_index *index = map->index;
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen mail_index_sync_lost_handler_t *const *handlers;
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen struct stat st;
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen unsigned int i, count;
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen int ret;
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen bool try_retry, retry;
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen
e063aca6bc2f08bec516d4b631052ea9191f011dTimo Sirainen /* notify all "sync lost" handlers */
e063aca6bc2f08bec516d4b631052ea9191f011dTimo Sirainen handlers = array_get(&index->sync_lost_handlers, &count);
e063aca6bc2f08bec516d4b631052ea9191f011dTimo Sirainen for (i = 0; i < count; i++)
e063aca6bc2f08bec516d4b631052ea9191f011dTimo Sirainen (*handlers[i])(index);
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen for (i = 0;; i++) {
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen try_retry = i < MAIL_INDEX_ESTALE_RETRY_COUNT;
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen if (file_size == (uoff_t)-1) {
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen /* fstat() below failed */
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen ret = 0;
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen retry = try_retry;
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen } else {
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen ret = mail_index_try_read_map(map, file_size,
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen &retry, try_retry);
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen }
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen if (ret != 0 || !retry)
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen break;
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen /* ESTALE - reopen index file */
0c909e3461607eadcd66f4eac69b7f34e37fccf1Timo Sirainen if (close(index->fd) < 0)
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen mail_index_set_syscall_error(index, "close()");
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen index->fd = -1;
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen ret = mail_index_try_open_only(index);
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen if (ret <= 0) {
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen if (ret == 0) {
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen /* the file was lost */
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen errno = ENOENT;
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen mail_index_set_syscall_error(index, "open()");
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen }
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen return -1;
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen }
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen if (fstat(index->fd, &st) == 0)
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen file_size = st.st_size;
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen else {
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen if (errno != ESTALE) {
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen mail_index_set_syscall_error(index, "fstat()");
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen return -1;
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen }
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen file_size = (uoff_t)-1;
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen }
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen }
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen return ret;
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen}
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen
d143077bd518de129b8d446fb58e003903e50867Timo Sirainenstatic void mail_index_header_init(struct mail_index *index,
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen struct mail_index_header *hdr)
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen{
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen i_assert((sizeof(*hdr) % sizeof(uint64_t)) == 0);
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen memset(hdr, 0, sizeof(*hdr));
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen
2c677e9d339bc91d5b54376ba2986f71476c06abTimo Sirainen hdr->major_version = MAIL_INDEX_MAJOR_VERSION;
2c677e9d339bc91d5b54376ba2986f71476c06abTimo Sirainen hdr->minor_version = MAIL_INDEX_MINOR_VERSION;
2c677e9d339bc91d5b54376ba2986f71476c06abTimo Sirainen hdr->base_header_size = sizeof(*hdr);
2c677e9d339bc91d5b54376ba2986f71476c06abTimo Sirainen hdr->header_size = sizeof(*hdr);
2c677e9d339bc91d5b54376ba2986f71476c06abTimo Sirainen hdr->record_size = sizeof(struct mail_index_record);
2c677e9d339bc91d5b54376ba2986f71476c06abTimo Sirainen
2c677e9d339bc91d5b54376ba2986f71476c06abTimo Sirainen#ifndef WORDS_BIGENDIAN
f81a4d2002da0db33d11ca694d3a91b3ee2a0fdbTimo Sirainen hdr->compat_flags |= MAIL_INDEX_COMPAT_LITTLE_ENDIAN;
f81a4d2002da0db33d11ca694d3a91b3ee2a0fdbTimo Sirainen#endif
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen hdr->indexid = index->indexid;
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen hdr->log_file_seq = 1;
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen hdr->next_uid = 1;
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen}
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen
d143077bd518de129b8d446fb58e003903e50867Timo Sirainenstruct mail_index_map *mail_index_map_alloc(struct mail_index *index)
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen{
c91de2744f8c1e61e91082ff5e214450f28a0e7cTimo Sirainen struct mail_index_map tmp_map;
c91de2744f8c1e61e91082ff5e214450f28a0e7cTimo Sirainen
a5b331e18b220fac557480b569b85215a1b3bd8eTimo Sirainen memset(&tmp_map, 0, sizeof(tmp_map));
c91de2744f8c1e61e91082ff5e214450f28a0e7cTimo Sirainen mail_index_header_init(index, &tmp_map.hdr);
c91de2744f8c1e61e91082ff5e214450f28a0e7cTimo Sirainen tmp_map.index = index;
c91de2744f8c1e61e91082ff5e214450f28a0e7cTimo Sirainen tmp_map.hdr_base = &tmp_map.hdr;
c91de2744f8c1e61e91082ff5e214450f28a0e7cTimo Sirainen
a0d34d3982507f513a9d800082481e9faeb9a943Timo Sirainen /* a bit kludgy way to do this, but it initializes everything
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen nicely and correctly */
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen return mail_index_map_clone(&tmp_map);
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen}
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen
d143077bd518de129b8d446fb58e003903e50867Timo Sirainenstatic int mail_index_map_latest_file(struct mail_index *index,
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen struct mail_index_map **map)
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen{
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen struct mail_index_map *new_map;
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen struct stat st;
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen unsigned int lock_id;
6e07b4251bf6a3cf34019c351a32a65c08392e58Timo Sirainen uoff_t file_size;
a5b331e18b220fac557480b569b85215a1b3bd8eTimo Sirainen bool use_mmap;
6e07b4251bf6a3cf34019c351a32a65c08392e58Timo Sirainen int ret;
6e07b4251bf6a3cf34019c351a32a65c08392e58Timo Sirainen
a5b331e18b220fac557480b569b85215a1b3bd8eTimo Sirainen ret = mail_index_reopen_if_changed(index);
a5b331e18b220fac557480b569b85215a1b3bd8eTimo Sirainen if (ret <= 0) {
a5b331e18b220fac557480b569b85215a1b3bd8eTimo Sirainen if (ret < 0)
a5b331e18b220fac557480b569b85215a1b3bd8eTimo Sirainen return -1;
a5b331e18b220fac557480b569b85215a1b3bd8eTimo Sirainen
ec922832ddc917e48d98fdb409051b9c162b90a3Timo Sirainen /* the index file is lost/broken. let's hope that we can
6e07b4251bf6a3cf34019c351a32a65c08392e58Timo Sirainen build it from the transaction log. */
6e07b4251bf6a3cf34019c351a32a65c08392e58Timo Sirainen return 0;
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen }
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen /* the index file is still open, lock it */
8bb360f9e5de1c25e4f875205bb06e8bf15dae14Timo Sirainen if (mail_index_lock_shared(index, &lock_id) < 0)
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen return -1;
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen if (fstat(index->fd, &st) == 0)
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen file_size = st.st_size;
a5b331e18b220fac557480b569b85215a1b3bd8eTimo Sirainen else {
a5b331e18b220fac557480b569b85215a1b3bd8eTimo Sirainen if (errno != ESTALE) {
a5b331e18b220fac557480b569b85215a1b3bd8eTimo Sirainen mail_index_set_syscall_error(index, "fstat()");
a5b331e18b220fac557480b569b85215a1b3bd8eTimo Sirainen mail_index_unlock(index, &lock_id);
a5b331e18b220fac557480b569b85215a1b3bd8eTimo Sirainen return -1;
a5b331e18b220fac557480b569b85215a1b3bd8eTimo Sirainen }
a5b331e18b220fac557480b569b85215a1b3bd8eTimo Sirainen file_size = (uoff_t)-1;
a5b331e18b220fac557480b569b85215a1b3bd8eTimo Sirainen }
a5b331e18b220fac557480b569b85215a1b3bd8eTimo Sirainen
e76f5e07be5bec4e5ca99c3e093ff7f11edbe1b7Timo Sirainen /* mmaping seems to be slower than just reading the file, so even if
e76f5e07be5bec4e5ca99c3e093ff7f11edbe1b7Timo Sirainen mmap isn't disabled don't use it unless the file is large enough */
e76f5e07be5bec4e5ca99c3e093ff7f11edbe1b7Timo Sirainen use_mmap = !index->mmap_disable && file_size != (uoff_t)-1 &&
e76f5e07be5bec4e5ca99c3e093ff7f11edbe1b7Timo Sirainen file_size > MAIL_INDEX_MMAP_MIN_SIZE;
e76f5e07be5bec4e5ca99c3e093ff7f11edbe1b7Timo Sirainen
e76f5e07be5bec4e5ca99c3e093ff7f11edbe1b7Timo Sirainen new_map = mail_index_map_alloc(index);
e76f5e07be5bec4e5ca99c3e093ff7f11edbe1b7Timo Sirainen if (use_mmap) {
e76f5e07be5bec4e5ca99c3e093ff7f11edbe1b7Timo Sirainen new_map->lock_id = lock_id;
e76f5e07be5bec4e5ca99c3e093ff7f11edbe1b7Timo Sirainen ret = mail_index_mmap(new_map, file_size);
e76f5e07be5bec4e5ca99c3e093ff7f11edbe1b7Timo Sirainen } else {
e76f5e07be5bec4e5ca99c3e093ff7f11edbe1b7Timo Sirainen ret = mail_index_read_map(new_map, file_size);
e76f5e07be5bec4e5ca99c3e093ff7f11edbe1b7Timo Sirainen mail_index_unlock(index, &lock_id);
8bb360f9e5de1c25e4f875205bb06e8bf15dae14Timo Sirainen }
e76f5e07be5bec4e5ca99c3e093ff7f11edbe1b7Timo Sirainen if (ret > 0) {
e76f5e07be5bec4e5ca99c3e093ff7f11edbe1b7Timo Sirainen /* make sure the header is ok before using this mapping */
e76f5e07be5bec4e5ca99c3e093ff7f11edbe1b7Timo Sirainen ret = mail_index_check_header(new_map);
e76f5e07be5bec4e5ca99c3e093ff7f11edbe1b7Timo Sirainen if (ret >= 0)
e76f5e07be5bec4e5ca99c3e093ff7f11edbe1b7Timo Sirainen ret = mail_index_parse_extensions(new_map);
e76f5e07be5bec4e5ca99c3e093ff7f11edbe1b7Timo Sirainen if (ret++ == 0)
e76f5e07be5bec4e5ca99c3e093ff7f11edbe1b7Timo Sirainen index->fsck = TRUE;
e76f5e07be5bec4e5ca99c3e093ff7f11edbe1b7Timo Sirainen }
e76f5e07be5bec4e5ca99c3e093ff7f11edbe1b7Timo Sirainen if (ret <= 0) {
e76f5e07be5bec4e5ca99c3e093ff7f11edbe1b7Timo Sirainen mail_index_unmap(&new_map);
e76f5e07be5bec4e5ca99c3e093ff7f11edbe1b7Timo Sirainen return ret;
e76f5e07be5bec4e5ca99c3e093ff7f11edbe1b7Timo Sirainen }
e76f5e07be5bec4e5ca99c3e093ff7f11edbe1b7Timo Sirainen
e76f5e07be5bec4e5ca99c3e093ff7f11edbe1b7Timo Sirainen index->last_read_log_file_seq = new_map->hdr.log_file_seq;
e76f5e07be5bec4e5ca99c3e093ff7f11edbe1b7Timo Sirainen index->last_read_log_file_head_offset =
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen new_map->hdr.log_file_head_offset;
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen index->last_read_log_file_tail_offset =
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen new_map->hdr.log_file_tail_offset;
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen index->last_read_stat = st;
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen mail_index_unmap(map);
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen *map = new_map;
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen return 1;
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen}
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen
a5b331e18b220fac557480b569b85215a1b3bd8eTimo Sirainenint mail_index_map(struct mail_index *index,
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen enum mail_index_sync_handler_type type)
a5b331e18b220fac557480b569b85215a1b3bd8eTimo Sirainen{
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen int ret;
7ded22760598b78ee29f9418eacc0abe3fb51055Timo Sirainen
2d79e603e20a32bdae4c2b516ead5c5c9169545aTimo Sirainen i_assert(index->lock_type != F_WRLCK);
86d52f310fe939090c66b780a3b6ffe5d10dc8faTimo Sirainen i_assert(!index->mapping);
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen index->mapping = TRUE;
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen if (index->map == NULL)
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen index->map = mail_index_map_alloc(index);
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen /* first try updating the existing mapping from transaction log. */
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen if (index->map->hdr.indexid != 0) {
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen /* we're not creating the index, or opening transaction log.
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen sync this as a view from transaction log. */
7ded22760598b78ee29f9418eacc0abe3fb51055Timo Sirainen ret = mail_index_sync_map(&index->map, type, FALSE);
7ded22760598b78ee29f9418eacc0abe3fb51055Timo Sirainen } else {
2d79e603e20a32bdae4c2b516ead5c5c9169545aTimo Sirainen ret = 0;
2d79e603e20a32bdae4c2b516ead5c5c9169545aTimo Sirainen }
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen
a5b331e18b220fac557480b569b85215a1b3bd8eTimo Sirainen if (ret == 0) {
a5b331e18b220fac557480b569b85215a1b3bd8eTimo Sirainen /* try to open and read the latest index. if it fails for
a5b331e18b220fac557480b569b85215a1b3bd8eTimo Sirainen any reason, we'll fallback to updating the existing mapping
a5b331e18b220fac557480b569b85215a1b3bd8eTimo Sirainen from transaction logs (which we'll also do even if the
a5b331e18b220fac557480b569b85215a1b3bd8eTimo Sirainen reopening succeeds) */
a5b331e18b220fac557480b569b85215a1b3bd8eTimo Sirainen (void)mail_index_map_latest_file(index, &index->map);
a5b331e18b220fac557480b569b85215a1b3bd8eTimo Sirainen
a5b331e18b220fac557480b569b85215a1b3bd8eTimo Sirainen /* if we're creating the index file, we don't have any
a5b331e18b220fac557480b569b85215a1b3bd8eTimo Sirainen logs yet */
a5b331e18b220fac557480b569b85215a1b3bd8eTimo Sirainen if (index->log->head != NULL) {
a0d34d3982507f513a9d800082481e9faeb9a943Timo Sirainen /* and update the map with the latest changes from
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen transaction log */
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen ret = mail_index_sync_map(&index->map, type, TRUE);
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen }
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen }
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen
c5794838af9995f50bfecb06a3cd4f9a0ac77858Timo Sirainen index->mapping = FALSE;
c5794838af9995f50bfecb06a3cd4f9a0ac77858Timo Sirainen return ret;
c5794838af9995f50bfecb06a3cd4f9a0ac77858Timo Sirainen}
c5794838af9995f50bfecb06a3cd4f9a0ac77858Timo Sirainen
c5794838af9995f50bfecb06a3cd4f9a0ac77858Timo Sirainenvoid mail_index_unmap(struct mail_index_map **_map)
c5794838af9995f50bfecb06a3cd4f9a0ac77858Timo Sirainen{
c5794838af9995f50bfecb06a3cd4f9a0ac77858Timo Sirainen struct mail_index_map *map = *_map;
c5794838af9995f50bfecb06a3cd4f9a0ac77858Timo Sirainen
c5794838af9995f50bfecb06a3cd4f9a0ac77858Timo Sirainen *_map = NULL;
c5794838af9995f50bfecb06a3cd4f9a0ac77858Timo Sirainen if (--map->refcount > 0)
c5794838af9995f50bfecb06a3cd4f9a0ac77858Timo Sirainen return;
c5794838af9995f50bfecb06a3cd4f9a0ac77858Timo Sirainen
c5794838af9995f50bfecb06a3cd4f9a0ac77858Timo Sirainen i_assert(map->refcount == 0);
c5794838af9995f50bfecb06a3cd4f9a0ac77858Timo Sirainen mail_index_map_clear(map);
c5794838af9995f50bfecb06a3cd4f9a0ac77858Timo Sirainen mail_index_map_unlock(map);
c5794838af9995f50bfecb06a3cd4f9a0ac77858Timo Sirainen
c5794838af9995f50bfecb06a3cd4f9a0ac77858Timo Sirainen if (map->extension_pool != NULL)
c5794838af9995f50bfecb06a3cd4f9a0ac77858Timo Sirainen pool_unref(map->extension_pool);
c5794838af9995f50bfecb06a3cd4f9a0ac77858Timo Sirainen if (array_is_created(&map->keyword_idx_map))
c5794838af9995f50bfecb06a3cd4f9a0ac77858Timo Sirainen array_free(&map->keyword_idx_map);
c5794838af9995f50bfecb06a3cd4f9a0ac77858Timo Sirainen buffer_free(map->hdr_copy_buf);
c5794838af9995f50bfecb06a3cd4f9a0ac77858Timo Sirainen i_free(map);
c5794838af9995f50bfecb06a3cd4f9a0ac77858Timo Sirainen}
c5794838af9995f50bfecb06a3cd4f9a0ac77858Timo Sirainen
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainenint mail_index_map_lock(struct mail_index_map *map)
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen{
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen if (map->lock_id != 0 || MAIL_INDEX_MAP_IS_IN_MEMORY(map))
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen return 0;
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen return mail_index_lock_shared(map->index, &map->lock_id);
faed8babca9914257f34fb2e603d74016d563b2dTimo Sirainen}
faed8babca9914257f34fb2e603d74016d563b2dTimo Sirainen
faed8babca9914257f34fb2e603d74016d563b2dTimo Sirainenvoid mail_index_map_unlock(struct mail_index_map *map)
faed8babca9914257f34fb2e603d74016d563b2dTimo Sirainen{
faed8babca9914257f34fb2e603d74016d563b2dTimo Sirainen mail_index_unlock(map->index, &map->lock_id);
faed8babca9914257f34fb2e603d74016d563b2dTimo Sirainen}
bddd52cb7f3e5a894c080f60750aa76b5aeaf103Timo Sirainen
8bb360f9e5de1c25e4f875205bb06e8bf15dae14Timo Sirainenstatic void mail_index_map_copy(struct mail_index_map *dest,
bddd52cb7f3e5a894c080f60750aa76b5aeaf103Timo Sirainen const struct mail_index_map *src)
bddd52cb7f3e5a894c080f60750aa76b5aeaf103Timo Sirainen{
bddd52cb7f3e5a894c080f60750aa76b5aeaf103Timo Sirainen size_t size;
bddd52cb7f3e5a894c080f60750aa76b5aeaf103Timo Sirainen
bddd52cb7f3e5a894c080f60750aa76b5aeaf103Timo Sirainen /* copy records */
bddd52cb7f3e5a894c080f60750aa76b5aeaf103Timo Sirainen size = src->records_count * src->hdr.record_size;
ad48319996942463675b53877092ab7e13a7a75aTimo Sirainen dest->buffer = buffer_create_dynamic(default_pool, size);
ad48319996942463675b53877092ab7e13a7a75aTimo Sirainen buffer_append(dest->buffer, src->records, size);
ad48319996942463675b53877092ab7e13a7a75aTimo Sirainen
ad48319996942463675b53877092ab7e13a7a75aTimo Sirainen dest->records = buffer_get_modifiable_data(dest->buffer, NULL);
ad48319996942463675b53877092ab7e13a7a75aTimo Sirainen dest->records_count = src->records_count;
ad48319996942463675b53877092ab7e13a7a75aTimo Sirainen
651fc0f1e43fef3e02e0e7b5f498973b05f641d7Timo Sirainen /* copy header. use src->hdr copy directly, because if we got here
d041ddb437ee7000174161405581ab85c0ba314aTimo Sirainen from syncing it has the latest changes. */
d041ddb437ee7000174161405581ab85c0ba314aTimo Sirainen dest->hdr = src->hdr;
d041ddb437ee7000174161405581ab85c0ba314aTimo Sirainen if (dest->hdr_copy_buf != NULL)
d041ddb437ee7000174161405581ab85c0ba314aTimo Sirainen buffer_set_used_size(dest->hdr_copy_buf, 0);
8872e5c991430f96138a46e36b7f3c2c40d8e5c2Timo Sirainen else {
d041ddb437ee7000174161405581ab85c0ba314aTimo Sirainen dest->hdr_copy_buf =
651fc0f1e43fef3e02e0e7b5f498973b05f641d7Timo Sirainen buffer_create_dynamic(default_pool,
8872e5c991430f96138a46e36b7f3c2c40d8e5c2Timo Sirainen dest->hdr.header_size);
8872e5c991430f96138a46e36b7f3c2c40d8e5c2Timo Sirainen }
8872e5c991430f96138a46e36b7f3c2c40d8e5c2Timo Sirainen buffer_append(dest->hdr_copy_buf, &dest->hdr,
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen I_MIN(sizeof(dest->hdr), src->hdr.base_header_size));
20261d71760e4199cb8d906ab9704a4561d954d7Timo Sirainen buffer_write(dest->hdr_copy_buf, src->hdr.base_header_size,
20261d71760e4199cb8d906ab9704a4561d954d7Timo Sirainen CONST_PTR_OFFSET(src->hdr_base, src->hdr.base_header_size),
20261d71760e4199cb8d906ab9704a4561d954d7Timo Sirainen src->hdr.header_size - src->hdr.base_header_size);
20261d71760e4199cb8d906ab9704a4561d954d7Timo Sirainen dest->hdr_base = buffer_get_modifiable_data(dest->hdr_copy_buf, NULL);
20261d71760e4199cb8d906ab9704a4561d954d7Timo Sirainen}
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen
d143077bd518de129b8d446fb58e003903e50867Timo Sirainenstruct mail_index_map *mail_index_map_clone(const struct mail_index_map *map)
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen{
d143077bd518de129b8d446fb58e003903e50867Timo Sirainen struct mail_index_map *mem_map;
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen struct mail_index_ext *extensions;
5626ae5e3316eced244adb6485c0927f1c7fdc41Timo Sirainen unsigned int i, count;
5626ae5e3316eced244adb6485c0927f1c7fdc41Timo Sirainen
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen mem_map = i_new(struct mail_index_map, 1);
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen mem_map->index = map->index;
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen mem_map->refcount = 1;
7ded22760598b78ee29f9418eacc0abe3fb51055Timo Sirainen
5626ae5e3316eced244adb6485c0927f1c7fdc41Timo Sirainen mail_index_map_copy(mem_map, map);
a2f250a332dfc1e6cd4ffd196c621eb9dbf7b8a1Timo Sirainen
5626ae5e3316eced244adb6485c0927f1c7fdc41Timo Sirainen /* if the map is ever written back to disk, we need to keep track of
5626ae5e3316eced244adb6485c0927f1c7fdc41Timo Sirainen what has changed. */
5626ae5e3316eced244adb6485c0927f1c7fdc41Timo Sirainen if (map->write_atomic)
5626ae5e3316eced244adb6485c0927f1c7fdc41Timo Sirainen mem_map->write_atomic = TRUE;
5626ae5e3316eced244adb6485c0927f1c7fdc41Timo Sirainen else {
5626ae5e3316eced244adb6485c0927f1c7fdc41Timo Sirainen mem_map->write_seq_first = map->write_seq_first;
a2f250a332dfc1e6cd4ffd196c621eb9dbf7b8a1Timo Sirainen mem_map->write_seq_last = map->write_seq_last;
a2f250a332dfc1e6cd4ffd196c621eb9dbf7b8a1Timo Sirainen mem_map->write_base_header = map->write_base_header;
91d4c7b37580b031ed7b0154ae10c643521803f3Timo Sirainen mem_map->write_ext_header = map->write_ext_header;
0f66f12eb4cdbf47670975044c88d8f388bf92dfTimo Sirainen }
5626ae5e3316eced244adb6485c0927f1c7fdc41Timo Sirainen
5626ae5e3316eced244adb6485c0927f1c7fdc41Timo Sirainen /* copy extensions */
5626ae5e3316eced244adb6485c0927f1c7fdc41Timo Sirainen if (array_is_created(&map->ext_id_map)) {
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen count = array_count(&map->ext_id_map);
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen mail_index_map_init_extbufs(mem_map, count + 2);
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen
ccffbed92cb02c24fd717808a84138240bf1885bTimo Sirainen array_append_array(&mem_map->extensions, &map->extensions);
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen array_append_array(&mem_map->ext_id_map, &map->ext_id_map);
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen
ccffbed92cb02c24fd717808a84138240bf1885bTimo Sirainen /* fix the name pointers to use our own pool */
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen extensions = array_get_modifiable(&mem_map->extensions, &count);
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen for (i = 0; i < count; i++) {
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen i_assert(extensions[i].record_offset +
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen extensions[i].record_size <=
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen mem_map->hdr.record_size);
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen extensions[i].name = p_strdup(mem_map->extension_pool,
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen extensions[i].name);
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen }
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen }
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen return mem_map;
ccffbed92cb02c24fd717808a84138240bf1885bTimo Sirainen}
ccffbed92cb02c24fd717808a84138240bf1885bTimo Sirainen
e26a771fad55dfba4d5021d12ed5685c951d9b7bTimo Sirainenvoid mail_index_map_move_to_memory(struct mail_index_map *map)
e26a771fad55dfba4d5021d12ed5685c951d9b7bTimo Sirainen{
e26a771fad55dfba4d5021d12ed5685c951d9b7bTimo Sirainen if (map->mmap_base == NULL)
e26a771fad55dfba4d5021d12ed5685c951d9b7bTimo Sirainen return;
1d3f7c1278168d5b1cbfa9a2cc9929a0909056b4Timo Sirainen
68f4cc25b3a5627b9de42bb0f12b570ee0e56e9cTimo Sirainen i_assert(map->lock_id != 0);
e26a771fad55dfba4d5021d12ed5685c951d9b7bTimo Sirainen
d12f05c7c391786d0d9795ec3aa4377280bbfaeaTimo Sirainen mail_index_map_copy(map, map);
d12f05c7c391786d0d9795ec3aa4377280bbfaeaTimo Sirainen mail_index_map_unlock(map);
e26a771fad55dfba4d5021d12ed5685c951d9b7bTimo Sirainen
e26a771fad55dfba4d5021d12ed5685c951d9b7bTimo Sirainen if (munmap(map->mmap_base, map->mmap_size) < 0)
e26a771fad55dfba4d5021d12ed5685c951d9b7bTimo Sirainen i_error("munmap(index map) failed: %m");
68f4cc25b3a5627b9de42bb0f12b570ee0e56e9cTimo Sirainen map->mmap_base = NULL;
68f4cc25b3a5627b9de42bb0f12b570ee0e56e9cTimo Sirainen}
e26a771fad55dfba4d5021d12ed5685c951d9b7bTimo Sirainen
e26a771fad55dfba4d5021d12ed5685c951d9b7bTimo Sirainenint mail_index_map_get_ext_idx(struct mail_index_map *map,
e26a771fad55dfba4d5021d12ed5685c951d9b7bTimo Sirainen uint32_t ext_id, uint32_t *idx_r)
e26a771fad55dfba4d5021d12ed5685c951d9b7bTimo Sirainen{
e26a771fad55dfba4d5021d12ed5685c951d9b7bTimo Sirainen const uint32_t *id;
e26a771fad55dfba4d5021d12ed5685c951d9b7bTimo Sirainen
e26a771fad55dfba4d5021d12ed5685c951d9b7bTimo Sirainen if (!array_is_created(&map->ext_id_map) ||
e26a771fad55dfba4d5021d12ed5685c951d9b7bTimo Sirainen ext_id >= array_count(&map->ext_id_map))
e26a771fad55dfba4d5021d12ed5685c951d9b7bTimo Sirainen return 0;
e26a771fad55dfba4d5021d12ed5685c951d9b7bTimo Sirainen
e26a771fad55dfba4d5021d12ed5685c951d9b7bTimo Sirainen id = array_idx(&map->ext_id_map, ext_id);
e26a771fad55dfba4d5021d12ed5685c951d9b7bTimo Sirainen *idx_r = *id;
e26a771fad55dfba4d5021d12ed5685c951d9b7bTimo Sirainen return *idx_r != (uint32_t)-1;
e26a771fad55dfba4d5021d12ed5685c951d9b7bTimo Sirainen}
e26a771fad55dfba4d5021d12ed5685c951d9b7bTimo Sirainen