mail-index-open.c revision 99b621cc5076398c5d780d2ea33dd7391341d630
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainen/* Copyright (C) 2002-2003 Timo Sirainen */
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainen
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainen#include "lib.h"
568fec5b1e629f25d288b48007485b9aa4a018b1Timo Sirainen#include "ioloop.h"
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainen#include "file-lock.h"
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainen#include "file-set-size.h"
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainen#include "hostpid.h"
568fec5b1e629f25d288b48007485b9aa4a018b1Timo Sirainen#include "mmap-util.h"
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainen#include "unlink-lockfiles.h"
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainen#include "write-full.h"
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainen#include "mail-index.h"
568fec5b1e629f25d288b48007485b9aa4a018b1Timo Sirainen#include "mail-index-data.h"
568fec5b1e629f25d288b48007485b9aa4a018b1Timo Sirainen#include "mail-index-util.h"
568fec5b1e629f25d288b48007485b9aa4a018b1Timo Sirainen#include "mail-tree.h"
568fec5b1e629f25d288b48007485b9aa4a018b1Timo Sirainen#include "mail-modifylog.h"
568fec5b1e629f25d288b48007485b9aa4a018b1Timo Sirainen#include "mail-custom-flags.h"
568fec5b1e629f25d288b48007485b9aa4a018b1Timo Sirainen
62fc0b4f07eb6f18a3bff4b1fccb636e6fae3cf4Timo Sirainen#include <stdio.h>
62fc0b4f07eb6f18a3bff4b1fccb636e6fae3cf4Timo Sirainen#include <stdlib.h>
62fc0b4f07eb6f18a3bff4b1fccb636e6fae3cf4Timo Sirainen#include <unistd.h>
62fc0b4f07eb6f18a3bff4b1fccb636e6fae3cf4Timo Sirainen#include <fcntl.h>
62fc0b4f07eb6f18a3bff4b1fccb636e6fae3cf4Timo Sirainen
62fc0b4f07eb6f18a3bff4b1fccb636e6fae3cf4Timo Sirainenstatic int mail_index_open_init(struct mail_index *index,
62fc0b4f07eb6f18a3bff4b1fccb636e6fae3cf4Timo Sirainen enum mail_index_open_flags flags)
62fc0b4f07eb6f18a3bff4b1fccb636e6fae3cf4Timo Sirainen{
62fc0b4f07eb6f18a3bff4b1fccb636e6fae3cf4Timo Sirainen struct mail_index_header *hdr;
62fc0b4f07eb6f18a3bff4b1fccb636e6fae3cf4Timo Sirainen
62fc0b4f07eb6f18a3bff4b1fccb636e6fae3cf4Timo Sirainen hdr = index->header;
62fc0b4f07eb6f18a3bff4b1fccb636e6fae3cf4Timo Sirainen
b04e76cbc807707d299055be79500f8ff131da43Timo Sirainen /* update \Recent message counters */
b04e76cbc807707d299055be79500f8ff131da43Timo Sirainen if ((flags & MAIL_INDEX_OPEN_FLAG_UPDATE_RECENT) != 0 &&
72c4ef3b44c50c662b37bba93b463b0caeb63a4fTimo Sirainen hdr->last_nonrecent_uid != hdr->next_uid-1) {
0c5854b6891c59c1c3f443569bc823d7db571582Teemu Huovila /* keep last_recent_uid to next_uid-1 */
62fc0b4f07eb6f18a3bff4b1fccb636e6fae3cf4Timo Sirainen if (index->lock_type == MAIL_LOCK_SHARED) {
62fc0b4f07eb6f18a3bff4b1fccb636e6fae3cf4Timo Sirainen if (!index->set_lock(index, MAIL_LOCK_UNLOCK))
62fc0b4f07eb6f18a3bff4b1fccb636e6fae3cf4Timo Sirainen return FALSE;
62fc0b4f07eb6f18a3bff4b1fccb636e6fae3cf4Timo Sirainen }
62fc0b4f07eb6f18a3bff4b1fccb636e6fae3cf4Timo Sirainen
62fc0b4f07eb6f18a3bff4b1fccb636e6fae3cf4Timo Sirainen if (!index->set_lock(index, MAIL_LOCK_EXCLUSIVE))
62fc0b4f07eb6f18a3bff4b1fccb636e6fae3cf4Timo Sirainen return FALSE;
62fc0b4f07eb6f18a3bff4b1fccb636e6fae3cf4Timo Sirainen
62fc0b4f07eb6f18a3bff4b1fccb636e6fae3cf4Timo Sirainen index->first_recent_uid = index->header->last_nonrecent_uid+1;
62fc0b4f07eb6f18a3bff4b1fccb636e6fae3cf4Timo Sirainen index->header->last_nonrecent_uid = index->header->next_uid-1;
f5c0d5cada4da23a167c38426d0c481a3e1d5583Timo Sirainen } else {
f5c0d5cada4da23a167c38426d0c481a3e1d5583Timo Sirainen index->first_recent_uid = hdr->last_nonrecent_uid+1;
f5c0d5cada4da23a167c38426d0c481a3e1d5583Timo Sirainen }
f5c0d5cada4da23a167c38426d0c481a3e1d5583Timo Sirainen
f5c0d5cada4da23a167c38426d0c481a3e1d5583Timo Sirainen if (hdr->next_uid >= MAX_ALLOWED_UID - 1000) {
f5c0d5cada4da23a167c38426d0c481a3e1d5583Timo Sirainen /* UID values are getting too high, rebuild index */
f5c0d5cada4da23a167c38426d0c481a3e1d5583Timo Sirainen index->set_flags |= MAIL_INDEX_FLAG_REBUILD;
f5c0d5cada4da23a167c38426d0c481a3e1d5583Timo Sirainen }
62fc0b4f07eb6f18a3bff4b1fccb636e6fae3cf4Timo Sirainen
568fec5b1e629f25d288b48007485b9aa4a018b1Timo Sirainen if (index->lock_type == MAIL_LOCK_EXCLUSIVE) {
62fc0b4f07eb6f18a3bff4b1fccb636e6fae3cf4Timo Sirainen /* finally reset the modify log marks, fsck or syncing might
62fc0b4f07eb6f18a3bff4b1fccb636e6fae3cf4Timo Sirainen have deleted some messages, and since we're only just
568fec5b1e629f25d288b48007485b9aa4a018b1Timo Sirainen opening the index, there's no need to remember them */
568fec5b1e629f25d288b48007485b9aa4a018b1Timo Sirainen if (!mail_modifylog_mark_synced(index->modifylog))
8b1a9a4d63b0abccdf7cb1acb8359d5396dd657bTimo Sirainen return FALSE;
62fc0b4f07eb6f18a3bff4b1fccb636e6fae3cf4Timo Sirainen }
568fec5b1e629f25d288b48007485b9aa4a018b1Timo Sirainen
568fec5b1e629f25d288b48007485b9aa4a018b1Timo Sirainen return TRUE;
62fc0b4f07eb6f18a3bff4b1fccb636e6fae3cf4Timo Sirainen}
8b1a9a4d63b0abccdf7cb1acb8359d5396dd657bTimo Sirainen
568fec5b1e629f25d288b48007485b9aa4a018b1Timo Sirainenstatic int index_open_and_fix(struct mail_index *index,
568fec5b1e629f25d288b48007485b9aa4a018b1Timo Sirainen enum mail_index_open_flags flags)
568fec5b1e629f25d288b48007485b9aa4a018b1Timo Sirainen{
8b1a9a4d63b0abccdf7cb1acb8359d5396dd657bTimo Sirainen /* open/create the index files */
568fec5b1e629f25d288b48007485b9aa4a018b1Timo Sirainen if ((flags & _MAIL_INDEX_OPEN_FLAG_CREATING) == 0) {
568fec5b1e629f25d288b48007485b9aa4a018b1Timo Sirainen if (!mail_index_data_open(index)) {
568fec5b1e629f25d288b48007485b9aa4a018b1Timo Sirainen if ((index->set_flags & MAIL_INDEX_FLAG_REBUILD) == 0)
62fc0b4f07eb6f18a3bff4b1fccb636e6fae3cf4Timo Sirainen return FALSE;
568fec5b1e629f25d288b48007485b9aa4a018b1Timo Sirainen
568fec5b1e629f25d288b48007485b9aa4a018b1Timo Sirainen /* data file is corrupted, need to rebuild index */
62fc0b4f07eb6f18a3bff4b1fccb636e6fae3cf4Timo Sirainen flags |= _MAIL_INDEX_OPEN_FLAG_CREATING;
62fc0b4f07eb6f18a3bff4b1fccb636e6fae3cf4Timo Sirainen index->set_flags = 0;
568fec5b1e629f25d288b48007485b9aa4a018b1Timo Sirainen index->inconsistent = FALSE;
8b1a9a4d63b0abccdf7cb1acb8359d5396dd657bTimo Sirainen }
568fec5b1e629f25d288b48007485b9aa4a018b1Timo Sirainen }
568fec5b1e629f25d288b48007485b9aa4a018b1Timo Sirainen
568fec5b1e629f25d288b48007485b9aa4a018b1Timo Sirainen if ((flags & _MAIL_INDEX_OPEN_FLAG_CREATING) != 0) {
568fec5b1e629f25d288b48007485b9aa4a018b1Timo Sirainen if (!mail_index_set_lock(index, MAIL_LOCK_EXCLUSIVE))
8b1a9a4d63b0abccdf7cb1acb8359d5396dd657bTimo Sirainen return FALSE;
568fec5b1e629f25d288b48007485b9aa4a018b1Timo Sirainen if (!mail_index_data_create(index))
568fec5b1e629f25d288b48007485b9aa4a018b1Timo Sirainen return FALSE;
568fec5b1e629f25d288b48007485b9aa4a018b1Timo Sirainen }
62fc0b4f07eb6f18a3bff4b1fccb636e6fae3cf4Timo Sirainen
568fec5b1e629f25d288b48007485b9aa4a018b1Timo Sirainen /* custom flags file needs to be open before
568fec5b1e629f25d288b48007485b9aa4a018b1Timo Sirainen rebuilding index */
62fc0b4f07eb6f18a3bff4b1fccb636e6fae3cf4Timo Sirainen if (!mail_custom_flags_open_or_create(index))
62fc0b4f07eb6f18a3bff4b1fccb636e6fae3cf4Timo Sirainen return FALSE;
568fec5b1e629f25d288b48007485b9aa4a018b1Timo Sirainen
568fec5b1e629f25d288b48007485b9aa4a018b1Timo Sirainen if ((flags & _MAIL_INDEX_OPEN_FLAG_CREATING) != 0 ||
568fec5b1e629f25d288b48007485b9aa4a018b1Timo Sirainen (index->header->flags & MAIL_INDEX_FLAG_REBUILD) != 0) {
8b1a9a4d63b0abccdf7cb1acb8359d5396dd657bTimo Sirainen if (!index->rebuild(index))
568fec5b1e629f25d288b48007485b9aa4a018b1Timo Sirainen return FALSE;
568fec5b1e629f25d288b48007485b9aa4a018b1Timo Sirainen
568fec5b1e629f25d288b48007485b9aa4a018b1Timo Sirainen /* no inconsistency problems since we're still opening
568fec5b1e629f25d288b48007485b9aa4a018b1Timo Sirainen the index */
8b1a9a4d63b0abccdf7cb1acb8359d5396dd657bTimo Sirainen index->inconsistent = FALSE;
568fec5b1e629f25d288b48007485b9aa4a018b1Timo Sirainen }
568fec5b1e629f25d288b48007485b9aa4a018b1Timo Sirainen
568fec5b1e629f25d288b48007485b9aa4a018b1Timo Sirainen if ((flags & _MAIL_INDEX_OPEN_FLAG_CREATING) == 0) {
62fc0b4f07eb6f18a3bff4b1fccb636e6fae3cf4Timo Sirainen if (!mail_tree_open_or_create(index))
0c5854b6891c59c1c3f443569bc823d7db571582Teemu Huovila return FALSE;
62fc0b4f07eb6f18a3bff4b1fccb636e6fae3cf4Timo Sirainen if (!mail_modifylog_open_or_create(index))
62fc0b4f07eb6f18a3bff4b1fccb636e6fae3cf4Timo Sirainen return FALSE;
62fc0b4f07eb6f18a3bff4b1fccb636e6fae3cf4Timo Sirainen } else {
62fc0b4f07eb6f18a3bff4b1fccb636e6fae3cf4Timo Sirainen if (!mail_tree_create(index))
62fc0b4f07eb6f18a3bff4b1fccb636e6fae3cf4Timo Sirainen return FALSE;
62fc0b4f07eb6f18a3bff4b1fccb636e6fae3cf4Timo Sirainen if (!mail_modifylog_create(index))
62fc0b4f07eb6f18a3bff4b1fccb636e6fae3cf4Timo Sirainen return FALSE;
62fc0b4f07eb6f18a3bff4b1fccb636e6fae3cf4Timo Sirainen }
62fc0b4f07eb6f18a3bff4b1fccb636e6fae3cf4Timo Sirainen
62fc0b4f07eb6f18a3bff4b1fccb636e6fae3cf4Timo Sirainen if (index->header->flags & MAIL_INDEX_FLAG_FSCK) {
62fc0b4f07eb6f18a3bff4b1fccb636e6fae3cf4Timo Sirainen /* index needs fscking */
62fc0b4f07eb6f18a3bff4b1fccb636e6fae3cf4Timo Sirainen if (!index->fsck(index))
62fc0b4f07eb6f18a3bff4b1fccb636e6fae3cf4Timo Sirainen return FALSE;
62fc0b4f07eb6f18a3bff4b1fccb636e6fae3cf4Timo Sirainen }
568fec5b1e629f25d288b48007485b9aa4a018b1Timo Sirainen
568fec5b1e629f25d288b48007485b9aa4a018b1Timo Sirainen if ((index->header->flags & MAIL_INDEX_FLAG_REBUILD_TREE) != 0) {
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainen if (!mail_tree_rebuild(index->tree))
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainen return FALSE;
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainen }
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainen
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainen /* sync ourself. do it before updating cache and compression which
568fec5b1e629f25d288b48007485b9aa4a018b1Timo Sirainen may happen because of this. */
568fec5b1e629f25d288b48007485b9aa4a018b1Timo Sirainen if (!index->sync_and_lock(index, MAIL_LOCK_SHARED, NULL))
568fec5b1e629f25d288b48007485b9aa4a018b1Timo Sirainen return FALSE;
568fec5b1e629f25d288b48007485b9aa4a018b1Timo Sirainen index->inconsistent = FALSE;
568fec5b1e629f25d288b48007485b9aa4a018b1Timo Sirainen
78f87ea1d30f3f54bdf8560ea947ab7ee094283aTeemu Huovila /* we never want to keep shared lock if syncing happens to set it.
62fc0b4f07eb6f18a3bff4b1fccb636e6fae3cf4Timo Sirainen either exclusive or nothing (NOTE: drop it directly, not through
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainen index->set_lock() so mbox lock won't be affected). */
b04e76cbc807707d299055be79500f8ff131da43Timo Sirainen if (index->lock_type == MAIL_LOCK_SHARED) {
b04e76cbc807707d299055be79500f8ff131da43Timo Sirainen if (!mail_index_set_lock(index, MAIL_LOCK_UNLOCK))
0c5854b6891c59c1c3f443569bc823d7db571582Teemu Huovila return FALSE;
0c5854b6891c59c1c3f443569bc823d7db571582Teemu Huovila }
0c5854b6891c59c1c3f443569bc823d7db571582Teemu Huovila
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainen if ((flags & MAIL_INDEX_OPEN_FLAG_FAST) == 0) {
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainen if (index->header->flags & MAIL_INDEX_FLAG_COMPRESS) {
62fc0b4f07eb6f18a3bff4b1fccb636e6fae3cf4Timo Sirainen /* remove deleted blocks from index file */
62fc0b4f07eb6f18a3bff4b1fccb636e6fae3cf4Timo Sirainen if (!mail_index_compress(index))
62fc0b4f07eb6f18a3bff4b1fccb636e6fae3cf4Timo Sirainen return FALSE;
62fc0b4f07eb6f18a3bff4b1fccb636e6fae3cf4Timo Sirainen }
62fc0b4f07eb6f18a3bff4b1fccb636e6fae3cf4Timo Sirainen
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainen if (index->header->flags & MAIL_INDEX_FLAG_CACHE_FIELDS) {
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainen /* need to update cached fields */
568fec5b1e629f25d288b48007485b9aa4a018b1Timo Sirainen if (!mail_index_update_cache(index))
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainen return FALSE;
62fc0b4f07eb6f18a3bff4b1fccb636e6fae3cf4Timo Sirainen }
f5c0d5cada4da23a167c38426d0c481a3e1d5583Timo Sirainen
62fc0b4f07eb6f18a3bff4b1fccb636e6fae3cf4Timo Sirainen if (index->header->flags & MAIL_INDEX_FLAG_COMPRESS_DATA) {
62fc0b4f07eb6f18a3bff4b1fccb636e6fae3cf4Timo Sirainen /* remove unused space from index data file.
62fc0b4f07eb6f18a3bff4b1fccb636e6fae3cf4Timo Sirainen keep after cache updates which may move data
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainen and create unused space */
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainen if (!mail_index_compress_data(index))
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainen return FALSE;
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainen }
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainen }
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainen
62fc0b4f07eb6f18a3bff4b1fccb636e6fae3cf4Timo Sirainen if (!mail_index_open_init(index, flags))
62fc0b4f07eb6f18a3bff4b1fccb636e6fae3cf4Timo Sirainen return FALSE;
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainen
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainen return TRUE;
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainen}
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainen
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainenstatic int mail_index_read_header(struct mail_index *index,
568fec5b1e629f25d288b48007485b9aa4a018b1Timo Sirainen struct mail_index_header *hdr)
568fec5b1e629f25d288b48007485b9aa4a018b1Timo Sirainen{
568fec5b1e629f25d288b48007485b9aa4a018b1Timo Sirainen ssize_t ret;
568fec5b1e629f25d288b48007485b9aa4a018b1Timo Sirainen
568fec5b1e629f25d288b48007485b9aa4a018b1Timo Sirainen ret = read(index->fd, hdr, sizeof(*hdr));
568fec5b1e629f25d288b48007485b9aa4a018b1Timo Sirainen if (ret < 0) {
62fc0b4f07eb6f18a3bff4b1fccb636e6fae3cf4Timo Sirainen index_set_syscall_error(index, "read()");
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainen return -1;
b04e76cbc807707d299055be79500f8ff131da43Timo Sirainen }
b04e76cbc807707d299055be79500f8ff131da43Timo Sirainen
0c5854b6891c59c1c3f443569bc823d7db571582Teemu Huovila if (ret != sizeof(*hdr)) {
0c5854b6891c59c1c3f443569bc823d7db571582Teemu Huovila /* missing data */
0c5854b6891c59c1c3f443569bc823d7db571582Teemu Huovila return 0;
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainen }
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainen
62fc0b4f07eb6f18a3bff4b1fccb636e6fae3cf4Timo Sirainen return 1;
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainen}
62fc0b4f07eb6f18a3bff4b1fccb636e6fae3cf4Timo Sirainen
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainenstatic int mail_index_is_compatible(const struct mail_index_header *hdr)
62fc0b4f07eb6f18a3bff4b1fccb636e6fae3cf4Timo Sirainen{
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainen return hdr->compat_data[0] == MAIL_INDEX_VERSION &&
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainen hdr->compat_data[1] == MAIL_INDEX_COMPAT_FLAGS &&
568fec5b1e629f25d288b48007485b9aa4a018b1Timo Sirainen hdr->compat_data[2] == sizeof(unsigned int) &&
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainen hdr->compat_data[3] == sizeof(time_t) &&
62fc0b4f07eb6f18a3bff4b1fccb636e6fae3cf4Timo Sirainen hdr->compat_data[4] == sizeof(uoff_t) &&
f5c0d5cada4da23a167c38426d0c481a3e1d5583Timo Sirainen hdr->compat_data[5] == MEM_ALIGN_SIZE;
62fc0b4f07eb6f18a3bff4b1fccb636e6fae3cf4Timo Sirainen}
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainen
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainenstatic int mail_index_init_file(struct mail_index *index,
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainen struct mail_index_header *hdr)
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainen{
568fec5b1e629f25d288b48007485b9aa4a018b1Timo Sirainen hdr->used_file_size = sizeof(*hdr) +
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainen INDEX_MIN_RECORDS_COUNT * sizeof(struct mail_index_record);
568fec5b1e629f25d288b48007485b9aa4a018b1Timo Sirainen
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainen if (lseek(index->fd, 0, SEEK_SET) < 0) {
568fec5b1e629f25d288b48007485b9aa4a018b1Timo Sirainen index_set_syscall_error(index, "lseek()");
568fec5b1e629f25d288b48007485b9aa4a018b1Timo Sirainen return FALSE;
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainen }
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainen
568fec5b1e629f25d288b48007485b9aa4a018b1Timo Sirainen if (write_full(index->fd, hdr, sizeof(*hdr)) < 0) {
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainen index_set_syscall_error(index, "write_full()");
568fec5b1e629f25d288b48007485b9aa4a018b1Timo Sirainen return FALSE;
908c417cc19ec4a2a01db542498c13ade3943601Timo Sirainen }
62fc0b4f07eb6f18a3bff4b1fccb636e6fae3cf4Timo Sirainen
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainen if (file_set_size(index->fd, (off_t)hdr->used_file_size) < 0) {
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainen index_set_syscall_error(index, "file_set_size()");
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainen return FALSE;
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainen }
568fec5b1e629f25d288b48007485b9aa4a018b1Timo Sirainen
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainen return TRUE;
568fec5b1e629f25d288b48007485b9aa4a018b1Timo Sirainen}
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainen
568fec5b1e629f25d288b48007485b9aa4a018b1Timo Sirainenvoid mail_index_init_header(struct mail_index *index,
568fec5b1e629f25d288b48007485b9aa4a018b1Timo Sirainen struct mail_index_header *hdr)
568fec5b1e629f25d288b48007485b9aa4a018b1Timo Sirainen{
568fec5b1e629f25d288b48007485b9aa4a018b1Timo Sirainen memset(hdr, 0, sizeof(*hdr));
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainen hdr->compat_data[0] = MAIL_INDEX_VERSION;
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainen hdr->compat_data[1] = MAIL_INDEX_COMPAT_FLAGS;
568fec5b1e629f25d288b48007485b9aa4a018b1Timo Sirainen hdr->compat_data[2] = sizeof(unsigned int);
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainen hdr->compat_data[3] = sizeof(time_t);
568fec5b1e629f25d288b48007485b9aa4a018b1Timo Sirainen hdr->compat_data[4] = sizeof(uoff_t);
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainen hdr->compat_data[5] = MEM_ALIGN_SIZE;
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainen hdr->indexid = ioloop_time;
62fc0b4f07eb6f18a3bff4b1fccb636e6fae3cf4Timo Sirainen
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainen /* mark the index requiring rebuild - rebuild() removes this flag
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainen when it succeeds */
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainen hdr->flags = MAIL_INDEX_FLAG_REBUILD;
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainen
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainen /* set the fields we always want to cache */
e4bf76afb82ea28ec9d06823fa7deed5f8277183Timo Sirainen hdr->cache_fields |= index->default_cache_fields;
e4bf76afb82ea28ec9d06823fa7deed5f8277183Timo Sirainen
568fec5b1e629f25d288b48007485b9aa4a018b1Timo Sirainen hdr->used_file_size = sizeof(struct mail_index_header);
e4bf76afb82ea28ec9d06823fa7deed5f8277183Timo Sirainen hdr->uid_validity = ioloop_time;
568fec5b1e629f25d288b48007485b9aa4a018b1Timo Sirainen hdr->next_uid = 1;
568fec5b1e629f25d288b48007485b9aa4a018b1Timo Sirainen}
568fec5b1e629f25d288b48007485b9aa4a018b1Timo Sirainen
568fec5b1e629f25d288b48007485b9aa4a018b1Timo Sirainenstatic void mail_index_cleanup_temp_files(const char *dir)
e4bf76afb82ea28ec9d06823fa7deed5f8277183Timo Sirainen{
568fec5b1e629f25d288b48007485b9aa4a018b1Timo Sirainen unlink_lockfiles(dir, t_strconcat("temp.", my_hostname, NULL),
e4bf76afb82ea28ec9d06823fa7deed5f8277183Timo Sirainen "temp.", time(NULL) - TEMP_FILE_TIMEOUT);
e4bf76afb82ea28ec9d06823fa7deed5f8277183Timo Sirainen}
e4bf76afb82ea28ec9d06823fa7deed5f8277183Timo Sirainen
568fec5b1e629f25d288b48007485b9aa4a018b1Timo Sirainenvoid mail_index_init(struct mail_index *index, const char *dir)
e4bf76afb82ea28ec9d06823fa7deed5f8277183Timo Sirainen{
e4bf76afb82ea28ec9d06823fa7deed5f8277183Timo Sirainen size_t len;
62fc0b4f07eb6f18a3bff4b1fccb636e6fae3cf4Timo Sirainen
c4b772bfbdafe68ac1a0076eab26cd681f8e5046Timo Sirainen index->fd = -1;
2730605833442b5ddcb261f90b8375fc98201e35Timo Sirainen
8b1a9a4d63b0abccdf7cb1acb8359d5396dd657bTimo Sirainen if (dir != NULL) {
8b1a9a4d63b0abccdf7cb1acb8359d5396dd657bTimo Sirainen index->dir = i_strdup(dir);
2730605833442b5ddcb261f90b8375fc98201e35Timo Sirainen
8b1a9a4d63b0abccdf7cb1acb8359d5396dd657bTimo Sirainen len = strlen(index->dir);
c4b772bfbdafe68ac1a0076eab26cd681f8e5046Timo Sirainen if (index->dir[len-1] == '/')
8b1a9a4d63b0abccdf7cb1acb8359d5396dd657bTimo Sirainen index->dir[len-1] = '\0';
8b1a9a4d63b0abccdf7cb1acb8359d5396dd657bTimo Sirainen }
2730605833442b5ddcb261f90b8375fc98201e35Timo Sirainen
8b1a9a4d63b0abccdf7cb1acb8359d5396dd657bTimo Sirainen index->mail_read_mmaped = getenv("MAIL_READ_MMAPED") != NULL;
c4b772bfbdafe68ac1a0076eab26cd681f8e5046Timo Sirainen}
8b1a9a4d63b0abccdf7cb1acb8359d5396dd657bTimo Sirainen
8b1a9a4d63b0abccdf7cb1acb8359d5396dd657bTimo Sirainenstatic int mail_index_create_memory(struct mail_index *index,
2730605833442b5ddcb261f90b8375fc98201e35Timo Sirainen enum mail_index_open_flags flags)
8b1a9a4d63b0abccdf7cb1acb8359d5396dd657bTimo Sirainen{
c4b772bfbdafe68ac1a0076eab26cd681f8e5046Timo Sirainen if ((flags & MAIL_INDEX_OPEN_FLAG_CREATE) == 0)
2730605833442b5ddcb261f90b8375fc98201e35Timo Sirainen return FALSE;
8b1a9a4d63b0abccdf7cb1acb8359d5396dd657bTimo Sirainen
2730605833442b5ddcb261f90b8375fc98201e35Timo Sirainen flags |= _MAIL_INDEX_OPEN_FLAG_CREATING;
8b1a9a4d63b0abccdf7cb1acb8359d5396dd657bTimo Sirainen
8b1a9a4d63b0abccdf7cb1acb8359d5396dd657bTimo Sirainen index->mmap_full_length = INDEX_FILE_MIN_SIZE;
2730605833442b5ddcb261f90b8375fc98201e35Timo Sirainen index->mmap_base = mmap_anon(index->mmap_full_length);
8b1a9a4d63b0abccdf7cb1acb8359d5396dd657bTimo Sirainen
2730605833442b5ddcb261f90b8375fc98201e35Timo Sirainen mail_index_init_header(index, index->mmap_base);
e4bf76afb82ea28ec9d06823fa7deed5f8277183Timo Sirainen index->header = index->mmap_base;
e4bf76afb82ea28ec9d06823fa7deed5f8277183Timo Sirainen index->mmap_used_length = index->header->used_file_size;
e4bf76afb82ea28ec9d06823fa7deed5f8277183Timo Sirainen
e4bf76afb82ea28ec9d06823fa7deed5f8277183Timo Sirainen index->anon_mmap = TRUE;
e4bf76afb82ea28ec9d06823fa7deed5f8277183Timo Sirainen index->lock_type = MAIL_LOCK_EXCLUSIVE;
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainen index->indexid = index->header->indexid;
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainen index->filepath = i_strdup_printf("(in-memory index for %s)",
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainen index->mailbox_path);
f5c0d5cada4da23a167c38426d0c481a3e1d5583Timo Sirainen
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainen if (!index_open_and_fix(index, flags)) {
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainen mail_index_close(index);
568fec5b1e629f25d288b48007485b9aa4a018b1Timo Sirainen return FALSE;
568fec5b1e629f25d288b48007485b9aa4a018b1Timo Sirainen }
e4bf76afb82ea28ec9d06823fa7deed5f8277183Timo Sirainen
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainen return TRUE;
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainen}
b1965419f329eb7cf78ee39e7c5942462eabb256Timo Sirainen
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainenint mail_index_open(struct mail_index *index, enum mail_index_open_flags flags)
b1965419f329eb7cf78ee39e7c5942462eabb256Timo Sirainen{
b1965419f329eb7cf78ee39e7c5942462eabb256Timo Sirainen struct mail_index_header hdr;
b1965419f329eb7cf78ee39e7c5942462eabb256Timo Sirainen const char *path;
b1965419f329eb7cf78ee39e7c5942462eabb256Timo Sirainen int ret;
c865b0e9c65fd77f7b2ab6f8616d3def5501ecb3Timo Sirainen
i_assert(!index->opened);
if (index->dir == NULL)
return mail_index_create_memory(index, flags);
mail_index_cleanup_temp_files(index->dir);
/* open/create the file */
path = t_strconcat(index->dir, "/", INDEX_FILE_PREFIX, NULL);
if ((flags & MAIL_INDEX_OPEN_FLAG_CREATE) != 0)
index->fd = open(path, O_RDWR | O_CREAT, 0660);
else
index->fd = open(path, O_RDWR);
if (index->fd == -1) {
if (errno != ENOENT)
index_file_set_syscall_error(index, path, "open()");
return mail_index_create_memory(index, flags);
}
index->filepath = i_strdup(path);
for (;;) {
/* if index is being created, we'll wait here until it's
finished */
if ((flags & _MAIL_INDEX_OPEN_FLAG_CREATING) == 0)
index->lock_type = MAIL_LOCK_SHARED;
else
index->lock_type = MAIL_LOCK_EXCLUSIVE;
if (!mail_index_wait_lock(index,
MAIL_LOCK_TO_FLOCK(index->lock_type)))
break;
if ((ret = mail_index_read_header(index, &hdr)) < 0)
break;
if (ret == 0 || !mail_index_is_compatible(&hdr)) {
if ((flags & MAIL_INDEX_OPEN_FLAG_CREATE) == 0)
break;
flags |= _MAIL_INDEX_OPEN_FLAG_CREATING;
/* so, we're creating the index */
if (index->lock_type != MAIL_LOCK_EXCLUSIVE) {
/* have to get exclusive lock first */
if (!mail_index_wait_lock(index, F_UNLCK))
break;
continue;
}
mail_index_init_header(index, &hdr);
if (!mail_index_init_file(index, &hdr))
break;
}
index->indexid = hdr.indexid;
if (!mail_index_mmap_update(index))
break;
if (index->lock_type == MAIL_LOCK_SHARED) {
/* we don't want to keep the shared lock while opening
indexes. opening should work unlocked and some
things want exclusive lock */
if (!mail_index_wait_lock(index, F_UNLCK))
break;
index->lock_type = MAIL_LOCK_UNLOCK;
}
if (!index_open_and_fix(index, flags) ||
!index->set_lock(index, MAIL_LOCK_UNLOCK)) {
mail_index_close(index);
return mail_index_create_memory(index, flags);
}
index->opened = TRUE;
return TRUE;
}
(void)close(index->fd);
index->fd = -1;
i_free(index->filepath);
index->filepath = NULL;
return mail_index_create_memory(index, flags);
}