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