mail-index-map-read.c revision 9644b7914445f0fb1098038218bfcb7d135a8698
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen/* Copyright (c) 2003-2016 Dovecot authors, see the included COPYING file */
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen#include "lib.h"
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen#include "array.h"
78fa3c578c14ee8a612f86cf73b6181c7f16463fTimo Sirainen#include "nfs-workarounds.h"
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen#include "mmap-util.h"
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen#include "read-full.h"
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen#include "mail-index-private.h"
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen#include "mail-index-sync-private.h"
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen#include "mail-transaction-log-private.h"
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen#include "ioloop.h"
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainenstatic void mail_index_map_copy_hdr(struct mail_index_map *map,
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen const struct mail_index_header *hdr)
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen{
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if (hdr->base_header_size < sizeof(map->hdr)) {
6ec925f52d04ec8700e47cb005bd7ddc65ac5614Timo Sirainen /* header smaller than ours, make a copy so our newer headers
c60178b2610a9b193ff72aa18448398ef72529a1Timo Sirainen won't have garbage in them */
4d4d6d4745682790c20d759ba93dbea46b812c5dTimo Sirainen memset(&map->hdr, 0, sizeof(map->hdr));
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen memcpy(&map->hdr, hdr, hdr->base_header_size);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen } else {
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen map->hdr = *hdr;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen }
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen /* FIXME: backwards compatibility, remove later. In case this index is
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen accessed with Dovecot v1.0, avoid recent message counter errors. */
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen map->hdr.unused_old_recent_messages_count = 0;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen}
5323bec1c24184863a13bc14a2dc9487093eea3dTimo Sirainen
5323bec1c24184863a13bc14a2dc9487093eea3dTimo Sirainenstatic int mail_index_mmap(struct mail_index_map *map, uoff_t file_size)
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen{
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen struct mail_index *index = map->index;
617e13833c798435e2be425b99c27ecaad1b8393Timo Sirainen struct mail_index_record_map *rec_map = map->rec_map;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen const struct mail_index_header *hdr;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen const char *error;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen i_assert(rec_map->mmap_base == NULL);
c60178b2610a9b193ff72aa18448398ef72529a1Timo Sirainen
c60178b2610a9b193ff72aa18448398ef72529a1Timo Sirainen buffer_free(&rec_map->buffer);
c60178b2610a9b193ff72aa18448398ef72529a1Timo Sirainen if (file_size > SSIZE_T_MAX) {
c60178b2610a9b193ff72aa18448398ef72529a1Timo Sirainen /* too large file to map into memory */
c60178b2610a9b193ff72aa18448398ef72529a1Timo Sirainen mail_index_set_error(index, "Index file too large: %s",
c60178b2610a9b193ff72aa18448398ef72529a1Timo Sirainen index->filepath);
78fa3c578c14ee8a612f86cf73b6181c7f16463fTimo Sirainen return -1;
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen }
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen rec_map->mmap_base = mmap(NULL, file_size, PROT_READ | PROT_WRITE,
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen MAP_PRIVATE, index->fd, 0);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if (rec_map->mmap_base == MAP_FAILED) {
7487ff578435377bbeefffdbfb78ca09ed1292dfTimo Sirainen rec_map->mmap_base = NULL;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if (ioloop_time != index->last_mmap_error_time) {
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen index->last_mmap_error_time = ioloop_time;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen mail_index_set_syscall_error(index, t_strdup_printf(
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen "mmap(size=%"PRIuUOFF_T")", file_size));
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen }
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen return -1;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen }
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen rec_map->mmap_size = file_size;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen hdr = rec_map->mmap_base;
78fa3c578c14ee8a612f86cf73b6181c7f16463fTimo Sirainen if (rec_map->mmap_size >
78fa3c578c14ee8a612f86cf73b6181c7f16463fTimo Sirainen offsetof(struct mail_index_header, major_version) &&
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen hdr->major_version != MAIL_INDEX_MAJOR_VERSION) {
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen /* major version change - handle silently */
78fa3c578c14ee8a612f86cf73b6181c7f16463fTimo Sirainen return 0;
78fa3c578c14ee8a612f86cf73b6181c7f16463fTimo Sirainen }
78fa3c578c14ee8a612f86cf73b6181c7f16463fTimo Sirainen
78fa3c578c14ee8a612f86cf73b6181c7f16463fTimo Sirainen if (rec_map->mmap_size < MAIL_INDEX_HEADER_MIN_SIZE) {
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen mail_index_set_error(index, "Corrupted index file %s: "
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen "File too small (%"PRIuSIZE_T")",
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen index->filepath, rec_map->mmap_size);
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen return 0;
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen }
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen if (!mail_index_check_header_compat(index, hdr, rec_map->mmap_size, &error)) {
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen /* Can't use this file */
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen mail_index_set_error(index, "Corrupted index file %s: %s",
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen index->filepath, error);
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen return 0;
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen }
78fa3c578c14ee8a612f86cf73b6181c7f16463fTimo Sirainen
78fa3c578c14ee8a612f86cf73b6181c7f16463fTimo Sirainen rec_map->mmap_used_size = hdr->header_size +
7487ff578435377bbeefffdbfb78ca09ed1292dfTimo Sirainen hdr->messages_count * hdr->record_size;
78fa3c578c14ee8a612f86cf73b6181c7f16463fTimo Sirainen
7487ff578435377bbeefffdbfb78ca09ed1292dfTimo Sirainen if (rec_map->mmap_used_size <= rec_map->mmap_size)
617e13833c798435e2be425b99c27ecaad1b8393Timo Sirainen rec_map->records_count = hdr->messages_count;
617e13833c798435e2be425b99c27ecaad1b8393Timo Sirainen else {
7487ff578435377bbeefffdbfb78ca09ed1292dfTimo Sirainen rec_map->records_count =
7487ff578435377bbeefffdbfb78ca09ed1292dfTimo Sirainen (rec_map->mmap_size - hdr->header_size) /
7487ff578435377bbeefffdbfb78ca09ed1292dfTimo Sirainen hdr->record_size;
7487ff578435377bbeefffdbfb78ca09ed1292dfTimo Sirainen rec_map->mmap_used_size = hdr->header_size +
7487ff578435377bbeefffdbfb78ca09ed1292dfTimo Sirainen rec_map->records_count * hdr->record_size;
7487ff578435377bbeefffdbfb78ca09ed1292dfTimo Sirainen mail_index_set_error(index, "Corrupted index file %s: "
7487ff578435377bbeefffdbfb78ca09ed1292dfTimo Sirainen "messages_count too large (%u > %u)",
7487ff578435377bbeefffdbfb78ca09ed1292dfTimo Sirainen index->filepath, hdr->messages_count,
7487ff578435377bbeefffdbfb78ca09ed1292dfTimo Sirainen rec_map->records_count);
617e13833c798435e2be425b99c27ecaad1b8393Timo Sirainen }
7487ff578435377bbeefffdbfb78ca09ed1292dfTimo Sirainen
7487ff578435377bbeefffdbfb78ca09ed1292dfTimo Sirainen mail_index_map_copy_hdr(map, hdr);
7487ff578435377bbeefffdbfb78ca09ed1292dfTimo Sirainen
7487ff578435377bbeefffdbfb78ca09ed1292dfTimo Sirainen map->hdr_base = rec_map->mmap_base;
7487ff578435377bbeefffdbfb78ca09ed1292dfTimo Sirainen rec_map->records = PTR_OFFSET(rec_map->mmap_base, map->hdr.header_size);
7487ff578435377bbeefffdbfb78ca09ed1292dfTimo Sirainen return 1;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen}
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainenstatic int mail_index_read_header(struct mail_index *index,
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen void *buf, size_t buf_size, size_t *pos_r)
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen{
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen size_t pos;
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen int ret;
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen memset(buf, 0, sizeof(struct mail_index_header));
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen /* try to read the whole header, but it's not necessarily an error to
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen read less since the older versions of the index format could be
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen smaller. Request reading up to buf_size, but accept if we only got
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen the header. */
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen pos = 0;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen do {
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen ret = pread(index->fd, PTR_OFFSET(buf, pos),
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen buf_size - pos, pos);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if (ret > 0)
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen pos += ret;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen } while (ret > 0 && pos < sizeof(struct mail_index_header));
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen *pos_r = pos;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen return ret;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen}
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainenstatic int
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainenmail_index_try_read_map(struct mail_index_map *map,
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen uoff_t file_size, bool *retry_r, bool try_retry)
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen{
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen struct mail_index *index = map->index;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen const struct mail_index_header *hdr;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen unsigned char read_buf[IO_BLOCK_SIZE];
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen const char *error;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen const void *buf;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen void *data = NULL;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen ssize_t ret;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen size_t pos, records_size, initial_buf_pos = 0;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen unsigned int records_count = 0, extra;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen i_assert(map->rec_map->mmap_base == NULL);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen *retry_r = FALSE;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen ret = mail_index_read_header(index, read_buf, sizeof(read_buf), &pos);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen buf = read_buf; hdr = buf;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if (pos > (ssize_t)offsetof(struct mail_index_header, major_version) &&
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen hdr->major_version != MAIL_INDEX_MAJOR_VERSION) {
55bc6a7a0940ec48a68558ef70838991c5d301d2Timo Sirainen /* major version change - handle silently */
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen return 0;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen }
7487ff578435377bbeefffdbfb78ca09ed1292dfTimo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if (ret >= 0 && pos >= MAIL_INDEX_HEADER_MIN_SIZE &&
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen (ret > 0 || pos >= hdr->base_header_size)) {
fb7ac3e31c92627efe076318319976ac1c27ae2aTimo Sirainen if (!mail_index_check_header_compat(index, hdr, file_size, &error)) {
fb7ac3e31c92627efe076318319976ac1c27ae2aTimo Sirainen /* Can't use this file */
fb7ac3e31c92627efe076318319976ac1c27ae2aTimo Sirainen mail_index_set_error(index, "Corrupted index file %s: %s",
fb7ac3e31c92627efe076318319976ac1c27ae2aTimo Sirainen index->filepath, error);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen return 0;
fb7ac3e31c92627efe076318319976ac1c27ae2aTimo Sirainen }
fb7ac3e31c92627efe076318319976ac1c27ae2aTimo Sirainen
fb7ac3e31c92627efe076318319976ac1c27ae2aTimo Sirainen initial_buf_pos = pos;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if (pos > hdr->header_size)
d74c7c6d900f7b38017403a0da9106b8a6c647b2Timo Sirainen pos = hdr->header_size;
5323bec1c24184863a13bc14a2dc9487093eea3dTimo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen /* place the base header into memory. */
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen buffer_set_used_size(map->hdr_copy_buf, 0);
fb7ac3e31c92627efe076318319976ac1c27ae2aTimo Sirainen buffer_append(map->hdr_copy_buf, buf, pos);
fb7ac3e31c92627efe076318319976ac1c27ae2aTimo Sirainen
fb7ac3e31c92627efe076318319976ac1c27ae2aTimo Sirainen if (pos != hdr->header_size) {
fb7ac3e31c92627efe076318319976ac1c27ae2aTimo Sirainen /* @UNSAFE: read the rest of the header into memory */
fb7ac3e31c92627efe076318319976ac1c27ae2aTimo Sirainen data = buffer_append_space_unsafe(map->hdr_copy_buf,
fb7ac3e31c92627efe076318319976ac1c27ae2aTimo Sirainen hdr->header_size -
fb7ac3e31c92627efe076318319976ac1c27ae2aTimo Sirainen pos);
fb7ac3e31c92627efe076318319976ac1c27ae2aTimo Sirainen ret = pread_full(index->fd, data,
fb7ac3e31c92627efe076318319976ac1c27ae2aTimo Sirainen hdr->header_size - pos, pos);
fb7ac3e31c92627efe076318319976ac1c27ae2aTimo Sirainen }
fb7ac3e31c92627efe076318319976ac1c27ae2aTimo Sirainen }
fb7ac3e31c92627efe076318319976ac1c27ae2aTimo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if (ret > 0) {
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen /* header read, read the records now. */
5323bec1c24184863a13bc14a2dc9487093eea3dTimo Sirainen records_size = (size_t)hdr->messages_count * hdr->record_size;
0ef40aa9ca6084393fe0a56feac2cf801e8b52f0Timo Sirainen records_count = hdr->messages_count;
5323bec1c24184863a13bc14a2dc9487093eea3dTimo Sirainen
5323bec1c24184863a13bc14a2dc9487093eea3dTimo Sirainen if (file_size - hdr->header_size < records_size ||
d74c7c6d900f7b38017403a0da9106b8a6c647b2Timo Sirainen (hdr->record_size != 0 &&
0ef40aa9ca6084393fe0a56feac2cf801e8b52f0Timo Sirainen records_size / hdr->record_size != hdr->messages_count)) {
0ef40aa9ca6084393fe0a56feac2cf801e8b52f0Timo Sirainen records_count = (file_size - hdr->header_size) /
5323bec1c24184863a13bc14a2dc9487093eea3dTimo Sirainen hdr->record_size;
0ef40aa9ca6084393fe0a56feac2cf801e8b52f0Timo Sirainen records_size = (size_t)records_count * hdr->record_size;
0ef40aa9ca6084393fe0a56feac2cf801e8b52f0Timo Sirainen mail_index_set_error(index, "Corrupted index file %s: "
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen "messages_count too large (%u > %u)",
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen index->filepath, hdr->messages_count,
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen records_count);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen }
5323bec1c24184863a13bc14a2dc9487093eea3dTimo Sirainen
0ef40aa9ca6084393fe0a56feac2cf801e8b52f0Timo Sirainen if (map->rec_map->buffer == NULL) {
5323bec1c24184863a13bc14a2dc9487093eea3dTimo Sirainen map->rec_map->buffer =
5323bec1c24184863a13bc14a2dc9487093eea3dTimo Sirainen buffer_create_dynamic(default_pool,
d74c7c6d900f7b38017403a0da9106b8a6c647b2Timo Sirainen records_size);
0ef40aa9ca6084393fe0a56feac2cf801e8b52f0Timo Sirainen }
0ef40aa9ca6084393fe0a56feac2cf801e8b52f0Timo Sirainen
5323bec1c24184863a13bc14a2dc9487093eea3dTimo Sirainen /* @UNSAFE */
0ef40aa9ca6084393fe0a56feac2cf801e8b52f0Timo Sirainen buffer_set_used_size(map->rec_map->buffer, 0);
0ef40aa9ca6084393fe0a56feac2cf801e8b52f0Timo Sirainen if (initial_buf_pos <= hdr->header_size)
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen extra = 0;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen else {
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen extra = initial_buf_pos - hdr->header_size;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen buffer_append(map->rec_map->buffer,
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen CONST_PTR_OFFSET(buf, hdr->header_size),
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen extra);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen }
e3ae2ac7a93b418cf46e829c94973b6e962a7830Timo Sirainen if (records_size > extra) {
e3ae2ac7a93b418cf46e829c94973b6e962a7830Timo Sirainen data = buffer_append_space_unsafe(map->rec_map->buffer,
e3ae2ac7a93b418cf46e829c94973b6e962a7830Timo Sirainen records_size - extra);
e3ae2ac7a93b418cf46e829c94973b6e962a7830Timo Sirainen ret = pread_full(index->fd, data, records_size - extra,
e3ae2ac7a93b418cf46e829c94973b6e962a7830Timo Sirainen hdr->header_size + extra);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen }
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen }
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if (ret < 0) {
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if (errno == ESTALE && try_retry) {
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen /* a new index file was renamed over this one. */
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen *retry_r = TRUE;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen return 0;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen }
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen mail_index_set_syscall_error(index, "pread_full()");
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen return -1;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen }
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if (ret == 0) {
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen mail_index_set_error(index,
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen "Corrupted index file %s: File too small",
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen index->filepath);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen return 0;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen }
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
e3ae2ac7a93b418cf46e829c94973b6e962a7830Timo Sirainen map->rec_map->records =
e3ae2ac7a93b418cf46e829c94973b6e962a7830Timo Sirainen buffer_get_modifiable_data(map->rec_map->buffer, NULL);
e3ae2ac7a93b418cf46e829c94973b6e962a7830Timo Sirainen map->rec_map->records_count = records_count;
e3ae2ac7a93b418cf46e829c94973b6e962a7830Timo Sirainen
e3ae2ac7a93b418cf46e829c94973b6e962a7830Timo Sirainen mail_index_map_copy_hdr(map, hdr);
e3ae2ac7a93b418cf46e829c94973b6e962a7830Timo Sirainen map->hdr_base = map->hdr_copy_buf->data;
e3ae2ac7a93b418cf46e829c94973b6e962a7830Timo Sirainen i_assert(map->hdr_copy_buf->used == map->hdr.header_size);
e3ae2ac7a93b418cf46e829c94973b6e962a7830Timo Sirainen return 1;
e3ae2ac7a93b418cf46e829c94973b6e962a7830Timo Sirainen}
e3ae2ac7a93b418cf46e829c94973b6e962a7830Timo Sirainen
e3ae2ac7a93b418cf46e829c94973b6e962a7830Timo Sirainenstatic int mail_index_read_map(struct mail_index_map *map, uoff_t file_size)
e3ae2ac7a93b418cf46e829c94973b6e962a7830Timo Sirainen{
e3ae2ac7a93b418cf46e829c94973b6e962a7830Timo Sirainen struct mail_index *index = map->index;
e3ae2ac7a93b418cf46e829c94973b6e962a7830Timo Sirainen mail_index_sync_lost_handler_t *const *handlerp;
e3ae2ac7a93b418cf46e829c94973b6e962a7830Timo Sirainen struct stat st;
e3ae2ac7a93b418cf46e829c94973b6e962a7830Timo Sirainen unsigned int i;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen int ret;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen bool try_retry, retry;
e3ae2ac7a93b418cf46e829c94973b6e962a7830Timo Sirainen
e3ae2ac7a93b418cf46e829c94973b6e962a7830Timo Sirainen /* notify all "sync lost" handlers */
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen array_foreach(&index->sync_lost_handlers, handlerp)
617e13833c798435e2be425b99c27ecaad1b8393Timo Sirainen (**handlerp)(index);
617e13833c798435e2be425b99c27ecaad1b8393Timo Sirainen
617e13833c798435e2be425b99c27ecaad1b8393Timo Sirainen for (i = 0;; i++) {
617e13833c798435e2be425b99c27ecaad1b8393Timo Sirainen try_retry = i < MAIL_INDEX_ESTALE_RETRY_COUNT;
617e13833c798435e2be425b99c27ecaad1b8393Timo Sirainen if (file_size == (uoff_t)-1) {
617e13833c798435e2be425b99c27ecaad1b8393Timo Sirainen /* fstat() below failed */
617e13833c798435e2be425b99c27ecaad1b8393Timo Sirainen ret = 0;
617e13833c798435e2be425b99c27ecaad1b8393Timo Sirainen retry = try_retry;
617e13833c798435e2be425b99c27ecaad1b8393Timo Sirainen } else {
617e13833c798435e2be425b99c27ecaad1b8393Timo Sirainen ret = mail_index_try_read_map(map, file_size,
617e13833c798435e2be425b99c27ecaad1b8393Timo Sirainen &retry, try_retry);
617e13833c798435e2be425b99c27ecaad1b8393Timo Sirainen }
617e13833c798435e2be425b99c27ecaad1b8393Timo Sirainen if (ret != 0 || !retry)
617e13833c798435e2be425b99c27ecaad1b8393Timo Sirainen break;
617e13833c798435e2be425b99c27ecaad1b8393Timo Sirainen
c60178b2610a9b193ff72aa18448398ef72529a1Timo Sirainen /* ESTALE - reopen index file */
c60178b2610a9b193ff72aa18448398ef72529a1Timo Sirainen mail_index_close_file(index);
c60178b2610a9b193ff72aa18448398ef72529a1Timo Sirainen
c60178b2610a9b193ff72aa18448398ef72529a1Timo Sirainen ret = mail_index_try_open_only(index);
c60178b2610a9b193ff72aa18448398ef72529a1Timo Sirainen if (ret <= 0) {
c60178b2610a9b193ff72aa18448398ef72529a1Timo Sirainen if (ret == 0) {
c60178b2610a9b193ff72aa18448398ef72529a1Timo Sirainen /* the file was lost */
c60178b2610a9b193ff72aa18448398ef72529a1Timo Sirainen errno = ENOENT;
c60178b2610a9b193ff72aa18448398ef72529a1Timo Sirainen mail_index_set_syscall_error(index, "open()");
c60178b2610a9b193ff72aa18448398ef72529a1Timo Sirainen }
c60178b2610a9b193ff72aa18448398ef72529a1Timo Sirainen return -1;
c60178b2610a9b193ff72aa18448398ef72529a1Timo Sirainen }
c60178b2610a9b193ff72aa18448398ef72529a1Timo Sirainen
c60178b2610a9b193ff72aa18448398ef72529a1Timo Sirainen if (fstat(index->fd, &st) == 0)
c60178b2610a9b193ff72aa18448398ef72529a1Timo Sirainen file_size = st.st_size;
c60178b2610a9b193ff72aa18448398ef72529a1Timo Sirainen else {
c60178b2610a9b193ff72aa18448398ef72529a1Timo Sirainen if (!ESTALE_FSTAT(errno)) {
c60178b2610a9b193ff72aa18448398ef72529a1Timo Sirainen mail_index_set_syscall_error(index, "fstat()");
c60178b2610a9b193ff72aa18448398ef72529a1Timo Sirainen return -1;
c60178b2610a9b193ff72aa18448398ef72529a1Timo Sirainen }
c60178b2610a9b193ff72aa18448398ef72529a1Timo Sirainen file_size = (uoff_t)-1;
c60178b2610a9b193ff72aa18448398ef72529a1Timo Sirainen }
c60178b2610a9b193ff72aa18448398ef72529a1Timo Sirainen }
c60178b2610a9b193ff72aa18448398ef72529a1Timo Sirainen return ret;
c60178b2610a9b193ff72aa18448398ef72529a1Timo Sirainen}
c60178b2610a9b193ff72aa18448398ef72529a1Timo Sirainen
c60178b2610a9b193ff72aa18448398ef72529a1Timo Sirainen/* returns -1 = error, 0 = index files are unusable,
c60178b2610a9b193ff72aa18448398ef72529a1Timo Sirainen 1 = index files are usable or at least repairable */
c60178b2610a9b193ff72aa18448398ef72529a1Timo Sirainenstatic int
c60178b2610a9b193ff72aa18448398ef72529a1Timo Sirainenmail_index_map_latest_file(struct mail_index *index, const char **reason_r)
c60178b2610a9b193ff72aa18448398ef72529a1Timo Sirainen{
c60178b2610a9b193ff72aa18448398ef72529a1Timo Sirainen struct mail_index_map *old_map, *new_map;
c60178b2610a9b193ff72aa18448398ef72529a1Timo Sirainen struct stat st;
c60178b2610a9b193ff72aa18448398ef72529a1Timo Sirainen uoff_t file_size;
c60178b2610a9b193ff72aa18448398ef72529a1Timo Sirainen bool use_mmap, unusable = FALSE;
c60178b2610a9b193ff72aa18448398ef72529a1Timo Sirainen const char *error;
c60178b2610a9b193ff72aa18448398ef72529a1Timo Sirainen int ret, try;
c60178b2610a9b193ff72aa18448398ef72529a1Timo Sirainen
c60178b2610a9b193ff72aa18448398ef72529a1Timo Sirainen *reason_r = NULL;
c60178b2610a9b193ff72aa18448398ef72529a1Timo Sirainen
c60178b2610a9b193ff72aa18448398ef72529a1Timo Sirainen ret = mail_index_reopen_if_changed(index, reason_r);
c60178b2610a9b193ff72aa18448398ef72529a1Timo Sirainen if (ret <= 0) {
c60178b2610a9b193ff72aa18448398ef72529a1Timo Sirainen if (ret < 0)
c60178b2610a9b193ff72aa18448398ef72529a1Timo Sirainen return -1;
c60178b2610a9b193ff72aa18448398ef72529a1Timo Sirainen
c60178b2610a9b193ff72aa18448398ef72529a1Timo Sirainen /* the index file is lost/broken. let's hope that we can
c60178b2610a9b193ff72aa18448398ef72529a1Timo Sirainen build it from the transaction log. */
c60178b2610a9b193ff72aa18448398ef72529a1Timo Sirainen return 1;
c60178b2610a9b193ff72aa18448398ef72529a1Timo Sirainen }
c60178b2610a9b193ff72aa18448398ef72529a1Timo Sirainen i_assert(index->fd != -1);
c60178b2610a9b193ff72aa18448398ef72529a1Timo Sirainen
c60178b2610a9b193ff72aa18448398ef72529a1Timo Sirainen if ((index->flags & MAIL_INDEX_OPEN_FLAG_NFS_FLUSH) != 0)
c60178b2610a9b193ff72aa18448398ef72529a1Timo Sirainen nfs_flush_attr_cache_fd_locked(index->filepath, index->fd);
c60178b2610a9b193ff72aa18448398ef72529a1Timo Sirainen
c60178b2610a9b193ff72aa18448398ef72529a1Timo Sirainen if (fstat(index->fd, &st) == 0)
c60178b2610a9b193ff72aa18448398ef72529a1Timo Sirainen file_size = st.st_size;
c60178b2610a9b193ff72aa18448398ef72529a1Timo Sirainen else {
c60178b2610a9b193ff72aa18448398ef72529a1Timo Sirainen if (!ESTALE_FSTAT(errno)) {
c60178b2610a9b193ff72aa18448398ef72529a1Timo Sirainen mail_index_set_syscall_error(index, "fstat()");
fb7ac3e31c92627efe076318319976ac1c27ae2aTimo Sirainen return -1;
fb7ac3e31c92627efe076318319976ac1c27ae2aTimo Sirainen }
fb7ac3e31c92627efe076318319976ac1c27ae2aTimo Sirainen file_size = (uoff_t)-1;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen }
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen /* mmaping seems to be slower than just reading the file, so even if
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen mmap isn't disabled don't use it unless the file is large enough */
72cc352b25ad401b923436c6ed0f1f3adaffa737Timo Sirainen use_mmap = (index->flags & MAIL_INDEX_OPEN_FLAG_MMAP_DISABLE) == 0 &&
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen file_size != (uoff_t)-1 && file_size > MAIL_INDEX_MMAP_MIN_SIZE;
e154d8764089896a693cbb83d6831b2398f22ee8Timo Sirainen
e154d8764089896a693cbb83d6831b2398f22ee8Timo Sirainen new_map = mail_index_map_alloc(index);
e154d8764089896a693cbb83d6831b2398f22ee8Timo Sirainen if (use_mmap) {
6ec925f52d04ec8700e47cb005bd7ddc65ac5614Timo Sirainen ret = mail_index_mmap(new_map, file_size);
6ec925f52d04ec8700e47cb005bd7ddc65ac5614Timo Sirainen } else {
6ec925f52d04ec8700e47cb005bd7ddc65ac5614Timo Sirainen ret = mail_index_read_map(new_map, file_size);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen }
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if (ret == 0) {
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen /* the index files are unusable */
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen unusable = TRUE;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen }
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen for (try = 0; ret > 0; try++) {
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen /* make sure the header is ok before using this mapping */
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen ret = mail_index_map_check_header(new_map, &error);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if (ret < 0) {
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen mail_index_set_error(index,
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen "Corrupted index file %s: %s",
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen index->filepath, error);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen }
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if (ret > 0) T_BEGIN {
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if (mail_index_map_parse_extensions(new_map) < 0)
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen ret = 0;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen else if (mail_index_map_parse_keywords(new_map) < 0)
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen ret = 0;
617e13833c798435e2be425b99c27ecaad1b8393Timo Sirainen } T_END;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if (ret != 0 || try == 2) {
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if (ret < 0) {
fb7ac3e31c92627efe076318319976ac1c27ae2aTimo Sirainen *reason_r = "Corrupted index file";
fb7ac3e31c92627efe076318319976ac1c27ae2aTimo Sirainen unusable = TRUE;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen ret = 0;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen }
c60178b2610a9b193ff72aa18448398ef72529a1Timo Sirainen break;
c60178b2610a9b193ff72aa18448398ef72529a1Timo Sirainen }
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
72cc352b25ad401b923436c6ed0f1f3adaffa737Timo Sirainen /* fsck and try again */
72cc352b25ad401b923436c6ed0f1f3adaffa737Timo Sirainen old_map = index->map;
72cc352b25ad401b923436c6ed0f1f3adaffa737Timo Sirainen index->map = new_map;
72cc352b25ad401b923436c6ed0f1f3adaffa737Timo Sirainen if (mail_index_fsck(index) < 0) {
72cc352b25ad401b923436c6ed0f1f3adaffa737Timo Sirainen ret = -1;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen break;
72cc352b25ad401b923436c6ed0f1f3adaffa737Timo Sirainen }
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen /* fsck replaced the map */
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen new_map = index->map;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen index->map = old_map;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen }
bad5fa318c6c1384ab83bd72d53ce06593274c18Timo Sirainen if (ret <= 0) {
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen mail_index_unmap(&new_map);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen return ret < 0 ? -1 : (unusable ? 0 : 1);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen }
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen i_assert(new_map->rec_map->records != NULL);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen index->last_read_log_file_seq = new_map->hdr.log_file_seq;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen index->last_read_log_file_tail_offset =
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen new_map->hdr.log_file_tail_offset;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen mail_index_unmap(&index->map);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen index->map = new_map;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen *reason_r = "Index mapped";
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen return 1;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen}
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainenint mail_index_map(struct mail_index *index,
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen enum mail_index_sync_handler_type type)
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen{
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen const char *reason;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen int ret;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen i_assert(!index->mapping);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
bad5fa318c6c1384ab83bd72d53ce06593274c18Timo Sirainen index->mapping = TRUE;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if (index->map == NULL)
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen index->map = mail_index_map_alloc(index);
3a0f9aa9504497e4e47f32df54fbf47fdc7423b6Timo Sirainen
3a0f9aa9504497e4e47f32df54fbf47fdc7423b6Timo Sirainen /* first try updating the existing mapping from transaction log. */
788f275469ad9ed530e440d6690d0e4381a323b2Timo Sirainen if (index->initial_mapped) {
788f275469ad9ed530e440d6690d0e4381a323b2Timo Sirainen /* we're not creating/opening the index.
788f275469ad9ed530e440d6690d0e4381a323b2Timo Sirainen sync this as a view from transaction log. */
788f275469ad9ed530e440d6690d0e4381a323b2Timo Sirainen ret = mail_index_sync_map(&index->map, type, FALSE, "initial mapping");
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen } else {
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen ret = 0;
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen }
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen
43d7e7ce608f5451e4907b5f5c48c00beb265802Timo Sirainen if (ret == 0) {
43d7e7ce608f5451e4907b5f5c48c00beb265802Timo Sirainen /* try to open and read the latest index. if it fails, we'll
43d7e7ce608f5451e4907b5f5c48c00beb265802Timo Sirainen fallback to updating the existing mapping from transaction
43d7e7ce608f5451e4907b5f5c48c00beb265802Timo Sirainen logs (which we'll also do even if the reopening succeeds).
43d7e7ce608f5451e4907b5f5c48c00beb265802Timo Sirainen if index files are unusable (e.g. major version change)
43d7e7ce608f5451e4907b5f5c48c00beb265802Timo Sirainen don't even try to use the transaction log. */
43d7e7ce608f5451e4907b5f5c48c00beb265802Timo Sirainen ret = mail_index_map_latest_file(index, &reason);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if (ret > 0) {
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen /* if we're creating the index file, we don't have any
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen logs yet */
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if (index->log->head != NULL && index->indexid != 0) {
55bc6a7a0940ec48a68558ef70838991c5d301d2Timo Sirainen /* and update the map with the latest changes
55bc6a7a0940ec48a68558ef70838991c5d301d2Timo Sirainen from transaction log */
55bc6a7a0940ec48a68558ef70838991c5d301d2Timo Sirainen ret = mail_index_sync_map(&index->map, type,
55bc6a7a0940ec48a68558ef70838991c5d301d2Timo Sirainen TRUE, reason);
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen }
55bc6a7a0940ec48a68558ef70838991c5d301d2Timo Sirainen } else if (ret == 0 && !index->readonly) {
55bc6a7a0940ec48a68558ef70838991c5d301d2Timo Sirainen /* make sure we don't try to open the file again */
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen if (unlink(index->filepath) < 0 && errno != ENOENT)
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen mail_index_set_syscall_error(index, "unlink()");
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen }
d176f84ce5ca2073f4dfbafb457b9c74f6bf0d76Timo Sirainen }
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen if (ret >= 0)
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen index->initial_mapped = TRUE;
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen index->mapping = FALSE;
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen return ret;
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen}
6c2ce1d5bf17b21e804a079eb0f973b7ab83e0d8Timo Sirainen