mail-index.c revision d1faa68ce3878906b99aa96a06bdb7139e23bac9
a8c5a86d183db25a57bf193c06b41e092ec2e151Timo Sirainen/* Copyright (C) 2002 Timo Sirainen */
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen#include "lib.h"
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen#include "ioloop.h"
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen#include "file-lock.h"
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen#include "file-set-size.h"
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen#include "mmap-util.h"
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen#include "mail-index.h"
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen#include "mail-index-data.h"
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen#include "mail-index-util.h"
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen#include "mail-tree.h"
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen#include "mail-modifylog.h"
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen#include "mail-custom-flags.h"
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen#include <unistd.h>
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen#include <fcntl.h>
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen#include <utime.h>
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainenstatic int mmap_verify(MailIndex *index)
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen{
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen MailIndexHeader *hdr;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen unsigned int extra;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen index->mmap_used_length = 0;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen if (index->mmap_full_length < sizeof(MailIndexHeader)) {
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen index_set_corrupted(index, "File too small");
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen return FALSE;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen }
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen extra = (index->mmap_full_length - sizeof(MailIndexHeader)) %
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen sizeof(MailIndexRecord);
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen if (extra != 0) {
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen /* partial write or corrupted -
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen truncate the file to valid length */
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen i_assert(!index->anon_mmap);
4ee00532a265bdfb38539d811fcd12d51210ac35Timo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen index->mmap_full_length -= extra;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen (void)ftruncate(index->fd, (off_t)index->mmap_full_length);
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen }
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen index->last_lookup_seq = 0;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen index->last_lookup = NULL;
939a0d82523538b2de38a02bc9f790a67b7ebf47Timo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen /* keep the header set even if we fail, so we can update the flags */
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen hdr = index->mmap_base;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen index->header = hdr;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen if (hdr->used_file_size > index->mmap_full_length) {
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen index_set_corrupted(index, "used_file_size larger than real "
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen "file size (%"PRIuUOFF_T" vs %"PRIuSIZE_T
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen ")", hdr->used_file_size,
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen index->mmap_full_length);
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen return FALSE;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen }
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen if ((hdr->used_file_size - sizeof(MailIndexHeader)) %
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen sizeof(MailIndexRecord) != 0) {
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen index_set_corrupted(index, "Invalid used_file_size in header "
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen "(%"PRIuUOFF_T")",
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen hdr->used_file_size);
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen return FALSE;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen }
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen if (hdr->messages_count < hdr->seen_messages_count) {
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen index_set_corrupted(index, "Invalid seen messages count "
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen "(%u < %u)", hdr->messages_count,
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen hdr->seen_messages_count);
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen return FALSE;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen }
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen if (hdr->messages_count < hdr->deleted_messages_count) {
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen index_set_corrupted(index, "Invalid deleted messages count "
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen "(%u < %u)", hdr->messages_count,
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen hdr->deleted_messages_count);
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen return FALSE;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen }
84ed9f8f3d0e5ed47607ef417618e49e4f865557Timo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen index->sync_id = hdr->sync_id;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen index->mmap_used_length = hdr->used_file_size;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen return TRUE;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen}
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainenint mail_index_mmap_update(MailIndex *index)
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen{
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen if (index->anon_mmap)
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen return mmap_verify(index);
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen if (index->mmap_base != NULL) {
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen index->header = (MailIndexHeader *) index->mmap_base;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen /* make sure file size hasn't changed */
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen if (index->header->sync_id == index->sync_id) {
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen index->mmap_used_length = index->header->used_file_size;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen if (index->mmap_used_length > index->mmap_full_length) {
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen i_panic("Index file size was grown without "
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen "updating sync_id");
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen }
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen return TRUE;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen }
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen if (msync(index->mmap_base,
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen index->mmap_used_length, MS_SYNC) < 0)
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen return index_set_syscall_error(index, "msync()");
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen if (munmap(index->mmap_base, index->mmap_full_length) < 0)
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen return index_set_syscall_error(index, "munmap()");
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen }
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen index->mmap_base = mmap_rw_file(index->fd, &index->mmap_full_length);
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen if (index->mmap_base == MAP_FAILED) {
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen index->mmap_base = NULL;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen index->mmap_used_length = 0;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen index_set_syscall_error(index, "mmap()");
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen return FALSE;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen }
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen return mmap_verify(index);
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen}
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
c9dea5c23355dea35c6fa423de69f6507852efe4Timo Sirainenvoid mail_index_close(MailIndex *index)
c9dea5c23355dea35c6fa423de69f6507852efe4Timo Sirainen{
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen index->set_flags = 0;
7a24bdc1a5e2d5368c2569b4852192f2bdb5a31fTimo Sirainen index->set_cache_fields = 0;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen
7a24bdc1a5e2d5368c2569b4852192f2bdb5a31fTimo Sirainen index->opened = FALSE;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen index->inconsistent = FALSE;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen index->lock_type = MAIL_LOCK_UNLOCK;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen index->header = NULL;
4cf5f0934a25f1fd58f2780108f9d6498c455a1fTimo Sirainen
4cf5f0934a25f1fd58f2780108f9d6498c455a1fTimo Sirainen if (index->fd != -1) {
4cf5f0934a25f1fd58f2780108f9d6498c455a1fTimo Sirainen if (close(index->fd) < 0)
4cf5f0934a25f1fd58f2780108f9d6498c455a1fTimo Sirainen index_set_syscall_error(index, "close()");
4cf5f0934a25f1fd58f2780108f9d6498c455a1fTimo Sirainen index->fd = -1;
4cf5f0934a25f1fd58f2780108f9d6498c455a1fTimo Sirainen }
4cf5f0934a25f1fd58f2780108f9d6498c455a1fTimo Sirainen
4cf5f0934a25f1fd58f2780108f9d6498c455a1fTimo Sirainen if (index->filepath != NULL) {
4cf5f0934a25f1fd58f2780108f9d6498c455a1fTimo Sirainen i_free(index->filepath);
4cf5f0934a25f1fd58f2780108f9d6498c455a1fTimo Sirainen index->filepath = NULL;
4cf5f0934a25f1fd58f2780108f9d6498c455a1fTimo Sirainen }
d22301419109ed4a38351715e6760011421dadecTimo Sirainen
4cf5f0934a25f1fd58f2780108f9d6498c455a1fTimo Sirainen if (index->anon_mmap) {
4cf5f0934a25f1fd58f2780108f9d6498c455a1fTimo Sirainen if (munmap_anon(index->mmap_base, index->mmap_full_length) < 0)
4cf5f0934a25f1fd58f2780108f9d6498c455a1fTimo Sirainen index_set_syscall_error(index, "munmap_anon()");
4cf5f0934a25f1fd58f2780108f9d6498c455a1fTimo Sirainen index->anon_mmap = FALSE;
4cf5f0934a25f1fd58f2780108f9d6498c455a1fTimo Sirainen } else if (index->mmap_base != NULL) {
4cf5f0934a25f1fd58f2780108f9d6498c455a1fTimo Sirainen if (munmap(index->mmap_base, index->mmap_full_length) < 0)
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen index_set_syscall_error(index, "munmap()");
ca98892a6b8a30ffc1fe26fcf02c7d59e3204e7eTimo Sirainen }
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen index->mmap_base = NULL;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen if (index->data != NULL) {
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen mail_index_data_free(index->data);
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen index->data = NULL;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen }
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen if (index->tree != NULL) {
4cf5f0934a25f1fd58f2780108f9d6498c455a1fTimo Sirainen mail_tree_free(index->tree);
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen index->tree = NULL;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen }
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen if (index->modifylog != NULL) {
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen mail_modifylog_free(index->modifylog);
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen index->modifylog = NULL;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen }
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen if (index->custom_flags != NULL) {
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen mail_custom_flags_free(index->custom_flags);
6d6c1517ef20e340a3aace406724fc8916f2d13fTimo Sirainen index->custom_flags = NULL;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen }
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen if (index->error != NULL) {
7e209b78ca757294dbbc15604c88673b3a6b0c39Timo Sirainen i_free(index->error);
7e209b78ca757294dbbc15604c88673b3a6b0c39Timo Sirainen index->error = NULL;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen }
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen}
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainenstatic int mail_index_sync_file(MailIndex *index)
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen{
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen struct utimbuf ut;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen int failed;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen if (index->anon_mmap)
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen return TRUE;
939a0d82523538b2de38a02bc9f790a67b7ebf47Timo Sirainen
ca98892a6b8a30ffc1fe26fcf02c7d59e3204e7eTimo Sirainen if (!mail_index_data_sync_file(index->data))
939a0d82523538b2de38a02bc9f790a67b7ebf47Timo Sirainen return FALSE;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen
4cf5f0934a25f1fd58f2780108f9d6498c455a1fTimo Sirainen if (msync(index->mmap_base, index->mmap_used_length, MS_SYNC) < 0)
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen return index_set_syscall_error(index, "msync()");
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen failed = FALSE;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen if (index->tree != NULL) {
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen if (!mail_tree_sync_file(index->tree))
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen failed = TRUE;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen }
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen if (index->modifylog != NULL) {
939a0d82523538b2de38a02bc9f790a67b7ebf47Timo Sirainen if (!mail_modifylog_sync_file(index->modifylog))
ca98892a6b8a30ffc1fe26fcf02c7d59e3204e7eTimo Sirainen failed = TRUE;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen }
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen /* keep index's modify stamp same as the sync file's stamp */
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen ut.actime = ioloop_time;
939a0d82523538b2de38a02bc9f790a67b7ebf47Timo Sirainen ut.modtime = index->file_sync_stamp;
ca98892a6b8a30ffc1fe26fcf02c7d59e3204e7eTimo Sirainen if (utime(index->filepath, &ut) < 0)
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen return index_set_syscall_error(index, "utime()");
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen if (fsync(index->fd) < 0)
939a0d82523538b2de38a02bc9f790a67b7ebf47Timo Sirainen return index_set_syscall_error(index, "fsync()");
ca98892a6b8a30ffc1fe26fcf02c7d59e3204e7eTimo Sirainen
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen return !failed;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen}
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainenint mail_index_fmsync(MailIndex *index, size_t size)
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen{
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen i_assert(index->lock_type == MAIL_LOCK_EXCLUSIVE);
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen if (!index->anon_mmap) {
4cf5f0934a25f1fd58f2780108f9d6498c455a1fTimo Sirainen if (msync(index->mmap_base, size, MS_SYNC) < 0)
4cf5f0934a25f1fd58f2780108f9d6498c455a1fTimo Sirainen return index_set_syscall_error(index, "msync()");
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen if (fsync(index->fd) < 0)
4cf5f0934a25f1fd58f2780108f9d6498c455a1fTimo Sirainen return index_set_syscall_error(index, "fsync()");
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen }
4cf5f0934a25f1fd58f2780108f9d6498c455a1fTimo Sirainen
4cf5f0934a25f1fd58f2780108f9d6498c455a1fTimo Sirainen return TRUE;
4cf5f0934a25f1fd58f2780108f9d6498c455a1fTimo Sirainen}
4cf5f0934a25f1fd58f2780108f9d6498c455a1fTimo Sirainen
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainenstatic void mail_index_update_header_changes(MailIndex *index)
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen{
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen if (index->set_flags != 0) {
6d6c1517ef20e340a3aace406724fc8916f2d13fTimo Sirainen index->header->flags |= index->set_flags;
6d6c1517ef20e340a3aace406724fc8916f2d13fTimo Sirainen index->set_flags = 0;
6d6c1517ef20e340a3aace406724fc8916f2d13fTimo Sirainen }
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen if (index->set_cache_fields != 0) {
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen index->header->cache_fields = index->set_cache_fields;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen index->set_cache_fields = 0;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen }
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen}
939a0d82523538b2de38a02bc9f790a67b7ebf47Timo Sirainen
939a0d82523538b2de38a02bc9f790a67b7ebf47Timo Sirainen#define MAIL_LOCK_TO_FLOCK(lock_type) \
4cf5f0934a25f1fd58f2780108f9d6498c455a1fTimo Sirainen ((lock_type) == MAIL_LOCK_UNLOCK ? F_UNLCK : \
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen (lock_type) == MAIL_LOCK_SHARED ? F_RDLCK : F_WRLCK)
939a0d82523538b2de38a02bc9f790a67b7ebf47Timo Sirainen
939a0d82523538b2de38a02bc9f790a67b7ebf47Timo Sirainenint mail_index_try_lock(MailIndex *index, MailLockType lock_type)
4cf5f0934a25f1fd58f2780108f9d6498c455a1fTimo Sirainen{
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen int ret;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen if (index->lock_type == lock_type)
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen return TRUE;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen if (index->anon_mmap)
4cf5f0934a25f1fd58f2780108f9d6498c455a1fTimo Sirainen return TRUE;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen ret = file_try_lock(index->fd, MAIL_LOCK_TO_FLOCK(lock_type));
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen if (ret < 0)
c9dea5c23355dea35c6fa423de69f6507852efe4Timo Sirainen index_set_syscall_error(index, "file_try_lock()");
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen return ret > 0;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen}
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainenstatic int mail_index_write_header_changes(MailIndex *index)
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen{
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen int failed;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen /* use our own locking here so we don't mess up with any other
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen index states, like inconsistency. */
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen if (file_wait_lock(index->fd, F_WRLCK) < 0)
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen return index_set_syscall_error(index, "file_wait_lock()");
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen mail_index_update_header_changes(index);
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen failed = msync(index->mmap_base, sizeof(MailIndexHeader), MS_SYNC) < 0;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen if (failed)
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen index_set_syscall_error(index, "msync()");
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen if (file_wait_lock(index->fd, F_UNLCK) < 0)
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen return index_set_syscall_error(index, "file_wait_lock()");
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen return !failed;
7e209b78ca757294dbbc15604c88673b3a6b0c39Timo Sirainen}
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainenstatic int mail_index_lock_remove(MailIndex *index)
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen{
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen MailLockType old_lock_type;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen if (file_wait_lock(index->fd, F_UNLCK) < 0)
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen return index_set_syscall_error(index, "file_wait_lock()");
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen old_lock_type = index->lock_type;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen index->lock_type = MAIL_LOCK_UNLOCK;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen /* reset last_lookup so rebuilds don't try to use it */
6d6c1517ef20e340a3aace406724fc8916f2d13fTimo Sirainen index->last_lookup_seq = 0;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen index->last_lookup = NULL;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen if (old_lock_type == MAIL_LOCK_SHARED) {
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen /* releasing shared lock. we may need to update some
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen flags in header. */
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen unsigned int old_flags, old_cache;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen old_flags = index->header->flags;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen old_cache = index->header->cache_fields;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen if ((old_flags | index->set_flags) != old_flags ||
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen (old_cache | index->set_cache_fields) != old_cache)
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen return mail_index_write_header_changes(index);
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen }
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen return TRUE;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen}
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainenstatic int mail_index_lock_change(MailIndex *index, MailLockType lock_type)
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen{
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen /* shared -> exclusive isn't allowed */
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen i_assert(lock_type != MAIL_LOCK_EXCLUSIVE ||
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen index->lock_type != MAIL_LOCK_SHARED);
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen if (index->inconsistent) {
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen /* index is in inconsistent state and nothing else than
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen free() is allowed for it. */
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen return FALSE;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen }
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen if (file_wait_lock(index->fd, MAIL_LOCK_TO_FLOCK(lock_type)) < 0)
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen return index_set_syscall_error(index, "file_wait_lock()");
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen index->lock_type = lock_type;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen if (!mail_index_mmap_update(index)) {
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen (void)mail_index_set_lock(index, MAIL_LOCK_UNLOCK);
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen return FALSE;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen }
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen if (index->indexid != index->header->indexid) {
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen /* index was rebuilt, there's no way we can maintain
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen consistency */
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen index_set_error(index, "Warning: Inconsistency - Index "
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen "%s was rebuilt while we had it open",
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen index->filepath);
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen index->inconsistent = TRUE;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen return FALSE;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen }
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen if (lock_type == MAIL_LOCK_EXCLUSIVE) {
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen /* while holding exclusive lock, keep the FSCK flag on.
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen when the lock is released, the FSCK flag will also be
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen removed. */
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen index->header->flags |= MAIL_INDEX_FLAG_FSCK;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen if (!mail_index_fmsync(index, sizeof(MailIndexHeader))) {
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen (void)mail_index_set_lock(index, MAIL_LOCK_UNLOCK);
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen return FALSE;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen }
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen }
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen return TRUE;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen}
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainenint mail_index_set_lock(MailIndex *index, MailLockType lock_type)
03010dbaa74ec70f062994dfe3cd39bedc99a28bTimo Sirainen{
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen int keep_fsck;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen if (index->lock_type == lock_type)
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen return TRUE;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen if (index->anon_mmap) {
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen /* anonymous mmaps are private and don't need any locking */
42270b2d8d9bb0d04b16e0ead727154b32399a3fTimo Sirainen mail_index_update_header_changes(index);
42270b2d8d9bb0d04b16e0ead727154b32399a3fTimo Sirainen index->lock_type = lock_type;
42270b2d8d9bb0d04b16e0ead727154b32399a3fTimo Sirainen return TRUE;
42270b2d8d9bb0d04b16e0ead727154b32399a3fTimo Sirainen }
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen if (index->lock_type == MAIL_LOCK_EXCLUSIVE) {
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen /* dropping exclusive lock (either unlock or to shared) */
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen keep_fsck = (index->set_flags & MAIL_INDEX_FLAG_FSCK) != 0;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen mail_index_update_header_changes(index);
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen /* remove the FSCK flag only after successful fsync() */
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen if (mail_index_sync_file(index) && !keep_fsck) {
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen index->header->flags &= ~MAIL_INDEX_FLAG_FSCK;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen if (msync(index->mmap_base, sizeof(MailIndexHeader),
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen MS_SYNC) < 0) {
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen /* we only failed to remove the fsck flag,
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen so this isn't fatal. */
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen index_set_syscall_error(index, "msync()");
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen }
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen }
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen }
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen if (lock_type == MAIL_LOCK_UNLOCK)
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen return mail_index_lock_remove(index);
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen else
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen return mail_index_lock_change(index, lock_type);
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen}
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainenint mail_index_verify_hole_range(MailIndex *index)
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen{
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen MailIndexHeader *hdr;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen unsigned int max_records, first_records;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
4182d8cd818e76856a5a1e25b343fe5ddf69fd8eTimo Sirainen hdr = index->header;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen if (hdr->first_hole_position == 0)
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen return TRUE;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen /* make sure position is valid */
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen if (hdr->first_hole_position < sizeof(MailIndexHeader) ||
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen (hdr->first_hole_position -
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen sizeof(MailIndexHeader)) % sizeof(MailIndexRecord) != 0) {
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen index_set_corrupted(index, "first_hole_position contains "
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen "invalid value");
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen return FALSE;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen }
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen /* make sure position is in range.. */
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen if (hdr->first_hole_position >= index->mmap_used_length) {
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen index_set_corrupted(index, "first_hole_position points "
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen "outside file");
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen return FALSE;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen }
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
d22301419109ed4a38351715e6760011421dadecTimo Sirainen /* and finally check that first_hole_records is in valid range */
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen max_records = MAIL_INDEX_RECORD_COUNT(index);
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen first_records = (hdr->first_hole_position -
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen sizeof(MailIndexHeader)) / sizeof(MailIndexRecord);
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen if (index->header->first_hole_records > max_records ||
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen first_records + index->header->first_hole_records > max_records) {
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen index_set_corrupted(index, "first_hole_records points "
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen "outside file");
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen return FALSE;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen }
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen return TRUE;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen}
d22301419109ed4a38351715e6760011421dadecTimo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo SirainenMailIndexHeader *mail_index_get_header(MailIndex *index)
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen{
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen i_assert(index->lock_type != MAIL_LOCK_UNLOCK);
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen return index->header;
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen}
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo SirainenMailIndexRecord *mail_index_lookup(MailIndex *index, unsigned int seq)
4ece61edd7c266a4b8f3b290a7f0a3cb3d13ca0fTimo Sirainen{
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen MailIndexHeader *hdr;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen MailIndexRecord *rec;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen const char *format;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen uoff_t pos;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen i_assert(seq > 0);
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen i_assert(index->lock_type != MAIL_LOCK_UNLOCK);
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen if (seq == index->last_lookup_seq &&
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen index->last_lookup != NULL && index->last_lookup->uid != 0) {
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen /* wanted the same record as last time */
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen return index->last_lookup;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen }
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen hdr = index->header;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen if (seq > hdr->messages_count) {
3e1d94509fd76c56f2eb54f98ea02ade9ac2d44aTimo Sirainen /* out of range */
3e1d94509fd76c56f2eb54f98ea02ade9ac2d44aTimo Sirainen return NULL;
3e1d94509fd76c56f2eb54f98ea02ade9ac2d44aTimo Sirainen }
3e1d94509fd76c56f2eb54f98ea02ade9ac2d44aTimo Sirainen
eef4ba0cc3e78f8c26804c1c9251a76580a41f0cTimo Sirainen if (!mail_index_verify_hole_range(index))
eef4ba0cc3e78f8c26804c1c9251a76580a41f0cTimo Sirainen return NULL;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen pos = sizeof(MailIndexHeader) +
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen (uoff_t)(seq-1) * sizeof(MailIndexRecord);
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen if (hdr->first_hole_position == 0 ||
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen hdr->first_hole_position > pos) {
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen /* easy, it's just at the expected index */
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen format = "Invalid first_hole_position in header: %"PRIuUOFF_T;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen } else if (hdr->first_hole_records ==
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen MAIL_INDEX_RECORD_COUNT(index) - hdr->messages_count) {
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen /* only one hole in file, skip it and we're at
eef4ba0cc3e78f8c26804c1c9251a76580a41f0cTimo Sirainen correct position */
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen pos += (size_t)hdr->first_hole_records *
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen sizeof(MailIndexRecord);
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen format = "Invalid hole locations in header: %"PRIuUOFF_T;
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen } else {
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen /* find from binary tree */
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen pos = mail_tree_lookup_sequence(index->tree, seq);
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen if (pos == 0) {
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen index_set_corrupted(index, "Sequence %u not found from "
24e5e4526d8f5cbc056ab97fd0d154d0936d7a5eTimo Sirainen "binary tree (%u msgs says header)",
fde0b1793a2842da00eaa105d5e13fec465f0443Timo Sirainen seq, hdr->messages_count);
fde0b1793a2842da00eaa105d5e13fec465f0443Timo Sirainen return NULL;
fde0b1793a2842da00eaa105d5e13fec465f0443Timo Sirainen }
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen format = "Invalid offset returned by binary tree: %"PRIuUOFF_T;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen }
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen if (pos < sizeof(MailIndexHeader) ||
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen pos > index->mmap_used_length - sizeof(MailIndexRecord) ||
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen (pos - sizeof(MailIndexHeader)) % sizeof(MailIndexRecord) != 0) {
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen index_set_corrupted(index, format, pos);
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen return NULL;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen }
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen rec = (MailIndexRecord *) ((char *) index->mmap_base + pos);
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen if (rec->uid == 0) {
e3736b5d480878031c386ac55d201fcf08e68766Timo Sirainen index_set_corrupted(index, format, pos);
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen return NULL;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen }
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen index->last_lookup = rec;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen index->last_lookup_seq = seq;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen return rec;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen}
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo SirainenMailIndexRecord *mail_index_next(MailIndex *index, MailIndexRecord *rec)
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen{
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen MailIndexRecord *end_rec;
fde0b1793a2842da00eaa105d5e13fec465f0443Timo Sirainen
fde0b1793a2842da00eaa105d5e13fec465f0443Timo Sirainen i_assert(index->lock_type != MAIL_LOCK_UNLOCK);
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen i_assert(rec >= (MailIndexRecord *) index->mmap_base);
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen if (rec == NULL)
e3736b5d480878031c386ac55d201fcf08e68766Timo Sirainen return NULL;
e3736b5d480878031c386ac55d201fcf08e68766Timo Sirainen
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen /* go to the next non-deleted record */
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen end_rec = (MailIndexRecord *) ((char *) index->mmap_base +
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen index->mmap_used_length);
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen while (++rec < end_rec) {
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen if (rec->uid != 0)
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen return rec;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen }
e3736b5d480878031c386ac55d201fcf08e68766Timo Sirainen
e3736b5d480878031c386ac55d201fcf08e68766Timo Sirainen return NULL;
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen}
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen
905457e0982fc15930d90e174f271dc69f9afcf9Timo SirainenMailIndexRecord *mail_index_lookup_uid_range(MailIndex *index,
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen unsigned int first_uid,
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen unsigned int last_uid,
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen unsigned int *seq_r)
fb7dd075cf883e5e7defbc0c8fb8326e30bdccdeTimo Sirainen{
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen MailIndexRecord *rec;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen uoff_t pos;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen i_assert(index->lock_type != MAIL_LOCK_UNLOCK);
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen i_assert(first_uid > 0 && last_uid > 0);
a21823d90cee6a18aeab0378637472c7e3fbbab2Timo Sirainen i_assert(first_uid <= last_uid);
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen
a21823d90cee6a18aeab0378637472c7e3fbbab2Timo Sirainen pos = mail_tree_lookup_uid_range(index->tree, seq_r,
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen first_uid, last_uid);
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen if (pos == 0)
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen return NULL;
a21823d90cee6a18aeab0378637472c7e3fbbab2Timo Sirainen
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen rec = (MailIndexRecord *) ((char *) index->mmap_base + pos);
a21823d90cee6a18aeab0378637472c7e3fbbab2Timo Sirainen if (rec->uid < first_uid || rec->uid > last_uid) {
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen index_set_error(index, "Corrupted binary tree for index %s: "
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen "lookup returned offset to wrong UID "
a21823d90cee6a18aeab0378637472c7e3fbbab2Timo Sirainen "(%u vs %u..%u)", index->filepath,
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen rec->uid, first_uid, last_uid);
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen index->set_flags |= MAIL_INDEX_FLAG_REBUILD_TREE;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen return NULL;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen }
a21823d90cee6a18aeab0378637472c7e3fbbab2Timo Sirainen
a21823d90cee6a18aeab0378637472c7e3fbbab2Timo Sirainen return rec;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen}
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen
fde0b1793a2842da00eaa105d5e13fec465f0443Timo Sirainenstatic MailIndexDataRecord *
fde0b1793a2842da00eaa105d5e13fec465f0443Timo Sirainenindex_lookup_data_field(MailIndex *index, MailIndexRecord *rec, MailField field)
fde0b1793a2842da00eaa105d5e13fec465f0443Timo Sirainen{
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen i_assert(index->lock_type != MAIL_LOCK_UNLOCK);
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen /* first check if the field even could be in the file */
a21823d90cee6a18aeab0378637472c7e3fbbab2Timo Sirainen if ((rec->cached_fields & field) != field) {
a21823d90cee6a18aeab0378637472c7e3fbbab2Timo Sirainen if ((index->header->cache_fields & field) == 0) {
a21823d90cee6a18aeab0378637472c7e3fbbab2Timo Sirainen /* no, but make sure the future records will have it.
a21823d90cee6a18aeab0378637472c7e3fbbab2Timo Sirainen we don't immediately mark the index to cache this
a21823d90cee6a18aeab0378637472c7e3fbbab2Timo Sirainen field for old messages as some clients never ask
a21823d90cee6a18aeab0378637472c7e3fbbab2Timo Sirainen the info again */
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen index->set_cache_fields |= field;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen } else {
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen /* this is at least the second time it's being asked,
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen make sure it'll be cached soon. */
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen index->set_flags |= MAIL_INDEX_FLAG_CACHE_FIELDS;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen }
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen
a21823d90cee6a18aeab0378637472c7e3fbbab2Timo Sirainen return NULL;
41955c400476941fa274f18b106a5922866fd780Timo Sirainen }
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen return mail_index_data_lookup(index->data, rec, field);
a21823d90cee6a18aeab0378637472c7e3fbbab2Timo Sirainen}
e3736b5d480878031c386ac55d201fcf08e68766Timo Sirainen
e3736b5d480878031c386ac55d201fcf08e68766Timo Sirainenconst char *mail_index_lookup_field(MailIndex *index, MailIndexRecord *rec,
a21823d90cee6a18aeab0378637472c7e3fbbab2Timo Sirainen MailField field)
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen{
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen MailIndexDataRecord *datarec;
d516e6848ecfbc7381abe9414fd8011fdf9d8c95Timo Sirainen
a21823d90cee6a18aeab0378637472c7e3fbbab2Timo Sirainen datarec = index_lookup_data_field(index, rec, field);
d516e6848ecfbc7381abe9414fd8011fdf9d8c95Timo Sirainen if (datarec == NULL)
d516e6848ecfbc7381abe9414fd8011fdf9d8c95Timo Sirainen return NULL;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen if (!mail_index_data_record_verify(index->data, datarec)) {
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen /* index is corrupted, it will be rebuilt */
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen return NULL;
c9dea5c23355dea35c6fa423de69f6507852efe4Timo Sirainen }
c9dea5c23355dea35c6fa423de69f6507852efe4Timo Sirainen
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen return datarec->data;
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen}
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainenconst void *mail_index_lookup_field_raw(MailIndex *index, MailIndexRecord *rec,
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen MailField field, size_t *size)
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen{
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen MailIndexDataRecord *datarec;
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen datarec = index_lookup_data_field(index, rec, field);
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen if (datarec == NULL) {
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen *size = 0;
c9dea5c23355dea35c6fa423de69f6507852efe4Timo Sirainen return NULL;
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen }
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen *size = datarec->full_field_size;
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen return datarec->data;
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen}
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainenvoid mail_index_mark_flag_changes(MailIndex *index, MailIndexRecord *rec,
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen MailFlags old_flags, MailFlags new_flags)
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen{
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen if ((old_flags & MAIL_SEEN) == 0 && (new_flags & MAIL_SEEN)) {
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen /* unseen -> seen */
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen index->header->seen_messages_count++;
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen } else if ((old_flags & MAIL_SEEN) && (new_flags & MAIL_SEEN) == 0) {
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen /* seen -> unseen */
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen if (index->header->seen_messages_count ==
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen index->header->messages_count) {
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen /* this is the first unseen message */
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen index->header->first_unseen_uid_lowwater = rec->uid;
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen } else if (rec->uid < index->header->first_unseen_uid_lowwater)
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen index->header->first_unseen_uid_lowwater = rec->uid;
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen if (index->header->seen_messages_count == 0) {
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen index_set_corrupted(index, "seen_messages_count in "
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen "header is invalid");
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen } else {
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen index->header->seen_messages_count--;
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen }
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen }
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen if ((old_flags & MAIL_DELETED) == 0 &&
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen (new_flags & MAIL_DELETED)) {
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen /* undeleted -> deleted */
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen index->header->deleted_messages_count++;
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen
03010dbaa74ec70f062994dfe3cd39bedc99a28bTimo Sirainen if (index->header->deleted_messages_count == 1) {
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen /* this is the first deleted message */
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen index->header->first_deleted_uid_lowwater = rec->uid;
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen } else if (rec->uid < index->header->first_deleted_uid_lowwater)
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen index->header->first_deleted_uid_lowwater = rec->uid;
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen } else if ((old_flags & MAIL_DELETED) &&
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen (new_flags & MAIL_DELETED) == 0) {
ca98d6a1bbe73499da758a36bfab2963375c8d06Timo Sirainen /* deleted -> undeleted */
ca98d6a1bbe73499da758a36bfab2963375c8d06Timo Sirainen if (index->header->deleted_messages_count == 0) {
86bde2c1838d1ce967fa2b394bb952004a4adcb7Timo Sirainen index_set_corrupted(index, "deleted_messages_count in "
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen "header is invalid");
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen } else {
86bde2c1838d1ce967fa2b394bb952004a4adcb7Timo Sirainen index->header->deleted_messages_count--;
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen }
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen }
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen}
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainenstatic void update_first_hole_records(MailIndex *index)
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen{
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen MailIndexRecord *rec, *end_rec;
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen /* see if first_hole_records can be grown */
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen rec = (MailIndexRecord *) ((char *) index->mmap_base +
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen index->header->first_hole_position) +
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen index->header->first_hole_records;
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen end_rec = (MailIndexRecord *) ((char *) index->mmap_base +
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen index->mmap_used_length);
ca98d6a1bbe73499da758a36bfab2963375c8d06Timo Sirainen while (rec < end_rec && rec->uid == 0) {
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen index->header->first_hole_records++;
6cd263d9a9812174a63e852ad6a9a8cdf63cfd8eTimo Sirainen rec++;
3b1dd975d0c543d76679593f86e136d43bf40635Timo Sirainen }
6cd263d9a9812174a63e852ad6a9a8cdf63cfd8eTimo Sirainen}
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainenstatic int mail_index_truncate_hole(MailIndex *index)
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen{
3e1d94509fd76c56f2eb54f98ea02ade9ac2d44aTimo Sirainen index->header->used_file_size =
3e1d94509fd76c56f2eb54f98ea02ade9ac2d44aTimo Sirainen (size_t)index->header->first_hole_position;
3e1d94509fd76c56f2eb54f98ea02ade9ac2d44aTimo Sirainen index->header->first_hole_position = 0;
3e1d94509fd76c56f2eb54f98ea02ade9ac2d44aTimo Sirainen index->header->first_hole_records = 0;
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen index->mmap_used_length = index->header->used_file_size;
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen if (!mail_index_truncate(index))
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen return FALSE;
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen
6cd263d9a9812174a63e852ad6a9a8cdf63cfd8eTimo Sirainen if (index->header->messages_count == 0) {
6cd263d9a9812174a63e852ad6a9a8cdf63cfd8eTimo Sirainen /* all mail was deleted, truncate data file */
6cd263d9a9812174a63e852ad6a9a8cdf63cfd8eTimo Sirainen if (!mail_index_data_reset(index->data))
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen return FALSE;
ca98d6a1bbe73499da758a36bfab2963375c8d06Timo Sirainen }
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen return TRUE;
ca98d6a1bbe73499da758a36bfab2963375c8d06Timo Sirainen}
3b1dd975d0c543d76679593f86e136d43bf40635Timo Sirainen
6cd263d9a9812174a63e852ad6a9a8cdf63cfd8eTimo Sirainenint mail_index_expunge(MailIndex *index, MailIndexRecord *rec,
3b1dd975d0c543d76679593f86e136d43bf40635Timo Sirainen unsigned int seq, int external_change)
3b1dd975d0c543d76679593f86e136d43bf40635Timo Sirainen{
ca98d6a1bbe73499da758a36bfab2963375c8d06Timo Sirainen MailIndexHeader *hdr;
3b1dd975d0c543d76679593f86e136d43bf40635Timo Sirainen uoff_t pos;
ca98d6a1bbe73499da758a36bfab2963375c8d06Timo Sirainen
86bde2c1838d1ce967fa2b394bb952004a4adcb7Timo Sirainen i_assert(index->lock_type == MAIL_LOCK_EXCLUSIVE);
3b1dd975d0c543d76679593f86e136d43bf40635Timo Sirainen i_assert(seq != 0);
6cd263d9a9812174a63e852ad6a9a8cdf63cfd8eTimo Sirainen i_assert(rec->uid != 0);
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen if (seq != 0 && index->modifylog != NULL) {
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen if (!mail_modifylog_add_expunge(index->modifylog, seq,
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen rec->uid, external_change))
6cd263d9a9812174a63e852ad6a9a8cdf63cfd8eTimo Sirainen return FALSE;
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen }
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen /* expunge() may be called while index is being rebuilt and when
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen there's no hash yet */
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen if (index->tree != NULL)
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen mail_tree_delete(index->tree, rec->uid);
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen else {
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen /* make sure it also gets updated */
18a41cbd38f83429b790414c1159c097af4a59b8Timo Sirainen index->header->flags |= MAIL_INDEX_FLAG_REBUILD_TREE;
18a41cbd38f83429b790414c1159c097af4a59b8Timo Sirainen }
18a41cbd38f83429b790414c1159c097af4a59b8Timo Sirainen
18a41cbd38f83429b790414c1159c097af4a59b8Timo Sirainen /* setting UID to 0 is enough for deleting the mail from index */
18a41cbd38f83429b790414c1159c097af4a59b8Timo Sirainen rec->uid = 0;
18a41cbd38f83429b790414c1159c097af4a59b8Timo Sirainen
18a41cbd38f83429b790414c1159c097af4a59b8Timo Sirainen /* update last_lookup_seq */
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen if (seq != 0) {
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen /* note that last_lookup can be left to point to
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen invalid record so that next() works properly */
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen if (seq == index->last_lookup_seq)
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen index->last_lookup = NULL;
3b49aee9ced3b0370a3be396aca53acd5f21418cTimo Sirainen else if (seq < index->last_lookup_seq)
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen index->last_lookup_seq--;
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen }
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen if (!mail_index_verify_hole_range(index))
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen return FALSE;
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen hdr = index->header;
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen /* update first hole */
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen pos = INDEX_FILE_POSITION(index, rec);
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen if (hdr->first_hole_position < sizeof(MailIndexRecord)) {
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen /* first deleted message in index */
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen hdr->first_hole_position = pos;
fde0b1793a2842da00eaa105d5e13fec465f0443Timo Sirainen hdr->first_hole_records = 1;
fde0b1793a2842da00eaa105d5e13fec465f0443Timo Sirainen } else if (hdr->first_hole_position - sizeof(MailIndexRecord) == pos) {
fde0b1793a2842da00eaa105d5e13fec465f0443Timo Sirainen /* deleted the previous record before hole */
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen hdr->first_hole_position -= sizeof(MailIndexRecord);
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen hdr->first_hole_records++;
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen } else if (hdr->first_hole_position +
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen (hdr->first_hole_records * sizeof(MailIndexRecord)) == pos) {
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen /* deleted the next record after hole */
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen hdr->first_hole_records++;
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen update_first_hole_records(index);
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen } else {
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen /* second hole coming to index file */
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen if (hdr->first_hole_position > pos) {
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen /* new hole before the old hole */
86bde2c1838d1ce967fa2b394bb952004a4adcb7Timo Sirainen hdr->first_hole_position = pos;
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen hdr->first_hole_records = 1;
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen }
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen }
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen /* update message counts */
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen if (hdr->messages_count == 0) {
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen /* corrupted */
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen index_set_corrupted(index, "Header says there's no mail "
7fc0f80480063a9d4cb9e8c07b50db2a5627799eTimo Sirainen "while expunging");
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen return FALSE;
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen }
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen hdr->messages_count--;
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen mail_index_mark_flag_changes(index, rec, rec->msg_flags, 0);
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen if ((hdr->first_hole_position - sizeof(MailIndexHeader)) /
c20d64512d687f0abf7c1a0aa4fa0174da0a18e3Timo Sirainen sizeof(MailIndexRecord) == hdr->messages_count) {
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen /* the hole reaches end of file, truncate it */
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen (void)mail_index_truncate_hole(index);
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen } else {
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen /* update deleted_space in data file */
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen (void)mail_index_data_add_deleted_space(index->data,
fde0b1793a2842da00eaa105d5e13fec465f0443Timo Sirainen rec->data_size);
fde0b1793a2842da00eaa105d5e13fec465f0443Timo Sirainen }
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen
c20d64512d687f0abf7c1a0aa4fa0174da0a18e3Timo Sirainen return TRUE;
fde0b1793a2842da00eaa105d5e13fec465f0443Timo Sirainen}
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainenint mail_index_update_flags(MailIndex *index, MailIndexRecord *rec,
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen unsigned int seq, MailFlags flags,
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen int external_change)
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen{
c20d64512d687f0abf7c1a0aa4fa0174da0a18e3Timo Sirainen i_assert(index->lock_type == MAIL_LOCK_EXCLUSIVE);
86bde2c1838d1ce967fa2b394bb952004a4adcb7Timo Sirainen i_assert(seq != 0);
c20d64512d687f0abf7c1a0aa4fa0174da0a18e3Timo Sirainen
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen if (flags == rec->msg_flags)
c20d64512d687f0abf7c1a0aa4fa0174da0a18e3Timo Sirainen return TRUE; /* no changes */
c20d64512d687f0abf7c1a0aa4fa0174da0a18e3Timo Sirainen
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen mail_index_mark_flag_changes(index, rec, rec->msg_flags, flags);
c20d64512d687f0abf7c1a0aa4fa0174da0a18e3Timo Sirainen
c20d64512d687f0abf7c1a0aa4fa0174da0a18e3Timo Sirainen rec->msg_flags = flags;
c20d64512d687f0abf7c1a0aa4fa0174da0a18e3Timo Sirainen return index->modifylog == NULL ? TRUE :
c20d64512d687f0abf7c1a0aa4fa0174da0a18e3Timo Sirainen mail_modifylog_add_flags(index->modifylog, seq,
86bde2c1838d1ce967fa2b394bb952004a4adcb7Timo Sirainen rec->uid, external_change);
280b771b7ec7e49caa399540dfe8faf42999a1adTimo Sirainen}
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainenstatic int mail_index_grow(MailIndex *index)
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen{
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen uoff_t pos;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen unsigned int grow_count;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen void *base;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen grow_count = index->header->messages_count *
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen INDEX_GROW_PERCENTAGE / 100;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen if (grow_count < 16)
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen grow_count = 16;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen pos = index->mmap_full_length + (grow_count * sizeof(MailIndexRecord));
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen i_assert(pos < OFF_T_MAX);
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen if (index->anon_mmap) {
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen i_assert(pos < SSIZE_T_MAX);
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen base = mremap_anon(index->mmap_base, index->mmap_full_length,
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen (size_t)pos, MREMAP_MAYMOVE);
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen if (base == MAP_FAILED)
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen return index_set_syscall_error(index, "mremap_anon()");
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen
905457e0982fc15930d90e174f271dc69f9afcf9Timo Sirainen index->mmap_base = base;
7fc0f80480063a9d4cb9e8c07b50db2a5627799eTimo Sirainen index->mmap_full_length = (size_t)pos;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen return TRUE;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen }
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen if (file_set_size(index->fd, (off_t)pos) < 0) {
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen if (errno == ENOSPC)
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen index->nodiskspace = TRUE;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen return index_set_syscall_error(index, "file_set_size()");
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen }
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen
461ffead9720d1e516b959d5e41f049c73d38c7cTimo Sirainen /* file size changed, let others know about it too by changing
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen sync_id in header. */
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen index->header->sync_id++;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen if (!mail_index_mmap_update(index))
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen return FALSE;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen return TRUE;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen}
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainenint mail_index_append_begin(MailIndex *index, MailIndexRecord **rec)
41955c400476941fa274f18b106a5922866fd780Timo Sirainen{
41955c400476941fa274f18b106a5922866fd780Timo Sirainen MailIndexRecord *destrec;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen i_assert(index->lock_type == MAIL_LOCK_EXCLUSIVE);
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen i_assert((*rec)->uid == 0);
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen i_assert((*rec)->msg_flags == 0);
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen if (index->mmap_used_length == index->mmap_full_length) {
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen if (!mail_index_grow(index))
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen return FALSE;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen }
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen i_assert(index->header->used_file_size == index->mmap_used_length);
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen i_assert(index->mmap_used_length + sizeof(MailIndexRecord) <=
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen index->mmap_full_length);
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen destrec = (MailIndexRecord *) ((char *) index->mmap_base +
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen index->mmap_used_length);
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen memcpy(destrec, *rec, sizeof(MailIndexRecord));
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen *rec = destrec;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen index->header->used_file_size += sizeof(MailIndexRecord);
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen index->mmap_used_length += sizeof(MailIndexRecord);
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen return TRUE;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen}
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainenint mail_index_append_end(MailIndex *index, MailIndexRecord *rec)
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen{
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen i_assert(rec->uid == 0);
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen index->header->messages_count++;
ca98d6a1bbe73499da758a36bfab2963375c8d06Timo Sirainen
ca98d6a1bbe73499da758a36bfab2963375c8d06Timo Sirainen rec->uid = index->header->next_uid++;
fde0b1793a2842da00eaa105d5e13fec465f0443Timo Sirainen
fde0b1793a2842da00eaa105d5e13fec465f0443Timo Sirainen if (index->tree != NULL) {
fde0b1793a2842da00eaa105d5e13fec465f0443Timo Sirainen mail_tree_insert(index->tree, rec->uid,
fde0b1793a2842da00eaa105d5e13fec465f0443Timo Sirainen INDEX_FILE_POSITION(index, rec));
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen }
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen return TRUE;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen}
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainenconst char *mail_index_get_last_error(MailIndex *index)
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen{
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen return index->error;
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen}
dee43975a70bcdb9dc83d34d6a2b177d37bb7194Timo Sirainen
41955c400476941fa274f18b106a5922866fd780Timo Sirainenint mail_index_is_diskspace_error(MailIndex *index)
41955c400476941fa274f18b106a5922866fd780Timo Sirainen{
41955c400476941fa274f18b106a5922866fd780Timo Sirainen return !index->inconsistent && index->nodiskspace;
41955c400476941fa274f18b106a5922866fd780Timo Sirainen}
41955c400476941fa274f18b106a5922866fd780Timo Sirainen
41955c400476941fa274f18b106a5922866fd780Timo Sirainenint mail_index_is_inconsistency_error(MailIndex *index)
41955c400476941fa274f18b106a5922866fd780Timo Sirainen{
41955c400476941fa274f18b106a5922866fd780Timo Sirainen return index->inconsistent;
ca98d6a1bbe73499da758a36bfab2963375c8d06Timo Sirainen}
ca98d6a1bbe73499da758a36bfab2963375c8d06Timo Sirainen