mail-index.c revision 0e17a51126ed6f376f9207217797103b610ff8eb
5f5870385cff47efd2f58e7892f251cf13761528Timo Sirainen/* Copyright (C) 2003-2004 Timo Sirainen */
d13a8e21656e1b7005e094f7b9c9e3611105c648Timo Sirainenstatic int mail_index_try_open_only(struct mail_index *index);
d13a8e21656e1b7005e094f7b9c9e3611105c648Timo Sirainenstatic void mail_index_create_in_memory(struct mail_index *index,
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainenstruct mail_index *mail_index_alloc(const char *dir, const char *prefix)
3ec16f23d3c94c225e5b74d84c6a69064922cd9dTimo Sirainen index->extension_pool = pool_alloconly_create("extension", 512);
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen ARRAY_CREATE(&index->extensions, index->extension_pool,
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen ARRAY_CREATE(&index->sync_lost_handlers, default_pool,
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen mail_index_ext_register(index, "keywords", 128, 2, 1);
b3f46fa8a890527996fd0288cf964b7f3567cd22Timo Sirainen index->keywords_pool = pool_alloconly_create("keywords", 512);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen ARRAY_CREATE(&index->keywords, default_pool, const char *, 16);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen hash_create(default_pool, index->keywords_pool, 0,
f1ea65eb88b4f67e572c4640882bdf00fe3a2186Timo Sirainen strcase_hash, (hash_cmp_callback_t *)strcasecmp);
5fbf8719b9ef072295c16bc4492f9f0ece92117dTimo Sirainenvoid mail_index_set_permissions(struct mail_index *index,
6ef7e31619edfaa17ed044b45861d106a86191efTimo Sirainenuint32_t mail_index_ext_register(struct mail_index *index, const char *name,
b57cd9928909b51fa473c3eea81442e296006438Timo Sirainen const struct mail_index_registered_ext *extensions;
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen unsigned int i, ext_count;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen extensions = array_get(&index->extensions, &ext_count);
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen /* see if it's already there */
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen for (i = 0; i < ext_count; i++) {
c87d1e148ae76cf20f3adc7fc84fd54219dc62d5Timo Sirainen rext.name = p_strdup(index->extension_pool, name);
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainenvoid mail_index_register_expunge_handler(struct mail_index *index,
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen rext = array_idx_modifyable(&index->extensions, ext_id);
4e9070b89501c0ce7ad6aaf4f5e49aba1ee56decTimo Sirainenvoid mail_index_unregister_expunge_handler(struct mail_index *index,
f635aa2fd6c47ec297cf68981203a8dc7f8a23c3Timo Sirainen rext = array_idx_modifyable(&index->extensions, ext_id);
685a84a0ccb55cb9359dcd57d9eb3b6b836034a2Timo Sirainenvoid mail_index_register_sync_handler(struct mail_index *index, uint32_t ext_id,
5fbf8719b9ef072295c16bc4492f9f0ece92117dTimo Sirainen rext = array_idx_modifyable(&index->extensions, ext_id);
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen i_assert(rext->sync_handler.callback == NULL);
3ec16f23d3c94c225e5b74d84c6a69064922cd9dTimo Sirainenvoid mail_index_unregister_sync_handler(struct mail_index *index,
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen rext = array_idx_modifyable(&index->extensions, ext_id);
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen i_assert(rext->sync_handler.callback != NULL);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainenvoid mail_index_register_sync_lost_handler(struct mail_index *index,
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen array_append(&index->sync_lost_handlers, &cb, 1);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainenvoid mail_index_unregister_sync_lost_handler(struct mail_index *index,
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen mail_index_sync_lost_handler_t *const *handlers;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen unsigned int i, count;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen handlers = array_get(&index->sync_lost_handlers, &count);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen for (i = 0; i < count; i++) {
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen array_delete(&index->sync_lost_handlers, i, 1);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainenstatic void mail_index_map_init_extbufs(struct mail_index_map *map,
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen size = (sizeof(array_t) + BUFFER_APPROX_SIZE) * 2 +
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen sizeof(struct mail_index_ext) +
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen ARRAY_CREATE(&map->extensions, map->extension_pool,
57ca8cc86193103127066c724815e7e7a24926dbTimo Sirainen ARRAY_CREATE(&map->ext_id_map, map->extension_pool,
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainenuint32_t mail_index_map_lookup_ext(struct mail_index_map *map, const char *name)
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen unsigned int i, size;
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen extensions = array_get(&map->extensions, &size);
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen for (i = 0; i < size; i++) {
3e28b527dd6048a40684afd29cff0ee008fc0014Timo Sirainenmail_index_map_register_ext(struct mail_index *index,
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen i_assert(mail_index_map_lookup_ext(map, name) == (uint32_t)-1);
9222c96ab9f42b25d5d5260f9e7a42c694715b0aTimo Sirainen ext->name = p_strdup(map->extension_pool, name);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen ext->index_idx = mail_index_ext_register(index, name, hdr_size,
6bca3405636e3ec95724350c3a10d6fcb737782aTimo Sirainen /* Update index ext_id -> map ext_id mapping. Fill non-used
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen ext_ids with (uint32_t)-1 */
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen while (array_count(&map->ext_id_map) < ext->index_idx)
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen array_append(&map->ext_id_map, &empty_idx, 1);
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen array_idx_set(&map->ext_id_map, ext->index_idx, &idx);
a5be5a0d074ed0f3e4106612a2792e143a43efc6Timo Sirainenstatic int size_check(size_t *size_left, size_t size)
24ce0c343cefe54af841871fa39dbc3464028b06Timo Sirainen size_t size = sizeof(struct mail_index_ext_header) + name_len;
24ce0c343cefe54af841871fa39dbc3464028b06Timo Sirainen return MAIL_INDEX_HEADER_SIZE_ALIGN(size) - size;
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainenstatic int mail_index_read_extensions(struct mail_index *index,
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen unsigned int i, old_count;
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen /* extension headers always start from 64bit offsets, so if base header
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen doesn't happen to be 64bit aligned we'll skip some bytes */
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen offset = MAIL_INDEX_HEADER_SIZE_ALIGN(map->hdr.base_header_size);
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen if (offset >= map->hdr.header_size && map->extension_pool == NULL) {
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen /* nothing to do, skip allocatations and all */
24ce0c343cefe54af841871fa39dbc3464028b06Timo Sirainen mail_index_map_init_extbufs(map, old_count + 5);
24ce0c343cefe54af841871fa39dbc3464028b06Timo Sirainen for (i = 0; i < old_count; i++)
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen ext_hdr = CONST_PTR_OFFSET(map->hdr_base, offset);
5fbf8719b9ef072295c16bc4492f9f0ece92117dTimo Sirainen /* Extension header contains:
5fbf8719b9ef072295c16bc4492f9f0ece92117dTimo Sirainen - struct mail_index_ext_header
3db8062598ce08e9320c84f77c267b9c70cb0809Timo Sirainen - name (not 0-terminated)
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen - 64bit alignment padding
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen - extension header contents
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen - 64bit alignment padding
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen if (!size_check(&size_left, sizeof(*ext_hdr)) ||
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen !size_check(&size_left, ext_hdr->name_size) ||
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen !size_check(&size_left, get_align(ext_hdr->name_size)) ||
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen mail_index_set_error(index, "Corrupted index file %s: "
eeea0a402bcd9533e9e359f2a2518e3216162151Timo Sirainen "Header extension goes outside header",
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen offset += ext_hdr->name_size + get_align(ext_hdr->name_size);
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen name = t_strndup(CONST_PTR_OFFSET(map->hdr_base, name_offset),
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen if (mail_index_map_lookup_ext(map, name) != (uint32_t)-1) {
a5be5a0d074ed0f3e4106612a2792e143a43efc6Timo Sirainen mail_index_set_error(index, "Corrupted index file %s: "
a5be5a0d074ed0f3e4106612a2792e143a43efc6Timo Sirainen "Duplicate header extension %s",
e8fd206cf9dca263278efba21864606126fc29b8Timo Sirainen if ((ext_hdr->record_offset % ext_hdr->record_align) != 0 ||
e8fd206cf9dca263278efba21864606126fc29b8Timo Sirainen (map->hdr.record_size % ext_hdr->record_align) != 0) {
e8fd206cf9dca263278efba21864606126fc29b8Timo Sirainen mail_index_set_error(index, "Corrupted index file %s: "
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen "Record field %s alignmentation %u not used",
4e9070b89501c0ce7ad6aaf4f5e49aba1ee56decTimo Sirainen index->filepath, name, ext_hdr->record_align);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen offset += MAIL_INDEX_HEADER_SIZE_ALIGN(ext_hdr->hdr_size);
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainenint mail_index_keyword_lookup(struct mail_index *index,
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen unsigned int *idx_r)
3656c91dcb8336814bebd4500e81c3dde25233e6Timo Sirainen /* keywords_hash keeps a name => index mapping of keywords.
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen Keywords are never removed from it, so the index values are valid
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen for the lifetime of the mail_index. */
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen if (hash_lookup_full(index->keywords_hash, keyword, NULL, &value)) {
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen *idx_r = POINTER_CAST_TO(value, unsigned int);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen keyword = keyword_dup = p_strdup(index->keywords_pool, keyword);
fedb73c7e918653877286ede0fe18029b3cce7d3Timo Sirainen hash_insert(index->keywords_hash, keyword_dup, POINTER_CAST(*idx_r));
3ec16f23d3c94c225e5b74d84c6a69064922cd9dTimo Sirainenint mail_index_map_read_keywords(struct mail_index *index,
3ec16f23d3c94c225e5b74d84c6a69064922cd9dTimo Sirainen const struct mail_index_keyword_header *kw_hdr;
3ec16f23d3c94c225e5b74d84c6a69064922cd9dTimo Sirainen const struct mail_index_keyword_header_rec *kw_rec;
3ec16f23d3c94c225e5b74d84c6a69064922cd9dTimo Sirainen unsigned int i, name_area_end_offset, old_count;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen ext_id = mail_index_map_lookup_ext(map, "keywords");
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen /* Extension header contains:
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen - struct mail_index_keyword_header
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen - struct mail_index_keyword_header_rec * keywords_count
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen - const char names[] * keywords_count
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen kw_hdr = CONST_PTR_OFFSET(map->hdr_base, ext->hdr_offset);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen name = (const char *)(kw_rec + kw_hdr->keywords_count);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen old_count = !array_is_created(&map->keyword_idx_map) ? 0 :
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen /* Keywords can only be added into same mapping. Removing requires a
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen new mapping (recreating the index file) */
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen /* nothing changed */
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen /* make sure the header is valid */
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen mail_index_set_error(index, "Corrupted index file %s: "
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen "Keywords removed unexpectedly",
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen if ((size_t)(name - (const char *)kw_hdr) > ext->hdr_size) {
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen mail_index_set_error(index, "Corrupted index file %s: "
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen "keywords_count larger than header size",
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen name_area_end_offset = (const char *)kw_hdr + ext->hdr_size - name;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen for (i = 0; i < kw_hdr->keywords_count; i++) {
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen if (kw_rec[i].name_offset > name_area_end_offset) {
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen mail_index_set_error(index, "Corrupted index file %s: "
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen "name_offset points outside allocated header",
b3f46fa8a890527996fd0288cf964b7f3567cd22Timo Sirainen mail_index_set_error(index, "Corrupted index file %s: "
1ac19c5c2b66a12f5598792aad15114ee3eb62e2Timo Sirainen "Keyword header doesn't end with NUL",
b3f46fa8a890527996fd0288cf964b7f3567cd22Timo Sirainen /* create file -> index mapping */
b3f46fa8a890527996fd0288cf964b7f3567cd22Timo Sirainen if (!array_is_created(&map->keyword_idx_map)) {
b3f46fa8a890527996fd0288cf964b7f3567cd22Timo Sirainen ARRAY_CREATE(&map->keyword_idx_map, default_pool,
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen /* Check that existing headers are still the same. It's behind DEBUG
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen since it's pretty useless waste of CPU normally. */
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen for (i = 0; i < array_count(&map->keyword_idx_map); i++) {
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen const char *keyword = name + kw_rec[i].name_offset;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen const unsigned int *old_idx;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen unsigned int idx;
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen old_idx = array_idx(&map->keyword_idx_map, i);
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen if (!mail_index_keyword_lookup(index, keyword, FALSE, &idx) ||
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen mail_index_set_error(index, "Corrupted index file %s: "
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen "Keywords changed unexpectedly",
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen /* Register the newly seen keywords */
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainen const char *keyword = name + kw_rec[i].name_offset;
3ec16f23d3c94c225e5b74d84c6a69064922cd9dTimo Sirainen unsigned int idx;
933de3f374e6971f50308cb7bea13a51a45287bfTimo Sirainen (void)mail_index_keyword_lookup(index, keyword, TRUE, &idx);
3ec16f23d3c94c225e5b74d84c6a69064922cd9dTimo Sirainenconst array_t *mail_index_get_keywords(struct mail_index *index)
3ec16f23d3c94c225e5b74d84c6a69064922cd9dTimo Sirainen /* Make sure all the keywords are in index->keywords. It's quick to do
3ec16f23d3c94c225e5b74d84c6a69064922cd9dTimo Sirainen if nothing has changed. */
3ec16f23d3c94c225e5b74d84c6a69064922cd9dTimo Sirainen (void)mail_index_map_read_keywords(index, index->map);
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainenstatic int mail_index_check_header(struct mail_index *index,
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen const struct mail_index_header *hdr = &map->hdr;
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen enum mail_index_header_compat_flags compat_flags = 0;
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen compat_flags |= MAIL_INDEX_COMPAT_LITTLE_ENDIAN;
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen if (hdr->major_version != MAIL_INDEX_MAJOR_VERSION) {
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen /* major version change - handle silently(?) */
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen /* architecture change - handle silently(?) */
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen if ((map->hdr.flags & MAIL_INDEX_HDR_FLAG_CORRUPTED) != 0) {
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen /* we've already complained about it */
7d075009a641d88a45940238676883a8eaf1507bTimo Sirainen /* following some extra checks that only take a bit of CPU */
f1ea65eb88b4f67e572c4640882bdf00fe3a2186Timo Sirainen if (hdr->uid_validity == 0 && hdr->next_uid != 1) {
7d075009a641d88a45940238676883a8eaf1507bTimo Sirainen mail_index_set_error(index, "Corrupted index file %s: "
7d075009a641d88a45940238676883a8eaf1507bTimo Sirainen "uid_validity = 0, next_uid = %u",
f1ea65eb88b4f67e572c4640882bdf00fe3a2186Timo Sirainen if (hdr->record_size < sizeof(struct mail_index_record)) {
f1ea65eb88b4f67e572c4640882bdf00fe3a2186Timo Sirainen mail_index_set_error(index, "Corrupted index file %s: "
59811ccfeb7dccc51e3be50c299c2ed853a1e2f3Timo Sirainen sizeof(struct mail_index_record));
f1ea65eb88b4f67e572c4640882bdf00fe3a2186Timo Sirainen if ((hdr->flags & MAIL_INDEX_HDR_FLAG_FSCK) != 0)
a343811459d1d2259e668f369646a20f02301c2cTimo Sirainen if (hdr->recent_messages_count > hdr->messages_count ||
a343811459d1d2259e668f369646a20f02301c2cTimo Sirainen hdr->seen_messages_count > hdr->messages_count ||
a343811459d1d2259e668f369646a20f02301c2cTimo Sirainen hdr->deleted_messages_count > hdr->messages_count)
a343811459d1d2259e668f369646a20f02301c2cTimo Sirainen if (hdr->first_recent_uid_lowwater > hdr->next_uid ||
a343811459d1d2259e668f369646a20f02301c2cTimo Sirainen hdr->first_unseen_uid_lowwater > hdr->next_uid ||
a343811459d1d2259e668f369646a20f02301c2cTimo Sirainen hdr->first_deleted_uid_lowwater > hdr->next_uid)
a343811459d1d2259e668f369646a20f02301c2cTimo Sirainen return mail_index_read_extensions(index, map);
a343811459d1d2259e668f369646a20f02301c2cTimo Sirainenstatic void mail_index_map_clear(struct mail_index *index,
a343811459d1d2259e668f369646a20f02301c2cTimo Sirainen if (munmap(map->mmap_base, map->mmap_size) < 0)
a343811459d1d2259e668f369646a20f02301c2cTimo Sirainen mail_index_set_syscall_error(index, "munmap()");
a343811459d1d2259e668f369646a20f02301c2cTimo Sirainenvoid mail_index_unmap(struct mail_index *index, struct mail_index_map *map)
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainenstatic void mail_index_map_copy_hdr(struct mail_index_map *map,
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen if (hdr->base_header_size < sizeof(map->hdr)) {
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen /* header smaller than ours, make a copy so our newer headers
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen won't have garbage in them */
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainen memcpy(&map->hdr, hdr, hdr->base_header_size);
dc9de21d4375faeedbe5b7e941502ac578650da9Timo Sirainenstatic int mail_index_mmap(struct mail_index *index, struct mail_index_map *map)
0db5b158a00c08955bdacc99b1e2cd1ec07f4311Timo Sirainen /* we had temporarily used a buffer, eg. for updating index */
0ae010139a1bb3b29fbf117c5da1a6a6c6b7b5a0Timo Sirainen mail_index_set_syscall_error(index, "mmap()");
0ae010139a1bb3b29fbf117c5da1a6a6c6b7b5a0Timo Sirainen offsetof(struct mail_index_header, major_version) &&
0ae010139a1bb3b29fbf117c5da1a6a6c6b7b5a0Timo Sirainen hdr->major_version != MAIL_INDEX_MAJOR_VERSION) {
0ae010139a1bb3b29fbf117c5da1a6a6c6b7b5a0Timo Sirainen /* major version change - handle silently */
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen if (map->mmap_size < MAIL_INDEX_HEADER_MIN_SIZE) {
0db5b158a00c08955bdacc99b1e2cd1ec07f4311Timo Sirainen mail_index_set_error(index, "Corrupted index file %s: "
1ac19c5c2b66a12f5598792aad15114ee3eb62e2Timo Sirainen records_count = (map->mmap_size - hdr->header_size) /
1ac19c5c2b66a12f5598792aad15114ee3eb62e2Timo Sirainen mail_index_set_error(index, "Corrupted index file %s: "
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainen "messages_count too large (%u > %u)",
7bafda1813454621e03615e83d55bccfa7cc56bdTimo Sirainen map->records = PTR_OFFSET(map->mmap_base, map->hdr.header_size);
6b2738c39a868ff9291867138c55029fc40cf105Timo Sirainenstatic int mail_index_read_header(struct mail_index *index,
0371406d952fe51367c7be91703e5634b7d9d225Timo Sirainen for (pos = 0; ret > 0 && pos < sizeof(*hdr); ) {
6c2c5f20760b06bfb4a40b0ee2ef5ab016bc41f0Timo Sirainenstatic int mail_index_read_map(struct mail_index *index,
if (ret > 0) {
if (ret < 0) {
if (ret == 0) {
int sync_to_index)
const void *tdata;
if (sync_to_index) {
MAIL_TRANSACTION_TYPE_MASK) < 0) {
&skipped)) > 0) {
&prev_offset);
if (sync_to_index) {
int sync_to_index)
unsigned int i, count;
if (ret != 0)
return ret;
for (i = 0; i < count; i++)
for (i = 0; i < MAIL_INDEX_ESTALE_RETRY_COUNT; i++) {
return ret;
if (ret <= 0) {
if (ret == 0) {
int ret;
if (ret != 0) {
return ret;
if (ret > 0) {
if (ret < 0)
ret = 0;
else if (ret == 0) {
if (ret <= 0) {
return ret;
int ret;
if (ret > 0)
return ret;
struct mail_index_map *
unsigned int i, count;
for (i = 0; i < count; i++) {
return mem_map;
unsigned int lock_id;
int ret;
*lock_id_r = 0;
if (ret <= 0)
return ret;
if (ret == 0) {
*lock_id_r = 0;
return ret;
const char *path;
int fd;
return fd;
const char *path;
int ret;
if (ret != 0) {
/* create it fully in index.tmp first */
if (ret == 0) {
if (ret < 0) {
return ret;
#ifndef WORDS_BIGENDIAN
unsigned int lock_id = 0;
if (ret > 0)
else if (ret == 0) {
} else if (ret < 0)
if (lock_id != 0) {
lock_id = 0;
if (lock_id == 0) {
int i = 0, ret;
if (ret <= 0)
if (ret == 0) {
if (ret <= 0)
return ret;
ret = 0;
if (ret > 0)
else if (ret == 0) {
if (ret == 0) {
if (lock_id != 0)
if (ret == 0) {
return ret;
unsigned int lock_id;
int ret;
const char *function)
const char *filepath,
const char *function)
return MAIL_INDEX_ERROR_DISKSPACE;
return MAIL_INDEX_ERROR_INTERNAL;
return MAIL_INDEX_ERROR_NONE;