mail-index.c revision e06c0b65c16ccce69bbee009ead14d7d3d17a256
02c335c23bf5fa225a467c19f2c063fb0dc7b8c3Timo Sirainen/* Copyright (C) 2003-2004 Timo Sirainen */
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen#include "lib.h"
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen#include "buffer.h"
bdd36cfdba3ff66d25570a9ff568d69e1eb543cfTimo Sirainen#include "file-lock.h"
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen#include "mmap-util.h"
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen#include "read-full.h"
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen#include "write-full.h"
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen#include "mail-index-private.h"
09060303d565e15d54e42b4ef722f9d3c26f5336Timo Sirainen#include "mail-transaction-log.h"
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen
9522aa5f33cc37fe8ccd0d647cc51dd3ba6a9b55Timo Sirainen#include <stdio.h>
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen#include <stddef.h>
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen#include <time.h>
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen#include <sys/stat.h>
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainenstruct mail_index *mail_index_alloc(const char *dir, const char *prefix)
4fda77c9e9fc68feb292c4dacae1fac49dd08165Timo Sirainen{
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen struct mail_index *index;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen index = i_new(struct mail_index, 1);
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen index->dir = i_strdup(dir);
f158d9a303bb15a6848ca276c9391c7ca52e452bTimo Sirainen index->prefix = i_strdup(prefix);
f158d9a303bb15a6848ca276c9391c7ca52e452bTimo Sirainen index->fd = -1;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen index->mode = 0600;
11ee3b40320a31669bd717fecbe1e332dad4fd84Timo Sirainen index->gid = (gid_t)-1;
11ee3b40320a31669bd717fecbe1e332dad4fd84Timo Sirainen return index;
11ee3b40320a31669bd717fecbe1e332dad4fd84Timo Sirainen}
11ee3b40320a31669bd717fecbe1e332dad4fd84Timo Sirainen
11ee3b40320a31669bd717fecbe1e332dad4fd84Timo Sirainenvoid mail_index_free(struct mail_index *index)
11ee3b40320a31669bd717fecbe1e332dad4fd84Timo Sirainen{
11ee3b40320a31669bd717fecbe1e332dad4fd84Timo Sirainen mail_index_close(index);
11ee3b40320a31669bd717fecbe1e332dad4fd84Timo Sirainen
11ee3b40320a31669bd717fecbe1e332dad4fd84Timo Sirainen i_free(index->error);
11ee3b40320a31669bd717fecbe1e332dad4fd84Timo Sirainen i_free(index->dir);
11ee3b40320a31669bd717fecbe1e332dad4fd84Timo Sirainen i_free(index->prefix);
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen i_free(index);
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen}
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainenstatic int mail_index_check_header(struct mail_index *index,
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen struct mail_index_map *map)
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen{
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen const struct mail_index_header *hdr = map->hdr;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen unsigned char compat_data[3];
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen#ifndef WORDS_BIGENDIAN
11ee3b40320a31669bd717fecbe1e332dad4fd84Timo Sirainen compat_data[0] = MAIL_INDEX_COMPAT_LITTLE_ENDIAN;
11ee3b40320a31669bd717fecbe1e332dad4fd84Timo Sirainen#else
0dffa25d211be541ee3c953b23566a1a990789dfTimo Sirainen compat_data[0] = 0;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen#endif
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen compat_data[1] = sizeof(uoff_t);
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen compat_data[2] = sizeof(time_t);
11ee3b40320a31669bd717fecbe1e332dad4fd84Timo Sirainen compat_data[3] = sizeof(keywords_mask_t);
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen
11ee3b40320a31669bd717fecbe1e332dad4fd84Timo Sirainen if (hdr->major_version != MAIL_INDEX_MAJOR_VERSION) {
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen /* major version change - handle silently(?) */
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen return -1;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen }
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen if (memcmp(hdr->compat_data, compat_data, sizeof(compat_data)) != 0) {
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen /* architecture change - handle silently(?) */
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen return -1;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen }
cf9d67e4a9bfee31cf3be05244555d51a3d1b9feTimo Sirainen
09060303d565e15d54e42b4ef722f9d3c26f5336Timo Sirainen if ((map->hdr->flags & MAIL_INDEX_HDR_FLAG_CORRUPTED) != 0) {
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen /* either a crash or we've already complained about it */
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen return -1;
093b42b11c1236a687d3da564b26a324e2189ae6Timo Sirainen }
a5ddfd7a8b473f73135b93d5e081e470a87f0f7eTimo Sirainen
a5ddfd7a8b473f73135b93d5e081e470a87f0f7eTimo Sirainen /* following some extra checks that only take a bit of CPU */
09060303d565e15d54e42b4ef722f9d3c26f5336Timo Sirainen if (hdr->uid_validity == 0) {
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen mail_index_set_error(index, "Corrupted index file %s: "
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen "uid_validity = 0", index->filepath);
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen return -1;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen }
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen
8b16d3b00f051401c97568697ccdbba48663759aTimo Sirainen if (hdr->next_uid == 0)
8b16d3b00f051401c97568697ccdbba48663759aTimo Sirainen return 0;
8b16d3b00f051401c97568697ccdbba48663759aTimo Sirainen
8b16d3b00f051401c97568697ccdbba48663759aTimo Sirainen if (hdr->recent_messages_count > hdr->messages_count ||
8b16d3b00f051401c97568697ccdbba48663759aTimo Sirainen hdr->seen_messages_count > hdr->messages_count ||
8b16d3b00f051401c97568697ccdbba48663759aTimo Sirainen hdr->deleted_messages_count > hdr->messages_count)
8b16d3b00f051401c97568697ccdbba48663759aTimo Sirainen return 0;
8b16d3b00f051401c97568697ccdbba48663759aTimo Sirainen if (hdr->first_recent_uid_lowwater > hdr->next_uid ||
eb209d12e3b1cfed564c35cf19fdb1bf7fcc6811Timo Sirainen hdr->first_unseen_uid_lowwater > hdr->next_uid ||
8b16d3b00f051401c97568697ccdbba48663759aTimo Sirainen hdr->first_deleted_uid_lowwater > hdr->next_uid)
8b16d3b00f051401c97568697ccdbba48663759aTimo Sirainen return 0;
8b16d3b00f051401c97568697ccdbba48663759aTimo Sirainen
8b16d3b00f051401c97568697ccdbba48663759aTimo Sirainen return 1;
8b16d3b00f051401c97568697ccdbba48663759aTimo Sirainen}
8b16d3b00f051401c97568697ccdbba48663759aTimo Sirainen
8b16d3b00f051401c97568697ccdbba48663759aTimo Sirainenstatic void mail_index_map_clear(struct mail_index *index,
8b16d3b00f051401c97568697ccdbba48663759aTimo Sirainen struct mail_index_map *map)
8b16d3b00f051401c97568697ccdbba48663759aTimo Sirainen{
8b16d3b00f051401c97568697ccdbba48663759aTimo Sirainen if (map->buffer != NULL) {
8b16d3b00f051401c97568697ccdbba48663759aTimo Sirainen i_assert(map->mmap_base == NULL);
8b16d3b00f051401c97568697ccdbba48663759aTimo Sirainen buffer_free(map->buffer);
8b16d3b00f051401c97568697ccdbba48663759aTimo Sirainen map->buffer = NULL;
8b16d3b00f051401c97568697ccdbba48663759aTimo Sirainen } else if (map->mmap_base != NULL) {
8b16d3b00f051401c97568697ccdbba48663759aTimo Sirainen i_assert(map->buffer == NULL);
8b16d3b00f051401c97568697ccdbba48663759aTimo Sirainen if (munmap(map->mmap_base, map->mmap_size) < 0)
8b16d3b00f051401c97568697ccdbba48663759aTimo Sirainen mail_index_set_syscall_error(index, "munmap()");
8b16d3b00f051401c97568697ccdbba48663759aTimo Sirainen map->mmap_base = NULL;
8b16d3b00f051401c97568697ccdbba48663759aTimo Sirainen }
8b16d3b00f051401c97568697ccdbba48663759aTimo Sirainen
8b16d3b00f051401c97568697ccdbba48663759aTimo Sirainen if (map->refcount > 0) {
8b16d3b00f051401c97568697ccdbba48663759aTimo Sirainen map->mmap_size = 0;
8b16d3b00f051401c97568697ccdbba48663759aTimo Sirainen map->mmap_used_size = 0;
8b16d3b00f051401c97568697ccdbba48663759aTimo Sirainen map->hdr = NULL;
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen map->records = NULL;
8b16d3b00f051401c97568697ccdbba48663759aTimo Sirainen map->records_count = 0;
8b16d3b00f051401c97568697ccdbba48663759aTimo Sirainen }
8b16d3b00f051401c97568697ccdbba48663759aTimo Sirainen}
8b16d3b00f051401c97568697ccdbba48663759aTimo Sirainen
ad404d294fedf792619aed432ed8de5174e9ce7cTimo Sirainenvoid mail_index_unmap(struct mail_index *index, struct mail_index_map *map)
ad404d294fedf792619aed432ed8de5174e9ce7cTimo Sirainen{
ad404d294fedf792619aed432ed8de5174e9ce7cTimo Sirainen if (--map->refcount > 0)
ad404d294fedf792619aed432ed8de5174e9ce7cTimo Sirainen return;
ad404d294fedf792619aed432ed8de5174e9ce7cTimo Sirainen
ad404d294fedf792619aed432ed8de5174e9ce7cTimo Sirainen i_assert(map->refcount == 0);
ad404d294fedf792619aed432ed8de5174e9ce7cTimo Sirainen mail_index_map_clear(index, map);
ad404d294fedf792619aed432ed8de5174e9ce7cTimo Sirainen i_free(map);
ad404d294fedf792619aed432ed8de5174e9ce7cTimo Sirainen}
ad404d294fedf792619aed432ed8de5174e9ce7cTimo Sirainen
ad404d294fedf792619aed432ed8de5174e9ce7cTimo Sirainenstatic void mail_index_unmap_forced(struct mail_index *index,
ad404d294fedf792619aed432ed8de5174e9ce7cTimo Sirainen struct mail_index_map *map)
ad404d294fedf792619aed432ed8de5174e9ce7cTimo Sirainen{
ad404d294fedf792619aed432ed8de5174e9ce7cTimo Sirainen mail_index_map_clear(index, map);
ad404d294fedf792619aed432ed8de5174e9ce7cTimo Sirainen mail_index_unmap(index, map);
ad404d294fedf792619aed432ed8de5174e9ce7cTimo Sirainen}
ad404d294fedf792619aed432ed8de5174e9ce7cTimo Sirainen
ad404d294fedf792619aed432ed8de5174e9ce7cTimo Sirainenstatic int mail_index_mmap(struct mail_index *index, struct mail_index_map *map)
ad404d294fedf792619aed432ed8de5174e9ce7cTimo Sirainen{
ad404d294fedf792619aed432ed8de5174e9ce7cTimo Sirainen const struct mail_index_header *hdr;
ad404d294fedf792619aed432ed8de5174e9ce7cTimo Sirainen unsigned int records_count;
ad404d294fedf792619aed432ed8de5174e9ce7cTimo Sirainen
ad404d294fedf792619aed432ed8de5174e9ce7cTimo Sirainen i_assert(map->buffer == NULL);
ad404d294fedf792619aed432ed8de5174e9ce7cTimo Sirainen
ad404d294fedf792619aed432ed8de5174e9ce7cTimo Sirainen map->mmap_base = index->lock_type != F_WRLCK ?
ad404d294fedf792619aed432ed8de5174e9ce7cTimo Sirainen mmap_ro_file(index->fd, &map->mmap_size) :
ad404d294fedf792619aed432ed8de5174e9ce7cTimo Sirainen mmap_rw_file(index->fd, &map->mmap_size);
ad404d294fedf792619aed432ed8de5174e9ce7cTimo Sirainen if (map->mmap_base == MAP_FAILED) {
ad404d294fedf792619aed432ed8de5174e9ce7cTimo Sirainen map->mmap_base = NULL;
ad404d294fedf792619aed432ed8de5174e9ce7cTimo Sirainen mail_index_set_syscall_error(index, "mmap()");
ad404d294fedf792619aed432ed8de5174e9ce7cTimo Sirainen return -1;
ad404d294fedf792619aed432ed8de5174e9ce7cTimo Sirainen }
ad404d294fedf792619aed432ed8de5174e9ce7cTimo Sirainen
ad404d294fedf792619aed432ed8de5174e9ce7cTimo Sirainen if (map->mmap_size < MAIL_INDEX_HEADER_MIN_SIZE) {
ad404d294fedf792619aed432ed8de5174e9ce7cTimo Sirainen mail_index_set_error(index, "Corrupted index file %s: "
ad404d294fedf792619aed432ed8de5174e9ce7cTimo Sirainen "File too small (%"PRIuSIZE_T")",
ad404d294fedf792619aed432ed8de5174e9ce7cTimo Sirainen index->filepath, map->mmap_size);
ad404d294fedf792619aed432ed8de5174e9ce7cTimo Sirainen return 0;
ad404d294fedf792619aed432ed8de5174e9ce7cTimo Sirainen }
ad404d294fedf792619aed432ed8de5174e9ce7cTimo Sirainen
ad404d294fedf792619aed432ed8de5174e9ce7cTimo Sirainen hdr = map->mmap_base;
ad404d294fedf792619aed432ed8de5174e9ce7cTimo Sirainen map->mmap_used_size = hdr->header_size +
ad404d294fedf792619aed432ed8de5174e9ce7cTimo Sirainen hdr->messages_count * sizeof(struct mail_index_record);
ad404d294fedf792619aed432ed8de5174e9ce7cTimo Sirainen
ad404d294fedf792619aed432ed8de5174e9ce7cTimo Sirainen if (map->mmap_used_size > map->mmap_size) {
ad404d294fedf792619aed432ed8de5174e9ce7cTimo Sirainen records_count = (map->mmap_size - hdr->header_size) /
ad404d294fedf792619aed432ed8de5174e9ce7cTimo Sirainen sizeof(struct mail_index_record);
ad404d294fedf792619aed432ed8de5174e9ce7cTimo Sirainen mail_index_set_error(index, "Corrupted index file %s: "
ad404d294fedf792619aed432ed8de5174e9ce7cTimo Sirainen "messages_count too large (%u > %u)",
ad404d294fedf792619aed432ed8de5174e9ce7cTimo Sirainen index->filepath, map->hdr->messages_count,
ad404d294fedf792619aed432ed8de5174e9ce7cTimo Sirainen records_count);
ad404d294fedf792619aed432ed8de5174e9ce7cTimo Sirainen return 0;
ad404d294fedf792619aed432ed8de5174e9ce7cTimo Sirainen }
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen map->hdr = hdr;
4fda77c9e9fc68feb292c4dacae1fac49dd08165Timo Sirainen if (map->hdr->header_size < sizeof(*map->hdr)) {
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen /* header smaller than ours, make a copy so our newer headers
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen won't have garbage in them */
4fda77c9e9fc68feb292c4dacae1fac49dd08165Timo Sirainen memcpy(&map->hdr_copy, map->hdr, map->hdr->header_size);
4fda77c9e9fc68feb292c4dacae1fac49dd08165Timo Sirainen map->hdr = &map->hdr_copy;
8c2b4a45f17a5cb13bb01058ca37798cf48d91baTimo Sirainen }
4fda77c9e9fc68feb292c4dacae1fac49dd08165Timo Sirainen
4fda77c9e9fc68feb292c4dacae1fac49dd08165Timo Sirainen map->records = PTR_OFFSET(map->mmap_base, map->hdr->header_size);
4fda77c9e9fc68feb292c4dacae1fac49dd08165Timo Sirainen map->records_count = map->hdr->messages_count;
4fda77c9e9fc68feb292c4dacae1fac49dd08165Timo Sirainen return 1;
4fda77c9e9fc68feb292c4dacae1fac49dd08165Timo Sirainen}
4fda77c9e9fc68feb292c4dacae1fac49dd08165Timo Sirainen
4fda77c9e9fc68feb292c4dacae1fac49dd08165Timo Sirainenstatic int mail_index_read_map(struct mail_index *index,
4fda77c9e9fc68feb292c4dacae1fac49dd08165Timo Sirainen struct mail_index_map *map)
4fda77c9e9fc68feb292c4dacae1fac49dd08165Timo Sirainen{
e4194f4703eeec32b432371ae30fc8f25ab720d8Timo Sirainen struct mail_index_header hdr;
e4194f4703eeec32b432371ae30fc8f25ab720d8Timo Sirainen void *data = NULL;
e4194f4703eeec32b432371ae30fc8f25ab720d8Timo Sirainen ssize_t ret;
4fda77c9e9fc68feb292c4dacae1fac49dd08165Timo Sirainen size_t pos, records_size;
4fda77c9e9fc68feb292c4dacae1fac49dd08165Timo Sirainen
4fda77c9e9fc68feb292c4dacae1fac49dd08165Timo Sirainen i_assert(map->mmap_base == NULL);
4fda77c9e9fc68feb292c4dacae1fac49dd08165Timo Sirainen
4fda77c9e9fc68feb292c4dacae1fac49dd08165Timo Sirainen memset(&hdr, 0, sizeof(hdr));
4fda77c9e9fc68feb292c4dacae1fac49dd08165Timo Sirainen
4fda77c9e9fc68feb292c4dacae1fac49dd08165Timo Sirainen ret = 1;
8c2b4a45f17a5cb13bb01058ca37798cf48d91baTimo Sirainen for (pos = 0; ret > 0 && pos < sizeof(hdr); ) {
8c2b4a45f17a5cb13bb01058ca37798cf48d91baTimo Sirainen ret = pread(index->fd, PTR_OFFSET(&hdr, pos),
8c2b4a45f17a5cb13bb01058ca37798cf48d91baTimo Sirainen sizeof(hdr) - pos, pos);
ad404d294fedf792619aed432ed8de5174e9ce7cTimo Sirainen if (ret > 0)
4fda77c9e9fc68feb292c4dacae1fac49dd08165Timo Sirainen pos += ret;
8c2b4a45f17a5cb13bb01058ca37798cf48d91baTimo Sirainen }
ad404d294fedf792619aed432ed8de5174e9ce7cTimo Sirainen if (ret >= 0 && pos >= MAIL_INDEX_HEADER_MIN_SIZE) {
ad404d294fedf792619aed432ed8de5174e9ce7cTimo Sirainen records_size = hdr.messages_count *
ad404d294fedf792619aed432ed8de5174e9ce7cTimo Sirainen sizeof(struct mail_index_record);
ad404d294fedf792619aed432ed8de5174e9ce7cTimo Sirainen
ad404d294fedf792619aed432ed8de5174e9ce7cTimo Sirainen if (map->buffer == NULL) {
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen map->buffer = buffer_create_dynamic(default_pool,
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen records_size,
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen (size_t)-1);
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen }
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen
3c3001681da75afc68578a180ec8f8b2d6dfacfaTimo Sirainen /* @UNSAFE */
892e25e1c0caad62ced087d9eba2741a59e3d9ceTimo Sirainen buffer_set_used_size(map->buffer, 0);
892e25e1c0caad62ced087d9eba2741a59e3d9ceTimo Sirainen data = buffer_append_space_unsafe(map->buffer, records_size);
e4194f4703eeec32b432371ae30fc8f25ab720d8Timo Sirainen
e4194f4703eeec32b432371ae30fc8f25ab720d8Timo Sirainen ret = pread_full(index->fd, data, records_size,
e4194f4703eeec32b432371ae30fc8f25ab720d8Timo Sirainen hdr.header_size);
009217abb57a24a4076092e8e4e165545747839eStephan Bosch }
e4194f4703eeec32b432371ae30fc8f25ab720d8Timo Sirainen
e4194f4703eeec32b432371ae30fc8f25ab720d8Timo Sirainen if (ret < 0) {
49ec317299dedfbc27be79ab97d5b7a8ba7a4eacTimo Sirainen if (errno == ESTALE)
009217abb57a24a4076092e8e4e165545747839eStephan Bosch return 0;
e4194f4703eeec32b432371ae30fc8f25ab720d8Timo Sirainen mail_index_set_syscall_error(index, "pread_full()");
3c3001681da75afc68578a180ec8f8b2d6dfacfaTimo Sirainen return -1;
e4194f4703eeec32b432371ae30fc8f25ab720d8Timo Sirainen }
e4194f4703eeec32b432371ae30fc8f25ab720d8Timo Sirainen if (ret == 0) {
e4194f4703eeec32b432371ae30fc8f25ab720d8Timo Sirainen mail_index_set_error(index,
e4194f4703eeec32b432371ae30fc8f25ab720d8Timo Sirainen "Unexpected EOF while reading index file");
e4194f4703eeec32b432371ae30fc8f25ab720d8Timo Sirainen return -1;
e4194f4703eeec32b432371ae30fc8f25ab720d8Timo Sirainen }
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen
3c3001681da75afc68578a180ec8f8b2d6dfacfaTimo Sirainen map->records = data;
e4194f4703eeec32b432371ae30fc8f25ab720d8Timo Sirainen map->records_count = hdr.messages_count;
e4194f4703eeec32b432371ae30fc8f25ab720d8Timo Sirainen
3c3001681da75afc68578a180ec8f8b2d6dfacfaTimo Sirainen map->hdr_copy = hdr;
892e25e1c0caad62ced087d9eba2741a59e3d9ceTimo Sirainen map->hdr = &map->hdr_copy;
892e25e1c0caad62ced087d9eba2741a59e3d9ceTimo Sirainen return 1;
e4194f4703eeec32b432371ae30fc8f25ab720d8Timo Sirainen}
e4194f4703eeec32b432371ae30fc8f25ab720d8Timo Sirainen
e4194f4703eeec32b432371ae30fc8f25ab720d8Timo Sirainenstatic int mail_index_read_map_with_retry(struct mail_index *index,
009217abb57a24a4076092e8e4e165545747839eStephan Bosch struct mail_index_map *map)
e4194f4703eeec32b432371ae30fc8f25ab720d8Timo Sirainen{
e4194f4703eeec32b432371ae30fc8f25ab720d8Timo Sirainen int i, ret;
49ec317299dedfbc27be79ab97d5b7a8ba7a4eacTimo Sirainen
009217abb57a24a4076092e8e4e165545747839eStephan Bosch for (i = 0; i < MAIL_INDEX_ESTALE_RETRY_COUNT; i++) {
e4194f4703eeec32b432371ae30fc8f25ab720d8Timo Sirainen ret = mail_index_read_map(index, map);
3c3001681da75afc68578a180ec8f8b2d6dfacfaTimo Sirainen if (ret != 0)
e4194f4703eeec32b432371ae30fc8f25ab720d8Timo Sirainen return ret;
e4194f4703eeec32b432371ae30fc8f25ab720d8Timo Sirainen
e4194f4703eeec32b432371ae30fc8f25ab720d8Timo Sirainen /* ESTALE - reopen index file */
e4194f4703eeec32b432371ae30fc8f25ab720d8Timo Sirainen if (close(index->fd) < 0)
e4194f4703eeec32b432371ae30fc8f25ab720d8Timo Sirainen mail_index_set_syscall_error(index, "close()");
e4194f4703eeec32b432371ae30fc8f25ab720d8Timo Sirainen index->fd = -1;
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen
e4194f4703eeec32b432371ae30fc8f25ab720d8Timo Sirainen ret = mail_index_try_open_only(index);
e4194f4703eeec32b432371ae30fc8f25ab720d8Timo Sirainen if (ret <= 0) {
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen if (ret == 0) {
e4194f4703eeec32b432371ae30fc8f25ab720d8Timo Sirainen /* the file was lost */
3c3001681da75afc68578a180ec8f8b2d6dfacfaTimo Sirainen errno = ENOENT;
e4194f4703eeec32b432371ae30fc8f25ab720d8Timo Sirainen mail_index_set_syscall_error(index, "open()");
e4194f4703eeec32b432371ae30fc8f25ab720d8Timo Sirainen }
3c3001681da75afc68578a180ec8f8b2d6dfacfaTimo Sirainen return -1;
892e25e1c0caad62ced087d9eba2741a59e3d9ceTimo Sirainen }
892e25e1c0caad62ced087d9eba2741a59e3d9ceTimo Sirainen }
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen
cf9d67e4a9bfee31cf3be05244555d51a3d1b9feTimo Sirainen /* Too many ESTALE retries */
892e25e1c0caad62ced087d9eba2741a59e3d9ceTimo Sirainen mail_index_set_syscall_error(index, "read_map()");
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen return -1;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen}
8ae72ad7d0c69e972cfa65d1e2ce4e3e9a8b765cTimo Sirainen
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainenint mail_index_map(struct mail_index *index, int force)
09060303d565e15d54e42b4ef722f9d3c26f5336Timo Sirainen{
09060303d565e15d54e42b4ef722f9d3c26f5336Timo Sirainen const struct mail_index_header *hdr;
09060303d565e15d54e42b4ef722f9d3c26f5336Timo Sirainen struct mail_index_map *map;
09060303d565e15d54e42b4ef722f9d3c26f5336Timo Sirainen size_t used_size;
09060303d565e15d54e42b4ef722f9d3c26f5336Timo Sirainen int ret;
09060303d565e15d54e42b4ef722f9d3c26f5336Timo Sirainen
09060303d565e15d54e42b4ef722f9d3c26f5336Timo Sirainen map = index->map;
09060303d565e15d54e42b4ef722f9d3c26f5336Timo Sirainen if (map == NULL) {
09060303d565e15d54e42b4ef722f9d3c26f5336Timo Sirainen map = i_new(struct mail_index_map, 1);
a4502a71879d6018bd2c64f13614bb619911dd9fTimo Sirainen map->refcount = 1;
a4502a71879d6018bd2c64f13614bb619911dd9fTimo Sirainen } else if (MAIL_INDEX_MAP_IS_IN_MEMORY(map)) {
892e25e1c0caad62ced087d9eba2741a59e3d9ceTimo Sirainen if (map->write_to_disk) {
892e25e1c0caad62ced087d9eba2741a59e3d9ceTimo Sirainen /* we have modified this mapping and it's waiting to
3c3001681da75afc68578a180ec8f8b2d6dfacfaTimo Sirainen be written to disk once we drop exclusive lock.
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen mapping couldn't have changed, so do nothing. */
8ae72ad7d0c69e972cfa65d1e2ce4e3e9a8b765cTimo Sirainen return 1;
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen }
3c3001681da75afc68578a180ec8f8b2d6dfacfaTimo Sirainen /* FIXME: we need to re-read header */
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen } else if (map->mmap_base != NULL) {
cf9d67e4a9bfee31cf3be05244555d51a3d1b9feTimo Sirainen /* see if re-mmaping is needed (file has grown) */
a4502a71879d6018bd2c64f13614bb619911dd9fTimo Sirainen hdr = map->mmap_base;
a4502a71879d6018bd2c64f13614bb619911dd9fTimo Sirainen used_size = hdr->header_size +
a4502a71879d6018bd2c64f13614bb619911dd9fTimo Sirainen hdr->messages_count * sizeof(struct mail_index_record);
3c3001681da75afc68578a180ec8f8b2d6dfacfaTimo Sirainen if (map->mmap_size >= used_size && !force) {
a4502a71879d6018bd2c64f13614bb619911dd9fTimo Sirainen map->records_count = hdr->messages_count;
09060303d565e15d54e42b4ef722f9d3c26f5336Timo Sirainen return 1;
9058f3006fffd25835ad701e1b2c3c8faafd3c80Timo Sirainen }
9058f3006fffd25835ad701e1b2c3c8faafd3c80Timo Sirainen
3c3001681da75afc68578a180ec8f8b2d6dfacfaTimo Sirainen if (munmap(map->mmap_base, map->mmap_size) < 0)
28789c7ce1aa66ab21798bfb73ec64308b9a4de8Timo Sirainen mail_index_set_syscall_error(index, "munmap()");
28789c7ce1aa66ab21798bfb73ec64308b9a4de8Timo Sirainen map->mmap_base = NULL;
28789c7ce1aa66ab21798bfb73ec64308b9a4de8Timo Sirainen }
3c3001681da75afc68578a180ec8f8b2d6dfacfaTimo Sirainen
a4502a71879d6018bd2c64f13614bb619911dd9fTimo Sirainen index->hdr = NULL;
8ae72ad7d0c69e972cfa65d1e2ce4e3e9a8b765cTimo Sirainen index->map = NULL;
87842f621233257b7a7945d994ba931508b34877Timo Sirainen
a4502a71879d6018bd2c64f13614bb619911dd9fTimo Sirainen if (!index->mmap_disable) {
09060303d565e15d54e42b4ef722f9d3c26f5336Timo Sirainen if ((ret = mail_index_mmap(index, map)) <= 0) {
09060303d565e15d54e42b4ef722f9d3c26f5336Timo Sirainen mail_index_unmap_forced(index, map);
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen return ret;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen }
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen } else {
3c3001681da75afc68578a180ec8f8b2d6dfacfaTimo Sirainen if (mail_index_read_map_with_retry(index, map) < 0) {
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen mail_index_unmap_forced(index, map);
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen return -1;
3c3001681da75afc68578a180ec8f8b2d6dfacfaTimo Sirainen }
892e25e1c0caad62ced087d9eba2741a59e3d9ceTimo Sirainen }
a4502a71879d6018bd2c64f13614bb619911dd9fTimo Sirainen
892e25e1c0caad62ced087d9eba2741a59e3d9ceTimo Sirainen ret = mail_index_check_header(index, map);
a4502a71879d6018bd2c64f13614bb619911dd9fTimo Sirainen if (ret < 0) {
a4502a71879d6018bd2c64f13614bb619911dd9fTimo Sirainen mail_index_unmap_forced(index, map);
3c3001681da75afc68578a180ec8f8b2d6dfacfaTimo Sirainen return 0;
892e25e1c0caad62ced087d9eba2741a59e3d9ceTimo Sirainen }
a4502a71879d6018bd2c64f13614bb619911dd9fTimo Sirainen if (ret == 0)
892e25e1c0caad62ced087d9eba2741a59e3d9ceTimo Sirainen index->fsck = TRUE;
a4502a71879d6018bd2c64f13614bb619911dd9fTimo Sirainen
a4502a71879d6018bd2c64f13614bb619911dd9fTimo Sirainen map->log_file_seq = map->hdr->log_file_seq;
3c3001681da75afc68578a180ec8f8b2d6dfacfaTimo Sirainen map->log_file_offset = map->hdr->log_file_offset;
a5ddfd7a8b473f73135b93d5e081e470a87f0f7eTimo Sirainen
892e25e1c0caad62ced087d9eba2741a59e3d9ceTimo Sirainen index->hdr = map->hdr;
a5ddfd7a8b473f73135b93d5e081e470a87f0f7eTimo Sirainen index->map = map;
a5ddfd7a8b473f73135b93d5e081e470a87f0f7eTimo Sirainen return 1;
a5ddfd7a8b473f73135b93d5e081e470a87f0f7eTimo Sirainen}
a5ddfd7a8b473f73135b93d5e081e470a87f0f7eTimo Sirainen
892e25e1c0caad62ced087d9eba2741a59e3d9ceTimo Sirainenstruct mail_index_map *mail_index_map_to_memory(struct mail_index_map *map)
a5ddfd7a8b473f73135b93d5e081e470a87f0f7eTimo Sirainen{
892e25e1c0caad62ced087d9eba2741a59e3d9ceTimo Sirainen const struct mail_index_header *hdr;
892e25e1c0caad62ced087d9eba2741a59e3d9ceTimo Sirainen struct mail_index_map *mem_map;
3c3001681da75afc68578a180ec8f8b2d6dfacfaTimo Sirainen size_t size;
a5ddfd7a8b473f73135b93d5e081e470a87f0f7eTimo Sirainen
a5ddfd7a8b473f73135b93d5e081e470a87f0f7eTimo Sirainen if (MAIL_INDEX_MAP_IS_IN_MEMORY(map)) {
a5ddfd7a8b473f73135b93d5e081e470a87f0f7eTimo Sirainen map->refcount++;
a5ddfd7a8b473f73135b93d5e081e470a87f0f7eTimo Sirainen return map;
3c3001681da75afc68578a180ec8f8b2d6dfacfaTimo Sirainen }
a5ddfd7a8b473f73135b93d5e081e470a87f0f7eTimo Sirainen
28789c7ce1aa66ab21798bfb73ec64308b9a4de8Timo Sirainen size = map->records_count * sizeof(struct mail_index_record);
28789c7ce1aa66ab21798bfb73ec64308b9a4de8Timo Sirainen
28789c7ce1aa66ab21798bfb73ec64308b9a4de8Timo Sirainen mem_map = i_new(struct mail_index_map, 1);
28789c7ce1aa66ab21798bfb73ec64308b9a4de8Timo Sirainen mem_map->refcount = 1;
28789c7ce1aa66ab21798bfb73ec64308b9a4de8Timo Sirainen mem_map->buffer = buffer_create_dynamic(default_pool, size, (size_t)-1);
3c3001681da75afc68578a180ec8f8b2d6dfacfaTimo Sirainen buffer_append(mem_map->buffer, map->records, size);
28789c7ce1aa66ab21798bfb73ec64308b9a4de8Timo Sirainen
87842f621233257b7a7945d994ba931508b34877Timo Sirainen mem_map->records = buffer_get_modifyable_data(mem_map->buffer, NULL);
a5ddfd7a8b473f73135b93d5e081e470a87f0f7eTimo Sirainen mem_map->records_count = map->records_count;
a5ddfd7a8b473f73135b93d5e081e470a87f0f7eTimo Sirainen
a5ddfd7a8b473f73135b93d5e081e470a87f0f7eTimo Sirainen hdr = map->mmap_base;
a5ddfd7a8b473f73135b93d5e081e470a87f0f7eTimo Sirainen memcpy(&mem_map->hdr_copy, map->mmap_base,
3c3001681da75afc68578a180ec8f8b2d6dfacfaTimo Sirainen I_MIN(hdr->header_size, sizeof(mem_map->hdr_copy)));
a5ddfd7a8b473f73135b93d5e081e470a87f0f7eTimo Sirainen mem_map->hdr = &mem_map->hdr_copy;
a5ddfd7a8b473f73135b93d5e081e470a87f0f7eTimo Sirainen return mem_map;
3c3001681da75afc68578a180ec8f8b2d6dfacfaTimo Sirainen}
892e25e1c0caad62ced087d9eba2741a59e3d9ceTimo Sirainen
892e25e1c0caad62ced087d9eba2741a59e3d9ceTimo Sirainenvoid mail_index_header_init(struct mail_index_header *hdr)
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen{
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen time_t now = time(NULL);
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen memset(hdr, 0, sizeof(*hdr));
892e25e1c0caad62ced087d9eba2741a59e3d9ceTimo Sirainen
5e9bb72de1209cd39fdf3e95bdb26e047cc5594eTimo Sirainen hdr->major_version = MAIL_INDEX_MAJOR_VERSION;
3c3001681da75afc68578a180ec8f8b2d6dfacfaTimo Sirainen hdr->minor_version = MAIL_INDEX_MINOR_VERSION;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen hdr->header_size = sizeof(*hdr);
cf9d67e4a9bfee31cf3be05244555d51a3d1b9feTimo Sirainen
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen#ifndef WORDS_BIGENDIAN
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen hdr->compat_data[0] = MAIL_INDEX_COMPAT_LITTLE_ENDIAN;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen#endif
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen hdr->compat_data[1] = sizeof(uoff_t);
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen hdr->compat_data[2] = sizeof(time_t);
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen hdr->compat_data[3] = sizeof(keywords_mask_t);
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen
3c3001681da75afc68578a180ec8f8b2d6dfacfaTimo Sirainen hdr->indexid = now;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen hdr->uid_validity = now;
5e9bb72de1209cd39fdf3e95bdb26e047cc5594eTimo Sirainen hdr->next_uid = 1;
5e9bb72de1209cd39fdf3e95bdb26e047cc5594eTimo Sirainen}
5e9bb72de1209cd39fdf3e95bdb26e047cc5594eTimo Sirainen
5e9bb72de1209cd39fdf3e95bdb26e047cc5594eTimo Sirainenint mail_index_write_header(struct mail_index *index,
9ffd3c8ca82bd2af8ca4f7e167339820ddcf1fe3Timo Sirainen const struct mail_index_header *hdr)
5e9bb72de1209cd39fdf3e95bdb26e047cc5594eTimo Sirainen{
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen if (!MAIL_INDEX_MAP_IS_IN_MEMORY(index->map)) {
9ffd3c8ca82bd2af8ca4f7e167339820ddcf1fe3Timo Sirainen memcpy(index->map->mmap_base, hdr, sizeof(*hdr));
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen if (msync(index->map->mmap_base, sizeof(*hdr), MS_SYNC) < 0)
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen return mail_index_set_syscall_error(index, "msync()");
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen } else {
9ffd3c8ca82bd2af8ca4f7e167339820ddcf1fe3Timo Sirainen if (pwrite_full(index->fd, hdr, sizeof(*hdr), 0) < 0) {
9ffd3c8ca82bd2af8ca4f7e167339820ddcf1fe3Timo Sirainen mail_index_set_syscall_error(index, "pwrite_full()");
9ffd3c8ca82bd2af8ca4f7e167339820ddcf1fe3Timo Sirainen return -1;
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen }
5e9bb72de1209cd39fdf3e95bdb26e047cc5594eTimo Sirainen
5e9bb72de1209cd39fdf3e95bdb26e047cc5594eTimo Sirainen index->map->hdr_copy = *hdr;
3c3001681da75afc68578a180ec8f8b2d6dfacfaTimo Sirainen index->hdr = &index->map->hdr_copy;
892e25e1c0caad62ced087d9eba2741a59e3d9ceTimo Sirainen }
5e9bb72de1209cd39fdf3e95bdb26e047cc5594eTimo Sirainen
5e9bb72de1209cd39fdf3e95bdb26e047cc5594eTimo Sirainen return 0;
5e9bb72de1209cd39fdf3e95bdb26e047cc5594eTimo Sirainen}
5e9bb72de1209cd39fdf3e95bdb26e047cc5594eTimo Sirainen
892e25e1c0caad62ced087d9eba2741a59e3d9ceTimo Sirainenint mail_index_create_tmp_file(struct mail_index *index, const char **path_r)
5e9bb72de1209cd39fdf3e95bdb26e047cc5594eTimo Sirainen{
3c3001681da75afc68578a180ec8f8b2d6dfacfaTimo Sirainen const char *path;
5e9bb72de1209cd39fdf3e95bdb26e047cc5594eTimo Sirainen int fd;
5e9bb72de1209cd39fdf3e95bdb26e047cc5594eTimo Sirainen
892e25e1c0caad62ced087d9eba2741a59e3d9ceTimo Sirainen path = *path_r = t_strconcat(index->filepath, ".tmp", NULL);
5e9bb72de1209cd39fdf3e95bdb26e047cc5594eTimo Sirainen fd = open(path, O_RDWR|O_CREAT|O_TRUNC, index->mode);
3c3001681da75afc68578a180ec8f8b2d6dfacfaTimo Sirainen if (fd == -1)
5e9bb72de1209cd39fdf3e95bdb26e047cc5594eTimo Sirainen return mail_index_file_set_syscall_error(index, path, "open()");
5e9bb72de1209cd39fdf3e95bdb26e047cc5594eTimo Sirainen
5e9bb72de1209cd39fdf3e95bdb26e047cc5594eTimo Sirainen if (index->gid != (gid_t)-1 &&
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen fchown(index->fd, (uid_t)-1, index->gid) < 0) {
5e9bb72de1209cd39fdf3e95bdb26e047cc5594eTimo Sirainen mail_index_file_set_syscall_error(index, path, "fchown()");
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen return -1;
0a53eb0283d7ec28c6105f61e118b96fce8ecb95Timo Sirainen }
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen
5e9bb72de1209cd39fdf3e95bdb26e047cc5594eTimo Sirainen return fd;
3c3001681da75afc68578a180ec8f8b2d6dfacfaTimo Sirainen}
5e9bb72de1209cd39fdf3e95bdb26e047cc5594eTimo Sirainen
5e9bb72de1209cd39fdf3e95bdb26e047cc5594eTimo Sirainenstatic int mail_index_create(struct mail_index *index,
11ee3b40320a31669bd717fecbe1e332dad4fd84Timo Sirainen struct mail_index_header *hdr)
11ee3b40320a31669bd717fecbe1e332dad4fd84Timo Sirainen{
11ee3b40320a31669bd717fecbe1e332dad4fd84Timo Sirainen const char *path;
11ee3b40320a31669bd717fecbe1e332dad4fd84Timo Sirainen uint32_t seq;
11ee3b40320a31669bd717fecbe1e332dad4fd84Timo Sirainen uoff_t offset;
11ee3b40320a31669bd717fecbe1e332dad4fd84Timo Sirainen int ret;
11ee3b40320a31669bd717fecbe1e332dad4fd84Timo Sirainen
11ee3b40320a31669bd717fecbe1e332dad4fd84Timo Sirainen /* log file lock protects index creation */
11ee3b40320a31669bd717fecbe1e332dad4fd84Timo Sirainen if (mail_transaction_log_sync_lock(index->log, &seq, &offset) < 0)
11ee3b40320a31669bd717fecbe1e332dad4fd84Timo Sirainen return -1;
11ee3b40320a31669bd717fecbe1e332dad4fd84Timo Sirainen
11ee3b40320a31669bd717fecbe1e332dad4fd84Timo Sirainen hdr->log_file_seq = seq;
11ee3b40320a31669bd717fecbe1e332dad4fd84Timo Sirainen hdr->log_file_offset = offset;
7bccaece91a0b1bc61111c30443d6bad6b22c6d0Timo Sirainen
7bccaece91a0b1bc61111c30443d6bad6b22c6d0Timo Sirainen ret = mail_index_try_open(index, NULL);
11ee3b40320a31669bd717fecbe1e332dad4fd84Timo Sirainen if (ret != 0) {
7bccaece91a0b1bc61111c30443d6bad6b22c6d0Timo Sirainen mail_transaction_log_sync_unlock(index->log);
7bccaece91a0b1bc61111c30443d6bad6b22c6d0Timo Sirainen return ret;
7bccaece91a0b1bc61111c30443d6bad6b22c6d0Timo Sirainen }
11ee3b40320a31669bd717fecbe1e332dad4fd84Timo Sirainen
11ee3b40320a31669bd717fecbe1e332dad4fd84Timo Sirainen /* create it fully in index.tmp first */
11ee3b40320a31669bd717fecbe1e332dad4fd84Timo Sirainen index->fd = mail_index_create_tmp_file(index, &path);
7bccaece91a0b1bc61111c30443d6bad6b22c6d0Timo Sirainen if (index->fd == -1)
7bccaece91a0b1bc61111c30443d6bad6b22c6d0Timo Sirainen ret = -1;
7bccaece91a0b1bc61111c30443d6bad6b22c6d0Timo Sirainen else if (write_full(index->fd, hdr, sizeof(*hdr)) < 0) {
11ee3b40320a31669bd717fecbe1e332dad4fd84Timo Sirainen mail_index_file_set_syscall_error(index, path, "write_full()");
11ee3b40320a31669bd717fecbe1e332dad4fd84Timo Sirainen ret = -1;
11ee3b40320a31669bd717fecbe1e332dad4fd84Timo Sirainen } else {
7bccaece91a0b1bc61111c30443d6bad6b22c6d0Timo Sirainen ret = mail_index_map(index, FALSE);
7bccaece91a0b1bc61111c30443d6bad6b22c6d0Timo Sirainen }
7bccaece91a0b1bc61111c30443d6bad6b22c6d0Timo Sirainen
093b42b11c1236a687d3da564b26a324e2189ae6Timo Sirainen if (ret == 0) {
093b42b11c1236a687d3da564b26a324e2189ae6Timo Sirainen /* it's corrupted even while we just created it,
7bccaece91a0b1bc61111c30443d6bad6b22c6d0Timo Sirainen should never happen unless someone pokes the file directly */
11ee3b40320a31669bd717fecbe1e332dad4fd84Timo Sirainen mail_index_set_error(index,
7bccaece91a0b1bc61111c30443d6bad6b22c6d0Timo Sirainen "Newly created index file is corrupted: %s", path);
7bccaece91a0b1bc61111c30443d6bad6b22c6d0Timo Sirainen ret = -1;
11ee3b40320a31669bd717fecbe1e332dad4fd84Timo Sirainen }
11ee3b40320a31669bd717fecbe1e332dad4fd84Timo Sirainen
7bccaece91a0b1bc61111c30443d6bad6b22c6d0Timo Sirainen if (ret < 0) {
11ee3b40320a31669bd717fecbe1e332dad4fd84Timo Sirainen if (unlink(path) < 0 && errno != ENOENT) {
11ee3b40320a31669bd717fecbe1e332dad4fd84Timo Sirainen mail_index_file_set_syscall_error(index, path,
7bccaece91a0b1bc61111c30443d6bad6b22c6d0Timo Sirainen "unlink()");
7bccaece91a0b1bc61111c30443d6bad6b22c6d0Timo Sirainen }
11ee3b40320a31669bd717fecbe1e332dad4fd84Timo Sirainen return -1;
7bccaece91a0b1bc61111c30443d6bad6b22c6d0Timo Sirainen }
7bccaece91a0b1bc61111c30443d6bad6b22c6d0Timo Sirainen
11ee3b40320a31669bd717fecbe1e332dad4fd84Timo Sirainen /* make it visible to others */
11ee3b40320a31669bd717fecbe1e332dad4fd84Timo Sirainen if (rename(path, index->filepath) < 0) {
7bccaece91a0b1bc61111c30443d6bad6b22c6d0Timo Sirainen mail_index_set_error(index, "rename(%s, %s) failed: %m",
11ee3b40320a31669bd717fecbe1e332dad4fd84Timo Sirainen path, index->filepath);
11ee3b40320a31669bd717fecbe1e332dad4fd84Timo Sirainen return -1;
7bccaece91a0b1bc61111c30443d6bad6b22c6d0Timo Sirainen }
11ee3b40320a31669bd717fecbe1e332dad4fd84Timo Sirainen
11ee3b40320a31669bd717fecbe1e332dad4fd84Timo Sirainen mail_transaction_log_sync_unlock(index->log);
11ee3b40320a31669bd717fecbe1e332dad4fd84Timo Sirainen return 1;
11ee3b40320a31669bd717fecbe1e332dad4fd84Timo Sirainen}
11ee3b40320a31669bd717fecbe1e332dad4fd84Timo Sirainen
11ee3b40320a31669bd717fecbe1e332dad4fd84Timo Sirainenint mail_index_try_open_only(struct mail_index *index)
11ee3b40320a31669bd717fecbe1e332dad4fd84Timo Sirainen{
11ee3b40320a31669bd717fecbe1e332dad4fd84Timo Sirainen int i;
11ee3b40320a31669bd717fecbe1e332dad4fd84Timo Sirainen
11ee3b40320a31669bd717fecbe1e332dad4fd84Timo Sirainen for (i = 0; i < 3; i++) {
11ee3b40320a31669bd717fecbe1e332dad4fd84Timo Sirainen index->fd = open(index->filepath, O_RDWR);
11ee3b40320a31669bd717fecbe1e332dad4fd84Timo Sirainen if (index->fd == -1 && errno == EACCES) {
11ee3b40320a31669bd717fecbe1e332dad4fd84Timo Sirainen index->fd = open(index->filepath, O_RDONLY);
11ee3b40320a31669bd717fecbe1e332dad4fd84Timo Sirainen index->readonly = TRUE;
11ee3b40320a31669bd717fecbe1e332dad4fd84Timo Sirainen }
11ee3b40320a31669bd717fecbe1e332dad4fd84Timo Sirainen if (index->fd != -1 || errno != ESTALE)
11ee3b40320a31669bd717fecbe1e332dad4fd84Timo Sirainen break;
7bccaece91a0b1bc61111c30443d6bad6b22c6d0Timo Sirainen
7bccaece91a0b1bc61111c30443d6bad6b22c6d0Timo Sirainen /* May happen with some OSes with NFS. Try again, although
3c3001681da75afc68578a180ec8f8b2d6dfacfaTimo Sirainen there's still a race condition with another computer
892e25e1c0caad62ced087d9eba2741a59e3d9ceTimo Sirainen creating the index file again. However, we can't try forever
892e25e1c0caad62ced087d9eba2741a59e3d9ceTimo Sirainen as ESTALE happens also if index directory has been deleted
7bccaece91a0b1bc61111c30443d6bad6b22c6d0Timo Sirainen from server.. */
11ee3b40320a31669bd717fecbe1e332dad4fd84Timo Sirainen }
7bccaece91a0b1bc61111c30443d6bad6b22c6d0Timo Sirainen if (index->fd == -1) {
11ee3b40320a31669bd717fecbe1e332dad4fd84Timo Sirainen if (errno != ENOENT)
11ee3b40320a31669bd717fecbe1e332dad4fd84Timo Sirainen return mail_index_set_syscall_error(index, "open()");
11ee3b40320a31669bd717fecbe1e332dad4fd84Timo Sirainen
7bccaece91a0b1bc61111c30443d6bad6b22c6d0Timo Sirainen /* have to create it */
11ee3b40320a31669bd717fecbe1e332dad4fd84Timo Sirainen return 0;
11ee3b40320a31669bd717fecbe1e332dad4fd84Timo Sirainen }
7bccaece91a0b1bc61111c30443d6bad6b22c6d0Timo Sirainen return 1;
3c3001681da75afc68578a180ec8f8b2d6dfacfaTimo Sirainen}
7bccaece91a0b1bc61111c30443d6bad6b22c6d0Timo Sirainen
11ee3b40320a31669bd717fecbe1e332dad4fd84Timo Sirainenint mail_index_try_open(struct mail_index *index, unsigned int *lock_id_r)
11ee3b40320a31669bd717fecbe1e332dad4fd84Timo Sirainen{
11ee3b40320a31669bd717fecbe1e332dad4fd84Timo Sirainen unsigned int lock_id;
11ee3b40320a31669bd717fecbe1e332dad4fd84Timo Sirainen int ret;
11ee3b40320a31669bd717fecbe1e332dad4fd84Timo Sirainen
11ee3b40320a31669bd717fecbe1e332dad4fd84Timo Sirainen if (lock_id_r != NULL)
11ee3b40320a31669bd717fecbe1e332dad4fd84Timo Sirainen *lock_id_r = 0;
11ee3b40320a31669bd717fecbe1e332dad4fd84Timo Sirainen
11ee3b40320a31669bd717fecbe1e332dad4fd84Timo Sirainen ret = mail_index_try_open_only(index);
11ee3b40320a31669bd717fecbe1e332dad4fd84Timo Sirainen if (ret <= 0)
9954af4b72850a7c3158c99b444d49a529109c4dTimo Sirainen return ret;
11ee3b40320a31669bd717fecbe1e332dad4fd84Timo Sirainen
11ee3b40320a31669bd717fecbe1e332dad4fd84Timo Sirainen if (mail_index_lock_shared(index, FALSE, &lock_id) < 0)
11ee3b40320a31669bd717fecbe1e332dad4fd84Timo Sirainen return -1;
11ee3b40320a31669bd717fecbe1e332dad4fd84Timo Sirainen ret = mail_index_map(index, FALSE);
11ee3b40320a31669bd717fecbe1e332dad4fd84Timo Sirainen if (ret == 0) {
11ee3b40320a31669bd717fecbe1e332dad4fd84Timo Sirainen /* it's corrupted - recreate it */
11ee3b40320a31669bd717fecbe1e332dad4fd84Timo Sirainen mail_index_unlock(index, lock_id);
11ee3b40320a31669bd717fecbe1e332dad4fd84Timo Sirainen if (lock_id_r != NULL)
11ee3b40320a31669bd717fecbe1e332dad4fd84Timo Sirainen *lock_id_r = 0;
11ee3b40320a31669bd717fecbe1e332dad4fd84Timo Sirainen
11ee3b40320a31669bd717fecbe1e332dad4fd84Timo Sirainen (void)close(index->fd);
11ee3b40320a31669bd717fecbe1e332dad4fd84Timo Sirainen index->fd = -1;
11ee3b40320a31669bd717fecbe1e332dad4fd84Timo Sirainen } else {
11ee3b40320a31669bd717fecbe1e332dad4fd84Timo Sirainen if (lock_id_r != NULL)
11ee3b40320a31669bd717fecbe1e332dad4fd84Timo Sirainen *lock_id_r = lock_id;
11ee3b40320a31669bd717fecbe1e332dad4fd84Timo Sirainen else
11ee3b40320a31669bd717fecbe1e332dad4fd84Timo Sirainen mail_index_unlock(index, lock_id);
11ee3b40320a31669bd717fecbe1e332dad4fd84Timo Sirainen }
11ee3b40320a31669bd717fecbe1e332dad4fd84Timo Sirainen return ret;
11ee3b40320a31669bd717fecbe1e332dad4fd84Timo Sirainen}
11ee3b40320a31669bd717fecbe1e332dad4fd84Timo Sirainen
11ee3b40320a31669bd717fecbe1e332dad4fd84Timo Sirainenstatic int mail_index_open_files(struct mail_index *index,
7bccaece91a0b1bc61111c30443d6bad6b22c6d0Timo Sirainen enum mail_index_open_flags flags)
3c3001681da75afc68578a180ec8f8b2d6dfacfaTimo Sirainen{
7bccaece91a0b1bc61111c30443d6bad6b22c6d0Timo Sirainen struct mail_index_header hdr;
7bccaece91a0b1bc61111c30443d6bad6b22c6d0Timo Sirainen unsigned int lock_id = 0;
3c3001681da75afc68578a180ec8f8b2d6dfacfaTimo Sirainen int ret;
892e25e1c0caad62ced087d9eba2741a59e3d9ceTimo Sirainen
892e25e1c0caad62ced087d9eba2741a59e3d9ceTimo Sirainen ret = mail_index_try_open(index, &lock_id);
b2024fa4e6ed39f9b5b6bb6c051f6d535fc0e011Timo Sirainen if (ret > 0)
b2024fa4e6ed39f9b5b6bb6c051f6d535fc0e011Timo Sirainen hdr = *index->hdr;
edd318d5866ac3fbc6e8df28fb24a4dfef93c884Timo Sirainen else if (ret == 0) {
892e25e1c0caad62ced087d9eba2741a59e3d9ceTimo Sirainen /* doesn't exist, or corrupted */
edd318d5866ac3fbc6e8df28fb24a4dfef93c884Timo Sirainen if ((flags & MAIL_INDEX_OPEN_FLAG_CREATE) == 0)
edd318d5866ac3fbc6e8df28fb24a4dfef93c884Timo Sirainen return 0;
edd318d5866ac3fbc6e8df28fb24a4dfef93c884Timo Sirainen mail_index_header_init(&hdr);
09060303d565e15d54e42b4ef722f9d3c26f5336Timo Sirainen index->hdr = &hdr;
09060303d565e15d54e42b4ef722f9d3c26f5336Timo Sirainen } else if (ret < 0)
09060303d565e15d54e42b4ef722f9d3c26f5336Timo Sirainen return -1;
09060303d565e15d54e42b4ef722f9d3c26f5336Timo Sirainen
09060303d565e15d54e42b4ef722f9d3c26f5336Timo Sirainen index->indexid = hdr.indexid;
09060303d565e15d54e42b4ef722f9d3c26f5336Timo Sirainen
09060303d565e15d54e42b4ef722f9d3c26f5336Timo Sirainen index->log = mail_transaction_log_open_or_create(index);
09060303d565e15d54e42b4ef722f9d3c26f5336Timo Sirainen if (index->log == NULL)
a56fcfa52e89601d96376a29cd392a671fe25713Timo Sirainen return -1;
b2024fa4e6ed39f9b5b6bb6c051f6d535fc0e011Timo Sirainen
edd318d5866ac3fbc6e8df28fb24a4dfef93c884Timo Sirainen if (lock_id != 0)
edd318d5866ac3fbc6e8df28fb24a4dfef93c884Timo Sirainen mail_index_unlock(index, lock_id);
b2024fa4e6ed39f9b5b6bb6c051f6d535fc0e011Timo Sirainen return index->fd != -1 ? 1 : mail_index_create(index, &hdr);
edd318d5866ac3fbc6e8df28fb24a4dfef93c884Timo Sirainen}
b2024fa4e6ed39f9b5b6bb6c051f6d535fc0e011Timo Sirainen
edd318d5866ac3fbc6e8df28fb24a4dfef93c884Timo Sirainenint mail_index_open(struct mail_index *index, enum mail_index_open_flags flags)
edd318d5866ac3fbc6e8df28fb24a4dfef93c884Timo Sirainen{
edd318d5866ac3fbc6e8df28fb24a4dfef93c884Timo Sirainen int i = 0, ret;
b2024fa4e6ed39f9b5b6bb6c051f6d535fc0e011Timo Sirainen
edd318d5866ac3fbc6e8df28fb24a4dfef93c884Timo Sirainen if (index->opened)
edd318d5866ac3fbc6e8df28fb24a4dfef93c884Timo Sirainen return 0;
09060303d565e15d54e42b4ef722f9d3c26f5336Timo Sirainen
edd318d5866ac3fbc6e8df28fb24a4dfef93c884Timo Sirainen index->filepath = i_strconcat(index->dir, "/", index->prefix, NULL);
edd318d5866ac3fbc6e8df28fb24a4dfef93c884Timo Sirainen
edd318d5866ac3fbc6e8df28fb24a4dfef93c884Timo Sirainen do {
edd318d5866ac3fbc6e8df28fb24a4dfef93c884Timo Sirainen index->shared_lock_count = 0;
edd318d5866ac3fbc6e8df28fb24a4dfef93c884Timo Sirainen index->excl_lock_count = 0;
edd318d5866ac3fbc6e8df28fb24a4dfef93c884Timo Sirainen index->lock_type = F_UNLCK;
edd318d5866ac3fbc6e8df28fb24a4dfef93c884Timo Sirainen index->lock_id = 2;
09060303d565e15d54e42b4ef722f9d3c26f5336Timo Sirainen
edd318d5866ac3fbc6e8df28fb24a4dfef93c884Timo Sirainen index->nodiskspace = FALSE;
a99dcacb7cb6e0288f8642483f395f8e4a7aa79cTimo Sirainen index->index_lock_timeout = FALSE;
edd318d5866ac3fbc6e8df28fb24a4dfef93c884Timo Sirainen index->log_locked = FALSE;
edd318d5866ac3fbc6e8df28fb24a4dfef93c884Timo Sirainen index->mmap_disable =
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen (flags & MAIL_INDEX_OPEN_FLAG_MMAP_DISABLE) != 0;
3c3001681da75afc68578a180ec8f8b2d6dfacfaTimo Sirainen index->mmap_no_write =
b2024fa4e6ed39f9b5b6bb6c051f6d535fc0e011Timo Sirainen (flags & MAIL_INDEX_OPEN_FLAG_MMAP_NO_WRITE) != 0;
b2024fa4e6ed39f9b5b6bb6c051f6d535fc0e011Timo Sirainen index->fcntl_locks_disable =
3c3001681da75afc68578a180ec8f8b2d6dfacfaTimo Sirainen (flags & MAIL_INDEX_OPEN_FLAG_FCNTL_LOCKS_DISABLE) != 0;
892e25e1c0caad62ced087d9eba2741a59e3d9ceTimo Sirainen index->readonly = FALSE;
caa1fa99c79c568ce2e42477bc169e7024fb220bTimo Sirainen
caa1fa99c79c568ce2e42477bc169e7024fb220bTimo Sirainen ret = mail_index_open_files(index, flags);
caa1fa99c79c568ce2e42477bc169e7024fb220bTimo Sirainen if (ret <= 0)
caa1fa99c79c568ce2e42477bc169e7024fb220bTimo Sirainen break;
caa1fa99c79c568ce2e42477bc169e7024fb220bTimo Sirainen
892e25e1c0caad62ced087d9eba2741a59e3d9ceTimo Sirainen index->opened = TRUE;
892e25e1c0caad62ced087d9eba2741a59e3d9ceTimo Sirainen if (index->fsck) {
caa1fa99c79c568ce2e42477bc169e7024fb220bTimo Sirainen index->fsck = FALSE;
3c3001681da75afc68578a180ec8f8b2d6dfacfaTimo Sirainen ret = mail_index_fsck(index);
caa1fa99c79c568ce2e42477bc169e7024fb220bTimo Sirainen if (ret == 0) {
caa1fa99c79c568ce2e42477bc169e7024fb220bTimo Sirainen /* completely broken, reopen */
caa1fa99c79c568ce2e42477bc169e7024fb220bTimo Sirainen if (i++ < 3)
caa1fa99c79c568ce2e42477bc169e7024fb220bTimo Sirainen continue;
caa1fa99c79c568ce2e42477bc169e7024fb220bTimo Sirainen /* too many tries */
caa1fa99c79c568ce2e42477bc169e7024fb220bTimo Sirainen ret = -1;
caa1fa99c79c568ce2e42477bc169e7024fb220bTimo Sirainen }
caa1fa99c79c568ce2e42477bc169e7024fb220bTimo Sirainen }
caa1fa99c79c568ce2e42477bc169e7024fb220bTimo Sirainen break;
caa1fa99c79c568ce2e42477bc169e7024fb220bTimo Sirainen } while (1);
caa1fa99c79c568ce2e42477bc169e7024fb220bTimo Sirainen
caa1fa99c79c568ce2e42477bc169e7024fb220bTimo Sirainen if (ret <= 0)
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen mail_index_close(index);
caa1fa99c79c568ce2e42477bc169e7024fb220bTimo Sirainen
caa1fa99c79c568ce2e42477bc169e7024fb220bTimo Sirainen return ret;
caa1fa99c79c568ce2e42477bc169e7024fb220bTimo Sirainen}
caa1fa99c79c568ce2e42477bc169e7024fb220bTimo Sirainen
caa1fa99c79c568ce2e42477bc169e7024fb220bTimo Sirainenvoid mail_index_close(struct mail_index *index)
caa1fa99c79c568ce2e42477bc169e7024fb220bTimo Sirainen{
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen if (index->log != NULL) {
3c3001681da75afc68578a180ec8f8b2d6dfacfaTimo Sirainen mail_transaction_log_close(index->log);
caa1fa99c79c568ce2e42477bc169e7024fb220bTimo Sirainen index->log = NULL;
caa1fa99c79c568ce2e42477bc169e7024fb220bTimo Sirainen }
3c3001681da75afc68578a180ec8f8b2d6dfacfaTimo Sirainen
892e25e1c0caad62ced087d9eba2741a59e3d9ceTimo Sirainen if (index->map != NULL) {
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen mail_index_unmap(index, index->map);
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen index->map = NULL;
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen }
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen if (index->fd != -1) {
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen if (close(index->fd) < 0)
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen mail_index_set_syscall_error(index, "close()");
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen index->fd = -1;
892e25e1c0caad62ced087d9eba2741a59e3d9ceTimo Sirainen }
3c3001681da75afc68578a180ec8f8b2d6dfacfaTimo Sirainen
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen i_free(index->copy_lock_path);
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen index->copy_lock_path = NULL;
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen i_free(index->filepath);
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen index->filepath = NULL;
3c3001681da75afc68578a180ec8f8b2d6dfacfaTimo Sirainen
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen index->indexid = 0;
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen index->opened = FALSE;
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen}
60835f193436504acd13acc09928c4b4ff6934d8Timo Sirainen
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainenstruct mail_cache *mail_index_get_cache(struct mail_index *index)
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen{
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen return index->cache;
3c3001681da75afc68578a180ec8f8b2d6dfacfaTimo Sirainen}
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainenint mail_index_set_error(struct mail_index *index, const char *fmt, ...)
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen{
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen va_list va;
e2a88d59c0d47d63ce1ad5b1fd95e487124a3fd4Timo Sirainen
3c3001681da75afc68578a180ec8f8b2d6dfacfaTimo Sirainen i_free(index->error);
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen
15ab2452b0220a115f4351ad9d7fd5ec70ae7966Timo Sirainen if (fmt == NULL)
3c3001681da75afc68578a180ec8f8b2d6dfacfaTimo Sirainen index->error = NULL;
892e25e1c0caad62ced087d9eba2741a59e3d9ceTimo Sirainen else {
550d2fe097e95f12e8fa60ef52753ea7fe53d4eaTimo Sirainen va_start(va, fmt);
550d2fe097e95f12e8fa60ef52753ea7fe53d4eaTimo Sirainen index->error = i_strdup_vprintf(fmt, va);
892e25e1c0caad62ced087d9eba2741a59e3d9ceTimo Sirainen va_end(va);
3c3001681da75afc68578a180ec8f8b2d6dfacfaTimo Sirainen
550d2fe097e95f12e8fa60ef52753ea7fe53d4eaTimo Sirainen i_error("%s", index->error);
550d2fe097e95f12e8fa60ef52753ea7fe53d4eaTimo Sirainen }
550d2fe097e95f12e8fa60ef52753ea7fe53d4eaTimo Sirainen
550d2fe097e95f12e8fa60ef52753ea7fe53d4eaTimo Sirainen return -1;
3c3001681da75afc68578a180ec8f8b2d6dfacfaTimo Sirainen}
550d2fe097e95f12e8fa60ef52753ea7fe53d4eaTimo Sirainen
550d2fe097e95f12e8fa60ef52753ea7fe53d4eaTimo Sirainenvoid mail_index_set_inconsistent(struct mail_index *index)
9ba1a38e2fa5ffe9d0db83c4a14a6552bcff3181Timo Sirainen{
9ba1a38e2fa5ffe9d0db83c4a14a6552bcff3181Timo Sirainen index->indexid = 0;
9ba1a38e2fa5ffe9d0db83c4a14a6552bcff3181Timo Sirainen}
892e25e1c0caad62ced087d9eba2741a59e3d9ceTimo Sirainen
9ba1a38e2fa5ffe9d0db83c4a14a6552bcff3181Timo Sirainenvoid mail_index_mark_corrupted(struct mail_index *index)
9ba1a38e2fa5ffe9d0db83c4a14a6552bcff3181Timo Sirainen{
892e25e1c0caad62ced087d9eba2741a59e3d9ceTimo Sirainen struct mail_index_header hdr;
892e25e1c0caad62ced087d9eba2741a59e3d9ceTimo Sirainen
892e25e1c0caad62ced087d9eba2741a59e3d9ceTimo Sirainen mail_index_set_inconsistent(index);
892e25e1c0caad62ced087d9eba2741a59e3d9ceTimo Sirainen
9ba1a38e2fa5ffe9d0db83c4a14a6552bcff3181Timo Sirainen if (index->readonly)
892e25e1c0caad62ced087d9eba2741a59e3d9ceTimo Sirainen return;
892e25e1c0caad62ced087d9eba2741a59e3d9ceTimo Sirainen
9ba1a38e2fa5ffe9d0db83c4a14a6552bcff3181Timo Sirainen /* make sure we can write the header */
9ba1a38e2fa5ffe9d0db83c4a14a6552bcff3181Timo Sirainen if (!MAIL_INDEX_MAP_IS_IN_MEMORY(index->map)) {
9ba1a38e2fa5ffe9d0db83c4a14a6552bcff3181Timo Sirainen if (mprotect(index->map->mmap_base, sizeof(hdr),
9ba1a38e2fa5ffe9d0db83c4a14a6552bcff3181Timo Sirainen PROT_READ | PROT_WRITE) < 0) {
9ba1a38e2fa5ffe9d0db83c4a14a6552bcff3181Timo Sirainen mail_index_set_syscall_error(index, "mprotect()");
9ba1a38e2fa5ffe9d0db83c4a14a6552bcff3181Timo Sirainen return;
9ba1a38e2fa5ffe9d0db83c4a14a6552bcff3181Timo Sirainen }
9ba1a38e2fa5ffe9d0db83c4a14a6552bcff3181Timo Sirainen }
9ba1a38e2fa5ffe9d0db83c4a14a6552bcff3181Timo Sirainen
9ba1a38e2fa5ffe9d0db83c4a14a6552bcff3181Timo Sirainen hdr = *index->hdr;
9ba1a38e2fa5ffe9d0db83c4a14a6552bcff3181Timo Sirainen hdr.flags |= MAIL_INDEX_HDR_FLAG_CORRUPTED;
9ba1a38e2fa5ffe9d0db83c4a14a6552bcff3181Timo Sirainen if (mail_index_write_header(index, &hdr) == 0) {
9ba1a38e2fa5ffe9d0db83c4a14a6552bcff3181Timo Sirainen if (fsync(index->fd) < 0)
9ba1a38e2fa5ffe9d0db83c4a14a6552bcff3181Timo Sirainen mail_index_set_syscall_error(index, "fsync()");
9ba1a38e2fa5ffe9d0db83c4a14a6552bcff3181Timo Sirainen }
9ba1a38e2fa5ffe9d0db83c4a14a6552bcff3181Timo Sirainen}
9ba1a38e2fa5ffe9d0db83c4a14a6552bcff3181Timo Sirainen
9ba1a38e2fa5ffe9d0db83c4a14a6552bcff3181Timo Sirainenint mail_index_set_syscall_error(struct mail_index *index,
9ba1a38e2fa5ffe9d0db83c4a14a6552bcff3181Timo Sirainen const char *function)
9ba1a38e2fa5ffe9d0db83c4a14a6552bcff3181Timo Sirainen{
9ba1a38e2fa5ffe9d0db83c4a14a6552bcff3181Timo Sirainen i_assert(function != NULL);
9ba1a38e2fa5ffe9d0db83c4a14a6552bcff3181Timo Sirainen
9ba1a38e2fa5ffe9d0db83c4a14a6552bcff3181Timo Sirainen if (ENOSPACE(errno)) {
9ba1a38e2fa5ffe9d0db83c4a14a6552bcff3181Timo Sirainen index->nodiskspace = TRUE;
9ba1a38e2fa5ffe9d0db83c4a14a6552bcff3181Timo Sirainen return -1;
9ba1a38e2fa5ffe9d0db83c4a14a6552bcff3181Timo Sirainen }
9ba1a38e2fa5ffe9d0db83c4a14a6552bcff3181Timo Sirainen
9ba1a38e2fa5ffe9d0db83c4a14a6552bcff3181Timo Sirainen return mail_index_set_error(index, "%s failed with index file %s: %m",
9ba1a38e2fa5ffe9d0db83c4a14a6552bcff3181Timo Sirainen function, index->filepath);
9ba1a38e2fa5ffe9d0db83c4a14a6552bcff3181Timo Sirainen}
9ba1a38e2fa5ffe9d0db83c4a14a6552bcff3181Timo Sirainen
9ba1a38e2fa5ffe9d0db83c4a14a6552bcff3181Timo Sirainenint mail_index_file_set_syscall_error(struct mail_index *index,
9ba1a38e2fa5ffe9d0db83c4a14a6552bcff3181Timo Sirainen const char *filepath,
9ba1a38e2fa5ffe9d0db83c4a14a6552bcff3181Timo Sirainen const char *function)
9ba1a38e2fa5ffe9d0db83c4a14a6552bcff3181Timo Sirainen{
9ba1a38e2fa5ffe9d0db83c4a14a6552bcff3181Timo Sirainen i_assert(filepath != NULL);
9ba1a38e2fa5ffe9d0db83c4a14a6552bcff3181Timo Sirainen i_assert(function != NULL);
9ba1a38e2fa5ffe9d0db83c4a14a6552bcff3181Timo Sirainen
9ba1a38e2fa5ffe9d0db83c4a14a6552bcff3181Timo Sirainen if (ENOSPACE(errno)) {
9ba1a38e2fa5ffe9d0db83c4a14a6552bcff3181Timo Sirainen index->nodiskspace = TRUE;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen return -1;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen }
9ba1a38e2fa5ffe9d0db83c4a14a6552bcff3181Timo Sirainen
3c3001681da75afc68578a180ec8f8b2d6dfacfaTimo Sirainen return mail_index_set_error(index, "%s failed with file %s: %m",
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen function, filepath);
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen}
d2cadbf5445156fc12988506279d51d0e53b0449Timo Sirainen
d2cadbf5445156fc12988506279d51d0e53b0449Timo Sirainenenum mail_index_error mail_index_get_last_error(struct mail_index *index)
d2cadbf5445156fc12988506279d51d0e53b0449Timo Sirainen{
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen if (index->nodiskspace)
d2cadbf5445156fc12988506279d51d0e53b0449Timo Sirainen return MAIL_INDEX_ERROR_DISKSPACE;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen if (index->error != NULL)
f158d9a303bb15a6848ca276c9391c7ca52e452bTimo Sirainen return MAIL_INDEX_ERROR_INTERNAL;
f158d9a303bb15a6848ca276c9391c7ca52e452bTimo Sirainen
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen return MAIL_INDEX_ERROR_NONE;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen}
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainenconst char *mail_index_get_error_message(struct mail_index *index)
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen{
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen return index->error;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen}
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen
3c3001681da75afc68578a180ec8f8b2d6dfacfaTimo Sirainenvoid mail_index_reset_error(struct mail_index *index)
892e25e1c0caad62ced087d9eba2741a59e3d9ceTimo Sirainen{
892e25e1c0caad62ced087d9eba2741a59e3d9ceTimo Sirainen if (index->error != NULL) {
892e25e1c0caad62ced087d9eba2741a59e3d9ceTimo Sirainen i_free(index->error);
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen index->error = NULL;
3c3001681da75afc68578a180ec8f8b2d6dfacfaTimo Sirainen }
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen index->nodiskspace = FALSE;
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen index->index_lock_timeout = FALSE;
11ee3b40320a31669bd717fecbe1e332dad4fd84Timo Sirainen}
11ee3b40320a31669bd717fecbe1e332dad4fd84Timo Sirainen
11ee3b40320a31669bd717fecbe1e332dad4fd84Timo Sirainenint mail_index_is_in_memory(struct mail_index *index)
11ee3b40320a31669bd717fecbe1e332dad4fd84Timo Sirainen{
11ee3b40320a31669bd717fecbe1e332dad4fd84Timo Sirainen return FALSE; // FIXME
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen}
2670cd577aa57eb9f915a4f4220ae48c9b4fc5fbTimo Sirainen