mail-index.c revision 0c27b881989bc2b391281650ee89a8cc4d89f5e7
bcb4e51a409d94ae670de96afb8483a4f7855294Stephan Bosch/* Copyright (C) 2003-2004 Timo Sirainen */
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen#include "lib.h"
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen#include "buffer.h"
dfa2201c6ac8ddb2d2798dee15662cfe774e644eMartti Rannanjärvi#include "mmap-util.h"
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen#include "read-full.h"
fd8b93ca5cbeba64fe6fa5dc98a3e580fb046791Timo Sirainen#include "write-full.h"
472369cba85d9f7c995dda60e7cd01d78b4a960aTimo Sirainen#include "mail-index-private.h"
847caf605dc11acfb1861586b558d9cca4a85cb0Timo Sirainen#include "mail-index-sync-private.h"
e28fa207d1a097fa6e4a867f74ee0761472ef1ceTimo Sirainen#include "mail-transaction-log.h"
37847ec8eaec9ad55c9df10ae109efe7b37ac573Timo Sirainen#include "mail-cache.h"
bd4e36a8cd7257cca7d1434c49a1e343ed7c5100Timo Sirainen
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen#include <stdio.h>
b1f37113a5760bee842c5a7678bb5fa6f5bd8b60Timo Sirainen#include <stddef.h>
1c1cecd3dfaf71b0c9499b044023e631841e88aaTimo Sirainen#include <time.h>
94d8e51119003d2bc5a100c663f90141f297385dTimo Sirainen#include <sys/stat.h>
9393445a6dabd17ce62ebfc12fd73545b0065824Timo Sirainen
697ff56bf3cdc9e7989ea2a70accf866b14b64d1Timo Sirainenstatic int mail_index_try_open_only(struct mail_index *index);
e28fa207d1a097fa6e4a867f74ee0761472ef1ceTimo Sirainen
37847ec8eaec9ad55c9df10ae109efe7b37ac573Timo Sirainenstruct mail_index *mail_index_alloc(const char *dir, const char *prefix)
ef50336eefcb9ba99f73c6af37420eaf8857a39bTimo Sirainen{
d2e74f2af690b8e2d536400f02f397cbed1334b7Timo Sirainen struct mail_index *index;
13d98ffa534f2e7d04a832c9d0153fc9c568b878Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen index = i_new(struct mail_index, 1);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen index->dir = i_strdup(dir);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen index->prefix = i_strdup(prefix);
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen index->fd = -1;
5694eeb99b69dea8033ca77ad69743c6b4871370Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen index->extension_pool = pool_alloconly_create("extension", 256);
5694eeb99b69dea8033ca77ad69743c6b4871370Timo Sirainen index->extensions = buffer_create_dynamic(index->extension_pool, 64);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen index->sync_handlers = buffer_create_dynamic(default_pool, 64);
847caf605dc11acfb1861586b558d9cca4a85cb0Timo Sirainen index->expunge_handlers = buffer_create_dynamic(default_pool, 32);
847caf605dc11acfb1861586b558d9cca4a85cb0Timo Sirainen
847caf605dc11acfb1861586b558d9cca4a85cb0Timo Sirainen index->mode = 0600;
697ff56bf3cdc9e7989ea2a70accf866b14b64d1Timo Sirainen index->gid = (gid_t)-1;
697ff56bf3cdc9e7989ea2a70accf866b14b64d1Timo Sirainen return index;
697ff56bf3cdc9e7989ea2a70accf866b14b64d1Timo Sirainen}
697ff56bf3cdc9e7989ea2a70accf866b14b64d1Timo Sirainen
697ff56bf3cdc9e7989ea2a70accf866b14b64d1Timo Sirainenvoid mail_index_free(struct mail_index *index)
697ff56bf3cdc9e7989ea2a70accf866b14b64d1Timo Sirainen{
697ff56bf3cdc9e7989ea2a70accf866b14b64d1Timo Sirainen mail_index_close(index);
697ff56bf3cdc9e7989ea2a70accf866b14b64d1Timo Sirainen pool_unref(index->extension_pool);
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen
220e21750948941dc6e33b8f11b552fa21d7f81eTimo Sirainen buffer_free(index->sync_handlers);
4ee00532a265bdfb38539d811fcd12d51210ac35Timo Sirainen buffer_free(index->expunge_handlers);
697ff56bf3cdc9e7989ea2a70accf866b14b64d1Timo Sirainen
697ff56bf3cdc9e7989ea2a70accf866b14b64d1Timo Sirainen i_free(index->error);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen i_free(index->dir);
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainen i_free(index->prefix);
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainen i_free(index);
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainen}
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainen
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainenvoid mail_index_set_permissions(struct mail_index *index,
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainen mode_t mode, gid_t gid)
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainen{
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainen index->mode = mode & 0666;
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainen index->gid = gid;
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainen}
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainenuint32_t mail_index_ext_register(struct mail_index *index, const char *name,
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen uint32_t default_hdr_size,
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen uint16_t default_record_size,
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen uint16_t default_record_align)
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen{
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen const struct mail_index_ext *extensions;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen struct mail_index_ext ext;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen size_t ext_count;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen unsigned int i;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen extensions = buffer_get_data(index->extensions, &ext_count);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen ext_count /= sizeof(*extensions);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen i_assert(index->sync_handlers->used /
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen sizeof(struct mail_index_sync_handler) == ext_count);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainen /* see if it's already there */
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainen for (i = 0; i < ext_count; i++) {
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainen if (strcmp(extensions[i].name, name) == 0)
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainen return i;
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainen }
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen memset(&ext, 0, sizeof(ext));
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen ext.name = p_strdup(index->extension_pool, name);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen ext.index_idx = ext_count;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen ext.hdr_size = default_hdr_size;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen ext.record_size = default_record_size;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen ext.record_align = default_record_align;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen buffer_append(index->extensions, &ext, sizeof(ext));
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen buffer_append_zero(index->sync_handlers,
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen sizeof(struct mail_index_sync_handler));
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen return ext_count;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen}
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainenvoid mail_index_register_expunge_handler(struct mail_index *index,
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen uint32_t ext_id,
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen mail_index_expunge_handler_t *cb)
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen{
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen buffer_write(index->expunge_handlers, ext_id * sizeof(cb),
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen &cb, sizeof(cb));
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen}
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainenvoid mail_index_register_sync_handler(struct mail_index *index, uint32_t ext_id,
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen mail_index_sync_handler_t *cb,
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen enum mail_index_sync_handler_type type)
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen{
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen struct mail_index_sync_handler h;
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen memset(&h, 0, sizeof(h));
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen h.callback = cb;
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen h.type = type;
db8b0a3f74a20528d66a3c4be7df920e5c4554c2Timo Sirainen buffer_write(index->sync_handlers, ext_id * sizeof(h), &h, sizeof(h));
db8b0a3f74a20528d66a3c4be7df920e5c4554c2Timo Sirainen}
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
ac2defed599a97c4a71a9e90ba185929dfe59226Josef 'Jeff' Sipekstatic void mail_index_map_init_extbufs(struct mail_index_map *map,
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen unsigned int initial_count)
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen{
db8b0a3f74a20528d66a3c4be7df920e5c4554c2Timo Sirainen size_t ext_size, ext_id_map_size, size;
db8b0a3f74a20528d66a3c4be7df920e5c4554c2Timo Sirainen
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen ext_size = initial_count * sizeof(struct mail_index_ext);
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen ext_id_map_size = initial_count * sizeof(uint32_t);
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen if (map->extension_pool == NULL) {
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen size = ext_size + ext_id_map_size +
ac2defed599a97c4a71a9e90ba185929dfe59226Josef 'Jeff' Sipek (initial_count * 20); /* for names */
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen map->extension_pool =
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen pool_alloconly_create("extensions",
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen nearest_power(size));
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen } else {
ac2defed599a97c4a71a9e90ba185929dfe59226Josef 'Jeff' Sipek p_clear(map->extension_pool);
63e207529879438e9f4412d97cdc34bdc82a3702Timo Sirainen }
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen map->extensions = buffer_create_dynamic(map->extension_pool, ext_size);
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen map->ext_id_map =
ac2defed599a97c4a71a9e90ba185929dfe59226Josef 'Jeff' Sipek buffer_create_dynamic(map->extension_pool, ext_id_map_size);
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen}
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainenuint32_t mail_index_map_lookup_ext(struct mail_index_map *map, const char *name)
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen{
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen const struct mail_index_ext *extensions;
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen size_t i, size;
ac2defed599a97c4a71a9e90ba185929dfe59226Josef 'Jeff' Sipek
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen if (map->extensions == NULL)
ac2defed599a97c4a71a9e90ba185929dfe59226Josef 'Jeff' Sipek return (uint32_t)-1;
1701e3f91107051b1704721bf1dc1e32491faaf9Timo Sirainen
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen extensions = buffer_get_data(map->extensions, &size);
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen size /= sizeof(*extensions);
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen for (i = 0; i < size; i++) {
76b91bac787101e6b0075122ab6478dd98c8a884Timo Sirainen if (strcmp(extensions[i].name, name) == 0)
76b91bac787101e6b0075122ab6478dd98c8a884Timo Sirainen return i;
76b91bac787101e6b0075122ab6478dd98c8a884Timo Sirainen }
3fe67ec75ccae1230bb9eb9f16affc48377f6441Timo Sirainen return (uint32_t)-1;
eaa2d473ed2ecdb9856cd98a33f4d3063cfaf2a1Timo Sirainen}
eaa2d473ed2ecdb9856cd98a33f4d3063cfaf2a1Timo Sirainen
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainenuint32_t
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainenmail_index_map_register_ext(struct mail_index *index,
2a6dcd984104fed84bed8795ccdfabb20e41ce52Timo Sirainen struct mail_index_map *map, const char *name,
2a6dcd984104fed84bed8795ccdfabb20e41ce52Timo Sirainen uint32_t hdr_offset, uint32_t hdr_size,
2a6dcd984104fed84bed8795ccdfabb20e41ce52Timo Sirainen uint32_t record_offset, uint32_t record_size,
2a6dcd984104fed84bed8795ccdfabb20e41ce52Timo Sirainen uint32_t record_align, uint32_t reset_id)
2a6dcd984104fed84bed8795ccdfabb20e41ce52Timo Sirainen{
5da1aa5197a43d83f0fb3eeb83125c7cd73d1b62Timo Sirainen struct mail_index_ext *ext;
5da1aa5197a43d83f0fb3eeb83125c7cd73d1b62Timo Sirainen uint32_t idx, ext_id, empty_id = (uint32_t)-1;
5da1aa5197a43d83f0fb3eeb83125c7cd73d1b62Timo Sirainen
638600575ee95f2513c683ef09cb188f76eacd22Timo Sirainen if (map->extensions == NULL) {
638600575ee95f2513c683ef09cb188f76eacd22Timo Sirainen mail_index_map_init_extbufs(map, 5);
638600575ee95f2513c683ef09cb188f76eacd22Timo Sirainen idx = 0;
2a6dcd984104fed84bed8795ccdfabb20e41ce52Timo Sirainen } else {
2a6dcd984104fed84bed8795ccdfabb20e41ce52Timo Sirainen idx = map->extensions->used / sizeof(*ext);
2a6dcd984104fed84bed8795ccdfabb20e41ce52Timo Sirainen }
2a6dcd984104fed84bed8795ccdfabb20e41ce52Timo Sirainen
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen ext = buffer_append_space_unsafe(map->extensions, sizeof(*ext));
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen memset(ext, 0, sizeof(*ext));
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen ext->name = p_strdup(map->extension_pool, name);
fa780a18c41881036af582f7a3473d6399e9d34dTimo Sirainen ext->hdr_offset = hdr_offset;
fa780a18c41881036af582f7a3473d6399e9d34dTimo Sirainen ext->hdr_size = hdr_size;
49c48631cfd07017d5f93d83713fffe4f13730c4Timo Sirainen ext->record_offset = record_offset;
49c48631cfd07017d5f93d83713fffe4f13730c4Timo Sirainen ext->record_size = record_size;
5214b67a7dabab87da74e04bb8b227f94b95bce4Timo Sirainen ext->record_align = record_align;
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen ext->reset_id = reset_id;
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen ext_id = mail_index_ext_register(index, name, hdr_size,
27586e4785d56aeb76e1fd96af8db799688dc64aTimo Sirainen record_size, record_align);
360123b1b41b7aa8af6c4a91c39046be646cd349Timo Sirainen ext->index_idx = ext_id;
fd8b93ca5cbeba64fe6fa5dc98a3e580fb046791Timo Sirainen
12b4dbf933ee54f7b96968ba150095baa985fdafTimo Sirainen while (map->ext_id_map->used < ext_id * sizeof(uint32_t))
12b4dbf933ee54f7b96968ba150095baa985fdafTimo Sirainen buffer_append(map->ext_id_map, &empty_id, sizeof(empty_id));
1728ff34ee03de825ad3aeed67d19f8ae140ee2eTimo Sirainen buffer_write(map->ext_id_map, ext_id * sizeof(uint32_t),
eaa2d473ed2ecdb9856cd98a33f4d3063cfaf2a1Timo Sirainen &idx, sizeof(idx));
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen return idx;
5214b67a7dabab87da74e04bb8b227f94b95bce4Timo Sirainen}
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainenstatic int size_check(size_t *size_left, size_t size)
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen{
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen if (size > *size_left)
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen return FALSE;
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen *size_left -= size;
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen return TRUE;
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen}
f0d09be40bd0c4423873128ae2f88a4020075dc4Timo Sirainen
f0d09be40bd0c4423873128ae2f88a4020075dc4Timo Sirainenstatic size_t get_align(size_t name_len)
1c1cecd3dfaf71b0c9499b044023e631841e88aaTimo Sirainen{
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen size_t size = sizeof(struct mail_index_ext_header) + name_len;
917498e6f84969d2b93410c1e479735abe8e0ed7Timo Sirainen return MAIL_INDEX_HEADER_SIZE_ALIGN(size) - size;
917498e6f84969d2b93410c1e479735abe8e0ed7Timo Sirainen}
917498e6f84969d2b93410c1e479735abe8e0ed7Timo Sirainen
917498e6f84969d2b93410c1e479735abe8e0ed7Timo Sirainenstatic int mail_index_read_extensions(struct mail_index *index,
917498e6f84969d2b93410c1e479735abe8e0ed7Timo Sirainen struct mail_index_map *map)
917498e6f84969d2b93410c1e479735abe8e0ed7Timo Sirainen{
917498e6f84969d2b93410c1e479735abe8e0ed7Timo Sirainen const struct mail_index_ext_header *ext_hdr;
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen unsigned int i, old_count;
5da1aa5197a43d83f0fb3eeb83125c7cd73d1b62Timo Sirainen const char *name;
e5acc283bf030b0b5c79ca4e52d315c516a299faPascal Volk uint32_t ext_id, offset, name_offset;
e5acc283bf030b0b5c79ca4e52d315c516a299faPascal Volk size_t size_left;
e5acc283bf030b0b5c79ca4e52d315c516a299faPascal Volk
5da1aa5197a43d83f0fb3eeb83125c7cd73d1b62Timo Sirainen /* extension headers always start from 64bit offsets, so if base header
e5acc283bf030b0b5c79ca4e52d315c516a299faPascal Volk doesn't happen to be 64bit aligned we'll skip some bytes */
e5acc283bf030b0b5c79ca4e52d315c516a299faPascal Volk offset = MAIL_INDEX_HEADER_SIZE_ALIGN(map->hdr.base_header_size);
e5acc283bf030b0b5c79ca4e52d315c516a299faPascal Volk if (offset >= map->hdr.header_size && map->extension_pool == NULL) {
7920a47321690c932ffd4d286cd16b4048d22d41Timo Sirainen /* nothing to do, skip allocatations and all */
7920a47321690c932ffd4d286cd16b4048d22d41Timo Sirainen return 1;
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen }
db8b0a3f74a20528d66a3c4be7df920e5c4554c2Timo Sirainen
db8b0a3f74a20528d66a3c4be7df920e5c4554c2Timo Sirainen old_count = index->extensions->used / sizeof(struct mail_index_ext);
db8b0a3f74a20528d66a3c4be7df920e5c4554c2Timo Sirainen mail_index_map_init_extbufs(map, old_count + 5);
db8b0a3f74a20528d66a3c4be7df920e5c4554c2Timo Sirainen
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen ext_id = (uint32_t)-1;
5666a3d6a7ea89362b8d9e8b39b15424cd9d6388Timo Sirainen for (i = 0; i < old_count; i++)
1701e3f91107051b1704721bf1dc1e32491faaf9Timo Sirainen buffer_append(map->ext_id_map, &ext_id, sizeof(ext_id));
1701e3f91107051b1704721bf1dc1e32491faaf9Timo Sirainen
1701e3f91107051b1704721bf1dc1e32491faaf9Timo Sirainen while (offset < map->hdr.header_size) {
0bf25546c91ccafff9e2cc93368d2d25acb5c39eTimo Sirainen ext_hdr = CONST_PTR_OFFSET(map->hdr_base, offset);
94b0ff77495c3ed14bdd4b5d7ae1eb37e8c9efb5Timo Sirainen
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen size_left = map->hdr.header_size - offset;
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen if (!size_check(&size_left, sizeof(*ext_hdr)) ||
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen !size_check(&size_left, ext_hdr->name_size) ||
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen !size_check(&size_left, get_align(ext_hdr->name_size)) ||
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen !size_check(&size_left, ext_hdr->hdr_size)) {
0bf25546c91ccafff9e2cc93368d2d25acb5c39eTimo Sirainen mail_index_set_error(index, "Corrupted index file %s: "
0bf25546c91ccafff9e2cc93368d2d25acb5c39eTimo Sirainen "Header extension goes outside header",
0bf25546c91ccafff9e2cc93368d2d25acb5c39eTimo Sirainen index->filepath);
94b0ff77495c3ed14bdd4b5d7ae1eb37e8c9efb5Timo Sirainen return -1;
94b0ff77495c3ed14bdd4b5d7ae1eb37e8c9efb5Timo Sirainen }
94b0ff77495c3ed14bdd4b5d7ae1eb37e8c9efb5Timo Sirainen offset += sizeof(*ext_hdr);
94b0ff77495c3ed14bdd4b5d7ae1eb37e8c9efb5Timo Sirainen name_offset = offset;
94b0ff77495c3ed14bdd4b5d7ae1eb37e8c9efb5Timo Sirainen offset += ext_hdr->name_size + get_align(ext_hdr->name_size);
94b0ff77495c3ed14bdd4b5d7ae1eb37e8c9efb5Timo Sirainen
94b0ff77495c3ed14bdd4b5d7ae1eb37e8c9efb5Timo Sirainen t_push();
94b0ff77495c3ed14bdd4b5d7ae1eb37e8c9efb5Timo Sirainen name = t_strndup(CONST_PTR_OFFSET(map->hdr_base, name_offset),
94b0ff77495c3ed14bdd4b5d7ae1eb37e8c9efb5Timo Sirainen ext_hdr->name_size);
b365bd121cdc87f63e1dd47c5085a27091118e00Timo Sirainen mail_index_map_register_ext(index, map, name,
94b0ff77495c3ed14bdd4b5d7ae1eb37e8c9efb5Timo Sirainen offset, ext_hdr->hdr_size,
94b0ff77495c3ed14bdd4b5d7ae1eb37e8c9efb5Timo Sirainen ext_hdr->record_offset,
94b0ff77495c3ed14bdd4b5d7ae1eb37e8c9efb5Timo Sirainen ext_hdr->record_size,
94b0ff77495c3ed14bdd4b5d7ae1eb37e8c9efb5Timo Sirainen ext_hdr->record_align,
94b0ff77495c3ed14bdd4b5d7ae1eb37e8c9efb5Timo Sirainen ext_hdr->reset_id);
02e61e13a8360a9d3ec92c5fa5ae60c0f0181b71Timo Sirainen t_pop();
02e61e13a8360a9d3ec92c5fa5ae60c0f0181b71Timo Sirainen
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen offset += MAIL_INDEX_HEADER_SIZE_ALIGN(ext_hdr->hdr_size);
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen }
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen return 1;
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen}
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainenstatic int mail_index_check_header(struct mail_index *index,
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen struct mail_index_map *map)
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen{
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen const struct mail_index_header *hdr = &map->hdr;
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen unsigned char compat_data[sizeof(hdr->compat_data)];
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen
5c597df6aa8d81de4053c6986fab7739f3b44b20Timo Sirainen memset(compat_data, 0, sizeof(compat_data));
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen#ifndef WORDS_BIGENDIAN
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen compat_data[0] = MAIL_INDEX_COMPAT_LITTLE_ENDIAN;
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen#endif
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen compat_data[1] = sizeof(uoff_t);
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen compat_data[2] = sizeof(time_t);
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen if (hdr->major_version != MAIL_INDEX_MAJOR_VERSION) {
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen /* major version change - handle silently(?) */
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen return -1;
33525312d3f45995686aa0b538dea1cd6eb936e2Timo Sirainen }
33525312d3f45995686aa0b538dea1cd6eb936e2Timo Sirainen if (memcmp(hdr->compat_data, compat_data, sizeof(compat_data)) != 0) {
efe78d3ba24fc866af1c79b9223dc0809ba26cadStephan Bosch /* architecture change - handle silently(?) */
33525312d3f45995686aa0b538dea1cd6eb936e2Timo Sirainen return -1;
33525312d3f45995686aa0b538dea1cd6eb936e2Timo Sirainen }
fa780a18c41881036af582f7a3473d6399e9d34dTimo Sirainen
33525312d3f45995686aa0b538dea1cd6eb936e2Timo Sirainen if ((map->hdr.flags & MAIL_INDEX_HDR_FLAG_CORRUPTED) != 0) {
33525312d3f45995686aa0b538dea1cd6eb936e2Timo Sirainen /* we've already complained about it */
0bf25546c91ccafff9e2cc93368d2d25acb5c39eTimo Sirainen return -1;
0bf25546c91ccafff9e2cc93368d2d25acb5c39eTimo Sirainen }
0bf25546c91ccafff9e2cc93368d2d25acb5c39eTimo Sirainen
0bf25546c91ccafff9e2cc93368d2d25acb5c39eTimo Sirainen /* following some extra checks that only take a bit of CPU */
0bf25546c91ccafff9e2cc93368d2d25acb5c39eTimo Sirainen if (hdr->uid_validity == 0 && hdr->next_uid != 1) {
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen mail_index_set_error(index, "Corrupted index file %s: "
49c48631cfd07017d5f93d83713fffe4f13730c4Timo Sirainen "uid_validity = 0, next_uid = %u",
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen index->filepath, hdr->next_uid);
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen return -1;
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen }
33525312d3f45995686aa0b538dea1cd6eb936e2Timo Sirainen
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen if (hdr->keywords_mask_size != sizeof(keywords_mask_t)) {
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen mail_index_set_error(index, "Corrupted index file %s: "
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen "keywords_mask_size mismatch: %d != %d",
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen index->filepath, hdr->keywords_mask_size,
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen (int)sizeof(keywords_mask_t));
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen return -1;
0bf25546c91ccafff9e2cc93368d2d25acb5c39eTimo Sirainen }
94b0ff77495c3ed14bdd4b5d7ae1eb37e8c9efb5Timo Sirainen
02e61e13a8360a9d3ec92c5fa5ae60c0f0181b71Timo Sirainen if (hdr->record_size < sizeof(struct mail_index_record)) {
02e61e13a8360a9d3ec92c5fa5ae60c0f0181b71Timo Sirainen mail_index_set_error(index, "Corrupted index file %s: "
c58c12049c883b281c088d47a2a7278c21c390e1Timo Sirainen "record_size too small: %u < %"PRIuSIZE_T,
c58c12049c883b281c088d47a2a7278c21c390e1Timo Sirainen index->filepath, hdr->record_size,
c58c12049c883b281c088d47a2a7278c21c390e1Timo Sirainen sizeof(struct mail_index_record));
c58c12049c883b281c088d47a2a7278c21c390e1Timo Sirainen return -1;
c58c12049c883b281c088d47a2a7278c21c390e1Timo Sirainen }
c58c12049c883b281c088d47a2a7278c21c390e1Timo Sirainen
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen if (hdr->next_uid == 0)
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen return 0;
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen
1c1cecd3dfaf71b0c9499b044023e631841e88aaTimo Sirainen if (hdr->recent_messages_count > hdr->messages_count ||
1c1cecd3dfaf71b0c9499b044023e631841e88aaTimo Sirainen hdr->seen_messages_count > hdr->messages_count ||
1c1cecd3dfaf71b0c9499b044023e631841e88aaTimo Sirainen hdr->deleted_messages_count > hdr->messages_count)
1c1cecd3dfaf71b0c9499b044023e631841e88aaTimo Sirainen return 0;
1c1cecd3dfaf71b0c9499b044023e631841e88aaTimo Sirainen if (hdr->first_recent_uid_lowwater > hdr->next_uid ||
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen hdr->first_unseen_uid_lowwater > hdr->next_uid ||
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen hdr->first_deleted_uid_lowwater > hdr->next_uid)
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen return 0;
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen return mail_index_read_extensions(index, map);
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen}
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainenstatic void mail_index_map_clear(struct mail_index *index,
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen struct mail_index_map *map)
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen{
b365bd121cdc87f63e1dd47c5085a27091118e00Timo Sirainen if (map->buffer != NULL) {
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen i_assert(map->mmap_base == NULL);
b365bd121cdc87f63e1dd47c5085a27091118e00Timo Sirainen buffer_free(map->buffer);
5da1aa5197a43d83f0fb3eeb83125c7cd73d1b62Timo Sirainen map->buffer = NULL;
5da1aa5197a43d83f0fb3eeb83125c7cd73d1b62Timo Sirainen } else if (map->mmap_base != NULL) {
638600575ee95f2513c683ef09cb188f76eacd22Timo Sirainen i_assert(map->buffer == NULL);
638600575ee95f2513c683ef09cb188f76eacd22Timo Sirainen if (munmap(map->mmap_base, map->mmap_size) < 0)
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen mail_index_set_syscall_error(index, "munmap()");
b365bd121cdc87f63e1dd47c5085a27091118e00Timo Sirainen map->mmap_base = NULL;
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen }
b365bd121cdc87f63e1dd47c5085a27091118e00Timo Sirainen
360123b1b41b7aa8af6c4a91c39046be646cd349Timo Sirainen if (map->refcount > 0) {
360123b1b41b7aa8af6c4a91c39046be646cd349Timo Sirainen memset(&map->hdr, 0, sizeof(map->hdr));
360123b1b41b7aa8af6c4a91c39046be646cd349Timo Sirainen map->mmap_size = 0;
360123b1b41b7aa8af6c4a91c39046be646cd349Timo Sirainen map->mmap_used_size = 0;
b365bd121cdc87f63e1dd47c5085a27091118e00Timo Sirainen map->records = NULL;
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen map->records_count = 0;
b365bd121cdc87f63e1dd47c5085a27091118e00Timo Sirainen }
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen}
b365bd121cdc87f63e1dd47c5085a27091118e00Timo Sirainen
5494a6bc149da8f02fd25c0434a9d612ac33f659Timo Sirainenvoid mail_index_unmap(struct mail_index *index, struct mail_index_map *map)
b365bd121cdc87f63e1dd47c5085a27091118e00Timo Sirainen{
fd8b93ca5cbeba64fe6fa5dc98a3e580fb046791Timo Sirainen if (--map->refcount > 0)
fd8b93ca5cbeba64fe6fa5dc98a3e580fb046791Timo Sirainen return;
fa780a18c41881036af582f7a3473d6399e9d34dTimo Sirainen
fa780a18c41881036af582f7a3473d6399e9d34dTimo Sirainen i_assert(map->refcount == 0);
12b4dbf933ee54f7b96968ba150095baa985fdafTimo Sirainen mail_index_map_clear(index, map);
12b4dbf933ee54f7b96968ba150095baa985fdafTimo Sirainen if (map->extension_pool != NULL)
12b4dbf933ee54f7b96968ba150095baa985fdafTimo Sirainen pool_unref(map->extension_pool);
7d2d0ae1131c8b632cc7e86000adaaf8c9ef42a9Timo Sirainen buffer_free(map->hdr_copy_buf);
7d2d0ae1131c8b632cc7e86000adaaf8c9ef42a9Timo Sirainen i_free(map);
7d2d0ae1131c8b632cc7e86000adaaf8c9ef42a9Timo Sirainen}
7d2d0ae1131c8b632cc7e86000adaaf8c9ef42a9Timo Sirainen
7d2d0ae1131c8b632cc7e86000adaaf8c9ef42a9Timo Sirainenstatic void mail_index_unmap_forced(struct mail_index *index,
7d2d0ae1131c8b632cc7e86000adaaf8c9ef42a9Timo Sirainen struct mail_index_map *map)
7d2d0ae1131c8b632cc7e86000adaaf8c9ef42a9Timo Sirainen{
1728ff34ee03de825ad3aeed67d19f8ae140ee2eTimo Sirainen mail_index_map_clear(index, map);
1728ff34ee03de825ad3aeed67d19f8ae140ee2eTimo Sirainen mail_index_unmap(index, map);
1728ff34ee03de825ad3aeed67d19f8ae140ee2eTimo Sirainen}
eaa2d473ed2ecdb9856cd98a33f4d3063cfaf2a1Timo Sirainen
eaa2d473ed2ecdb9856cd98a33f4d3063cfaf2a1Timo Sirainenstatic void mail_index_map_copy_hdr(struct mail_index_map *map,
eaa2d473ed2ecdb9856cd98a33f4d3063cfaf2a1Timo Sirainen const struct mail_index_header *hdr)
655fc45da67a4cfa63d9d12cf106961a1afc12b9Aki Tuomi{
655fc45da67a4cfa63d9d12cf106961a1afc12b9Aki Tuomi if (hdr->base_header_size < sizeof(map->hdr)) {
655fc45da67a4cfa63d9d12cf106961a1afc12b9Aki Tuomi /* header smaller than ours, make a copy so our newer headers
12b4dbf933ee54f7b96968ba150095baa985fdafTimo Sirainen won't have garbage in them */
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen memset(&map->hdr, 0, sizeof(map->hdr));
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen memcpy(&map->hdr, hdr, hdr->base_header_size);
02e61e13a8360a9d3ec92c5fa5ae60c0f0181b71Timo Sirainen } else {
0bf25546c91ccafff9e2cc93368d2d25acb5c39eTimo Sirainen map->hdr = *hdr;
94b0ff77495c3ed14bdd4b5d7ae1eb37e8c9efb5Timo Sirainen }
02e61e13a8360a9d3ec92c5fa5ae60c0f0181b71Timo Sirainen}
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainenstatic int mail_index_mmap(struct mail_index *index, struct mail_index_map *map)
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen{
b365bd121cdc87f63e1dd47c5085a27091118e00Timo Sirainen const struct mail_index_header *hdr;
b365bd121cdc87f63e1dd47c5085a27091118e00Timo Sirainen unsigned int records_count;
1728ff34ee03de825ad3aeed67d19f8ae140ee2eTimo Sirainen
1728ff34ee03de825ad3aeed67d19f8ae140ee2eTimo Sirainen i_assert(!map->write_to_disk);
1728ff34ee03de825ad3aeed67d19f8ae140ee2eTimo Sirainen
1728ff34ee03de825ad3aeed67d19f8ae140ee2eTimo Sirainen if (map->buffer != NULL) {
1728ff34ee03de825ad3aeed67d19f8ae140ee2eTimo Sirainen /* we had temporarily used a buffer, eg. for updating index */
49c48631cfd07017d5f93d83713fffe4f13730c4Timo Sirainen buffer_free(map->buffer);
49c48631cfd07017d5f93d83713fffe4f13730c4Timo Sirainen map->buffer = NULL;
49c48631cfd07017d5f93d83713fffe4f13730c4Timo Sirainen }
49c48631cfd07017d5f93d83713fffe4f13730c4Timo Sirainen
49c48631cfd07017d5f93d83713fffe4f13730c4Timo Sirainen map->mmap_base = index->readonly ?
49c48631cfd07017d5f93d83713fffe4f13730c4Timo Sirainen mmap_ro_file(index->fd, &map->mmap_size) :
49c48631cfd07017d5f93d83713fffe4f13730c4Timo Sirainen mmap_rw_file(index->fd, &map->mmap_size);
49c48631cfd07017d5f93d83713fffe4f13730c4Timo Sirainen if (map->mmap_base == MAP_FAILED) {
49c48631cfd07017d5f93d83713fffe4f13730c4Timo Sirainen map->mmap_base = NULL;
49c48631cfd07017d5f93d83713fffe4f13730c4Timo Sirainen mail_index_set_syscall_error(index, "mmap()");
49c48631cfd07017d5f93d83713fffe4f13730c4Timo Sirainen return -1;
49c48631cfd07017d5f93d83713fffe4f13730c4Timo Sirainen }
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen hdr = map->mmap_base;
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen if (map->mmap_size >
0bf25546c91ccafff9e2cc93368d2d25acb5c39eTimo Sirainen offsetof(struct mail_index_header, major_version) &&
0bf25546c91ccafff9e2cc93368d2d25acb5c39eTimo Sirainen hdr->major_version != MAIL_INDEX_MAJOR_VERSION) {
0bf25546c91ccafff9e2cc93368d2d25acb5c39eTimo Sirainen /* major version change - handle silently */
0bf25546c91ccafff9e2cc93368d2d25acb5c39eTimo Sirainen return 0;
0bf25546c91ccafff9e2cc93368d2d25acb5c39eTimo Sirainen }
0bf25546c91ccafff9e2cc93368d2d25acb5c39eTimo Sirainen
0bf25546c91ccafff9e2cc93368d2d25acb5c39eTimo Sirainen if (map->mmap_size < MAIL_INDEX_HEADER_MIN_SIZE) {
0bf25546c91ccafff9e2cc93368d2d25acb5c39eTimo Sirainen mail_index_set_error(index, "Corrupted index file %s: "
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen "File too small (%"PRIuSIZE_T")",
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen index->filepath, map->mmap_size);
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen return 0;
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen }
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen map->mmap_used_size = hdr->header_size +
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen hdr->messages_count * hdr->record_size;
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen if (map->mmap_used_size > map->mmap_size) {
94d8e51119003d2bc5a100c663f90141f297385dTimo Sirainen records_count = (map->mmap_size - hdr->header_size) /
1433bf361ddb0bba8878c8ada5726d0284edad57Timo Sirainen hdr->record_size;
1433bf361ddb0bba8878c8ada5726d0284edad57Timo Sirainen mail_index_set_error(index, "Corrupted index file %s: "
1433bf361ddb0bba8878c8ada5726d0284edad57Timo Sirainen "messages_count too large (%u > %u)",
1433bf361ddb0bba8878c8ada5726d0284edad57Timo Sirainen index->filepath, hdr->messages_count,
94d8e51119003d2bc5a100c663f90141f297385dTimo Sirainen records_count);
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen return 0;
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen }
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen mail_index_map_copy_hdr(map, hdr);
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen map->hdr_base = map->mmap_base;
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen map->records = PTR_OFFSET(map->mmap_base, map->hdr.header_size);
94d8e51119003d2bc5a100c663f90141f297385dTimo Sirainen map->records_count = map->hdr.messages_count;
4a514fb20e04df397842cde11cc9ea92abfe9728Timo Sirainen return 1;
94d8e51119003d2bc5a100c663f90141f297385dTimo Sirainen}
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainenstatic int mail_index_read_header(struct mail_index *index,
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen struct mail_index_header *hdr, size_t *pos_r)
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen{
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen size_t pos;
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen int ret;
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen memset(hdr, 0, sizeof(*hdr));
0bf25546c91ccafff9e2cc93368d2d25acb5c39eTimo Sirainen
0bf25546c91ccafff9e2cc93368d2d25acb5c39eTimo Sirainen ret = 1;
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen for (pos = 0; ret > 0 && pos < sizeof(*hdr); ) {
d9a7e950a9cd21f2b4a90ec7759fca9e8fcc7995Timo Sirainen ret = pread(index->fd, PTR_OFFSET(hdr, pos),
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen sizeof(*hdr) - pos, pos);
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen if (ret > 0)
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen pos += ret;
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen }
d508ab8db2b0f74b5e225d199b4aaa5293342746Timo Sirainen *pos_r = pos;
d508ab8db2b0f74b5e225d199b4aaa5293342746Timo Sirainen return ret;
2ac5f36aa7c2e7a07ba8815d43a6d7483f62e74cTimo Sirainen}
d508ab8db2b0f74b5e225d199b4aaa5293342746Timo Sirainen
d508ab8db2b0f74b5e225d199b4aaa5293342746Timo Sirainenstatic int mail_index_read_map(struct mail_index *index,
d508ab8db2b0f74b5e225d199b4aaa5293342746Timo Sirainen struct mail_index_map *map, int *retry_r)
d508ab8db2b0f74b5e225d199b4aaa5293342746Timo Sirainen{
d508ab8db2b0f74b5e225d199b4aaa5293342746Timo Sirainen struct mail_index_header hdr;
d508ab8db2b0f74b5e225d199b4aaa5293342746Timo Sirainen void *data = NULL;
d508ab8db2b0f74b5e225d199b4aaa5293342746Timo Sirainen ssize_t ret;
d508ab8db2b0f74b5e225d199b4aaa5293342746Timo Sirainen size_t pos, records_size;
d508ab8db2b0f74b5e225d199b4aaa5293342746Timo Sirainen
d508ab8db2b0f74b5e225d199b4aaa5293342746Timo Sirainen i_assert(map->mmap_base == NULL);
d508ab8db2b0f74b5e225d199b4aaa5293342746Timo Sirainen
d508ab8db2b0f74b5e225d199b4aaa5293342746Timo Sirainen *retry_r = FALSE;
d508ab8db2b0f74b5e225d199b4aaa5293342746Timo Sirainen ret = mail_index_read_header(index, &hdr, &pos);
d508ab8db2b0f74b5e225d199b4aaa5293342746Timo Sirainen
d508ab8db2b0f74b5e225d199b4aaa5293342746Timo Sirainen if (pos > (ssize_t)offsetof(struct mail_index_header, major_version) &&
d508ab8db2b0f74b5e225d199b4aaa5293342746Timo Sirainen hdr.major_version != MAIL_INDEX_MAJOR_VERSION) {
d3e5a14ea363264dcc7640ca7226249d0c27a793Timo Sirainen /* major version change - handle silently */
a4e2101473cfd7ce960fc49b3ce097c3f89ec2adTimo Sirainen return 0;
a4e2101473cfd7ce960fc49b3ce097c3f89ec2adTimo Sirainen }
a4e2101473cfd7ce960fc49b3ce097c3f89ec2adTimo Sirainen
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen if (ret >= 0 && pos >= MAIL_INDEX_HEADER_MIN_SIZE &&
2ac5f36aa7c2e7a07ba8815d43a6d7483f62e74cTimo Sirainen (ret > 0 || pos >= hdr.base_header_size)) {
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen if (hdr.base_header_size < MAIL_INDEX_HEADER_MIN_SIZE ||
d9a7e950a9cd21f2b4a90ec7759fca9e8fcc7995Timo Sirainen hdr.header_size < hdr.base_header_size) {
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen mail_index_set_error(index, "Corrupted index file %s: "
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen "Corrupted header sizes (base %u, full %u)",
a4e2101473cfd7ce960fc49b3ce097c3f89ec2adTimo Sirainen index->filepath, hdr.base_header_size,
a4e2101473cfd7ce960fc49b3ce097c3f89ec2adTimo Sirainen hdr.header_size);
a4e2101473cfd7ce960fc49b3ce097c3f89ec2adTimo Sirainen return 0;
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen }
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen buffer_reset(map->hdr_copy_buf);
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen buffer_append(map->hdr_copy_buf, &hdr, hdr.base_header_size);
a4e2101473cfd7ce960fc49b3ce097c3f89ec2adTimo Sirainen
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen /* @UNSAFE */
d508ab8db2b0f74b5e225d199b4aaa5293342746Timo Sirainen data = buffer_append_space_unsafe(map->hdr_copy_buf,
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen hdr.header_size -
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen hdr.base_header_size);
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen ret = pread_full(index->fd, data,
6f970b9a0dadb80e120d017c75c637b5a3879dacTimo Sirainen hdr.header_size - hdr.base_header_size,
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen hdr.base_header_size);
a4e2101473cfd7ce960fc49b3ce097c3f89ec2adTimo Sirainen }
d508ab8db2b0f74b5e225d199b4aaa5293342746Timo Sirainen
d508ab8db2b0f74b5e225d199b4aaa5293342746Timo Sirainen if (ret > 0) {
a4e2101473cfd7ce960fc49b3ce097c3f89ec2adTimo Sirainen records_size = hdr.messages_count * hdr.record_size;
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen
a4e2101473cfd7ce960fc49b3ce097c3f89ec2adTimo Sirainen if (map->buffer == NULL) {
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen map->buffer = buffer_create_dynamic(default_pool,
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen records_size);
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen }
d508ab8db2b0f74b5e225d199b4aaa5293342746Timo Sirainen
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen /* @UNSAFE */
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen buffer_set_used_size(map->buffer, 0);
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen data = buffer_append_space_unsafe(map->buffer, records_size);
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen
a4e2101473cfd7ce960fc49b3ce097c3f89ec2adTimo Sirainen ret = pread_full(index->fd, data, records_size,
a4e2101473cfd7ce960fc49b3ce097c3f89ec2adTimo Sirainen hdr.header_size);
a4e2101473cfd7ce960fc49b3ce097c3f89ec2adTimo Sirainen }
a4e2101473cfd7ce960fc49b3ce097c3f89ec2adTimo Sirainen
a4e2101473cfd7ce960fc49b3ce097c3f89ec2adTimo Sirainen if (ret < 0) {
a4e2101473cfd7ce960fc49b3ce097c3f89ec2adTimo Sirainen if (errno == ESTALE) {
a4e2101473cfd7ce960fc49b3ce097c3f89ec2adTimo Sirainen *retry_r = TRUE;
a4e2101473cfd7ce960fc49b3ce097c3f89ec2adTimo Sirainen return 0;
a4e2101473cfd7ce960fc49b3ce097c3f89ec2adTimo Sirainen }
69af83d4e6c2c5c825a17edd7a41a4fb014caa8fTimo Sirainen mail_index_set_syscall_error(index, "pread_full()");
69af83d4e6c2c5c825a17edd7a41a4fb014caa8fTimo Sirainen return -1;
69af83d4e6c2c5c825a17edd7a41a4fb014caa8fTimo Sirainen }
69af83d4e6c2c5c825a17edd7a41a4fb014caa8fTimo Sirainen if (ret == 0) {
69af83d4e6c2c5c825a17edd7a41a4fb014caa8fTimo Sirainen mail_index_set_error(index,
69af83d4e6c2c5c825a17edd7a41a4fb014caa8fTimo Sirainen "Corrupted index file %s: File too small",
69af83d4e6c2c5c825a17edd7a41a4fb014caa8fTimo Sirainen index->filepath);
69af83d4e6c2c5c825a17edd7a41a4fb014caa8fTimo Sirainen return 0;
69af83d4e6c2c5c825a17edd7a41a4fb014caa8fTimo Sirainen }
69af83d4e6c2c5c825a17edd7a41a4fb014caa8fTimo Sirainen
69af83d4e6c2c5c825a17edd7a41a4fb014caa8fTimo Sirainen map->records = data;
69af83d4e6c2c5c825a17edd7a41a4fb014caa8fTimo Sirainen map->records_count = hdr.messages_count;
69af83d4e6c2c5c825a17edd7a41a4fb014caa8fTimo Sirainen
69af83d4e6c2c5c825a17edd7a41a4fb014caa8fTimo Sirainen mail_index_map_copy_hdr(map, &hdr);
69af83d4e6c2c5c825a17edd7a41a4fb014caa8fTimo Sirainen map->hdr_base = map->hdr_copy_buf->data;
69af83d4e6c2c5c825a17edd7a41a4fb014caa8fTimo Sirainen
69af83d4e6c2c5c825a17edd7a41a4fb014caa8fTimo Sirainen index->sync_log_file_seq = hdr.log_file_seq;
69af83d4e6c2c5c825a17edd7a41a4fb014caa8fTimo Sirainen index->sync_log_file_offset = hdr.log_file_int_offset;
69af83d4e6c2c5c825a17edd7a41a4fb014caa8fTimo Sirainen return 1;
69af83d4e6c2c5c825a17edd7a41a4fb014caa8fTimo Sirainen}
69af83d4e6c2c5c825a17edd7a41a4fb014caa8fTimo Sirainen
69af83d4e6c2c5c825a17edd7a41a4fb014caa8fTimo Sirainenstatic int mail_index_sync_from_transactions(struct mail_index *index,
69af83d4e6c2c5c825a17edd7a41a4fb014caa8fTimo Sirainen struct mail_index_map **map,
69af83d4e6c2c5c825a17edd7a41a4fb014caa8fTimo Sirainen int sync_to_index)
69af83d4e6c2c5c825a17edd7a41a4fb014caa8fTimo Sirainen{
69af83d4e6c2c5c825a17edd7a41a4fb014caa8fTimo Sirainen const struct mail_index_header *map_hdr = &(*map)->hdr;
69af83d4e6c2c5c825a17edd7a41a4fb014caa8fTimo Sirainen struct mail_index_view *view;
69af83d4e6c2c5c825a17edd7a41a4fb014caa8fTimo Sirainen struct mail_transaction_log_view *log_view;
69af83d4e6c2c5c825a17edd7a41a4fb014caa8fTimo Sirainen struct mail_index_sync_map_ctx sync_map_ctx;
69af83d4e6c2c5c825a17edd7a41a4fb014caa8fTimo Sirainen struct mail_index_header hdr;
69af83d4e6c2c5c825a17edd7a41a4fb014caa8fTimo Sirainen const struct mail_transaction_header *thdr;
69af83d4e6c2c5c825a17edd7a41a4fb014caa8fTimo Sirainen const void *tdata;
69af83d4e6c2c5c825a17edd7a41a4fb014caa8fTimo Sirainen uint32_t max_seq;
69af83d4e6c2c5c825a17edd7a41a4fb014caa8fTimo Sirainen uoff_t max_offset;
69af83d4e6c2c5c825a17edd7a41a4fb014caa8fTimo Sirainen size_t pos;
69af83d4e6c2c5c825a17edd7a41a4fb014caa8fTimo Sirainen int ret, skipped;
69af83d4e6c2c5c825a17edd7a41a4fb014caa8fTimo Sirainen
69af83d4e6c2c5c825a17edd7a41a4fb014caa8fTimo Sirainen if (sync_to_index) {
69af83d4e6c2c5c825a17edd7a41a4fb014caa8fTimo Sirainen /* read the real log position where we are supposed to be
69af83d4e6c2c5c825a17edd7a41a4fb014caa8fTimo Sirainen synced */
69af83d4e6c2c5c825a17edd7a41a4fb014caa8fTimo Sirainen ret = mail_index_read_header(index, &hdr, &pos);
69af83d4e6c2c5c825a17edd7a41a4fb014caa8fTimo Sirainen if (ret < 0 && errno != ESTALE) {
69af83d4e6c2c5c825a17edd7a41a4fb014caa8fTimo Sirainen mail_index_set_syscall_error(index, "pread()");
69af83d4e6c2c5c825a17edd7a41a4fb014caa8fTimo Sirainen return -1;
69af83d4e6c2c5c825a17edd7a41a4fb014caa8fTimo Sirainen }
69af83d4e6c2c5c825a17edd7a41a4fb014caa8fTimo Sirainen if (pos < MAIL_INDEX_HEADER_MIN_SIZE)
69af83d4e6c2c5c825a17edd7a41a4fb014caa8fTimo Sirainen return 0;
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen if (map_hdr->log_file_seq == hdr.log_file_seq &&
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen map_hdr->log_file_int_offset == hdr.log_file_int_offset) {
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen /* nothing to do */
2ac5f36aa7c2e7a07ba8815d43a6d7483f62e74cTimo Sirainen return 1;
636f017be100bce67d66fd3ae1544a47681efd33Timo Sirainen }
636f017be100bce67d66fd3ae1544a47681efd33Timo Sirainen
69af83d4e6c2c5c825a17edd7a41a4fb014caa8fTimo Sirainen if (map_hdr->log_file_seq > hdr.log_file_seq ||
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen (map_hdr->log_file_seq == hdr.log_file_seq &&
e58f291e777b25c1286965b80e142ada6fdacb03Timo Sirainen map_hdr->log_file_int_offset > hdr.log_file_int_offset)) {
e58f291e777b25c1286965b80e142ada6fdacb03Timo Sirainen /* we went too far, have to re-read the file */
636f017be100bce67d66fd3ae1544a47681efd33Timo Sirainen return 0;
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen }
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen if (map_hdr->log_file_ext_offset !=
494a5de15db3b2806ab31d5ecc3e1c306ae14d06Timo Sirainen map_hdr->log_file_int_offset ||
e58f291e777b25c1286965b80e142ada6fdacb03Timo Sirainen hdr.log_file_ext_offset != hdr.log_file_int_offset) {
e58f291e777b25c1286965b80e142ada6fdacb03Timo Sirainen /* too much trouble to get this right. */
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen return 0;
636f017be100bce67d66fd3ae1544a47681efd33Timo Sirainen }
636f017be100bce67d66fd3ae1544a47681efd33Timo Sirainen max_seq = hdr.log_file_seq;
636f017be100bce67d66fd3ae1544a47681efd33Timo Sirainen max_offset = hdr.log_file_int_offset;
9d4c027e7de01ab948d6221bc27c9b45d32d1ea5Timo Sirainen } else {
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen /* sync everything there is */
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen max_seq = (uint32_t)-1;
636f017be100bce67d66fd3ae1544a47681efd33Timo Sirainen max_offset = (uoff_t)-1;
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen }
08ed4ab71fd2a4e800d9025a736f0f46b771ea90Timo Sirainen
08ed4ab71fd2a4e800d9025a736f0f46b771ea90Timo Sirainen log_view = mail_transaction_log_view_open(index->log);
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen if (mail_transaction_log_view_set(log_view,
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen map_hdr->log_file_seq,
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen map_hdr->log_file_int_offset,
1c1cecd3dfaf71b0c9499b044023e631841e88aaTimo Sirainen max_seq, max_offset,
1c1cecd3dfaf71b0c9499b044023e631841e88aaTimo Sirainen MAIL_TRANSACTION_TYPE_MASK) < 0) {
1c1cecd3dfaf71b0c9499b044023e631841e88aaTimo Sirainen mail_transaction_log_view_close(log_view);
1c1cecd3dfaf71b0c9499b044023e631841e88aaTimo Sirainen return 0;
1c1cecd3dfaf71b0c9499b044023e631841e88aaTimo Sirainen }
1c1cecd3dfaf71b0c9499b044023e631841e88aaTimo Sirainen
1c1cecd3dfaf71b0c9499b044023e631841e88aaTimo Sirainen index->map = *map;
636f017be100bce67d66fd3ae1544a47681efd33Timo Sirainen
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen view = mail_index_view_open(index);
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen mail_index_sync_map_init(&sync_map_ctx, view,
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen MAIL_INDEX_SYNC_HANDLER_VIEW);
3e0bae44b65f5c46989fcef3d1e07203f496327eTimo Sirainen
0bd259973f98837cf0e41fdee3e2a578e51ad09eTimo Sirainen while ((ret = mail_transaction_log_view_next(log_view, &thdr, &tdata,
0bd259973f98837cf0e41fdee3e2a578e51ad09eTimo Sirainen &skipped)) > 0) {
e4cb3bfcd42f1f2c9e676ece6f7f53803f5c6a16Timo Sirainen if (mail_index_sync_record(&sync_map_ctx, thdr, tdata) < 0) {
e4cb3bfcd42f1f2c9e676ece6f7f53803f5c6a16Timo Sirainen ret = -1;
e4cb3bfcd42f1f2c9e676ece6f7f53803f5c6a16Timo Sirainen break;
e4cb3bfcd42f1f2c9e676ece6f7f53803f5c6a16Timo Sirainen }
6f970b9a0dadb80e120d017c75c637b5a3879dacTimo Sirainen }
69af83d4e6c2c5c825a17edd7a41a4fb014caa8fTimo Sirainen
69af83d4e6c2c5c825a17edd7a41a4fb014caa8fTimo Sirainen mail_index_sync_map_deinit(&sync_map_ctx);
69af83d4e6c2c5c825a17edd7a41a4fb014caa8fTimo Sirainen mail_index_view_close(view);
69af83d4e6c2c5c825a17edd7a41a4fb014caa8fTimo Sirainen mail_transaction_log_view_close(log_view);
69af83d4e6c2c5c825a17edd7a41a4fb014caa8fTimo Sirainen
69af83d4e6c2c5c825a17edd7a41a4fb014caa8fTimo Sirainen *map = index->map;
69af83d4e6c2c5c825a17edd7a41a4fb014caa8fTimo Sirainen index->map = NULL;
69af83d4e6c2c5c825a17edd7a41a4fb014caa8fTimo Sirainen
69af83d4e6c2c5c825a17edd7a41a4fb014caa8fTimo Sirainen if (sync_to_index) {
69af83d4e6c2c5c825a17edd7a41a4fb014caa8fTimo Sirainen /* make sure log file offsets get copied. most of the other
69af83d4e6c2c5c825a17edd7a41a4fb014caa8fTimo Sirainen fields should stay the same. */
69af83d4e6c2c5c825a17edd7a41a4fb014caa8fTimo Sirainen (*map)->hdr = hdr;
636f017be100bce67d66fd3ae1544a47681efd33Timo Sirainen }
69af83d4e6c2c5c825a17edd7a41a4fb014caa8fTimo Sirainen
69af83d4e6c2c5c825a17edd7a41a4fb014caa8fTimo Sirainen return ret < 0 ? -1 : 1;
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen}
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen
69af83d4e6c2c5c825a17edd7a41a4fb014caa8fTimo Sirainenstatic int mail_index_read_map_with_retry(struct mail_index *index,
69af83d4e6c2c5c825a17edd7a41a4fb014caa8fTimo Sirainen struct mail_index_map **map,
69af83d4e6c2c5c825a17edd7a41a4fb014caa8fTimo Sirainen int sync_to_index)
69af83d4e6c2c5c825a17edd7a41a4fb014caa8fTimo Sirainen{
69af83d4e6c2c5c825a17edd7a41a4fb014caa8fTimo Sirainen int i, ret, retry;
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen if ((*map)->hdr.indexid != 0) {
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen /* sync this as a view from transaction log. */
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen ret = mail_index_sync_from_transactions(index, map,
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen sync_to_index);
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen if (ret != 0)
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen return ret;
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen /* transaction log lost/broken, fallback to re-reading it */
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen /* FIXME: file cache need to be reset (except not really with
d3e5a14ea363264dcc7640ca7226249d0c27a793Timo Sirainen sync_to_index if we were just rewinding..) */
a4e2101473cfd7ce960fc49b3ce097c3f89ec2adTimo Sirainen }
a4e2101473cfd7ce960fc49b3ce097c3f89ec2adTimo Sirainen
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen for (i = 0; i < MAIL_INDEX_ESTALE_RETRY_COUNT; i++) {
2ac5f36aa7c2e7a07ba8815d43a6d7483f62e74cTimo Sirainen ret = mail_index_read_map(index, *map, &retry);
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen if (ret != 0 || !retry)
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen return ret;
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen
a4e2101473cfd7ce960fc49b3ce097c3f89ec2adTimo Sirainen /* ESTALE - reopen index file */
a4e2101473cfd7ce960fc49b3ce097c3f89ec2adTimo Sirainen if (close(index->fd) < 0)
a4e2101473cfd7ce960fc49b3ce097c3f89ec2adTimo Sirainen mail_index_set_syscall_error(index, "close()");
8f70c97f7ab7b7e1683ed5cfcd96721a899c2520Timo Sirainen index->fd = -1;
8f70c97f7ab7b7e1683ed5cfcd96721a899c2520Timo Sirainen
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen ret = mail_index_try_open_only(index);
a4e2101473cfd7ce960fc49b3ce097c3f89ec2adTimo Sirainen if (ret <= 0) {
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen if (ret == 0) {
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen /* the file was lost */
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen errno = ENOENT;
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen mail_index_set_syscall_error(index, "open()");
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen }
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen return -1;
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen }
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen }
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen /* Too many ESTALE retries */
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen mail_index_set_syscall_error(index, "read_map()");
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen return -1;
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen}
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainenstatic int mail_index_map_try_existing(struct mail_index_map *map)
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen{
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen const struct mail_index_header *hdr;
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen size_t used_size;
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen if (MAIL_INDEX_MAP_IS_IN_MEMORY(map))
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen return 0;
a4e2101473cfd7ce960fc49b3ce097c3f89ec2adTimo Sirainen
a4e2101473cfd7ce960fc49b3ce097c3f89ec2adTimo Sirainen hdr = map->mmap_base;
a4e2101473cfd7ce960fc49b3ce097c3f89ec2adTimo Sirainen
a4e2101473cfd7ce960fc49b3ce097c3f89ec2adTimo Sirainen /* always check corrupted-flag to avoid errors later */
a4e2101473cfd7ce960fc49b3ce097c3f89ec2adTimo Sirainen if ((hdr->flags & MAIL_INDEX_HDR_FLAG_CORRUPTED) != 0)
a4e2101473cfd7ce960fc49b3ce097c3f89ec2adTimo Sirainen return -1;
a4e2101473cfd7ce960fc49b3ce097c3f89ec2adTimo Sirainen
a4e2101473cfd7ce960fc49b3ce097c3f89ec2adTimo Sirainen used_size = hdr->header_size + hdr->messages_count * hdr->record_size;
a4e2101473cfd7ce960fc49b3ce097c3f89ec2adTimo Sirainen if (map->mmap_size >= used_size && map->hdr_base == hdr) {
69af83d4e6c2c5c825a17edd7a41a4fb014caa8fTimo Sirainen map->records_count = hdr->messages_count;
69af83d4e6c2c5c825a17edd7a41a4fb014caa8fTimo Sirainen mail_index_map_copy_hdr(map, hdr);
69af83d4e6c2c5c825a17edd7a41a4fb014caa8fTimo Sirainen return 1;
69af83d4e6c2c5c825a17edd7a41a4fb014caa8fTimo Sirainen }
69af83d4e6c2c5c825a17edd7a41a4fb014caa8fTimo Sirainen return 0;
69af83d4e6c2c5c825a17edd7a41a4fb014caa8fTimo Sirainen}
69af83d4e6c2c5c825a17edd7a41a4fb014caa8fTimo Sirainen
69af83d4e6c2c5c825a17edd7a41a4fb014caa8fTimo Sirainenint mail_index_map(struct mail_index *index, int force)
69af83d4e6c2c5c825a17edd7a41a4fb014caa8fTimo Sirainen{
69af83d4e6c2c5c825a17edd7a41a4fb014caa8fTimo Sirainen struct mail_index_map *map;
69af83d4e6c2c5c825a17edd7a41a4fb014caa8fTimo Sirainen int ret;
69af83d4e6c2c5c825a17edd7a41a4fb014caa8fTimo Sirainen
69af83d4e6c2c5c825a17edd7a41a4fb014caa8fTimo Sirainen i_assert(index->map == NULL || index->map->refcount > 0);
69af83d4e6c2c5c825a17edd7a41a4fb014caa8fTimo Sirainen i_assert(index->lock_type != F_UNLCK);
69af83d4e6c2c5c825a17edd7a41a4fb014caa8fTimo Sirainen
69af83d4e6c2c5c825a17edd7a41a4fb014caa8fTimo Sirainen if (!force && index->map != NULL) {
69af83d4e6c2c5c825a17edd7a41a4fb014caa8fTimo Sirainen ret = mail_index_map_try_existing(index->map);
69af83d4e6c2c5c825a17edd7a41a4fb014caa8fTimo Sirainen if (ret != 0)
69af83d4e6c2c5c825a17edd7a41a4fb014caa8fTimo Sirainen return ret;
69af83d4e6c2c5c825a17edd7a41a4fb014caa8fTimo Sirainen
69af83d4e6c2c5c825a17edd7a41a4fb014caa8fTimo Sirainen if (index->lock_type == F_WRLCK) {
69af83d4e6c2c5c825a17edd7a41a4fb014caa8fTimo Sirainen /* we're syncing, don't break the mapping */
69af83d4e6c2c5c825a17edd7a41a4fb014caa8fTimo Sirainen return 1;
69af83d4e6c2c5c825a17edd7a41a4fb014caa8fTimo Sirainen }
69af83d4e6c2c5c825a17edd7a41a4fb014caa8fTimo Sirainen }
69af83d4e6c2c5c825a17edd7a41a4fb014caa8fTimo Sirainen
69af83d4e6c2c5c825a17edd7a41a4fb014caa8fTimo Sirainen if (index->map != NULL && index->map->refcount > 1) {
1f4399a277b861419b82758ab0462e90c00a4c41Timo Sirainen /* this map is already used by some views and they may have
69af83d4e6c2c5c825a17edd7a41a4fb014caa8fTimo Sirainen pointers into it. leave them and create a new mapping. */
69af83d4e6c2c5c825a17edd7a41a4fb014caa8fTimo Sirainen if (!index->mmap_disable) {
69af83d4e6c2c5c825a17edd7a41a4fb014caa8fTimo Sirainen map = NULL;
69af83d4e6c2c5c825a17edd7a41a4fb014caa8fTimo Sirainen } else {
69af83d4e6c2c5c825a17edd7a41a4fb014caa8fTimo Sirainen /* create a copy of the mapping instead so we don't
69af83d4e6c2c5c825a17edd7a41a4fb014caa8fTimo Sirainen have to re-read it */
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen map = mail_index_map_clone(index->map,
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen index->map->hdr.record_size);
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen }
2ac5f36aa7c2e7a07ba8815d43a6d7483f62e74cTimo Sirainen index->map->refcount--;
636f017be100bce67d66fd3ae1544a47681efd33Timo Sirainen index->map = NULL;
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen } else {
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen map = index->map;
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen }
9b00ecffbe74fd864d0d72e6112ec53b86f619baTimo Sirainen
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen if (map == NULL) {
9b00ecffbe74fd864d0d72e6112ec53b86f619baTimo Sirainen map = i_new(struct mail_index_map, 1);
9b00ecffbe74fd864d0d72e6112ec53b86f619baTimo Sirainen map->refcount = 1;
9b00ecffbe74fd864d0d72e6112ec53b86f619baTimo Sirainen map->hdr_copy_buf =
9b00ecffbe74fd864d0d72e6112ec53b86f619baTimo Sirainen buffer_create_dynamic(default_pool, sizeof(map->hdr));
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen } else if (MAIL_INDEX_MAP_IS_IN_MEMORY(map)) {
3e0bae44b65f5c46989fcef3d1e07203f496327eTimo Sirainen i_assert(!map->write_to_disk);
3e0bae44b65f5c46989fcef3d1e07203f496327eTimo Sirainen } else if (map->mmap_base != NULL) {
0bd259973f98837cf0e41fdee3e2a578e51ad09eTimo Sirainen i_assert(map->buffer == NULL);
0bd259973f98837cf0e41fdee3e2a578e51ad09eTimo Sirainen if (munmap(map->mmap_base, map->mmap_size) < 0)
e4cb3bfcd42f1f2c9e676ece6f7f53803f5c6a16Timo Sirainen mail_index_set_syscall_error(index, "munmap()");
e4cb3bfcd42f1f2c9e676ece6f7f53803f5c6a16Timo Sirainen map->mmap_base = NULL;
e4cb3bfcd42f1f2c9e676ece6f7f53803f5c6a16Timo Sirainen }
e4cb3bfcd42f1f2c9e676ece6f7f53803f5c6a16Timo Sirainen
636f017be100bce67d66fd3ae1544a47681efd33Timo Sirainen index->hdr = NULL;
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen index->map = NULL;
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen if (!index->mmap_disable)
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen ret = mail_index_mmap(index, map);
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen else
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen ret = mail_index_read_map_with_retry(index, &map, force);
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen if (ret <= 0) {
1c1cecd3dfaf71b0c9499b044023e631841e88aaTimo Sirainen mail_index_unmap_forced(index, map);
636f017be100bce67d66fd3ae1544a47681efd33Timo Sirainen return ret;
636f017be100bce67d66fd3ae1544a47681efd33Timo Sirainen }
69af83d4e6c2c5c825a17edd7a41a4fb014caa8fTimo Sirainen
69af83d4e6c2c5c825a17edd7a41a4fb014caa8fTimo Sirainen ret = mail_index_check_header(index, map);
69af83d4e6c2c5c825a17edd7a41a4fb014caa8fTimo Sirainen if (ret < 0) {
636f017be100bce67d66fd3ae1544a47681efd33Timo Sirainen mail_index_unmap_forced(index, map);
69af83d4e6c2c5c825a17edd7a41a4fb014caa8fTimo Sirainen return 0;
69af83d4e6c2c5c825a17edd7a41a4fb014caa8fTimo Sirainen }
69af83d4e6c2c5c825a17edd7a41a4fb014caa8fTimo Sirainen if (ret == 0)
69af83d4e6c2c5c825a17edd7a41a4fb014caa8fTimo Sirainen index->fsck = TRUE;
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen index->hdr = &map->hdr;
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen index->map = map;
6f970b9a0dadb80e120d017c75c637b5a3879dacTimo Sirainen return 1;
6f970b9a0dadb80e120d017c75c637b5a3879dacTimo Sirainen}
6f970b9a0dadb80e120d017c75c637b5a3879dacTimo Sirainen
6f970b9a0dadb80e120d017c75c637b5a3879dacTimo Sirainenstruct mail_index_map *
6f970b9a0dadb80e120d017c75c637b5a3879dacTimo Sirainenmail_index_map_clone(struct mail_index_map *map, uint32_t new_record_size)
6f970b9a0dadb80e120d017c75c637b5a3879dacTimo Sirainen{
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen struct mail_index_map *mem_map;
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen struct mail_index_header *hdr;
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen struct mail_index_ext *extensions;
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen void *src, *dest;
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen size_t size, copy_size;
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen unsigned int i, count;
e7d0bea63a08b08c47c4b5c187d2cb7127859657Timo Sirainen
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen size = map->records_count * new_record_size;
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen mem_map = i_new(struct mail_index_map, 1);
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen mem_map->refcount = 1;
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen mem_map->buffer = buffer_create_dynamic(default_pool, size);
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen if (map->hdr.record_size == new_record_size)
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen buffer_append(mem_map->buffer, map->records, size);
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen else {
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen copy_size = I_MIN(map->hdr.record_size, new_record_size);
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen src = map->records;
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen for (i = 0; i < map->records_count; i++) {
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen dest = buffer_append_space_unsafe(mem_map->buffer,
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen new_record_size);
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen memcpy(dest, src, copy_size);
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen src = PTR_OFFSET(src, map->hdr.record_size);
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen }
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen }
1701e3f91107051b1704721bf1dc1e32491faaf9Timo Sirainen
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen mem_map->records = buffer_get_modifyable_data(mem_map->buffer, NULL);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen mem_map->records_count = map->records_count;
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen
ff7056842f14fd3b30a2d327dfab165b9d15dd30Timo Sirainen mem_map->hdr_copy_buf =
8ca217bf3aa23c7922d0d4aa44fcd2320416d61cMartti Rannanjärvi buffer_create_dynamic(default_pool, map->hdr.header_size);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen if (map->hdr.base_header_size < sizeof(*hdr))
678d0463849ba777106eb7875f27db07a5d8e3dfTimo Sirainen buffer_append_zero(mem_map->hdr_copy_buf, sizeof(*hdr));
bd4e36a8cd7257cca7d1434c49a1e343ed7c5100Timo Sirainen buffer_write(mem_map->hdr_copy_buf, 0,
bd4e36a8cd7257cca7d1434c49a1e343ed7c5100Timo Sirainen &map->hdr, map->hdr.base_header_size);
bd4e36a8cd7257cca7d1434c49a1e343ed7c5100Timo Sirainen buffer_append(mem_map->hdr_copy_buf,
bd4e36a8cd7257cca7d1434c49a1e343ed7c5100Timo Sirainen CONST_PTR_OFFSET(map->hdr_base,
cb933f0a570a9cef5c975eadb818aa6b1002a269Timo Sirainen map->hdr.base_header_size),
cb933f0a570a9cef5c975eadb818aa6b1002a269Timo Sirainen map->hdr.header_size - map->hdr.base_header_size);
37847ec8eaec9ad55c9df10ae109efe7b37ac573Timo Sirainen
37847ec8eaec9ad55c9df10ae109efe7b37ac573Timo Sirainen hdr = buffer_get_modifyable_data(mem_map->hdr_copy_buf, NULL);
4654cf737f538f5de032b8c9908913f121917366Timo Sirainen if (hdr->base_header_size < sizeof(*hdr))
4654cf737f538f5de032b8c9908913f121917366Timo Sirainen hdr->base_header_size = sizeof(*hdr);
4654cf737f538f5de032b8c9908913f121917366Timo Sirainen hdr->record_size = new_record_size;
4654cf737f538f5de032b8c9908913f121917366Timo Sirainen mem_map->hdr = *hdr;
4654cf737f538f5de032b8c9908913f121917366Timo Sirainen mem_map->hdr_base = hdr;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen /* copy extensions */
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen if (map->ext_id_map != NULL) {
68a4946b12583b88fa802e52ebee45cd96056772Timo Sirainen count = map->ext_id_map->used / sizeof(uint32_t);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen mail_index_map_init_extbufs(mem_map, count + 2);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen buffer_append_buf(mem_map->extensions, map->extensions,
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen 0, (size_t)-1);
ae2b61a8c6318e56dabd44de17e227c95985aedaTimo Sirainen buffer_append_buf(mem_map->ext_id_map, map->ext_id_map,
ae2b61a8c6318e56dabd44de17e227c95985aedaTimo Sirainen 0, (size_t)-1);
ae2b61a8c6318e56dabd44de17e227c95985aedaTimo Sirainen
e36574dadcac802d6780fa94ee45951e75594c96Timo Sirainen /* fix the name pointers to use our own pool */
ae2b61a8c6318e56dabd44de17e227c95985aedaTimo Sirainen extensions = buffer_get_modifyable_data(mem_map->extensions,
ae2b61a8c6318e56dabd44de17e227c95985aedaTimo Sirainen NULL);
68a4946b12583b88fa802e52ebee45cd96056772Timo Sirainen for (i = 0; i < count; i++) {
c58906589cafc32df4c04ffbef933baadd3f2276Timo Sirainen extensions[i].name = p_strdup(mem_map->extension_pool,
c58906589cafc32df4c04ffbef933baadd3f2276Timo Sirainen extensions[i].name);
c58906589cafc32df4c04ffbef933baadd3f2276Timo Sirainen }
c58906589cafc32df4c04ffbef933baadd3f2276Timo Sirainen }
68a4946b12583b88fa802e52ebee45cd96056772Timo Sirainen
68a4946b12583b88fa802e52ebee45cd96056772Timo Sirainen return mem_map;
c58906589cafc32df4c04ffbef933baadd3f2276Timo Sirainen}
c58906589cafc32df4c04ffbef933baadd3f2276Timo Sirainen
c58906589cafc32df4c04ffbef933baadd3f2276Timo Sirainenint mail_index_map_get_ext_idx(struct mail_index_map *map,
c58906589cafc32df4c04ffbef933baadd3f2276Timo Sirainen uint32_t ext_id, uint32_t *idx_r)
6dd77763f5451269ace733579cf58f2f3b18bca4Timo Sirainen{
6dd77763f5451269ace733579cf58f2f3b18bca4Timo Sirainen const uint32_t *id_map;
6dd77763f5451269ace733579cf58f2f3b18bca4Timo Sirainen
6dd77763f5451269ace733579cf58f2f3b18bca4Timo Sirainen if (map->ext_id_map == NULL ||
6dd77763f5451269ace733579cf58f2f3b18bca4Timo Sirainen map->ext_id_map->used / sizeof(*id_map) <= ext_id)
6dd77763f5451269ace733579cf58f2f3b18bca4Timo Sirainen return 0;
6dd77763f5451269ace733579cf58f2f3b18bca4Timo Sirainen
6dd77763f5451269ace733579cf58f2f3b18bca4Timo Sirainen id_map = map->ext_id_map->data;
6dd77763f5451269ace733579cf58f2f3b18bca4Timo Sirainen *idx_r = id_map[ext_id];
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen return *idx_r != (uint32_t)-1;
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen}
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainenstatic int mail_index_try_open_only(struct mail_index *index)
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen{
0df9428baed48afaff90b4d4f03792d2fd756a43Timo Sirainen int i;
d2e74f2af690b8e2d536400f02f397cbed1334b7Timo Sirainen
d2e74f2af690b8e2d536400f02f397cbed1334b7Timo Sirainen for (i = 0; i < 3; i++) {
d2e74f2af690b8e2d536400f02f397cbed1334b7Timo Sirainen index->fd = open(index->filepath, O_RDWR);
d2e74f2af690b8e2d536400f02f397cbed1334b7Timo Sirainen if (index->fd == -1 && errno == EACCES) {
d2e74f2af690b8e2d536400f02f397cbed1334b7Timo Sirainen index->fd = open(index->filepath, O_RDONLY);
d2e74f2af690b8e2d536400f02f397cbed1334b7Timo Sirainen index->readonly = TRUE;
d2e74f2af690b8e2d536400f02f397cbed1334b7Timo Sirainen }
d2e74f2af690b8e2d536400f02f397cbed1334b7Timo Sirainen if (index->fd != -1 || errno != ESTALE)
d2e74f2af690b8e2d536400f02f397cbed1334b7Timo Sirainen break;
d2e74f2af690b8e2d536400f02f397cbed1334b7Timo Sirainen
d2e74f2af690b8e2d536400f02f397cbed1334b7Timo Sirainen /* May happen with some OSes with NFS. Try again, although
d2e74f2af690b8e2d536400f02f397cbed1334b7Timo Sirainen there's still a race condition with another computer
d2e74f2af690b8e2d536400f02f397cbed1334b7Timo Sirainen creating the index file again. However, we can't try forever
d2e74f2af690b8e2d536400f02f397cbed1334b7Timo Sirainen as ESTALE happens also if index directory has been deleted
4b1781e4c64be52e25b5994e5242dbe696cc7d29Timo Sirainen from server.. */
d2e74f2af690b8e2d536400f02f397cbed1334b7Timo Sirainen }
d2e74f2af690b8e2d536400f02f397cbed1334b7Timo Sirainen if (index->fd == -1) {
d2e74f2af690b8e2d536400f02f397cbed1334b7Timo Sirainen if (errno != ENOENT)
d2e74f2af690b8e2d536400f02f397cbed1334b7Timo Sirainen return mail_index_set_syscall_error(index, "open()");
d2e74f2af690b8e2d536400f02f397cbed1334b7Timo Sirainen
d2e74f2af690b8e2d536400f02f397cbed1334b7Timo Sirainen /* have to create it */
d2e74f2af690b8e2d536400f02f397cbed1334b7Timo Sirainen return 0;
d2e74f2af690b8e2d536400f02f397cbed1334b7Timo Sirainen }
d2e74f2af690b8e2d536400f02f397cbed1334b7Timo Sirainen return 1;
d2e74f2af690b8e2d536400f02f397cbed1334b7Timo Sirainen}
d2e74f2af690b8e2d536400f02f397cbed1334b7Timo Sirainen
d2e74f2af690b8e2d536400f02f397cbed1334b7Timo Sirainenstatic int
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainenmail_index_try_open(struct mail_index *index, unsigned int *lock_id_r)
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen{
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen unsigned int lock_id;
d2e74f2af690b8e2d536400f02f397cbed1334b7Timo Sirainen int ret;
d2e74f2af690b8e2d536400f02f397cbed1334b7Timo Sirainen
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen if (lock_id_r != NULL)
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen *lock_id_r = 0;
d2e74f2af690b8e2d536400f02f397cbed1334b7Timo Sirainen
15bfe73fb3988bb80e6afe6a60b9a715c7207600Timo Sirainen ret = mail_index_try_open_only(index);
4809537f0c5a2e1cee9559ec842cc869884d2cb7Timo Sirainen if (ret <= 0)
d2e74f2af690b8e2d536400f02f397cbed1334b7Timo Sirainen return ret;
d2e74f2af690b8e2d536400f02f397cbed1334b7Timo Sirainen
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen if (mail_index_lock_shared(index, FALSE, &lock_id) < 0) {
d2e74f2af690b8e2d536400f02f397cbed1334b7Timo Sirainen (void)close(index->fd);
d2e74f2af690b8e2d536400f02f397cbed1334b7Timo Sirainen index->fd = -1;
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen return -1;
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen }
8709b2fe6ec2b5ca1d90a63490f8371472062efdTimo Sirainen ret = mail_index_map(index, FALSE);
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen if (ret == 0) {
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen /* it's corrupted - recreate it */
949fa97a4ab5c62e4db73c3973e35ae3b73a2b23Timo Sirainen mail_index_unlock(index, lock_id);
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen if (lock_id_r != NULL)
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen *lock_id_r = 0;
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen (void)close(index->fd);
e353d03d3643f380dc7e6dc29a512dec86b8a3deTimo Sirainen index->fd = -1;
e353d03d3643f380dc7e6dc29a512dec86b8a3deTimo Sirainen } else {
e353d03d3643f380dc7e6dc29a512dec86b8a3deTimo Sirainen if (lock_id_r != NULL)
e353d03d3643f380dc7e6dc29a512dec86b8a3deTimo Sirainen *lock_id_r = lock_id;
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen else
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen mail_index_unlock(index, lock_id);
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen }
4225ae95dd2110fe678ee70c64be14784a53c364Timo Sirainen return ret;
4225ae95dd2110fe678ee70c64be14784a53c364Timo Sirainen}
4225ae95dd2110fe678ee70c64be14784a53c364Timo Sirainen
4225ae95dd2110fe678ee70c64be14784a53c364Timo Sirainenint mail_index_write_base_header(struct mail_index *index,
4225ae95dd2110fe678ee70c64be14784a53c364Timo Sirainen const struct mail_index_header *hdr)
4225ae95dd2110fe678ee70c64be14784a53c364Timo Sirainen{
4225ae95dd2110fe678ee70c64be14784a53c364Timo Sirainen size_t hdr_size;
4225ae95dd2110fe678ee70c64be14784a53c364Timo Sirainen
4225ae95dd2110fe678ee70c64be14784a53c364Timo Sirainen hdr_size = I_MIN(sizeof(*hdr), hdr->base_header_size);
4225ae95dd2110fe678ee70c64be14784a53c364Timo Sirainen
4225ae95dd2110fe678ee70c64be14784a53c364Timo Sirainen if (!MAIL_INDEX_MAP_IS_IN_MEMORY(index->map)) {
4225ae95dd2110fe678ee70c64be14784a53c364Timo Sirainen memcpy(index->map->mmap_base, hdr, hdr_size);
4225ae95dd2110fe678ee70c64be14784a53c364Timo Sirainen if (msync(index->map->mmap_base, hdr_size, MS_SYNC) < 0)
4225ae95dd2110fe678ee70c64be14784a53c364Timo Sirainen return mail_index_set_syscall_error(index, "msync()");
4225ae95dd2110fe678ee70c64be14784a53c364Timo Sirainen } else {
4225ae95dd2110fe678ee70c64be14784a53c364Timo Sirainen if (pwrite_full(index->fd, hdr, hdr_size, 0) < 0) {
4225ae95dd2110fe678ee70c64be14784a53c364Timo Sirainen mail_index_set_syscall_error(index, "pwrite_full()");
4225ae95dd2110fe678ee70c64be14784a53c364Timo Sirainen return -1;
4225ae95dd2110fe678ee70c64be14784a53c364Timo Sirainen }
4225ae95dd2110fe678ee70c64be14784a53c364Timo Sirainen
4225ae95dd2110fe678ee70c64be14784a53c364Timo Sirainen index->map->hdr = *hdr;
4225ae95dd2110fe678ee70c64be14784a53c364Timo Sirainen buffer_write(index->map->hdr_copy_buf, 0, hdr, hdr_size);
4225ae95dd2110fe678ee70c64be14784a53c364Timo Sirainen }
4225ae95dd2110fe678ee70c64be14784a53c364Timo Sirainen
4225ae95dd2110fe678ee70c64be14784a53c364Timo Sirainen return 0;
4225ae95dd2110fe678ee70c64be14784a53c364Timo Sirainen}
4225ae95dd2110fe678ee70c64be14784a53c364Timo Sirainen
4225ae95dd2110fe678ee70c64be14784a53c364Timo Sirainenint mail_index_create_tmp_file(struct mail_index *index, const char **path_r)
4225ae95dd2110fe678ee70c64be14784a53c364Timo Sirainen{
4225ae95dd2110fe678ee70c64be14784a53c364Timo Sirainen mode_t old_mask;
4225ae95dd2110fe678ee70c64be14784a53c364Timo Sirainen const char *path;
4225ae95dd2110fe678ee70c64be14784a53c364Timo Sirainen int fd;
4225ae95dd2110fe678ee70c64be14784a53c364Timo Sirainen
4225ae95dd2110fe678ee70c64be14784a53c364Timo Sirainen path = *path_r = t_strconcat(index->filepath, ".tmp", NULL);
4225ae95dd2110fe678ee70c64be14784a53c364Timo Sirainen old_mask = umask(0);
4225ae95dd2110fe678ee70c64be14784a53c364Timo Sirainen fd = open(path, O_RDWR|O_CREAT|O_TRUNC, index->mode);
4225ae95dd2110fe678ee70c64be14784a53c364Timo Sirainen umask(old_mask);
4225ae95dd2110fe678ee70c64be14784a53c364Timo Sirainen if (fd == -1)
4225ae95dd2110fe678ee70c64be14784a53c364Timo Sirainen return mail_index_file_set_syscall_error(index, path, "open()");
4225ae95dd2110fe678ee70c64be14784a53c364Timo Sirainen
4225ae95dd2110fe678ee70c64be14784a53c364Timo Sirainen if (index->gid != (gid_t)-1 && fchown(fd, (uid_t)-1, index->gid) < 0) {
4225ae95dd2110fe678ee70c64be14784a53c364Timo Sirainen mail_index_file_set_syscall_error(index, path, "fchown()");
4225ae95dd2110fe678ee70c64be14784a53c364Timo Sirainen return -1;
4225ae95dd2110fe678ee70c64be14784a53c364Timo Sirainen }
4225ae95dd2110fe678ee70c64be14784a53c364Timo Sirainen
4225ae95dd2110fe678ee70c64be14784a53c364Timo Sirainen return fd;
4225ae95dd2110fe678ee70c64be14784a53c364Timo Sirainen}
4225ae95dd2110fe678ee70c64be14784a53c364Timo Sirainen
4225ae95dd2110fe678ee70c64be14784a53c364Timo Sirainenstatic int mail_index_create(struct mail_index *index,
4225ae95dd2110fe678ee70c64be14784a53c364Timo Sirainen struct mail_index_header *hdr)
4225ae95dd2110fe678ee70c64be14784a53c364Timo Sirainen{
4225ae95dd2110fe678ee70c64be14784a53c364Timo Sirainen const char *path;
4225ae95dd2110fe678ee70c64be14784a53c364Timo Sirainen uint32_t seq;
4225ae95dd2110fe678ee70c64be14784a53c364Timo Sirainen uoff_t offset;
4225ae95dd2110fe678ee70c64be14784a53c364Timo Sirainen int ret;
4225ae95dd2110fe678ee70c64be14784a53c364Timo Sirainen
4225ae95dd2110fe678ee70c64be14784a53c364Timo Sirainen i_assert(index->lock_type == F_UNLCK);
4225ae95dd2110fe678ee70c64be14784a53c364Timo Sirainen
4225ae95dd2110fe678ee70c64be14784a53c364Timo Sirainen /* log file lock protects index creation */
4225ae95dd2110fe678ee70c64be14784a53c364Timo Sirainen if (mail_transaction_log_sync_lock(index->log, &seq, &offset) < 0)
4225ae95dd2110fe678ee70c64be14784a53c364Timo Sirainen return -1;
4225ae95dd2110fe678ee70c64be14784a53c364Timo Sirainen
4225ae95dd2110fe678ee70c64be14784a53c364Timo Sirainen ret = mail_index_try_open(index, NULL);
4225ae95dd2110fe678ee70c64be14784a53c364Timo Sirainen if (ret != 0) {
4225ae95dd2110fe678ee70c64be14784a53c364Timo Sirainen mail_transaction_log_sync_unlock(index->log);
a10ed8c47534b4c6b6bf2711ccfe577e720a47b4Timo Sirainen return ret < 0 ? -1 : 0;
a10ed8c47534b4c6b6bf2711ccfe577e720a47b4Timo Sirainen }
a10ed8c47534b4c6b6bf2711ccfe577e720a47b4Timo Sirainen
a10ed8c47534b4c6b6bf2711ccfe577e720a47b4Timo Sirainen /* create it fully in index.tmp first */
d02d34e138e32b4266f5a403d6c51d7803bf322fTimo Sirainen index->fd = mail_index_create_tmp_file(index, &path);
6763c5f6246a0705b141d99d32fe9e2096042bd3Timo Sirainen if (index->fd == -1)
d02d34e138e32b4266f5a403d6c51d7803bf322fTimo Sirainen ret = -1;
efe78d3ba24fc866af1c79b9223dc0809ba26cadStephan Bosch else if (write_full(index->fd, hdr, sizeof(*hdr)) < 0) {
47d5cc09738defd0020c797866e2a25a344aa65aTimo Sirainen mail_index_file_set_syscall_error(index, path, "write_full()");
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen ret = -1;
47d5cc09738defd0020c797866e2a25a344aa65aTimo Sirainen } else {
47d5cc09738defd0020c797866e2a25a344aa65aTimo Sirainen index->lock_type = F_WRLCK;
47d5cc09738defd0020c797866e2a25a344aa65aTimo Sirainen ret = mail_index_map(index, FALSE);
47d5cc09738defd0020c797866e2a25a344aa65aTimo Sirainen index->lock_type = F_UNLCK;
47d5cc09738defd0020c797866e2a25a344aa65aTimo Sirainen }
47d5cc09738defd0020c797866e2a25a344aa65aTimo Sirainen
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen if (ret == 0) {
4fce6ce68d13836faf6d68f35855eba4573b42b2Timo Sirainen /* it's corrupted even while we just created it,
4fce6ce68d13836faf6d68f35855eba4573b42b2Timo Sirainen should never happen unless someone pokes the file directly */
4fce6ce68d13836faf6d68f35855eba4573b42b2Timo Sirainen mail_index_set_error(index,
4fce6ce68d13836faf6d68f35855eba4573b42b2Timo Sirainen "Newly created index file is corrupted: %s", path);
4fce6ce68d13836faf6d68f35855eba4573b42b2Timo Sirainen ret = -1;
4fce6ce68d13836faf6d68f35855eba4573b42b2Timo Sirainen }
4fce6ce68d13836faf6d68f35855eba4573b42b2Timo Sirainen
6763c5f6246a0705b141d99d32fe9e2096042bd3Timo Sirainen if (ret < 0) {
6763c5f6246a0705b141d99d32fe9e2096042bd3Timo Sirainen if (unlink(path) < 0 && errno != ENOENT) {
6763c5f6246a0705b141d99d32fe9e2096042bd3Timo Sirainen mail_index_file_set_syscall_error(index, path,
6763c5f6246a0705b141d99d32fe9e2096042bd3Timo Sirainen "unlink()");
6763c5f6246a0705b141d99d32fe9e2096042bd3Timo Sirainen }
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen } else {
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen /* make it visible to others */
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen if (rename(path, index->filepath) < 0) {
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen mail_index_set_error(index, "rename(%s, %s) failed: %m",
6763c5f6246a0705b141d99d32fe9e2096042bd3Timo Sirainen path, index->filepath);
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen ret = -1;
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen }
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen }
758d8b46f9e8fd87cf58bb4912cddf6bf28918cfTimo Sirainen
6763c5f6246a0705b141d99d32fe9e2096042bd3Timo Sirainen mail_transaction_log_sync_unlock(index->log);
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen return ret;
4225ae95dd2110fe678ee70c64be14784a53c364Timo Sirainen}
4225ae95dd2110fe678ee70c64be14784a53c364Timo Sirainen
4225ae95dd2110fe678ee70c64be14784a53c364Timo Sirainenstatic void mail_index_header_init(struct mail_index_header *hdr)
4225ae95dd2110fe678ee70c64be14784a53c364Timo Sirainen{
4225ae95dd2110fe678ee70c64be14784a53c364Timo Sirainen time_t now = time(NULL);
4225ae95dd2110fe678ee70c64be14784a53c364Timo Sirainen
4225ae95dd2110fe678ee70c64be14784a53c364Timo Sirainen memset(hdr, 0, sizeof(*hdr));
4225ae95dd2110fe678ee70c64be14784a53c364Timo Sirainen
4225ae95dd2110fe678ee70c64be14784a53c364Timo Sirainen hdr->major_version = MAIL_INDEX_MAJOR_VERSION;
4225ae95dd2110fe678ee70c64be14784a53c364Timo Sirainen hdr->minor_version = MAIL_INDEX_MINOR_VERSION;
4225ae95dd2110fe678ee70c64be14784a53c364Timo Sirainen hdr->base_header_size = sizeof(*hdr);
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen hdr->header_size = sizeof(*hdr);
4225ae95dd2110fe678ee70c64be14784a53c364Timo Sirainen hdr->record_size = sizeof(struct mail_index_record);
4225ae95dd2110fe678ee70c64be14784a53c364Timo Sirainen hdr->keywords_mask_size = sizeof(keywords_mask_t);
4225ae95dd2110fe678ee70c64be14784a53c364Timo Sirainen
4225ae95dd2110fe678ee70c64be14784a53c364Timo Sirainen#ifndef WORDS_BIGENDIAN
47d5cc09738defd0020c797866e2a25a344aa65aTimo Sirainen hdr->compat_data[0] = MAIL_INDEX_COMPAT_LITTLE_ENDIAN;
47d5cc09738defd0020c797866e2a25a344aa65aTimo Sirainen#endif
47d5cc09738defd0020c797866e2a25a344aa65aTimo Sirainen hdr->compat_data[1] = sizeof(uoff_t);
47d5cc09738defd0020c797866e2a25a344aa65aTimo Sirainen hdr->compat_data[2] = sizeof(time_t);
6dd77763f5451269ace733579cf58f2f3b18bca4Timo Sirainen
490f66d6476d51cc02333d6eb398a5cd94b67f48Timo Sirainen hdr->indexid = now;
2f552aa8fb0fc86473c2d7dea85d8237373fb35fTimo Sirainen
2f552aa8fb0fc86473c2d7dea85d8237373fb35fTimo Sirainen hdr->next_uid = 1;
d02d34e138e32b4266f5a403d6c51d7803bf322fTimo Sirainen}
d02d34e138e32b4266f5a403d6c51d7803bf322fTimo Sirainen
fe813f74aaccb12f38e1bd9cd338c6a37fa646e5Timo Sirainen/* returns -1 = error, 0 = won't create, 1 = ok */
e5acc283bf030b0b5c79ca4e52d315c516a299faPascal Volkstatic int mail_index_open_files(struct mail_index *index,
dbc86748934bc34826d9cc8c43d24df09b3ba402Timo Sirainen enum mail_index_open_flags flags)
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen{
76b91bac787101e6b0075122ab6478dd98c8a884Timo Sirainen struct mail_index_header hdr;
dbc86748934bc34826d9cc8c43d24df09b3ba402Timo Sirainen unsigned int lock_id = 0;
dbc86748934bc34826d9cc8c43d24df09b3ba402Timo Sirainen int ret;
c78e7a94528078728cc639b26a1c83e11b4d7e1bTimo Sirainen
490f66d6476d51cc02333d6eb398a5cd94b67f48Timo Sirainen ret = mail_index_try_open(index, &lock_id);
490f66d6476d51cc02333d6eb398a5cd94b67f48Timo Sirainen if (ret > 0)
a10ed8c47534b4c6b6bf2711ccfe577e720a47b4Timo Sirainen hdr = *index->hdr;
a10ed8c47534b4c6b6bf2711ccfe577e720a47b4Timo Sirainen else if (ret == 0) {
a10ed8c47534b4c6b6bf2711ccfe577e720a47b4Timo Sirainen /* doesn't exist, or corrupted */
a10ed8c47534b4c6b6bf2711ccfe577e720a47b4Timo Sirainen if ((flags & MAIL_INDEX_OPEN_FLAG_CREATE) == 0)
a10ed8c47534b4c6b6bf2711ccfe577e720a47b4Timo Sirainen return 0;
a10ed8c47534b4c6b6bf2711ccfe577e720a47b4Timo Sirainen mail_index_header_init(&hdr);
17cf149e5f47183bfcc1503649dfb92a14f9dcd9Timo Sirainen index->hdr = &hdr;
76b91bac787101e6b0075122ab6478dd98c8a884Timo Sirainen } else if (ret < 0)
17cf149e5f47183bfcc1503649dfb92a14f9dcd9Timo Sirainen return -1;
76b91bac787101e6b0075122ab6478dd98c8a884Timo Sirainen
76b91bac787101e6b0075122ab6478dd98c8a884Timo Sirainen index->indexid = hdr.indexid;
76b91bac787101e6b0075122ab6478dd98c8a884Timo Sirainen
76b91bac787101e6b0075122ab6478dd98c8a884Timo Sirainen index->log = mail_transaction_log_open_or_create(index);
76b91bac787101e6b0075122ab6478dd98c8a884Timo Sirainen if (index->log == NULL)
490f66d6476d51cc02333d6eb398a5cd94b67f48Timo Sirainen return -1;
fea7b8b3fc182e415b1875d79587c0aa1adb09d7Timo Sirainen
fea7b8b3fc182e415b1875d79587c0aa1adb09d7Timo Sirainen if (index->fd == -1) {
5069b6adc4acb0efb3c6e87e778b820bae9bae9bTimo Sirainen if (lock_id != 0) {
5069b6adc4acb0efb3c6e87e778b820bae9bae9bTimo Sirainen mail_index_unlock(index, lock_id);
5069b6adc4acb0efb3c6e87e778b820bae9bae9bTimo Sirainen lock_id = 0;
5069b6adc4acb0efb3c6e87e778b820bae9bae9bTimo Sirainen }
5069b6adc4acb0efb3c6e87e778b820bae9bae9bTimo Sirainen if (mail_index_create(index, &hdr) < 0)
5069b6adc4acb0efb3c6e87e778b820bae9bae9bTimo Sirainen return -1;
5069b6adc4acb0efb3c6e87e778b820bae9bae9bTimo Sirainen }
5069b6adc4acb0efb3c6e87e778b820bae9bae9bTimo Sirainen
5069b6adc4acb0efb3c6e87e778b820bae9bae9bTimo Sirainen if (lock_id == 0) {
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen if (mail_index_lock_shared(index, FALSE, &lock_id) < 0)
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen return -1;
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen }
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen index->cache = mail_cache_open_or_create(index);
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen if (index->cache == NULL)
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen return -1;
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen mail_index_unlock(index, lock_id);
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen return 1;
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen}
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainenint mail_index_open(struct mail_index *index, enum mail_index_open_flags flags,
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen enum mail_index_lock_method lock_method)
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen{
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen int i = 0, ret;
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen if (index->opened) {
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen if (index->hdr != NULL &&
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen (index->hdr->flags & MAIL_INDEX_HDR_FLAG_CORRUPTED) != 0) {
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen /* corrupted, reopen files */
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen mail_index_close(index);
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen } else {
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen return 0;
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen }
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen }
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen index->filepath = i_strconcat(index->dir, "/", index->prefix, NULL);
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen do {
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen index->shared_lock_count = 0;
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen index->excl_lock_count = 0;
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen index->lock_type = F_UNLCK;
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen index->lock_id = 2;
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen index->readonly = FALSE;
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen index->nodiskspace = FALSE;
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen index->index_lock_timeout = FALSE;
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen index->log_locked = FALSE;
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen index->mmap_disable =
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen (flags & MAIL_INDEX_OPEN_FLAG_MMAP_DISABLE) != 0;
94f84d1c3f786d1b92dd2a1507f83a2dad887c56Timo Sirainen index->mmap_no_write =
94f84d1c3f786d1b92dd2a1507f83a2dad887c56Timo Sirainen (flags & MAIL_INDEX_OPEN_FLAG_MMAP_NO_WRITE) != 0;
94f84d1c3f786d1b92dd2a1507f83a2dad887c56Timo Sirainen index->lock_method = lock_method;
94f84d1c3f786d1b92dd2a1507f83a2dad887c56Timo Sirainen
94f84d1c3f786d1b92dd2a1507f83a2dad887c56Timo Sirainen /* don't even bother to handle dotlocking without mmap being
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen disabled. that combination simply doesn't make any sense */
94f84d1c3f786d1b92dd2a1507f83a2dad887c56Timo Sirainen i_assert(lock_method != MAIL_INDEX_LOCK_DOTLOCK ||
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen index->mmap_disable);
0bf25546c91ccafff9e2cc93368d2d25acb5c39eTimo Sirainen
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen ret = mail_index_open_files(index, flags);
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen if (ret <= 0)
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen break;
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen index->opened = TRUE;
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen if (index->fsck) {
0bf25546c91ccafff9e2cc93368d2d25acb5c39eTimo Sirainen index->fsck = FALSE;
0bf25546c91ccafff9e2cc93368d2d25acb5c39eTimo Sirainen ret = mail_index_fsck(index);
0bf25546c91ccafff9e2cc93368d2d25acb5c39eTimo Sirainen if (ret == 0) {
0bf25546c91ccafff9e2cc93368d2d25acb5c39eTimo Sirainen /* completely broken, reopen */
0bf25546c91ccafff9e2cc93368d2d25acb5c39eTimo Sirainen if (i++ < 3)
0bf25546c91ccafff9e2cc93368d2d25acb5c39eTimo Sirainen continue;
0bf25546c91ccafff9e2cc93368d2d25acb5c39eTimo Sirainen /* too many tries */
0bf25546c91ccafff9e2cc93368d2d25acb5c39eTimo Sirainen ret = -1;
0bf25546c91ccafff9e2cc93368d2d25acb5c39eTimo Sirainen }
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen }
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen break;
0bf25546c91ccafff9e2cc93368d2d25acb5c39eTimo Sirainen } while (1);
0bf25546c91ccafff9e2cc93368d2d25acb5c39eTimo Sirainen
0bf25546c91ccafff9e2cc93368d2d25acb5c39eTimo Sirainen if (ret <= 0)
0bf25546c91ccafff9e2cc93368d2d25acb5c39eTimo Sirainen mail_index_close(index);
0bf25546c91ccafff9e2cc93368d2d25acb5c39eTimo Sirainen
0bf25546c91ccafff9e2cc93368d2d25acb5c39eTimo Sirainen return ret;
0bf25546c91ccafff9e2cc93368d2d25acb5c39eTimo Sirainen}
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainenvoid mail_index_close(struct mail_index *index)
0bf25546c91ccafff9e2cc93368d2d25acb5c39eTimo Sirainen{
70a2782edc5cb342ed67a46ce30a95ca316f86c9Timo Sirainen if (index->log != NULL) {
c905571984fe8ccdb6f2a266b813f19b0643a66cTimo Sirainen mail_transaction_log_close(index->log);
c905571984fe8ccdb6f2a266b813f19b0643a66cTimo Sirainen index->log = NULL;
c905571984fe8ccdb6f2a266b813f19b0643a66cTimo Sirainen }
0bf25546c91ccafff9e2cc93368d2d25acb5c39eTimo Sirainen
70a2782edc5cb342ed67a46ce30a95ca316f86c9Timo Sirainen if (index->map != NULL) {
0bf25546c91ccafff9e2cc93368d2d25acb5c39eTimo Sirainen mail_index_unmap(index, index->map);
0bf25546c91ccafff9e2cc93368d2d25acb5c39eTimo Sirainen index->map = NULL;
0bf25546c91ccafff9e2cc93368d2d25acb5c39eTimo Sirainen }
0bf25546c91ccafff9e2cc93368d2d25acb5c39eTimo Sirainen
0bf25546c91ccafff9e2cc93368d2d25acb5c39eTimo Sirainen if (index->cache != NULL) {
0bf25546c91ccafff9e2cc93368d2d25acb5c39eTimo Sirainen mail_cache_free(index->cache);
0bf25546c91ccafff9e2cc93368d2d25acb5c39eTimo Sirainen index->cache = NULL;
0bf25546c91ccafff9e2cc93368d2d25acb5c39eTimo Sirainen }
0bf25546c91ccafff9e2cc93368d2d25acb5c39eTimo Sirainen
0bf25546c91ccafff9e2cc93368d2d25acb5c39eTimo Sirainen if (index->fd != -1) {
0bf25546c91ccafff9e2cc93368d2d25acb5c39eTimo Sirainen if (close(index->fd) < 0)
0bf25546c91ccafff9e2cc93368d2d25acb5c39eTimo Sirainen mail_index_set_syscall_error(index, "close()");
0bf25546c91ccafff9e2cc93368d2d25acb5c39eTimo Sirainen index->fd = -1;
0bf25546c91ccafff9e2cc93368d2d25acb5c39eTimo Sirainen }
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen i_free(index->copy_lock_path);
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen index->copy_lock_path = NULL;
4b8a6aec5fe2daa564799867f31e39e7ea46b9c3Timo Sirainen i_free(index->filepath);
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen index->filepath = NULL;
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen index->indexid = 0;
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen index->opened = FALSE;
94f84d1c3f786d1b92dd2a1507f83a2dad887c56Timo Sirainen}
94f84d1c3f786d1b92dd2a1507f83a2dad887c56Timo Sirainen
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainenint mail_index_reopen(struct mail_index *index, int fd)
2cb0a0438b625cd399a4aaa0615d69f4b54d349aTimo Sirainen{
94f84d1c3f786d1b92dd2a1507f83a2dad887c56Timo Sirainen struct mail_index_map *old_map;
94f84d1c3f786d1b92dd2a1507f83a2dad887c56Timo Sirainen unsigned int old_shared_locks, old_lock_id, lock_id = 0;
94f84d1c3f786d1b92dd2a1507f83a2dad887c56Timo Sirainen int ret, old_fd, old_lock_type;
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen
0bf25546c91ccafff9e2cc93368d2d25acb5c39eTimo Sirainen old_map = index->map;
0bf25546c91ccafff9e2cc93368d2d25acb5c39eTimo Sirainen old_fd = index->fd;
0bf25546c91ccafff9e2cc93368d2d25acb5c39eTimo Sirainen old_map->refcount++;
0bf25546c91ccafff9e2cc93368d2d25acb5c39eTimo Sirainen
0bf25546c91ccafff9e2cc93368d2d25acb5c39eTimo Sirainen /* new file, new locks. the old fd can keep it's locks, they don't
0bf25546c91ccafff9e2cc93368d2d25acb5c39eTimo Sirainen matter anymore as no-one's going to modify the file. */
0bf25546c91ccafff9e2cc93368d2d25acb5c39eTimo Sirainen old_lock_type = index->lock_type;
0bf25546c91ccafff9e2cc93368d2d25acb5c39eTimo Sirainen old_lock_id = index->lock_id;
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen old_shared_locks = index->shared_lock_count;
94f84d1c3f786d1b92dd2a1507f83a2dad887c56Timo Sirainen
94f84d1c3f786d1b92dd2a1507f83a2dad887c56Timo Sirainen if (index->lock_type == F_RDLCK)
94f84d1c3f786d1b92dd2a1507f83a2dad887c56Timo Sirainen index->lock_type = F_UNLCK;
94f84d1c3f786d1b92dd2a1507f83a2dad887c56Timo Sirainen index->lock_id += 2;
94f84d1c3f786d1b92dd2a1507f83a2dad887c56Timo Sirainen index->shared_lock_count = 0;
94f84d1c3f786d1b92dd2a1507f83a2dad887c56Timo Sirainen
94f84d1c3f786d1b92dd2a1507f83a2dad887c56Timo Sirainen if (fd != -1) {
4a14ae55292476bc0b8eb314d602a262ab094a52Timo Sirainen index->fd = fd;
94f84d1c3f786d1b92dd2a1507f83a2dad887c56Timo Sirainen ret = 0;
94f84d1c3f786d1b92dd2a1507f83a2dad887c56Timo Sirainen } else {
94f84d1c3f786d1b92dd2a1507f83a2dad887c56Timo Sirainen i_assert(index->excl_lock_count == 0);
94f84d1c3f786d1b92dd2a1507f83a2dad887c56Timo Sirainen ret = mail_index_try_open_only(index);
94f84d1c3f786d1b92dd2a1507f83a2dad887c56Timo Sirainen if (ret > 0)
94f84d1c3f786d1b92dd2a1507f83a2dad887c56Timo Sirainen ret = mail_index_lock_shared(index, FALSE, &lock_id);
d85f37fe02fadcd5144560495a7196133c8ec947Timo Sirainen else if (ret == 0) {
d85f37fe02fadcd5144560495a7196133c8ec947Timo Sirainen /* index file is lost */
d85f37fe02fadcd5144560495a7196133c8ec947Timo Sirainen ret = -1;
d85f37fe02fadcd5144560495a7196133c8ec947Timo Sirainen }
d85f37fe02fadcd5144560495a7196133c8ec947Timo Sirainen }
94f84d1c3f786d1b92dd2a1507f83a2dad887c56Timo Sirainen
94f84d1c3f786d1b92dd2a1507f83a2dad887c56Timo Sirainen if (ret == 0) {
94f84d1c3f786d1b92dd2a1507f83a2dad887c56Timo Sirainen /* read the new mapping. note that with mmap_disable we want
94f84d1c3f786d1b92dd2a1507f83a2dad887c56Timo Sirainen to keep the old mapping in index->map so we can update it
94f84d1c3f786d1b92dd2a1507f83a2dad887c56Timo Sirainen by reading transaction log. */
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen if (mail_index_map(index, TRUE) <= 0)
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen ret = -1;
94f84d1c3f786d1b92dd2a1507f83a2dad887c56Timo Sirainen }
94f84d1c3f786d1b92dd2a1507f83a2dad887c56Timo Sirainen
94f84d1c3f786d1b92dd2a1507f83a2dad887c56Timo Sirainen if (lock_id != 0)
94f84d1c3f786d1b92dd2a1507f83a2dad887c56Timo Sirainen mail_index_unlock(index, lock_id);
4a14ae55292476bc0b8eb314d602a262ab094a52Timo Sirainen
94f84d1c3f786d1b92dd2a1507f83a2dad887c56Timo Sirainen if (ret == 0) {
94f84d1c3f786d1b92dd2a1507f83a2dad887c56Timo Sirainen mail_index_unmap(index, old_map);
94f84d1c3f786d1b92dd2a1507f83a2dad887c56Timo Sirainen if (close(old_fd) < 0)
94f84d1c3f786d1b92dd2a1507f83a2dad887c56Timo Sirainen mail_index_set_syscall_error(index, "close()");
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen } else {
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen if (index->map != NULL)
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen mail_index_unmap(index, index->map);
76b91bac787101e6b0075122ab6478dd98c8a884Timo Sirainen if (index->fd != -1) {
76b91bac787101e6b0075122ab6478dd98c8a884Timo Sirainen if (close(index->fd) < 0)
76b91bac787101e6b0075122ab6478dd98c8a884Timo Sirainen mail_index_set_syscall_error(index, "close()");
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen }
4b8a6aec5fe2daa564799867f31e39e7ea46b9c3Timo Sirainen
4b8a6aec5fe2daa564799867f31e39e7ea46b9c3Timo Sirainen index->map = old_map;
4b8a6aec5fe2daa564799867f31e39e7ea46b9c3Timo Sirainen index->hdr = &index->map->hdr;
4b8a6aec5fe2daa564799867f31e39e7ea46b9c3Timo Sirainen index->fd = old_fd;
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen index->lock_type = old_lock_type;
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen index->lock_id = old_lock_id;
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen index->shared_lock_count = old_shared_locks;
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen }
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen return ret;
94f84d1c3f786d1b92dd2a1507f83a2dad887c56Timo Sirainen}
94f84d1c3f786d1b92dd2a1507f83a2dad887c56Timo Sirainen
94f84d1c3f786d1b92dd2a1507f83a2dad887c56Timo Sirainenint mail_index_refresh(struct mail_index *index)
94f84d1c3f786d1b92dd2a1507f83a2dad887c56Timo Sirainen{
94f84d1c3f786d1b92dd2a1507f83a2dad887c56Timo Sirainen struct stat st1, st2;
94f84d1c3f786d1b92dd2a1507f83a2dad887c56Timo Sirainen
94f84d1c3f786d1b92dd2a1507f83a2dad887c56Timo Sirainen if (fstat(index->fd, &st1) < 0)
94f84d1c3f786d1b92dd2a1507f83a2dad887c56Timo Sirainen return mail_index_set_syscall_error(index, "fstat()");
94f84d1c3f786d1b92dd2a1507f83a2dad887c56Timo Sirainen if (stat(index->filepath, &st2) < 0) {
43487bb7de9e907ad61e186714956a83f5be4a15Timo Sirainen mail_index_set_syscall_error(index, "stat()");
43487bb7de9e907ad61e186714956a83f5be4a15Timo Sirainen if (errno != ENOENT)
94f84d1c3f786d1b92dd2a1507f83a2dad887c56Timo Sirainen return -1;
94f84d1c3f786d1b92dd2a1507f83a2dad887c56Timo Sirainen
94f84d1c3f786d1b92dd2a1507f83a2dad887c56Timo Sirainen /* lost it? recreate */
442b4c6c0d69e04297c00beb1a06da9855cb5ebeTimo Sirainen (void)mail_index_mark_corrupted(index);
e9df0f285429d2b896ecdb4cd873d25e5e895620Timo Sirainen return -1;
e9df0f285429d2b896ecdb4cd873d25e5e895620Timo Sirainen }
442b4c6c0d69e04297c00beb1a06da9855cb5ebeTimo Sirainen
442b4c6c0d69e04297c00beb1a06da9855cb5ebeTimo Sirainen if (st1.st_ino != st2.st_ino ||
442b4c6c0d69e04297c00beb1a06da9855cb5ebeTimo Sirainen !CMP_DEV_T(st1.st_dev, st2.st_dev)) {
e9df0f285429d2b896ecdb4cd873d25e5e895620Timo Sirainen if (mail_index_reopen(index, -1) < 0)
e9df0f285429d2b896ecdb4cd873d25e5e895620Timo Sirainen return -1;
655fc45da67a4cfa63d9d12cf106961a1afc12b9Aki Tuomi return 1;
655fc45da67a4cfa63d9d12cf106961a1afc12b9Aki Tuomi } else {
442b4c6c0d69e04297c00beb1a06da9855cb5ebeTimo Sirainen return 0;
442b4c6c0d69e04297c00beb1a06da9855cb5ebeTimo Sirainen }
20856c63a2c0f694f32db4368cea2505937570cbTimo Sirainen}
20856c63a2c0f694f32db4368cea2505937570cbTimo Sirainen
20856c63a2c0f694f32db4368cea2505937570cbTimo Sirainenstruct mail_cache *mail_index_get_cache(struct mail_index *index)
20856c63a2c0f694f32db4368cea2505937570cbTimo Sirainen{
20856c63a2c0f694f32db4368cea2505937570cbTimo Sirainen return index->cache;
20856c63a2c0f694f32db4368cea2505937570cbTimo Sirainen}
20856c63a2c0f694f32db4368cea2505937570cbTimo Sirainen
20856c63a2c0f694f32db4368cea2505937570cbTimo Sirainenint mail_index_set_error(struct mail_index *index, const char *fmt, ...)
20856c63a2c0f694f32db4368cea2505937570cbTimo Sirainen{
442b4c6c0d69e04297c00beb1a06da9855cb5ebeTimo Sirainen va_list va;
e9df0f285429d2b896ecdb4cd873d25e5e895620Timo Sirainen
e9df0f285429d2b896ecdb4cd873d25e5e895620Timo Sirainen i_free(index->error);
e9df0f285429d2b896ecdb4cd873d25e5e895620Timo Sirainen
e9df0f285429d2b896ecdb4cd873d25e5e895620Timo Sirainen if (fmt == NULL)
e9df0f285429d2b896ecdb4cd873d25e5e895620Timo Sirainen index->error = NULL;
e9df0f285429d2b896ecdb4cd873d25e5e895620Timo Sirainen else {
442b4c6c0d69e04297c00beb1a06da9855cb5ebeTimo Sirainen va_start(va, fmt);
e9df0f285429d2b896ecdb4cd873d25e5e895620Timo Sirainen index->error = i_strdup_vprintf(fmt, va);
6d931bbce16786df431e9ae8201a78a95084316dTimo Sirainen va_end(va);
442b4c6c0d69e04297c00beb1a06da9855cb5ebeTimo Sirainen
442b4c6c0d69e04297c00beb1a06da9855cb5ebeTimo Sirainen i_error("%s", index->error);
a58e63b4928017b5af123967c1c98f8bcb242a9aTimo Sirainen }
a58e63b4928017b5af123967c1c98f8bcb242a9aTimo Sirainen
a58e63b4928017b5af123967c1c98f8bcb242a9aTimo Sirainen return -1;
a58e63b4928017b5af123967c1c98f8bcb242a9aTimo Sirainen}
2a86a88fb41f4777a937dec3b2d54dedd47ed6ccTimo Sirainen
442b4c6c0d69e04297c00beb1a06da9855cb5ebeTimo Sirainenvoid mail_index_set_inconsistent(struct mail_index *index)
a58e63b4928017b5af123967c1c98f8bcb242a9aTimo Sirainen{
2a86a88fb41f4777a937dec3b2d54dedd47ed6ccTimo Sirainen index->indexid = 0;
6d931bbce16786df431e9ae8201a78a95084316dTimo Sirainen}
442b4c6c0d69e04297c00beb1a06da9855cb5ebeTimo Sirainen
442b4c6c0d69e04297c00beb1a06da9855cb5ebeTimo Sirainenvoid mail_index_mark_corrupted(struct mail_index *index)
442b4c6c0d69e04297c00beb1a06da9855cb5ebeTimo Sirainen{
442b4c6c0d69e04297c00beb1a06da9855cb5ebeTimo Sirainen struct mail_index_header hdr;
442b4c6c0d69e04297c00beb1a06da9855cb5ebeTimo Sirainen
442b4c6c0d69e04297c00beb1a06da9855cb5ebeTimo Sirainen mail_index_set_inconsistent(index);
e9df0f285429d2b896ecdb4cd873d25e5e895620Timo Sirainen
e9df0f285429d2b896ecdb4cd873d25e5e895620Timo Sirainen if (index->readonly)
442b4c6c0d69e04297c00beb1a06da9855cb5ebeTimo Sirainen return;
e9df0f285429d2b896ecdb4cd873d25e5e895620Timo Sirainen
442b4c6c0d69e04297c00beb1a06da9855cb5ebeTimo Sirainen hdr = *index->hdr;
e9df0f285429d2b896ecdb4cd873d25e5e895620Timo Sirainen hdr.flags |= MAIL_INDEX_HDR_FLAG_CORRUPTED;
e9df0f285429d2b896ecdb4cd873d25e5e895620Timo Sirainen if (mail_index_write_base_header(index, &hdr) == 0) {
442b4c6c0d69e04297c00beb1a06da9855cb5ebeTimo Sirainen if (fsync(index->fd) < 0)
e9df0f285429d2b896ecdb4cd873d25e5e895620Timo Sirainen mail_index_set_syscall_error(index, "fsync()");
e9df0f285429d2b896ecdb4cd873d25e5e895620Timo Sirainen }
e9df0f285429d2b896ecdb4cd873d25e5e895620Timo Sirainen}
442b4c6c0d69e04297c00beb1a06da9855cb5ebeTimo Sirainen
e9df0f285429d2b896ecdb4cd873d25e5e895620Timo Sirainenint mail_index_set_syscall_error(struct mail_index *index,
442b4c6c0d69e04297c00beb1a06da9855cb5ebeTimo Sirainen const char *function)
442b4c6c0d69e04297c00beb1a06da9855cb5ebeTimo Sirainen{
442b4c6c0d69e04297c00beb1a06da9855cb5ebeTimo Sirainen i_assert(function != NULL);
442b4c6c0d69e04297c00beb1a06da9855cb5ebeTimo Sirainen
442b4c6c0d69e04297c00beb1a06da9855cb5ebeTimo Sirainen if (ENOSPACE(errno)) {
e9df0f285429d2b896ecdb4cd873d25e5e895620Timo Sirainen index->nodiskspace = TRUE;
442b4c6c0d69e04297c00beb1a06da9855cb5ebeTimo Sirainen return -1;
442b4c6c0d69e04297c00beb1a06da9855cb5ebeTimo Sirainen }
442b4c6c0d69e04297c00beb1a06da9855cb5ebeTimo Sirainen
e9df0f285429d2b896ecdb4cd873d25e5e895620Timo Sirainen return mail_index_set_error(index, "%s failed with index file %s: %m",
e9df0f285429d2b896ecdb4cd873d25e5e895620Timo Sirainen function, index->filepath);
442b4c6c0d69e04297c00beb1a06da9855cb5ebeTimo Sirainen}
e9df0f285429d2b896ecdb4cd873d25e5e895620Timo Sirainen
442b4c6c0d69e04297c00beb1a06da9855cb5ebeTimo Sirainenint mail_index_file_set_syscall_error(struct mail_index *index,
442b4c6c0d69e04297c00beb1a06da9855cb5ebeTimo Sirainen const char *filepath,
6d931bbce16786df431e9ae8201a78a95084316dTimo Sirainen const char *function)
442b4c6c0d69e04297c00beb1a06da9855cb5ebeTimo Sirainen{
6d931bbce16786df431e9ae8201a78a95084316dTimo Sirainen i_assert(filepath != NULL);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen i_assert(function != NULL);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
442b4c6c0d69e04297c00beb1a06da9855cb5ebeTimo Sirainen if (ENOSPACE(errno)) {
e9df0f285429d2b896ecdb4cd873d25e5e895620Timo Sirainen index->nodiskspace = TRUE;
e9df0f285429d2b896ecdb4cd873d25e5e895620Timo Sirainen return -1;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen }
64ee8113a88e5d6e3cba7b1c4abd537cc2632bb9Timo Sirainen
64ee8113a88e5d6e3cba7b1c4abd537cc2632bb9Timo Sirainen return mail_index_set_error(index, "%s failed with file %s: %m",
64ee8113a88e5d6e3cba7b1c4abd537cc2632bb9Timo Sirainen function, filepath);
64ee8113a88e5d6e3cba7b1c4abd537cc2632bb9Timo Sirainen}
64ee8113a88e5d6e3cba7b1c4abd537cc2632bb9Timo Sirainen
64ee8113a88e5d6e3cba7b1c4abd537cc2632bb9Timo Sirainenenum mail_index_error mail_index_get_last_error(struct mail_index *index)
64ee8113a88e5d6e3cba7b1c4abd537cc2632bb9Timo Sirainen{
64ee8113a88e5d6e3cba7b1c4abd537cc2632bb9Timo Sirainen if (index->nodiskspace)
625042f95d7eb71f6b94a61ea4f461866be1bef9Timo Sirainen return MAIL_INDEX_ERROR_DISKSPACE;
625042f95d7eb71f6b94a61ea4f461866be1bef9Timo Sirainen if (index->error != NULL)
e9df0f285429d2b896ecdb4cd873d25e5e895620Timo Sirainen return MAIL_INDEX_ERROR_INTERNAL;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen return MAIL_INDEX_ERROR_NONE;
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen}
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainenconst char *mail_index_get_error_message(struct mail_index *index)
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen{
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen return index->error;
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen}
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainenvoid mail_index_reset_error(struct mail_index *index)
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen{
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen if (index->error != NULL) {
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen i_free(index->error);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen index->error = NULL;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen }
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen index->nodiskspace = FALSE;
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen index->index_lock_timeout = FALSE;
a10ed8c47534b4c6b6bf2711ccfe577e720a47b4Timo Sirainen}
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainenuint32_t mail_index_uint32_to_offset(uint32_t offset)
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen{
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen unsigned char buf[4];
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen i_assert(offset < 0x40000000);
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen i_assert((offset & 3) == 0);
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen offset >>= 2;
a10ed8c47534b4c6b6bf2711ccfe577e720a47b4Timo Sirainen buf[0] = 0x80 | ((offset & 0x0fe00000) >> 21);
a10ed8c47534b4c6b6bf2711ccfe577e720a47b4Timo Sirainen buf[1] = 0x80 | ((offset & 0x001fc000) >> 14);
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen buf[2] = 0x80 | ((offset & 0x00003f80) >> 7);
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen buf[3] = 0x80 | (offset & 0x0000007f);
e0ca8f2484847b57e20798a9f9c7040708696a90Timo Sirainen return *((uint32_t *) buf);
e0ca8f2484847b57e20798a9f9c7040708696a90Timo Sirainen}
e0ca8f2484847b57e20798a9f9c7040708696a90Timo Sirainen
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainenuint32_t mail_index_offset_to_uint32(uint32_t offset)
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen{
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen const unsigned char *buf = (const unsigned char *) &offset;
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen if ((offset & 0x80808080) != 0x80808080)
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen return 0;
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen return (((uint32_t)buf[3] & 0x7f) << 2) |
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen (((uint32_t)buf[2] & 0x7f) << 9) |
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen (((uint32_t)buf[1] & 0x7f) << 16) |
9fc97c8aa8190df87624d214bcc5d0b5362bec93Timo Sirainen (((uint32_t)buf[0] & 0x7f) << 23);
e0ca8f2484847b57e20798a9f9c7040708696a90Timo Sirainen}
e0ca8f2484847b57e20798a9f9c7040708696a90Timo Sirainen