bcb4e51a409d94ae670de96afb8483a4f7855294Stephan Bosch/* Copyright (c) 2003-2018 Dovecot authors, see the included COPYING file */
2a34e2be33f8a17d21384a5527ed9f75f4d270e0Timo Sirainen
2a34e2be33f8a17d21384a5527ed9f75f4d270e0Timo Sirainen#include "lib.h"
2a34e2be33f8a17d21384a5527ed9f75f4d270e0Timo Sirainen#include "array.h"
ffd9a1898a18fadfc5dce399162c25d50548f905Timo Sirainen#include "str-sanitize.h"
2a34e2be33f8a17d21384a5527ed9f75f4d270e0Timo Sirainen#include "mmap-util.h"
2a34e2be33f8a17d21384a5527ed9f75f4d270e0Timo Sirainen#include "mail-index-private.h"
a2f250a332dfc1e6cd4ffd196c621eb9dbf7b8a1Timo Sirainen#include "mail-index-modseq.h"
2a34e2be33f8a17d21384a5527ed9f75f4d270e0Timo Sirainen
5806683c1c3f5b1997e92a023c0fe39912d4df5dTimo Sirainenvoid mail_index_map_init_extbufs(struct mail_index_map *map,
5806683c1c3f5b1997e92a023c0fe39912d4df5dTimo Sirainen unsigned int initial_count)
2a34e2be33f8a17d21384a5527ed9f75f4d270e0Timo Sirainen{
2a34e2be33f8a17d21384a5527ed9f75f4d270e0Timo Sirainen#define EXTENSION_NAME_APPROX_LEN 20
2a34e2be33f8a17d21384a5527ed9f75f4d270e0Timo Sirainen#define EXT_GLOBAL_ALLOC_SIZE \
8e361d2906b0e44f7175a20981f8d2280645b58bTimo Sirainen ((sizeof(map->extensions) + sizeof(buffer_t)) * 2)
2a34e2be33f8a17d21384a5527ed9f75f4d270e0Timo Sirainen#define EXT_PER_ALLOC_SIZE \
2a34e2be33f8a17d21384a5527ed9f75f4d270e0Timo Sirainen (EXTENSION_NAME_APPROX_LEN + \
2a34e2be33f8a17d21384a5527ed9f75f4d270e0Timo Sirainen sizeof(struct mail_index_ext) + sizeof(uint32_t))
2a34e2be33f8a17d21384a5527ed9f75f4d270e0Timo Sirainen size_t size;
2a34e2be33f8a17d21384a5527ed9f75f4d270e0Timo Sirainen
2a34e2be33f8a17d21384a5527ed9f75f4d270e0Timo Sirainen if (map->extension_pool == NULL) {
2a34e2be33f8a17d21384a5527ed9f75f4d270e0Timo Sirainen size = EXT_GLOBAL_ALLOC_SIZE +
2a34e2be33f8a17d21384a5527ed9f75f4d270e0Timo Sirainen initial_count * EXT_PER_ALLOC_SIZE;
2a34e2be33f8a17d21384a5527ed9f75f4d270e0Timo Sirainen map->extension_pool =
221351ed85c839e0b03d82c47654c3d17202e3dbTimo Sirainen pool_alloconly_create(MEMPOOL_GROWING"map extensions",
2a34e2be33f8a17d21384a5527ed9f75f4d270e0Timo Sirainen nearest_power(size));
2a34e2be33f8a17d21384a5527ed9f75f4d270e0Timo Sirainen } else {
2a34e2be33f8a17d21384a5527ed9f75f4d270e0Timo Sirainen p_clear(map->extension_pool);
2a34e2be33f8a17d21384a5527ed9f75f4d270e0Timo Sirainen
2a34e2be33f8a17d21384a5527ed9f75f4d270e0Timo Sirainen /* try to use the existing pool's size for initial_count so
19557f192d37cd54a1a090a8a26d9d47265e4413Aki Tuomi we don't grow it needlessly */
2a34e2be33f8a17d21384a5527ed9f75f4d270e0Timo Sirainen size = p_get_max_easy_alloc_size(map->extension_pool);
2a34e2be33f8a17d21384a5527ed9f75f4d270e0Timo Sirainen if (size > EXT_GLOBAL_ALLOC_SIZE + EXT_PER_ALLOC_SIZE) {
2a34e2be33f8a17d21384a5527ed9f75f4d270e0Timo Sirainen initial_count = (size - EXT_GLOBAL_ALLOC_SIZE) /
2a34e2be33f8a17d21384a5527ed9f75f4d270e0Timo Sirainen EXT_PER_ALLOC_SIZE;
2a34e2be33f8a17d21384a5527ed9f75f4d270e0Timo Sirainen }
2a34e2be33f8a17d21384a5527ed9f75f4d270e0Timo Sirainen }
2a34e2be33f8a17d21384a5527ed9f75f4d270e0Timo Sirainen
2a34e2be33f8a17d21384a5527ed9f75f4d270e0Timo Sirainen p_array_init(&map->extensions, map->extension_pool, initial_count);
2a34e2be33f8a17d21384a5527ed9f75f4d270e0Timo Sirainen p_array_init(&map->ext_id_map, map->extension_pool, initial_count);
2a34e2be33f8a17d21384a5527ed9f75f4d270e0Timo Sirainen}
2a34e2be33f8a17d21384a5527ed9f75f4d270e0Timo Sirainen
7ded22760598b78ee29f9418eacc0abe3fb51055Timo Sirainenbool mail_index_map_lookup_ext(struct mail_index_map *map, const char *name,
7ded22760598b78ee29f9418eacc0abe3fb51055Timo Sirainen uint32_t *idx_r)
2a34e2be33f8a17d21384a5527ed9f75f4d270e0Timo Sirainen{
7bd72e4deca3cbf757dd1ea298486d9f3bc24226Timo Sirainen const struct mail_index_ext *ext;
7bd72e4deca3cbf757dd1ea298486d9f3bc24226Timo Sirainen
7bd72e4deca3cbf757dd1ea298486d9f3bc24226Timo Sirainen if (!array_is_created(&map->extensions))
7bd72e4deca3cbf757dd1ea298486d9f3bc24226Timo Sirainen return FALSE;
7bd72e4deca3cbf757dd1ea298486d9f3bc24226Timo Sirainen
7bd72e4deca3cbf757dd1ea298486d9f3bc24226Timo Sirainen array_foreach(&map->extensions, ext) {
7bd72e4deca3cbf757dd1ea298486d9f3bc24226Timo Sirainen if (strcmp(ext->name, name) == 0) {
a10ed8c47534b4c6b6bf2711ccfe577e720a47b4Timo Sirainen *idx_r = array_foreach_idx(&map->extensions, ext);
7bd72e4deca3cbf757dd1ea298486d9f3bc24226Timo Sirainen return TRUE;
7ded22760598b78ee29f9418eacc0abe3fb51055Timo Sirainen }
2a34e2be33f8a17d21384a5527ed9f75f4d270e0Timo Sirainen }
7ded22760598b78ee29f9418eacc0abe3fb51055Timo Sirainen return FALSE;
2a34e2be33f8a17d21384a5527ed9f75f4d270e0Timo Sirainen}
2a34e2be33f8a17d21384a5527ed9f75f4d270e0Timo Sirainen
8ababf3e7b15f793370d1dedf85825d38b42633fTimo Sirainenunsigned int mail_index_map_ext_hdr_offset(unsigned int name_len)
cfa9359fbd6a967ccdcd553c5e483a093885ab6fTimo Sirainen{
cfa9359fbd6a967ccdcd553c5e483a093885ab6fTimo Sirainen size_t size = sizeof(struct mail_index_ext_header) + name_len;
cfa9359fbd6a967ccdcd553c5e483a093885ab6fTimo Sirainen return MAIL_INDEX_HEADER_SIZE_ALIGN(size);
cfa9359fbd6a967ccdcd553c5e483a093885ab6fTimo Sirainen}
cfa9359fbd6a967ccdcd553c5e483a093885ab6fTimo Sirainen
2a34e2be33f8a17d21384a5527ed9f75f4d270e0Timo Sirainenuint32_t
3675a7e9bd3775ba13fe8bc93915902513a0f1a4Timo Sirainenmail_index_map_register_ext(struct mail_index_map *map,
3675a7e9bd3775ba13fe8bc93915902513a0f1a4Timo Sirainen const char *name, uint32_t ext_offset,
3675a7e9bd3775ba13fe8bc93915902513a0f1a4Timo Sirainen const struct mail_index_ext_header *ext_hdr)
2a34e2be33f8a17d21384a5527ed9f75f4d270e0Timo Sirainen{
2a34e2be33f8a17d21384a5527ed9f75f4d270e0Timo Sirainen struct mail_index_ext *ext;
a10ed8c47534b4c6b6bf2711ccfe577e720a47b4Timo Sirainen uint32_t idx, ext_map_idx, empty_idx = (uint32_t)-1;
2a34e2be33f8a17d21384a5527ed9f75f4d270e0Timo Sirainen
2a34e2be33f8a17d21384a5527ed9f75f4d270e0Timo Sirainen if (!array_is_created(&map->extensions)) {
2a34e2be33f8a17d21384a5527ed9f75f4d270e0Timo Sirainen mail_index_map_init_extbufs(map, 5);
2a34e2be33f8a17d21384a5527ed9f75f4d270e0Timo Sirainen idx = 0;
2a34e2be33f8a17d21384a5527ed9f75f4d270e0Timo Sirainen } else {
2a34e2be33f8a17d21384a5527ed9f75f4d270e0Timo Sirainen idx = array_count(&map->extensions);
2a34e2be33f8a17d21384a5527ed9f75f4d270e0Timo Sirainen }
a10ed8c47534b4c6b6bf2711ccfe577e720a47b4Timo Sirainen i_assert(!mail_index_map_lookup_ext(map, name, &ext_map_idx));
2a34e2be33f8a17d21384a5527ed9f75f4d270e0Timo Sirainen
2a34e2be33f8a17d21384a5527ed9f75f4d270e0Timo Sirainen ext = array_append_space(&map->extensions);
2a34e2be33f8a17d21384a5527ed9f75f4d270e0Timo Sirainen ext->name = p_strdup(map->extension_pool, name);
cfa9359fbd6a967ccdcd553c5e483a093885ab6fTimo Sirainen ext->ext_offset = ext_offset;
2c488bf1ca9194cf36597959f1316b7e12102fd9Timo Sirainen ext->hdr_offset = ext_offset == (uint32_t)-1 ? (uint32_t)-1 :
2c488bf1ca9194cf36597959f1316b7e12102fd9Timo Sirainen ext_offset + mail_index_map_ext_hdr_offset(strlen(name));
3675a7e9bd3775ba13fe8bc93915902513a0f1a4Timo Sirainen ext->hdr_size = ext_hdr->hdr_size;
3675a7e9bd3775ba13fe8bc93915902513a0f1a4Timo Sirainen ext->record_offset = ext_hdr->record_offset;
3675a7e9bd3775ba13fe8bc93915902513a0f1a4Timo Sirainen ext->record_size = ext_hdr->record_size;
3675a7e9bd3775ba13fe8bc93915902513a0f1a4Timo Sirainen ext->record_align = ext_hdr->record_align;
3675a7e9bd3775ba13fe8bc93915902513a0f1a4Timo Sirainen ext->reset_id = ext_hdr->reset_id;
2a34e2be33f8a17d21384a5527ed9f75f4d270e0Timo Sirainen
3675a7e9bd3775ba13fe8bc93915902513a0f1a4Timo Sirainen ext->index_idx = mail_index_ext_register(map->index, name,
3675a7e9bd3775ba13fe8bc93915902513a0f1a4Timo Sirainen ext_hdr->hdr_size,
3675a7e9bd3775ba13fe8bc93915902513a0f1a4Timo Sirainen ext_hdr->record_size,
3675a7e9bd3775ba13fe8bc93915902513a0f1a4Timo Sirainen ext_hdr->record_align);
2a34e2be33f8a17d21384a5527ed9f75f4d270e0Timo Sirainen
2a34e2be33f8a17d21384a5527ed9f75f4d270e0Timo Sirainen /* Update index ext_id -> map ext_id mapping. Fill non-used
2a34e2be33f8a17d21384a5527ed9f75f4d270e0Timo Sirainen ext_ids with (uint32_t)-1 */
2a34e2be33f8a17d21384a5527ed9f75f4d270e0Timo Sirainen while (array_count(&map->ext_id_map) < ext->index_idx)
2a34e2be33f8a17d21384a5527ed9f75f4d270e0Timo Sirainen array_append(&map->ext_id_map, &empty_idx, 1);
2a34e2be33f8a17d21384a5527ed9f75f4d270e0Timo Sirainen array_idx_set(&map->ext_id_map, ext->index_idx, &idx);
2a34e2be33f8a17d21384a5527ed9f75f4d270e0Timo Sirainen return idx;
2a34e2be33f8a17d21384a5527ed9f75f4d270e0Timo Sirainen}
2a34e2be33f8a17d21384a5527ed9f75f4d270e0Timo Sirainen
746d35bf3dba3ae5ddbcecb9732f60d5e9de77efTimo Sirainenint mail_index_map_ext_get_next(struct mail_index_map *map,
746d35bf3dba3ae5ddbcecb9732f60d5e9de77efTimo Sirainen unsigned int *offset_p,
746d35bf3dba3ae5ddbcecb9732f60d5e9de77efTimo Sirainen const struct mail_index_ext_header **ext_hdr_r,
746d35bf3dba3ae5ddbcecb9732f60d5e9de77efTimo Sirainen const char **name_r)
746d35bf3dba3ae5ddbcecb9732f60d5e9de77efTimo Sirainen{
746d35bf3dba3ae5ddbcecb9732f60d5e9de77efTimo Sirainen const struct mail_index_ext_header *ext_hdr;
746d35bf3dba3ae5ddbcecb9732f60d5e9de77efTimo Sirainen unsigned int offset, name_offset;
746d35bf3dba3ae5ddbcecb9732f60d5e9de77efTimo Sirainen
746d35bf3dba3ae5ddbcecb9732f60d5e9de77efTimo Sirainen offset = *offset_p;
746d35bf3dba3ae5ddbcecb9732f60d5e9de77efTimo Sirainen *name_r = "";
746d35bf3dba3ae5ddbcecb9732f60d5e9de77efTimo Sirainen
746d35bf3dba3ae5ddbcecb9732f60d5e9de77efTimo Sirainen /* Extension header contains:
746d35bf3dba3ae5ddbcecb9732f60d5e9de77efTimo Sirainen - struct mail_index_ext_header
746d35bf3dba3ae5ddbcecb9732f60d5e9de77efTimo Sirainen - name (not 0-terminated)
746d35bf3dba3ae5ddbcecb9732f60d5e9de77efTimo Sirainen - 64bit alignment padding
746d35bf3dba3ae5ddbcecb9732f60d5e9de77efTimo Sirainen - extension header contents
746d35bf3dba3ae5ddbcecb9732f60d5e9de77efTimo Sirainen - 64bit alignment padding
746d35bf3dba3ae5ddbcecb9732f60d5e9de77efTimo Sirainen */
746d35bf3dba3ae5ddbcecb9732f60d5e9de77efTimo Sirainen name_offset = offset + sizeof(*ext_hdr);
746d35bf3dba3ae5ddbcecb9732f60d5e9de77efTimo Sirainen ext_hdr = CONST_PTR_OFFSET(map->hdr_base, offset);
746d35bf3dba3ae5ddbcecb9732f60d5e9de77efTimo Sirainen if (offset + sizeof(*ext_hdr) >= map->hdr.header_size)
746d35bf3dba3ae5ddbcecb9732f60d5e9de77efTimo Sirainen return -1;
746d35bf3dba3ae5ddbcecb9732f60d5e9de77efTimo Sirainen
8ababf3e7b15f793370d1dedf85825d38b42633fTimo Sirainen offset += mail_index_map_ext_hdr_offset(ext_hdr->name_size);
746d35bf3dba3ae5ddbcecb9732f60d5e9de77efTimo Sirainen if (offset > map->hdr.header_size)
746d35bf3dba3ae5ddbcecb9732f60d5e9de77efTimo Sirainen return -1;
746d35bf3dba3ae5ddbcecb9732f60d5e9de77efTimo Sirainen
746d35bf3dba3ae5ddbcecb9732f60d5e9de77efTimo Sirainen *name_r = t_strndup(CONST_PTR_OFFSET(map->hdr_base, name_offset),
746d35bf3dba3ae5ddbcecb9732f60d5e9de77efTimo Sirainen ext_hdr->name_size);
746d35bf3dba3ae5ddbcecb9732f60d5e9de77efTimo Sirainen if (strcmp(*name_r, str_sanitize(*name_r, -1)) != 0) {
746d35bf3dba3ae5ddbcecb9732f60d5e9de77efTimo Sirainen /* we allow only plain ASCII names, so this extension
746d35bf3dba3ae5ddbcecb9732f60d5e9de77efTimo Sirainen is most likely broken */
746d35bf3dba3ae5ddbcecb9732f60d5e9de77efTimo Sirainen *name_r = "";
746d35bf3dba3ae5ddbcecb9732f60d5e9de77efTimo Sirainen }
746d35bf3dba3ae5ddbcecb9732f60d5e9de77efTimo Sirainen
746d35bf3dba3ae5ddbcecb9732f60d5e9de77efTimo Sirainen /* finally make sure that the hdr_size is small enough.
746d35bf3dba3ae5ddbcecb9732f60d5e9de77efTimo Sirainen do this last so that we could return a usable name. */
746d35bf3dba3ae5ddbcecb9732f60d5e9de77efTimo Sirainen offset += MAIL_INDEX_HEADER_SIZE_ALIGN(ext_hdr->hdr_size);
746d35bf3dba3ae5ddbcecb9732f60d5e9de77efTimo Sirainen if (offset > map->hdr.header_size)
746d35bf3dba3ae5ddbcecb9732f60d5e9de77efTimo Sirainen return -1;
746d35bf3dba3ae5ddbcecb9732f60d5e9de77efTimo Sirainen
746d35bf3dba3ae5ddbcecb9732f60d5e9de77efTimo Sirainen *offset_p = offset;
746d35bf3dba3ae5ddbcecb9732f60d5e9de77efTimo Sirainen *ext_hdr_r = ext_hdr;
746d35bf3dba3ae5ddbcecb9732f60d5e9de77efTimo Sirainen return 0;
746d35bf3dba3ae5ddbcecb9732f60d5e9de77efTimo Sirainen}
746d35bf3dba3ae5ddbcecb9732f60d5e9de77efTimo Sirainen
eb958701f57066bce9cc8bbf9df73616bd322d09Timo Sirainenstatic int
eb958701f57066bce9cc8bbf9df73616bd322d09Timo Sirainenmail_index_map_ext_hdr_check_record(const struct mail_index_header *hdr,
eb958701f57066bce9cc8bbf9df73616bd322d09Timo Sirainen const struct mail_index_ext_header *ext_hdr,
eb958701f57066bce9cc8bbf9df73616bd322d09Timo Sirainen const char **error_r)
746d35bf3dba3ae5ddbcecb9732f60d5e9de77efTimo Sirainen{
eb958701f57066bce9cc8bbf9df73616bd322d09Timo Sirainen if (ext_hdr->record_align == 0) {
eb958701f57066bce9cc8bbf9df73616bd322d09Timo Sirainen *error_r = "Record field alignment is zero";
746d35bf3dba3ae5ddbcecb9732f60d5e9de77efTimo Sirainen return -1;
746d35bf3dba3ae5ddbcecb9732f60d5e9de77efTimo Sirainen }
746d35bf3dba3ae5ddbcecb9732f60d5e9de77efTimo Sirainen
4ad29660779873d7955151eb4568d132a32e9d9cTimo Sirainen /* until we get 128 bit CPUs having a larger alignment is pointless */
4ad29660779873d7955151eb4568d132a32e9d9cTimo Sirainen if (ext_hdr->record_align > sizeof(uint64_t)) {
4ad29660779873d7955151eb4568d132a32e9d9cTimo Sirainen *error_r = "Record alignment is too large";
4ad29660779873d7955151eb4568d132a32e9d9cTimo Sirainen return -1;
4ad29660779873d7955151eb4568d132a32e9d9cTimo Sirainen }
4ad29660779873d7955151eb4568d132a32e9d9cTimo Sirainen /* a large record size is most likely a bug somewhere. the maximum
4ad29660779873d7955151eb4568d132a32e9d9cTimo Sirainen record size is limited to 64k anyway, so try to fail earlier. */
a2aa37d224a70b2eccc00691d2893e09f107d7ccTimo Sirainen if (ext_hdr->record_size >= 32768) {
4ad29660779873d7955151eb4568d132a32e9d9cTimo Sirainen *error_r = "Record size is too large";
4ad29660779873d7955151eb4568d132a32e9d9cTimo Sirainen return -1;
4ad29660779873d7955151eb4568d132a32e9d9cTimo Sirainen }
4ad29660779873d7955151eb4568d132a32e9d9cTimo Sirainen
4a01681e0ed9a7b3f7a105dd2fcd2511e7160e99Timo Sirainen if (ext_hdr->record_offset == 0) {
4a01681e0ed9a7b3f7a105dd2fcd2511e7160e99Timo Sirainen /* if we get here from extension introduction, record_offset=0
4a01681e0ed9a7b3f7a105dd2fcd2511e7160e99Timo Sirainen and hdr->record_size hasn't been updated yet */
4a01681e0ed9a7b3f7a105dd2fcd2511e7160e99Timo Sirainen return 0;
4a01681e0ed9a7b3f7a105dd2fcd2511e7160e99Timo Sirainen }
4a01681e0ed9a7b3f7a105dd2fcd2511e7160e99Timo Sirainen
eb958701f57066bce9cc8bbf9df73616bd322d09Timo Sirainen if (ext_hdr->record_offset + ext_hdr->record_size > hdr->record_size) {
746d35bf3dba3ae5ddbcecb9732f60d5e9de77efTimo Sirainen *error_r = t_strdup_printf("Record field points "
746d35bf3dba3ae5ddbcecb9732f60d5e9de77efTimo Sirainen "outside record size (%u+%u > %u)",
746d35bf3dba3ae5ddbcecb9732f60d5e9de77efTimo Sirainen ext_hdr->record_offset,
746d35bf3dba3ae5ddbcecb9732f60d5e9de77efTimo Sirainen ext_hdr->record_size,
746d35bf3dba3ae5ddbcecb9732f60d5e9de77efTimo Sirainen hdr->record_size);
746d35bf3dba3ae5ddbcecb9732f60d5e9de77efTimo Sirainen return -1;
746d35bf3dba3ae5ddbcecb9732f60d5e9de77efTimo Sirainen }
746d35bf3dba3ae5ddbcecb9732f60d5e9de77efTimo Sirainen
eb958701f57066bce9cc8bbf9df73616bd322d09Timo Sirainen if ((ext_hdr->record_offset % ext_hdr->record_align) != 0) {
9573f4283f9118315b0865998d43223fedee0246Timo Sirainen *error_r = t_strdup_printf("Record field alignment %u "
746d35bf3dba3ae5ddbcecb9732f60d5e9de77efTimo Sirainen "not used", ext_hdr->record_align);
746d35bf3dba3ae5ddbcecb9732f60d5e9de77efTimo Sirainen return -1;
746d35bf3dba3ae5ddbcecb9732f60d5e9de77efTimo Sirainen }
eb958701f57066bce9cc8bbf9df73616bd322d09Timo Sirainen if ((hdr->record_size % ext_hdr->record_align) != 0) {
6c9699d37fbe4d8af3682ee7f341ede8d54faa87Timo Sirainen *error_r = t_strdup_printf("Record size not aligned by %u "
6c9699d37fbe4d8af3682ee7f341ede8d54faa87Timo Sirainen "as required by extension",
6c9699d37fbe4d8af3682ee7f341ede8d54faa87Timo Sirainen ext_hdr->record_align);
6c9699d37fbe4d8af3682ee7f341ede8d54faa87Timo Sirainen return -1;
6c9699d37fbe4d8af3682ee7f341ede8d54faa87Timo Sirainen }
eb958701f57066bce9cc8bbf9df73616bd322d09Timo Sirainen return 0;
eb958701f57066bce9cc8bbf9df73616bd322d09Timo Sirainen}
eb958701f57066bce9cc8bbf9df73616bd322d09Timo Sirainen
eb958701f57066bce9cc8bbf9df73616bd322d09Timo Sirainenint mail_index_map_ext_hdr_check(const struct mail_index_header *hdr,
eb958701f57066bce9cc8bbf9df73616bd322d09Timo Sirainen const struct mail_index_ext_header *ext_hdr,
eb958701f57066bce9cc8bbf9df73616bd322d09Timo Sirainen const char *name, const char **error_r)
eb958701f57066bce9cc8bbf9df73616bd322d09Timo Sirainen{
eb958701f57066bce9cc8bbf9df73616bd322d09Timo Sirainen if (ext_hdr->record_size == 0 && ext_hdr->hdr_size == 0) {
eb958701f57066bce9cc8bbf9df73616bd322d09Timo Sirainen *error_r = "Invalid field values";
eb958701f57066bce9cc8bbf9df73616bd322d09Timo Sirainen return -1;
eb958701f57066bce9cc8bbf9df73616bd322d09Timo Sirainen }
eb958701f57066bce9cc8bbf9df73616bd322d09Timo Sirainen if (*name == '\0') {
eb958701f57066bce9cc8bbf9df73616bd322d09Timo Sirainen *error_r = "Broken name";
eb958701f57066bce9cc8bbf9df73616bd322d09Timo Sirainen return -1;
eb958701f57066bce9cc8bbf9df73616bd322d09Timo Sirainen }
eb958701f57066bce9cc8bbf9df73616bd322d09Timo Sirainen
4a01681e0ed9a7b3f7a105dd2fcd2511e7160e99Timo Sirainen if (ext_hdr->record_size != 0) {
eb958701f57066bce9cc8bbf9df73616bd322d09Timo Sirainen if (mail_index_map_ext_hdr_check_record(hdr, ext_hdr,
eb958701f57066bce9cc8bbf9df73616bd322d09Timo Sirainen error_r) < 0)
eb958701f57066bce9cc8bbf9df73616bd322d09Timo Sirainen return -1;
eb958701f57066bce9cc8bbf9df73616bd322d09Timo Sirainen }
ed50658501d9ae8c85f6264831056b1debed11c3Timo Sirainen if (ext_hdr->hdr_size > MAIL_INDEX_EXT_HEADER_MAX_SIZE) {
ed50658501d9ae8c85f6264831056b1debed11c3Timo Sirainen *error_r = t_strdup_printf("Headersize too large (%u)",
ed50658501d9ae8c85f6264831056b1debed11c3Timo Sirainen ext_hdr->hdr_size);
ed50658501d9ae8c85f6264831056b1debed11c3Timo Sirainen return -1;
ed50658501d9ae8c85f6264831056b1debed11c3Timo Sirainen }
746d35bf3dba3ae5ddbcecb9732f60d5e9de77efTimo Sirainen return 0;
746d35bf3dba3ae5ddbcecb9732f60d5e9de77efTimo Sirainen}
746d35bf3dba3ae5ddbcecb9732f60d5e9de77efTimo Sirainen
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainenstatic void mail_index_header_init(struct mail_index *index,
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen struct mail_index_header *hdr)
2a34e2be33f8a17d21384a5527ed9f75f4d270e0Timo Sirainen{
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen i_assert((sizeof(*hdr) % sizeof(uint64_t)) == 0);
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen
efe78d3ba24fc866af1c79b9223dc0809ba26cadStephan Bosch i_zero(hdr);
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen hdr->major_version = MAIL_INDEX_MAJOR_VERSION;
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen hdr->minor_version = MAIL_INDEX_MINOR_VERSION;
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen hdr->base_header_size = sizeof(*hdr);
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen hdr->header_size = sizeof(*hdr);
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen hdr->record_size = sizeof(struct mail_index_record);
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen
debc93e622751c6c09e8105e504c5833f1ca0d6dMartti Rannanjärvi#ifndef WORDS_BIGENDIAN
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen hdr->compat_flags |= MAIL_INDEX_COMPAT_LITTLE_ENDIAN;
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen#endif
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen hdr->indexid = index->indexid;
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen hdr->log_file_seq = 1;
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen hdr->next_uid = 1;
1d3f7c1278168d5b1cbfa9a2cc9929a0909056b4Timo Sirainen hdr->first_recent_uid = 1;
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen}
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainenstruct mail_index_map *mail_index_map_alloc(struct mail_index *index)
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen{
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen struct mail_index_map tmp_map;
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen
efe78d3ba24fc866af1c79b9223dc0809ba26cadStephan Bosch i_zero(&tmp_map);
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen mail_index_header_init(index, &tmp_map.hdr);
b0be0bead3d6963149f7f2a9504b8ab5aced9af5Timo Sirainen tmp_map.index = index;
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen tmp_map.hdr_base = &tmp_map.hdr;
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen /* a bit kludgy way to do this, but it initializes everything
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen nicely and correctly */
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen return mail_index_map_clone(&tmp_map);
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen}
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainenstatic void mail_index_record_map_free(struct mail_index_map *map,
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen struct mail_index_record_map *rec_map)
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen{
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen if (rec_map->buffer != NULL) {
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen i_assert(rec_map->mmap_base == NULL);
0f66f12eb4cdbf47670975044c88d8f388bf92dfTimo Sirainen buffer_free(&rec_map->buffer);
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen } else if (rec_map->mmap_base != NULL) {
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen i_assert(rec_map->buffer == NULL);
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen if (munmap(rec_map->mmap_base, rec_map->mmap_size) < 0)
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen mail_index_set_syscall_error(map->index, "munmap()");
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen rec_map->mmap_base = NULL;
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen }
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen array_free(&rec_map->maps);
a2f250a332dfc1e6cd4ffd196c621eb9dbf7b8a1Timo Sirainen if (rec_map->modseq != NULL)
7de1c472fd23ddac6b4dc5cbeee6fa6a8418b071Timo Sirainen mail_index_map_modseq_free(&rec_map->modseq);
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen i_free(rec_map);
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen}
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainenstatic void mail_index_record_map_unlink(struct mail_index_map *map)
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen{
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen struct mail_index_map *const *maps;
8ae72ad7d0c69e972cfa65d1e2ce4e3e9a8b765cTimo Sirainen unsigned int idx = UINT_MAX;
7bd72e4deca3cbf757dd1ea298486d9f3bc24226Timo Sirainen
7bd72e4deca3cbf757dd1ea298486d9f3bc24226Timo Sirainen array_foreach(&map->rec_map->maps, maps) {
7bd72e4deca3cbf757dd1ea298486d9f3bc24226Timo Sirainen if (*maps == map) {
7bd72e4deca3cbf757dd1ea298486d9f3bc24226Timo Sirainen idx = array_foreach_idx(&map->rec_map->maps, maps);
7bd72e4deca3cbf757dd1ea298486d9f3bc24226Timo Sirainen break;
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen }
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen }
8ae72ad7d0c69e972cfa65d1e2ce4e3e9a8b765cTimo Sirainen i_assert(idx != UINT_MAX);
7bd72e4deca3cbf757dd1ea298486d9f3bc24226Timo Sirainen
7bd72e4deca3cbf757dd1ea298486d9f3bc24226Timo Sirainen array_delete(&map->rec_map->maps, idx, 1);
7bd72e4deca3cbf757dd1ea298486d9f3bc24226Timo Sirainen if (array_count(&map->rec_map->maps) == 0) {
7bd72e4deca3cbf757dd1ea298486d9f3bc24226Timo Sirainen mail_index_record_map_free(map, map->rec_map);
7bd72e4deca3cbf757dd1ea298486d9f3bc24226Timo Sirainen map->rec_map = NULL;
7bd72e4deca3cbf757dd1ea298486d9f3bc24226Timo Sirainen }
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen}
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen
b0be0bead3d6963149f7f2a9504b8ab5aced9af5Timo Sirainenvoid mail_index_unmap(struct mail_index_map **_map)
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen{
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen struct mail_index_map *map = *_map;
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen *_map = NULL;
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen if (--map->refcount > 0)
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen return;
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen i_assert(map->refcount == 0);
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen mail_index_record_map_unlink(map);
14c474d9f4591c397ed0b5206af6537c7b52c924Timo Sirainen
c69a177207ed18d0f0210347430a60957136bd6cJosef 'Jeff' Sipek pool_unref(&map->extension_pool);
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen if (array_is_created(&map->keyword_idx_map))
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen array_free(&map->keyword_idx_map);
0f66f12eb4cdbf47670975044c88d8f388bf92dfTimo Sirainen buffer_free(&map->hdr_copy_buf);
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen i_free(map);
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen}
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainenstatic void mail_index_map_copy_records(struct mail_index_record_map *dest,
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen const struct mail_index_record_map *src,
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen unsigned int record_size)
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen{
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen size_t size;
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen size = src->records_count * record_size;
749097cae4e02bdeccb8b09f7dda6e2da6812ee1Timo Sirainen /* +1% so we have a bit of space to grow. useful for huge mailboxes. */
749097cae4e02bdeccb8b09f7dda6e2da6812ee1Timo Sirainen dest->buffer = buffer_create_dynamic(default_pool,
749097cae4e02bdeccb8b09f7dda6e2da6812ee1Timo Sirainen size + I_MAX(size/100, 1024));
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen buffer_append(dest->buffer, src->records, size);
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen dest->records = buffer_get_modifiable_data(dest->buffer, NULL);
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen dest->records_count = src->records_count;
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen}
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainenstatic void mail_index_map_copy_header(struct mail_index_map *dest,
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen const struct mail_index_map *src)
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen{
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen /* use src->hdr copy directly, because if we got here
19779377be72c9fe8365bb9ba7a2e0d06dc99c3bTimo Sirainen from syncing it has the latest changes. */
a85d0d2b75e5effadf4d3c2167af0ff9ae95904aTimo Sirainen if (src != dest)
a85d0d2b75e5effadf4d3c2167af0ff9ae95904aTimo Sirainen dest->hdr = src->hdr;
5787e39e2be32f657b8c98fee8bac794aa852cf8Timo Sirainen if (dest->hdr_copy_buf != NULL) {
5787e39e2be32f657b8c98fee8bac794aa852cf8Timo Sirainen if (src == dest)
5787e39e2be32f657b8c98fee8bac794aa852cf8Timo Sirainen return;
5787e39e2be32f657b8c98fee8bac794aa852cf8Timo Sirainen
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen buffer_set_used_size(dest->hdr_copy_buf, 0);
5787e39e2be32f657b8c98fee8bac794aa852cf8Timo Sirainen } else {
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen dest->hdr_copy_buf =
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen buffer_create_dynamic(default_pool,
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen dest->hdr.header_size);
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen }
19779377be72c9fe8365bb9ba7a2e0d06dc99c3bTimo Sirainen buffer_append(dest->hdr_copy_buf, &dest->hdr,
19779377be72c9fe8365bb9ba7a2e0d06dc99c3bTimo Sirainen I_MIN(sizeof(dest->hdr), src->hdr.base_header_size));
a28a6267f48971117dec958b160deefd14ebb7a6Timo Sirainen if (src != dest) {
a28a6267f48971117dec958b160deefd14ebb7a6Timo Sirainen buffer_write(dest->hdr_copy_buf, src->hdr.base_header_size,
a28a6267f48971117dec958b160deefd14ebb7a6Timo Sirainen CONST_PTR_OFFSET(src->hdr_base,
a28a6267f48971117dec958b160deefd14ebb7a6Timo Sirainen src->hdr.base_header_size),
a28a6267f48971117dec958b160deefd14ebb7a6Timo Sirainen src->hdr.header_size - src->hdr.base_header_size);
a28a6267f48971117dec958b160deefd14ebb7a6Timo Sirainen }
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen dest->hdr_base = buffer_get_modifiable_data(dest->hdr_copy_buf, NULL);
5787e39e2be32f657b8c98fee8bac794aa852cf8Timo Sirainen i_assert(dest->hdr_copy_buf->used == dest->hdr.header_size);
2a34e2be33f8a17d21384a5527ed9f75f4d270e0Timo Sirainen}
2a34e2be33f8a17d21384a5527ed9f75f4d270e0Timo Sirainen
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainenstatic struct mail_index_record_map *
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainenmail_index_record_map_alloc(struct mail_index_map *map)
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen{
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen struct mail_index_record_map *rec_map;
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen rec_map = i_new(struct mail_index_record_map, 1);
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen i_array_init(&rec_map->maps, 4);
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen array_append(&rec_map->maps, &map, 1);
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen return rec_map;
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen}
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainenstruct mail_index_map *mail_index_map_clone(const struct mail_index_map *map)
2a34e2be33f8a17d21384a5527ed9f75f4d270e0Timo Sirainen{
2a34e2be33f8a17d21384a5527ed9f75f4d270e0Timo Sirainen struct mail_index_map *mem_map;
e20e638805c4bd54e039891a3e92760b1dfa189aTimo Sirainen struct mail_index_ext *ext;
e20e638805c4bd54e039891a3e92760b1dfa189aTimo Sirainen unsigned int count;
2a34e2be33f8a17d21384a5527ed9f75f4d270e0Timo Sirainen
2a34e2be33f8a17d21384a5527ed9f75f4d270e0Timo Sirainen mem_map = i_new(struct mail_index_map, 1);
b0be0bead3d6963149f7f2a9504b8ab5aced9af5Timo Sirainen mem_map->index = map->index;
2a34e2be33f8a17d21384a5527ed9f75f4d270e0Timo Sirainen mem_map->refcount = 1;
a28a6267f48971117dec958b160deefd14ebb7a6Timo Sirainen if (map->rec_map == NULL) {
a28a6267f48971117dec958b160deefd14ebb7a6Timo Sirainen mem_map->rec_map = mail_index_record_map_alloc(mem_map);
a28a6267f48971117dec958b160deefd14ebb7a6Timo Sirainen mem_map->rec_map->buffer =
a28a6267f48971117dec958b160deefd14ebb7a6Timo Sirainen buffer_create_dynamic(default_pool, 1024);
a28a6267f48971117dec958b160deefd14ebb7a6Timo Sirainen } else {
a28a6267f48971117dec958b160deefd14ebb7a6Timo Sirainen mem_map->rec_map = map->rec_map;
a28a6267f48971117dec958b160deefd14ebb7a6Timo Sirainen array_append(&mem_map->rec_map->maps, &mem_map, 1);
a28a6267f48971117dec958b160deefd14ebb7a6Timo Sirainen }
2a34e2be33f8a17d21384a5527ed9f75f4d270e0Timo Sirainen
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen mail_index_map_copy_header(mem_map, map);
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen
2a34e2be33f8a17d21384a5527ed9f75f4d270e0Timo Sirainen /* copy extensions */
2a34e2be33f8a17d21384a5527ed9f75f4d270e0Timo Sirainen if (array_is_created(&map->ext_id_map)) {
2a34e2be33f8a17d21384a5527ed9f75f4d270e0Timo Sirainen count = array_count(&map->ext_id_map);
2a34e2be33f8a17d21384a5527ed9f75f4d270e0Timo Sirainen mail_index_map_init_extbufs(mem_map, count + 2);
2a34e2be33f8a17d21384a5527ed9f75f4d270e0Timo Sirainen
2a34e2be33f8a17d21384a5527ed9f75f4d270e0Timo Sirainen array_append_array(&mem_map->extensions, &map->extensions);
2a34e2be33f8a17d21384a5527ed9f75f4d270e0Timo Sirainen array_append_array(&mem_map->ext_id_map, &map->ext_id_map);
2a34e2be33f8a17d21384a5527ed9f75f4d270e0Timo Sirainen
2a34e2be33f8a17d21384a5527ed9f75f4d270e0Timo Sirainen /* fix the name pointers to use our own pool */
e20e638805c4bd54e039891a3e92760b1dfa189aTimo Sirainen array_foreach_modifiable(&mem_map->extensions, ext) {
e20e638805c4bd54e039891a3e92760b1dfa189aTimo Sirainen i_assert(ext->record_offset + ext->record_size <=
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen mem_map->hdr.record_size);
e20e638805c4bd54e039891a3e92760b1dfa189aTimo Sirainen ext->name = p_strdup(mem_map->extension_pool,
e20e638805c4bd54e039891a3e92760b1dfa189aTimo Sirainen ext->name);
2a34e2be33f8a17d21384a5527ed9f75f4d270e0Timo Sirainen }
2a34e2be33f8a17d21384a5527ed9f75f4d270e0Timo Sirainen }
2a34e2be33f8a17d21384a5527ed9f75f4d270e0Timo Sirainen
d051664df497582e1eb75a9f238d04b65e858db8Timo Sirainen /* copy keyword map */
d051664df497582e1eb75a9f238d04b65e858db8Timo Sirainen if (array_is_created(&map->keyword_idx_map)) {
d051664df497582e1eb75a9f238d04b65e858db8Timo Sirainen i_array_init(&mem_map->keyword_idx_map,
d051664df497582e1eb75a9f238d04b65e858db8Timo Sirainen array_count(&map->keyword_idx_map) + 4);
d051664df497582e1eb75a9f238d04b65e858db8Timo Sirainen array_append_array(&mem_map->keyword_idx_map,
d051664df497582e1eb75a9f238d04b65e858db8Timo Sirainen &map->keyword_idx_map);
d051664df497582e1eb75a9f238d04b65e858db8Timo Sirainen }
d051664df497582e1eb75a9f238d04b65e858db8Timo Sirainen
2a34e2be33f8a17d21384a5527ed9f75f4d270e0Timo Sirainen return mem_map;
2a34e2be33f8a17d21384a5527ed9f75f4d270e0Timo Sirainen}
2a34e2be33f8a17d21384a5527ed9f75f4d270e0Timo Sirainen
a28a6267f48971117dec958b160deefd14ebb7a6Timo Sirainenvoid mail_index_record_map_move_to_private(struct mail_index_map *map)
a28a6267f48971117dec958b160deefd14ebb7a6Timo Sirainen{
a28a6267f48971117dec958b160deefd14ebb7a6Timo Sirainen struct mail_index_record_map *new_map;
d0ab5936be1cd971007fc2241e0be120c442cb84Timo Sirainen const struct mail_index_record *rec;
d0ab5936be1cd971007fc2241e0be120c442cb84Timo Sirainen
d0ab5936be1cd971007fc2241e0be120c442cb84Timo Sirainen if (array_count(&map->rec_map->maps) > 1) {
d0ab5936be1cd971007fc2241e0be120c442cb84Timo Sirainen new_map = mail_index_record_map_alloc(map);
d0ab5936be1cd971007fc2241e0be120c442cb84Timo Sirainen mail_index_map_copy_records(new_map, map->rec_map,
d0ab5936be1cd971007fc2241e0be120c442cb84Timo Sirainen map->hdr.record_size);
d0ab5936be1cd971007fc2241e0be120c442cb84Timo Sirainen mail_index_record_map_unlink(map);
d0ab5936be1cd971007fc2241e0be120c442cb84Timo Sirainen map->rec_map = new_map;
90a989e4f8bcb4fb86af32cbae577402e3f92b1aTimo Sirainen if (map->rec_map->modseq != NULL)
90a989e4f8bcb4fb86af32cbae577402e3f92b1aTimo Sirainen new_map->modseq = mail_index_map_modseq_clone(map->rec_map->modseq);
d0ab5936be1cd971007fc2241e0be120c442cb84Timo Sirainen } else {
d0ab5936be1cd971007fc2241e0be120c442cb84Timo Sirainen new_map = map->rec_map;
d0ab5936be1cd971007fc2241e0be120c442cb84Timo Sirainen }
a28a6267f48971117dec958b160deefd14ebb7a6Timo Sirainen
d0ab5936be1cd971007fc2241e0be120c442cb84Timo Sirainen if (new_map->records_count != map->hdr.messages_count) {
d0ab5936be1cd971007fc2241e0be120c442cb84Timo Sirainen new_map->records_count = map->hdr.messages_count;
d0ab5936be1cd971007fc2241e0be120c442cb84Timo Sirainen if (new_map->records_count == 0)
d0ab5936be1cd971007fc2241e0be120c442cb84Timo Sirainen new_map->last_appended_uid = 0;
d0ab5936be1cd971007fc2241e0be120c442cb84Timo Sirainen else {
1df526903ed039e8ff966a223c43b8d04eddf3c7Phil Carmody rec = MAIL_INDEX_REC_AT_SEQ(map, new_map->records_count);
d0ab5936be1cd971007fc2241e0be120c442cb84Timo Sirainen new_map->last_appended_uid = rec->uid;
d0ab5936be1cd971007fc2241e0be120c442cb84Timo Sirainen }
d0ab5936be1cd971007fc2241e0be120c442cb84Timo Sirainen buffer_set_used_size(new_map->buffer, new_map->records_count *
d0ab5936be1cd971007fc2241e0be120c442cb84Timo Sirainen map->hdr.record_size);
d0ab5936be1cd971007fc2241e0be120c442cb84Timo Sirainen }
a28a6267f48971117dec958b160deefd14ebb7a6Timo Sirainen}
a28a6267f48971117dec958b160deefd14ebb7a6Timo Sirainen
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainenvoid mail_index_map_move_to_memory(struct mail_index_map *map)
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen{
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen struct mail_index_record_map *new_map;
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen if (map->rec_map->mmap_base == NULL)
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen return;
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen
7de1c472fd23ddac6b4dc5cbeee6fa6a8418b071Timo Sirainen if (array_count(&map->rec_map->maps) == 1)
7de1c472fd23ddac6b4dc5cbeee6fa6a8418b071Timo Sirainen new_map = map->rec_map;
7de1c472fd23ddac6b4dc5cbeee6fa6a8418b071Timo Sirainen else {
7de1c472fd23ddac6b4dc5cbeee6fa6a8418b071Timo Sirainen new_map = mail_index_record_map_alloc(map);
7de1c472fd23ddac6b4dc5cbeee6fa6a8418b071Timo Sirainen new_map->modseq = map->rec_map->modseq == NULL ? NULL :
7de1c472fd23ddac6b4dc5cbeee6fa6a8418b071Timo Sirainen mail_index_map_modseq_clone(map->rec_map->modseq);
7de1c472fd23ddac6b4dc5cbeee6fa6a8418b071Timo Sirainen }
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen mail_index_map_copy_records(new_map, map->rec_map,
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen map->hdr.record_size);
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen mail_index_map_copy_header(map, map);
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen if (new_map != map->rec_map) {
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen mail_index_record_map_unlink(map);
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen map->rec_map = new_map;
88187ee880b4829443e0d55ea7d145d9d5880217Timo Sirainen } else {
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen if (munmap(new_map->mmap_base, new_map->mmap_size) < 0)
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen mail_index_set_syscall_error(map->index, "munmap()");
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen new_map->mmap_base = NULL;
3697080532ccd9f51fac108be6079b616c7a2ddfTimo Sirainen }
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen}
2a6af811ea3de3cf9e2f15e446674dd21b0705f3Timo Sirainen
12053b7b4b57dbd2790057426d1633988eedad56Timo Sirainenbool mail_index_map_get_ext_idx(struct mail_index_map *map,
12053b7b4b57dbd2790057426d1633988eedad56Timo Sirainen uint32_t ext_id, uint32_t *idx_r)
2a34e2be33f8a17d21384a5527ed9f75f4d270e0Timo Sirainen{
2a34e2be33f8a17d21384a5527ed9f75f4d270e0Timo Sirainen const uint32_t *id;
2a34e2be33f8a17d21384a5527ed9f75f4d270e0Timo Sirainen
2a34e2be33f8a17d21384a5527ed9f75f4d270e0Timo Sirainen if (!array_is_created(&map->ext_id_map) ||
2a34e2be33f8a17d21384a5527ed9f75f4d270e0Timo Sirainen ext_id >= array_count(&map->ext_id_map))
12053b7b4b57dbd2790057426d1633988eedad56Timo Sirainen return FALSE;
2a34e2be33f8a17d21384a5527ed9f75f4d270e0Timo Sirainen
2a34e2be33f8a17d21384a5527ed9f75f4d270e0Timo Sirainen id = array_idx(&map->ext_id_map, ext_id);
2a34e2be33f8a17d21384a5527ed9f75f4d270e0Timo Sirainen *idx_r = *id;
2a34e2be33f8a17d21384a5527ed9f75f4d270e0Timo Sirainen return *idx_r != (uint32_t)-1;
2a34e2be33f8a17d21384a5527ed9f75f4d270e0Timo Sirainen}
c24c0f0a208e5ffc35dc8be19a9b504a5326467aTimo Sirainen
c24c0f0a208e5ffc35dc8be19a9b504a5326467aTimo Sirainenstatic uint32_t mail_index_bsearch_uid(struct mail_index_map *map,
c24c0f0a208e5ffc35dc8be19a9b504a5326467aTimo Sirainen uint32_t uid, uint32_t left_idx,
c24c0f0a208e5ffc35dc8be19a9b504a5326467aTimo Sirainen int nearest_side)
c24c0f0a208e5ffc35dc8be19a9b504a5326467aTimo Sirainen{
c24c0f0a208e5ffc35dc8be19a9b504a5326467aTimo Sirainen const struct mail_index_record *rec_base, *rec;
c24c0f0a208e5ffc35dc8be19a9b504a5326467aTimo Sirainen uint32_t idx, right_idx, record_size;
c24c0f0a208e5ffc35dc8be19a9b504a5326467aTimo Sirainen
c24c0f0a208e5ffc35dc8be19a9b504a5326467aTimo Sirainen i_assert(map->hdr.messages_count <= map->rec_map->records_count);
c24c0f0a208e5ffc35dc8be19a9b504a5326467aTimo Sirainen
c24c0f0a208e5ffc35dc8be19a9b504a5326467aTimo Sirainen rec_base = map->rec_map->records;
c24c0f0a208e5ffc35dc8be19a9b504a5326467aTimo Sirainen record_size = map->hdr.record_size;
c24c0f0a208e5ffc35dc8be19a9b504a5326467aTimo Sirainen
c24c0f0a208e5ffc35dc8be19a9b504a5326467aTimo Sirainen idx = left_idx;
c24c0f0a208e5ffc35dc8be19a9b504a5326467aTimo Sirainen right_idx = I_MIN(map->hdr.messages_count, uid);
c24c0f0a208e5ffc35dc8be19a9b504a5326467aTimo Sirainen
25480af2e21cf136e461ec802177f52b43154485Timo Sirainen i_assert(right_idx < INT_MAX);
c24c0f0a208e5ffc35dc8be19a9b504a5326467aTimo Sirainen while (left_idx < right_idx) {
c24c0f0a208e5ffc35dc8be19a9b504a5326467aTimo Sirainen idx = (left_idx + right_idx) / 2;
c24c0f0a208e5ffc35dc8be19a9b504a5326467aTimo Sirainen
c24c0f0a208e5ffc35dc8be19a9b504a5326467aTimo Sirainen rec = CONST_PTR_OFFSET(rec_base, idx * record_size);
c24c0f0a208e5ffc35dc8be19a9b504a5326467aTimo Sirainen if (rec->uid < uid)
c24c0f0a208e5ffc35dc8be19a9b504a5326467aTimo Sirainen left_idx = idx+1;
c24c0f0a208e5ffc35dc8be19a9b504a5326467aTimo Sirainen else if (rec->uid > uid)
c24c0f0a208e5ffc35dc8be19a9b504a5326467aTimo Sirainen right_idx = idx;
c24c0f0a208e5ffc35dc8be19a9b504a5326467aTimo Sirainen else
c24c0f0a208e5ffc35dc8be19a9b504a5326467aTimo Sirainen break;
c24c0f0a208e5ffc35dc8be19a9b504a5326467aTimo Sirainen }
c24c0f0a208e5ffc35dc8be19a9b504a5326467aTimo Sirainen i_assert(idx < map->hdr.messages_count);
c24c0f0a208e5ffc35dc8be19a9b504a5326467aTimo Sirainen
c24c0f0a208e5ffc35dc8be19a9b504a5326467aTimo Sirainen rec = CONST_PTR_OFFSET(rec_base, idx * record_size);
c24c0f0a208e5ffc35dc8be19a9b504a5326467aTimo Sirainen if (rec->uid != uid) {
c24c0f0a208e5ffc35dc8be19a9b504a5326467aTimo Sirainen if (nearest_side > 0) {
c24c0f0a208e5ffc35dc8be19a9b504a5326467aTimo Sirainen /* we want uid or larger */
c24c0f0a208e5ffc35dc8be19a9b504a5326467aTimo Sirainen return rec->uid > uid ? idx+1 :
c24c0f0a208e5ffc35dc8be19a9b504a5326467aTimo Sirainen (idx == map->hdr.messages_count-1 ? 0 : idx+2);
c24c0f0a208e5ffc35dc8be19a9b504a5326467aTimo Sirainen } else {
c24c0f0a208e5ffc35dc8be19a9b504a5326467aTimo Sirainen /* we want uid or smaller */
c24c0f0a208e5ffc35dc8be19a9b504a5326467aTimo Sirainen return rec->uid < uid ? idx + 1 : idx;
c24c0f0a208e5ffc35dc8be19a9b504a5326467aTimo Sirainen }
c24c0f0a208e5ffc35dc8be19a9b504a5326467aTimo Sirainen }
c24c0f0a208e5ffc35dc8be19a9b504a5326467aTimo Sirainen
c24c0f0a208e5ffc35dc8be19a9b504a5326467aTimo Sirainen return idx+1;
c24c0f0a208e5ffc35dc8be19a9b504a5326467aTimo Sirainen}
c24c0f0a208e5ffc35dc8be19a9b504a5326467aTimo Sirainen
c24c0f0a208e5ffc35dc8be19a9b504a5326467aTimo Sirainenvoid mail_index_map_lookup_seq_range(struct mail_index_map *map,
c24c0f0a208e5ffc35dc8be19a9b504a5326467aTimo Sirainen uint32_t first_uid, uint32_t last_uid,
c24c0f0a208e5ffc35dc8be19a9b504a5326467aTimo Sirainen uint32_t *first_seq_r,
c24c0f0a208e5ffc35dc8be19a9b504a5326467aTimo Sirainen uint32_t *last_seq_r)
c24c0f0a208e5ffc35dc8be19a9b504a5326467aTimo Sirainen{
c24c0f0a208e5ffc35dc8be19a9b504a5326467aTimo Sirainen i_assert(first_uid > 0);
c24c0f0a208e5ffc35dc8be19a9b504a5326467aTimo Sirainen i_assert(first_uid <= last_uid);
c24c0f0a208e5ffc35dc8be19a9b504a5326467aTimo Sirainen
c24c0f0a208e5ffc35dc8be19a9b504a5326467aTimo Sirainen if (map->hdr.messages_count == 0) {
c24c0f0a208e5ffc35dc8be19a9b504a5326467aTimo Sirainen *first_seq_r = *last_seq_r = 0;
c24c0f0a208e5ffc35dc8be19a9b504a5326467aTimo Sirainen return;
c24c0f0a208e5ffc35dc8be19a9b504a5326467aTimo Sirainen }
c24c0f0a208e5ffc35dc8be19a9b504a5326467aTimo Sirainen
c24c0f0a208e5ffc35dc8be19a9b504a5326467aTimo Sirainen *first_seq_r = mail_index_bsearch_uid(map, first_uid, 0, 1);
c24c0f0a208e5ffc35dc8be19a9b504a5326467aTimo Sirainen if (*first_seq_r == 0 ||
1df526903ed039e8ff966a223c43b8d04eddf3c7Phil Carmody MAIL_INDEX_REC_AT_SEQ(map, *first_seq_r)->uid > last_uid) {
c24c0f0a208e5ffc35dc8be19a9b504a5326467aTimo Sirainen *first_seq_r = *last_seq_r = 0;
c24c0f0a208e5ffc35dc8be19a9b504a5326467aTimo Sirainen return;
c24c0f0a208e5ffc35dc8be19a9b504a5326467aTimo Sirainen }
c24c0f0a208e5ffc35dc8be19a9b504a5326467aTimo Sirainen
c24c0f0a208e5ffc35dc8be19a9b504a5326467aTimo Sirainen if (last_uid >= map->hdr.next_uid-1) {
c24c0f0a208e5ffc35dc8be19a9b504a5326467aTimo Sirainen /* we want the last message */
c24c0f0a208e5ffc35dc8be19a9b504a5326467aTimo Sirainen last_uid = map->hdr.next_uid-1;
c24c0f0a208e5ffc35dc8be19a9b504a5326467aTimo Sirainen if (first_uid > last_uid) {
c24c0f0a208e5ffc35dc8be19a9b504a5326467aTimo Sirainen *first_seq_r = *last_seq_r = 0;
c24c0f0a208e5ffc35dc8be19a9b504a5326467aTimo Sirainen return;
c24c0f0a208e5ffc35dc8be19a9b504a5326467aTimo Sirainen }
c24c0f0a208e5ffc35dc8be19a9b504a5326467aTimo Sirainen
c24c0f0a208e5ffc35dc8be19a9b504a5326467aTimo Sirainen *last_seq_r = map->hdr.messages_count;
c24c0f0a208e5ffc35dc8be19a9b504a5326467aTimo Sirainen return;
c24c0f0a208e5ffc35dc8be19a9b504a5326467aTimo Sirainen }
c24c0f0a208e5ffc35dc8be19a9b504a5326467aTimo Sirainen
c24c0f0a208e5ffc35dc8be19a9b504a5326467aTimo Sirainen if (first_uid == last_uid)
c24c0f0a208e5ffc35dc8be19a9b504a5326467aTimo Sirainen *last_seq_r = *first_seq_r;
c24c0f0a208e5ffc35dc8be19a9b504a5326467aTimo Sirainen else {
c24c0f0a208e5ffc35dc8be19a9b504a5326467aTimo Sirainen /* optimization - binary lookup only from right side: */
c24c0f0a208e5ffc35dc8be19a9b504a5326467aTimo Sirainen *last_seq_r = mail_index_bsearch_uid(map, last_uid,
c24c0f0a208e5ffc35dc8be19a9b504a5326467aTimo Sirainen *first_seq_r - 1, -1);
c24c0f0a208e5ffc35dc8be19a9b504a5326467aTimo Sirainen }
c24c0f0a208e5ffc35dc8be19a9b504a5326467aTimo Sirainen i_assert(*last_seq_r >= *first_seq_r);
c24c0f0a208e5ffc35dc8be19a9b504a5326467aTimo Sirainen}