mail-index-open.c revision 406a92a344f789e6ec763104b03de3f0b8fcfdb7
5f5870385cff47efd2f58e7892f251cf13761528Timo Sirainen/* Copyright (C) 2002-2003 Timo Sirainen */
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen#include "lib.h"
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen#include "ioloop.h"
6967fa47dde9f2726bd86019a50627dacf2d7509Timo Sirainen#include "file-lock.h"
34830cefe1757de0ffca67acdc529d5bc8b06b66Timo Sirainen#include "file-set-size.h"
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen#include "hostpid.h"
6967fa47dde9f2726bd86019a50627dacf2d7509Timo Sirainen#include "mmap-util.h"
0536ccb51d41e3078c3a9fa33e509fb4b2420f95Timo Sirainen#include "unlink-lockfiles.h"
4499995f7029bafd85094694b6a14752ea34c9b3Timo Sirainen#include "write-full.h"
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen#include "mail-index.h"
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen#include "mail-index-data.h"
34830cefe1757de0ffca67acdc529d5bc8b06b66Timo Sirainen#include "mail-index-util.h"
34830cefe1757de0ffca67acdc529d5bc8b06b66Timo Sirainen#include "mail-tree.h"
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen#include "mail-modifylog.h"
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen#include "mail-custom-flags.h"
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainen#include <stdio.h>
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen#include <stdlib.h>
fcca16701767c6b92227a9ee125de69d257882f6Timo Sirainen#include <unistd.h>
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen#include <fcntl.h>
d10cb4d7a80571af21f776c65604442bf09b1765Timo Sirainen
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainenstatic int mail_index_open_init(struct mail_index *index,
fcca16701767c6b92227a9ee125de69d257882f6Timo Sirainen enum mail_index_open_flags flags)
fcca16701767c6b92227a9ee125de69d257882f6Timo Sirainen{
fcca16701767c6b92227a9ee125de69d257882f6Timo Sirainen struct mail_index_header *hdr;
5702c81e2d788449c3bc207eb9c19e539458ad9eTimo Sirainen
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen hdr = index->header;
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen index->maildir_have_new =
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen (hdr->flags & MAIL_INDEX_FLAG_MAILDIR_NEW) != 0;
6967fa47dde9f2726bd86019a50627dacf2d7509Timo Sirainen
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen if ((hdr->flags & MAIL_INDEX_FLAG_DIRTY_MESSAGES) != 0)
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen index->next_dirty_flush = ioloop_time;
a94936bafd127680184da114c6a177b37ff656e5Timo Sirainen
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen /* update \Recent message counters */
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen if ((flags & MAIL_INDEX_OPEN_FLAG_UPDATE_RECENT) != 0 &&
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen hdr->last_nonrecent_uid != hdr->next_uid-1) {
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen /* keep last_recent_uid to next_uid-1 */
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen if (index->lock_type == MAIL_LOCK_SHARED) {
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen if (!index->set_lock(index, MAIL_LOCK_UNLOCK))
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen return FALSE;
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen }
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen if (!index->set_lock(index, MAIL_LOCK_EXCLUSIVE))
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen return FALSE;
a6f281d078ed03d555802c1a8e15fefce80132dcTimo Sirainen
a6f281d078ed03d555802c1a8e15fefce80132dcTimo Sirainen index->first_recent_uid = index->header->last_nonrecent_uid+1;
a6f281d078ed03d555802c1a8e15fefce80132dcTimo Sirainen index->header->last_nonrecent_uid = index->header->next_uid-1;
a6f281d078ed03d555802c1a8e15fefce80132dcTimo Sirainen } else {
a6f281d078ed03d555802c1a8e15fefce80132dcTimo Sirainen index->first_recent_uid = hdr->last_nonrecent_uid+1;
a6f281d078ed03d555802c1a8e15fefce80132dcTimo Sirainen }
a6f281d078ed03d555802c1a8e15fefce80132dcTimo Sirainen
a6f281d078ed03d555802c1a8e15fefce80132dcTimo Sirainen if (hdr->next_uid >= MAX_ALLOWED_UID - 1000) {
a94936bafd127680184da114c6a177b37ff656e5Timo Sirainen /* UID values are getting too high, rebuild index */
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen index->set_flags |= MAIL_INDEX_FLAG_REBUILD;
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen }
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen
5702c81e2d788449c3bc207eb9c19e539458ad9eTimo Sirainen if (index->lock_type == MAIL_LOCK_EXCLUSIVE) {
5702c81e2d788449c3bc207eb9c19e539458ad9eTimo Sirainen /* finally reset the modify log marks, fsck or syncing might
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen have deleted some messages, and since we're only just
d5cebe7f98e63d4e2822863ef2faa4971e8b3a5dTimo Sirainen opening the index, there's no need to remember them */
a6f281d078ed03d555802c1a8e15fefce80132dcTimo Sirainen if (!mail_modifylog_mark_synced(index->modifylog))
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen return FALSE;
6967fa47dde9f2726bd86019a50627dacf2d7509Timo Sirainen }
6967fa47dde9f2726bd86019a50627dacf2d7509Timo Sirainen
fcca16701767c6b92227a9ee125de69d257882f6Timo Sirainen return TRUE;
c1d4780bc0c9017e8e5d366b81e4fad31174c0adTimo Sirainen}
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainenstatic int index_open_and_fix(struct mail_index *index,
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainen enum mail_index_open_flags flags)
a94936bafd127680184da114c6a177b37ff656e5Timo Sirainen{
a94936bafd127680184da114c6a177b37ff656e5Timo Sirainen int rebuilt;
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen /* open/create the index files */
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen if ((flags & _MAIL_INDEX_OPEN_FLAG_CREATING) == 0) {
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen if (!mail_index_data_open(index)) {
597dba3488c648ffb375ee4a552bd52ac4346979Timo Sirainen if ((index->set_flags & MAIL_INDEX_FLAG_REBUILD) == 0)
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen return FALSE;
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen /* data file is corrupted, need to rebuild index */
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen flags |= _MAIL_INDEX_OPEN_FLAG_CREATING;
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen index->set_flags = 0;
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen index->inconsistent = FALSE;
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen }
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen }
7bcb308d0e13dfa48b483b0addccd889a77bb598Timo Sirainen
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen if ((flags & _MAIL_INDEX_OPEN_FLAG_CREATING) != 0) {
7bcb308d0e13dfa48b483b0addccd889a77bb598Timo Sirainen if (!mail_index_set_lock(index, MAIL_LOCK_EXCLUSIVE))
7bcb308d0e13dfa48b483b0addccd889a77bb598Timo Sirainen return FALSE;
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen if (!mail_index_data_create(index))
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen return FALSE;
fcca16701767c6b92227a9ee125de69d257882f6Timo Sirainen }
fcca16701767c6b92227a9ee125de69d257882f6Timo Sirainen
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen /* custom flags file needs to be open before
fcca16701767c6b92227a9ee125de69d257882f6Timo Sirainen rebuilding index */
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen if (!mail_custom_flags_open_or_create(index))
5702c81e2d788449c3bc207eb9c19e539458ad9eTimo Sirainen return FALSE;
34830cefe1757de0ffca67acdc529d5bc8b06b66Timo Sirainen
34830cefe1757de0ffca67acdc529d5bc8b06b66Timo Sirainen if ((flags & _MAIL_INDEX_OPEN_FLAG_CREATING) != 0 ||
4307c886579381dbb1897ea1388ae6978c96f560Timo Sirainen (index->header->flags & MAIL_INDEX_FLAG_REBUILD) != 0) {
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen if (!index->rebuild(index))
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen return FALSE;
34830cefe1757de0ffca67acdc529d5bc8b06b66Timo Sirainen
5702c81e2d788449c3bc207eb9c19e539458ad9eTimo Sirainen /* no inconsistency problems since we're still opening
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen the index */
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen index->inconsistent = FALSE;
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen rebuilt = TRUE;
597dba3488c648ffb375ee4a552bd52ac4346979Timo Sirainen } else {
7bcb308d0e13dfa48b483b0addccd889a77bb598Timo Sirainen rebuilt = FALSE;
7bcb308d0e13dfa48b483b0addccd889a77bb598Timo Sirainen }
7bcb308d0e13dfa48b483b0addccd889a77bb598Timo Sirainen
7bcb308d0e13dfa48b483b0addccd889a77bb598Timo Sirainen if ((flags & _MAIL_INDEX_OPEN_FLAG_CREATING) == 0) {
7bcb308d0e13dfa48b483b0addccd889a77bb598Timo Sirainen if (!mail_tree_open_or_create(index))
7bcb308d0e13dfa48b483b0addccd889a77bb598Timo Sirainen return FALSE;
7bcb308d0e13dfa48b483b0addccd889a77bb598Timo Sirainen if (!mail_modifylog_open_or_create(index))
7bcb308d0e13dfa48b483b0addccd889a77bb598Timo Sirainen return FALSE;
7bcb308d0e13dfa48b483b0addccd889a77bb598Timo Sirainen } else {
7bcb308d0e13dfa48b483b0addccd889a77bb598Timo Sirainen if (!mail_tree_create(index))
8cb72c59d5ea4e9e5f638d7ec840bb853f5a188eTimo Sirainen return FALSE;
8cb72c59d5ea4e9e5f638d7ec840bb853f5a188eTimo Sirainen if (!mail_modifylog_create(index))
7bcb308d0e13dfa48b483b0addccd889a77bb598Timo Sirainen return FALSE;
7bcb308d0e13dfa48b483b0addccd889a77bb598Timo Sirainen }
7bcb308d0e13dfa48b483b0addccd889a77bb598Timo Sirainen
7bcb308d0e13dfa48b483b0addccd889a77bb598Timo Sirainen if (index->header->flags & MAIL_INDEX_FLAG_FSCK) {
7bcb308d0e13dfa48b483b0addccd889a77bb598Timo Sirainen /* index needs fscking */
7bcb308d0e13dfa48b483b0addccd889a77bb598Timo Sirainen if (!index->fsck(index))
5702c81e2d788449c3bc207eb9c19e539458ad9eTimo Sirainen return FALSE;
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen }
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen if ((index->header->flags & MAIL_INDEX_FLAG_REBUILD_TREE) != 0) {
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen if (!mail_tree_rebuild(index->tree))
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen return FALSE;
5069adb2f5b3609fff9a0a705c6edeae56e0030aTimo Sirainen }
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen if (!rebuilt) {
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen /* sync ourself. do it before updating cache and compression
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen which may happen because of this. */
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen if (!index->sync_and_lock(index, MAIL_LOCK_SHARED, NULL) &&
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen !index->nodiskspace)
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen return FALSE;
8d56f3334e22619abf56833d290bb1f49ac6722cTimo Sirainen
8d56f3334e22619abf56833d290bb1f49ac6722cTimo Sirainen index->inconsistent = FALSE;
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen }
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen
156736910057b280cb9999d4c6c7221c4c80f5c2Timo Sirainen /* we never want to keep shared lock if syncing happens to set it.
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen either exclusive or nothing (NOTE: drop it directly, not through
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen index->set_lock() so mbox lock won't be affected). */
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen if (index->lock_type == MAIL_LOCK_SHARED) {
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen if (!mail_index_set_lock(index, MAIL_LOCK_UNLOCK))
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen return FALSE;
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen }
d10cb4d7a80571af21f776c65604442bf09b1765Timo Sirainen
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen if ((flags & MAIL_INDEX_OPEN_FLAG_FAST) == 0) {
81b1d14891415fef0c2f37ef1ef3680cdcc600f1Timo Sirainen if (index->header->flags & MAIL_INDEX_FLAG_COMPRESS) {
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen /* remove deleted blocks from index file */
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen if (!mail_index_compress(index))
5069adb2f5b3609fff9a0a705c6edeae56e0030aTimo Sirainen return FALSE;
5069adb2f5b3609fff9a0a705c6edeae56e0030aTimo Sirainen }
3785910c303507db5f629684e6dde2cc7f83668eTimo Sirainen
5069adb2f5b3609fff9a0a705c6edeae56e0030aTimo Sirainen if (index->header->flags & MAIL_INDEX_FLAG_CACHE_FIELDS) {
5069adb2f5b3609fff9a0a705c6edeae56e0030aTimo Sirainen /* need to update cached fields */
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen if (!mail_index_update_cache(index))
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen return FALSE;
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen }
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen
c09f9f95db314e7482c95e502e1c56ed6c555797Timo Sirainen if (index->header->flags & MAIL_INDEX_FLAG_COMPRESS_DATA) {
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen /* remove unused space from index data file.
252db51b6c0a605163326b3ea5d09e9936ca3b29Timo Sirainen keep after cache updates which may move data
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen and create unused space */
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen if (!mail_index_compress_data(index))
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen return FALSE;
f2b95f63ebdf77dba4dac938cf8c65c839f1067dTimo Sirainen }
f2b95f63ebdf77dba4dac938cf8c65c839f1067dTimo Sirainen }
5702c81e2d788449c3bc207eb9c19e539458ad9eTimo Sirainen
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen if (!mail_index_open_init(index, flags))
5702c81e2d788449c3bc207eb9c19e539458ad9eTimo Sirainen return FALSE;
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen return TRUE;
3785910c303507db5f629684e6dde2cc7f83668eTimo Sirainen}
3785910c303507db5f629684e6dde2cc7f83668eTimo Sirainen
34830cefe1757de0ffca67acdc529d5bc8b06b66Timo Sirainenstatic int mail_index_read_header(struct mail_index *index,
34830cefe1757de0ffca67acdc529d5bc8b06b66Timo Sirainen struct mail_index_header *hdr)
34830cefe1757de0ffca67acdc529d5bc8b06b66Timo Sirainen{
8d56f3334e22619abf56833d290bb1f49ac6722cTimo Sirainen ssize_t ret;
34830cefe1757de0ffca67acdc529d5bc8b06b66Timo Sirainen
34830cefe1757de0ffca67acdc529d5bc8b06b66Timo Sirainen ret = read(index->fd, hdr, sizeof(*hdr));
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen if (ret < 0) {
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen index_set_syscall_error(index, "read()");
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen return -1;
5297aa3ceddf3a4ecc09f49c832bc424eff8f906Timo Sirainen }
5702c81e2d788449c3bc207eb9c19e539458ad9eTimo Sirainen
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen if (ret != sizeof(*hdr)) {
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen /* missing data */
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen return 0;
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen }
5702c81e2d788449c3bc207eb9c19e539458ad9eTimo Sirainen
5702c81e2d788449c3bc207eb9c19e539458ad9eTimo Sirainen return 1;
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen}
c09f9f95db314e7482c95e502e1c56ed6c555797Timo Sirainen
c09f9f95db314e7482c95e502e1c56ed6c555797Timo Sirainenstatic int mail_index_is_compatible(const struct mail_index_header *hdr)
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen{
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen return hdr->compat_data[0] == MAIL_INDEX_VERSION &&
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen hdr->compat_data[1] == MAIL_INDEX_COMPAT_FLAGS &&
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen hdr->compat_data[2] == sizeof(unsigned int) &&
34830cefe1757de0ffca67acdc529d5bc8b06b66Timo Sirainen hdr->compat_data[3] == sizeof(time_t) &&
34830cefe1757de0ffca67acdc529d5bc8b06b66Timo Sirainen hdr->compat_data[4] == sizeof(uoff_t) &&
34830cefe1757de0ffca67acdc529d5bc8b06b66Timo Sirainen hdr->compat_data[5] == INDEX_ALIGN_SIZE;
34830cefe1757de0ffca67acdc529d5bc8b06b66Timo Sirainen}
34830cefe1757de0ffca67acdc529d5bc8b06b66Timo Sirainen
5702c81e2d788449c3bc207eb9c19e539458ad9eTimo Sirainenstatic int mail_index_init_file(struct mail_index *index,
34830cefe1757de0ffca67acdc529d5bc8b06b66Timo Sirainen const struct mail_index_header *hdr)
5702c81e2d788449c3bc207eb9c19e539458ad9eTimo Sirainen{
34830cefe1757de0ffca67acdc529d5bc8b06b66Timo Sirainen uoff_t file_size;
5702c81e2d788449c3bc207eb9c19e539458ad9eTimo Sirainen
34830cefe1757de0ffca67acdc529d5bc8b06b66Timo Sirainen if (lseek(index->fd, 0, SEEK_SET) < 0) {
34830cefe1757de0ffca67acdc529d5bc8b06b66Timo Sirainen index_set_syscall_error(index, "lseek()");
34830cefe1757de0ffca67acdc529d5bc8b06b66Timo Sirainen return FALSE;
5702c81e2d788449c3bc207eb9c19e539458ad9eTimo Sirainen }
34830cefe1757de0ffca67acdc529d5bc8b06b66Timo Sirainen
34830cefe1757de0ffca67acdc529d5bc8b06b66Timo Sirainen if (write_full(index->fd, hdr, sizeof(*hdr)) < 0) {
34830cefe1757de0ffca67acdc529d5bc8b06b66Timo Sirainen index_set_syscall_error(index, "write_full()");
4307c886579381dbb1897ea1388ae6978c96f560Timo Sirainen return FALSE;
34830cefe1757de0ffca67acdc529d5bc8b06b66Timo Sirainen }
34830cefe1757de0ffca67acdc529d5bc8b06b66Timo Sirainen
34830cefe1757de0ffca67acdc529d5bc8b06b66Timo Sirainen file_size = sizeof(*hdr) +
34830cefe1757de0ffca67acdc529d5bc8b06b66Timo Sirainen INDEX_MIN_RECORDS_COUNT * sizeof(struct mail_index_record);
34830cefe1757de0ffca67acdc529d5bc8b06b66Timo Sirainen if (file_set_size(index->fd, (off_t)file_size) < 0) {
34830cefe1757de0ffca67acdc529d5bc8b06b66Timo Sirainen index_set_syscall_error(index, "file_set_size()");
a94936bafd127680184da114c6a177b37ff656e5Timo Sirainen return FALSE;
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen }
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen return TRUE;
7efee0bb408b0d5253e41997857bdda57855cdc7Timo Sirainen}
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainenvoid mail_index_init_header(struct mail_index *index,
f2b95f63ebdf77dba4dac938cf8c65c839f1067dTimo Sirainen struct mail_index_header *hdr)
f2b95f63ebdf77dba4dac938cf8c65c839f1067dTimo Sirainen{
f2b95f63ebdf77dba4dac938cf8c65c839f1067dTimo Sirainen memset(hdr, 0, sizeof(*hdr));
f2b95f63ebdf77dba4dac938cf8c65c839f1067dTimo Sirainen hdr->compat_data[0] = MAIL_INDEX_VERSION;
5702c81e2d788449c3bc207eb9c19e539458ad9eTimo Sirainen hdr->compat_data[1] = MAIL_INDEX_COMPAT_FLAGS;
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen hdr->compat_data[2] = sizeof(unsigned int);
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen hdr->compat_data[3] = sizeof(time_t);
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen hdr->compat_data[4] = sizeof(uoff_t);
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen hdr->compat_data[5] = INDEX_ALIGN_SIZE;
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen hdr->indexid = ioloop_time;
34830cefe1757de0ffca67acdc529d5bc8b06b66Timo Sirainen
34830cefe1757de0ffca67acdc529d5bc8b06b66Timo Sirainen /* mark the index requiring rebuild - rebuild() removes this flag
34830cefe1757de0ffca67acdc529d5bc8b06b66Timo Sirainen when it succeeds */
34830cefe1757de0ffca67acdc529d5bc8b06b66Timo Sirainen hdr->flags = MAIL_INDEX_FLAG_REBUILD;
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen
5702c81e2d788449c3bc207eb9c19e539458ad9eTimo Sirainen if (!index->anon_mmap) {
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen /* set the fields we always want to cache,
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen but not if we're building into memory */
34830cefe1757de0ffca67acdc529d5bc8b06b66Timo Sirainen hdr->cache_fields |= index->default_cache_fields;
34830cefe1757de0ffca67acdc529d5bc8b06b66Timo Sirainen }
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen hdr->used_file_size = sizeof(struct mail_index_header);
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen hdr->uid_validity = ioloop_time;
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen hdr->next_uid = 1;
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen}
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainenstatic void mail_index_cleanup_temp_files(const char *dir)
34830cefe1757de0ffca67acdc529d5bc8b06b66Timo Sirainen{
34830cefe1757de0ffca67acdc529d5bc8b06b66Timo Sirainen unlink_lockfiles(dir, t_strconcat("temp.", my_hostname, NULL),
34830cefe1757de0ffca67acdc529d5bc8b06b66Timo Sirainen "temp.", time(NULL) - TEMP_FILE_TIMEOUT);
34830cefe1757de0ffca67acdc529d5bc8b06b66Timo Sirainen}
34830cefe1757de0ffca67acdc529d5bc8b06b66Timo Sirainen
34830cefe1757de0ffca67acdc529d5bc8b06b66Timo Sirainenvoid mail_index_init(struct mail_index *index, const char *dir)
34830cefe1757de0ffca67acdc529d5bc8b06b66Timo Sirainen{
34830cefe1757de0ffca67acdc529d5bc8b06b66Timo Sirainen size_t len;
34830cefe1757de0ffca67acdc529d5bc8b06b66Timo Sirainen
34830cefe1757de0ffca67acdc529d5bc8b06b66Timo Sirainen index->fd = -1;
34830cefe1757de0ffca67acdc529d5bc8b06b66Timo Sirainen
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen if (dir != NULL) {
7efee0bb408b0d5253e41997857bdda57855cdc7Timo Sirainen index->dir = i_strdup(dir);
34830cefe1757de0ffca67acdc529d5bc8b06b66Timo Sirainen
34830cefe1757de0ffca67acdc529d5bc8b06b66Timo Sirainen len = strlen(index->dir);
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen if (index->dir[len-1] == '/')
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen index->dir[len-1] = '\0';
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen }
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen index->mail_read_mmaped = getenv("MAIL_READ_MMAPED") != NULL;
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen}
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainenstatic int mail_index_create_memory(struct mail_index *index,
1b9aae1cb53708b5a3d861b4db6ba96ac2eb35b4Timo Sirainen enum mail_index_open_flags flags)
1b9aae1cb53708b5a3d861b4db6ba96ac2eb35b4Timo Sirainen{
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen if ((flags & MAIL_INDEX_OPEN_FLAG_CREATE) == 0)
7efee0bb408b0d5253e41997857bdda57855cdc7Timo Sirainen return FALSE;
7efee0bb408b0d5253e41997857bdda57855cdc7Timo Sirainen
7efee0bb408b0d5253e41997857bdda57855cdc7Timo Sirainen flags |= _MAIL_INDEX_OPEN_FLAG_CREATING;
7efee0bb408b0d5253e41997857bdda57855cdc7Timo Sirainen
7efee0bb408b0d5253e41997857bdda57855cdc7Timo Sirainen index->mmap_full_length = INDEX_FILE_MIN_SIZE;
4da70fe8c9cb6e57b36103d78ab1e9c8654f76d9Timo Sirainen index->mmap_base = mmap_anon(index->mmap_full_length);
7efee0bb408b0d5253e41997857bdda57855cdc7Timo Sirainen if (index->mmap_base == MAP_FAILED) {
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen index->mmap_base = NULL;
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen return index_set_error(index, "mmap_anon() failed: %m");
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen }
01f4ee4a0243f3fe9af763e1a540cd5cff0d63f5Timo Sirainen
a94936bafd127680184da114c6a177b37ff656e5Timo Sirainen mail_index_init_header(index, index->mmap_base);
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen index->header = index->mmap_base;
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen index->mmap_used_length = index->header->used_file_size;
01f4ee4a0243f3fe9af763e1a540cd5cff0d63f5Timo Sirainen
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen index->anon_mmap = TRUE;
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen index->lock_type = MAIL_LOCK_EXCLUSIVE;
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen index->indexid = index->header->indexid;
d10cb4d7a80571af21f776c65604442bf09b1765Timo Sirainen index->filepath = i_strdup_printf("(in-memory index for %s)",
d10cb4d7a80571af21f776c65604442bf09b1765Timo Sirainen index->mailbox_path);
d10cb4d7a80571af21f776c65604442bf09b1765Timo Sirainen
01f4ee4a0243f3fe9af763e1a540cd5cff0d63f5Timo Sirainen if (!index_open_and_fix(index, flags)) {
d10cb4d7a80571af21f776c65604442bf09b1765Timo Sirainen mail_index_close(index);
d10cb4d7a80571af21f776c65604442bf09b1765Timo Sirainen return FALSE;
5702c81e2d788449c3bc207eb9c19e539458ad9eTimo Sirainen }
8255a22cccf3b0ccf38206c594941820ac1c9e00Timo Sirainen
8255a22cccf3b0ccf38206c594941820ac1c9e00Timo Sirainen index->opened = TRUE;
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen return TRUE;
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen}
1fb8ce8b21d0616796ced699b1573b5dd0b61793Timo Sirainen
1fb8ce8b21d0616796ced699b1573b5dd0b61793Timo Sirainenstatic int mail_index_open_index(struct mail_index *index,
a94936bafd127680184da114c6a177b37ff656e5Timo Sirainen enum mail_index_open_flags flags)
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen{
7efee0bb408b0d5253e41997857bdda57855cdc7Timo Sirainen struct mail_index_header hdr;
7efee0bb408b0d5253e41997857bdda57855cdc7Timo Sirainen int ret;
9ec30d84a736a2d0726b600213dcf630ff28bdebTimo Sirainen
9ec30d84a736a2d0726b600213dcf630ff28bdebTimo Sirainen if ((flags & _MAIL_INDEX_OPEN_FLAG_CREATING) == 0)
9ec30d84a736a2d0726b600213dcf630ff28bdebTimo Sirainen index->lock_type = MAIL_LOCK_SHARED;
7efee0bb408b0d5253e41997857bdda57855cdc7Timo Sirainen else
1fb8ce8b21d0616796ced699b1573b5dd0b61793Timo Sirainen index->lock_type = MAIL_LOCK_EXCLUSIVE;
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen
a6f281d078ed03d555802c1a8e15fefce80132dcTimo Sirainen /* if index is being created, we'll wait here until it's finished */
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen if (!mail_index_wait_lock(index, MAIL_LOCK_TO_FLOCK(index->lock_type)))
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen return FALSE;
8255a22cccf3b0ccf38206c594941820ac1c9e00Timo Sirainen#ifdef DEBUG
8255a22cccf3b0ccf38206c594941820ac1c9e00Timo Sirainen if (index->mmap_base != NULL) {
01f4ee4a0243f3fe9af763e1a540cd5cff0d63f5Timo Sirainen mprotect(index->mmap_base, index->mmap_used_length,
01f4ee4a0243f3fe9af763e1a540cd5cff0d63f5Timo Sirainen PROT_READ|PROT_WRITE);
01f4ee4a0243f3fe9af763e1a540cd5cff0d63f5Timo Sirainen }
8255a22cccf3b0ccf38206c594941820ac1c9e00Timo Sirainen#endif
8255a22cccf3b0ccf38206c594941820ac1c9e00Timo Sirainen
5702c81e2d788449c3bc207eb9c19e539458ad9eTimo Sirainen if ((ret = mail_index_read_header(index, &hdr)) < 0)
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen return FALSE;
5702c81e2d788449c3bc207eb9c19e539458ad9eTimo Sirainen
8255a22cccf3b0ccf38206c594941820ac1c9e00Timo Sirainen if (ret == 0 || !mail_index_is_compatible(&hdr) ||
01f4ee4a0243f3fe9af763e1a540cd5cff0d63f5Timo Sirainen (hdr.flags & MAIL_INDEX_FLAG_REBUILD) != 0) {
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen if ((flags & MAIL_INDEX_OPEN_FLAG_CREATE) == 0)
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen return FALSE;
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen
4d33a3133e8484ebd00f677f457cda82f1365b84Timo Sirainen flags |= _MAIL_INDEX_OPEN_FLAG_CREATING;
4d33a3133e8484ebd00f677f457cda82f1365b84Timo Sirainen
4d33a3133e8484ebd00f677f457cda82f1365b84Timo Sirainen /* so, we're creating the index */
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen if (index->lock_type != MAIL_LOCK_EXCLUSIVE) {
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen /* have to get exclusive lock first */
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen if (!mail_index_wait_lock(index, F_UNLCK))
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen return FALSE;
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen return mail_index_open_index(index, flags);
ab7b5b9286104974c2a572a499ccf8b56c5d2955Timo Sirainen }
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen
ab7b5b9286104974c2a572a499ccf8b56c5d2955Timo Sirainen mail_index_init_header(index, &hdr);
ab7b5b9286104974c2a572a499ccf8b56c5d2955Timo Sirainen if (!mail_index_init_file(index, &hdr))
ab7b5b9286104974c2a572a499ccf8b56c5d2955Timo Sirainen return FALSE;
ab7b5b9286104974c2a572a499ccf8b56c5d2955Timo Sirainen }
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen
ab7b5b9286104974c2a572a499ccf8b56c5d2955Timo Sirainen index->indexid = hdr.indexid;
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen if (!mail_index_mmap_update(index))
fe363b433b8038a69b55169da9dca27892ad7d18Timo Sirainen return FALSE;
fcca16701767c6b92227a9ee125de69d257882f6Timo Sirainen
fcca16701767c6b92227a9ee125de69d257882f6Timo Sirainen if (index->lock_type == MAIL_LOCK_SHARED) {
5702c81e2d788449c3bc207eb9c19e539458ad9eTimo Sirainen /* we don't want to keep the shared lock while opening
597dba3488c648ffb375ee4a552bd52ac4346979Timo Sirainen indexes. opening should work unlocked and some
7bcb308d0e13dfa48b483b0addccd889a77bb598Timo Sirainen things want exclusive lock */
d10cb4d7a80571af21f776c65604442bf09b1765Timo Sirainen if (!mail_index_wait_lock(index, F_UNLCK))
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen return FALSE;
fe363b433b8038a69b55169da9dca27892ad7d18Timo Sirainen index->lock_type = MAIL_LOCK_UNLOCK;
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen }
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen if (!index_open_and_fix(index, flags)) {
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen if ((index->set_flags & MAIL_INDEX_FLAG_REBUILD) == 0 ||
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen (flags & _MAIL_INDEX_OPEN_FLAG_CREATING) != 0)
5702c81e2d788449c3bc207eb9c19e539458ad9eTimo Sirainen return FALSE;
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen /* needs a rebuild */
a94936bafd127680184da114c6a177b37ff656e5Timo Sirainen if (!index->set_lock(index, MAIL_LOCK_UNLOCK))
a94936bafd127680184da114c6a177b37ff656e5Timo Sirainen return FALSE;
a94936bafd127680184da114c6a177b37ff656e5Timo Sirainen
a94936bafd127680184da114c6a177b37ff656e5Timo Sirainen flags |= _MAIL_INDEX_OPEN_FLAG_CREATING;
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen return mail_index_open_index(index, flags);
a94936bafd127680184da114c6a177b37ff656e5Timo Sirainen }
a94936bafd127680184da114c6a177b37ff656e5Timo Sirainen
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen if (!index->set_lock(index, MAIL_LOCK_UNLOCK))
da2aa032ccfa8e7e4a4380ef738014549f4d2c2dTimo Sirainen return FALSE;
ab7b5b9286104974c2a572a499ccf8b56c5d2955Timo Sirainen
ab7b5b9286104974c2a572a499ccf8b56c5d2955Timo Sirainen index->opened = TRUE;
9511a40d933181045343110c8101b75887062aaeTimo Sirainen return TRUE;
2201e2cc1b3f744dac61c2bf8095bcb6b5719540Timo Sirainen}
4d33a3133e8484ebd00f677f457cda82f1365b84Timo Sirainen
c395e7d730eb4ee17e2b619acec487637a785110Timo Sirainenint mail_index_open(struct mail_index *index, enum mail_index_open_flags flags)
c395e7d730eb4ee17e2b619acec487637a785110Timo Sirainen{
c395e7d730eb4ee17e2b619acec487637a785110Timo Sirainen const char *path;
c395e7d730eb4ee17e2b619acec487637a785110Timo Sirainen
c395e7d730eb4ee17e2b619acec487637a785110Timo Sirainen i_assert(!index->opened);
c395e7d730eb4ee17e2b619acec487637a785110Timo Sirainen
c395e7d730eb4ee17e2b619acec487637a785110Timo Sirainen if (index->dir == NULL)
c395e7d730eb4ee17e2b619acec487637a785110Timo Sirainen return mail_index_create_memory(index, flags);
c395e7d730eb4ee17e2b619acec487637a785110Timo Sirainen
c395e7d730eb4ee17e2b619acec487637a785110Timo Sirainen mail_index_cleanup_temp_files(index->dir);
c395e7d730eb4ee17e2b619acec487637a785110Timo Sirainen
4d33a3133e8484ebd00f677f457cda82f1365b84Timo Sirainen /* open/create the file */
4d33a3133e8484ebd00f677f457cda82f1365b84Timo Sirainen path = t_strconcat(index->dir, "/", INDEX_FILE_PREFIX, NULL);
4d33a3133e8484ebd00f677f457cda82f1365b84Timo Sirainen if ((flags & MAIL_INDEX_OPEN_FLAG_CREATE) != 0)
4d33a3133e8484ebd00f677f457cda82f1365b84Timo Sirainen index->fd = open(path, O_RDWR | O_CREAT, 0660);
4d33a3133e8484ebd00f677f457cda82f1365b84Timo Sirainen else
4d33a3133e8484ebd00f677f457cda82f1365b84Timo Sirainen index->fd = open(path, O_RDWR);
4d33a3133e8484ebd00f677f457cda82f1365b84Timo Sirainen if (index->fd == -1) {
c395e7d730eb4ee17e2b619acec487637a785110Timo Sirainen if (errno != ENOENT)
4d33a3133e8484ebd00f677f457cda82f1365b84Timo Sirainen index_file_set_syscall_error(index, path, "open()");
4d33a3133e8484ebd00f677f457cda82f1365b84Timo Sirainen return mail_index_create_memory(index, flags);
4d33a3133e8484ebd00f677f457cda82f1365b84Timo Sirainen }
4d33a3133e8484ebd00f677f457cda82f1365b84Timo Sirainen
6967fa47dde9f2726bd86019a50627dacf2d7509Timo Sirainen index->filepath = i_strdup(path);
6967fa47dde9f2726bd86019a50627dacf2d7509Timo Sirainen
6967fa47dde9f2726bd86019a50627dacf2d7509Timo Sirainen if (!mail_index_open_index(index, flags)) {
6967fa47dde9f2726bd86019a50627dacf2d7509Timo Sirainen mail_index_close(index);
6967fa47dde9f2726bd86019a50627dacf2d7509Timo Sirainen return mail_index_create_memory(index, flags);
6967fa47dde9f2726bd86019a50627dacf2d7509Timo Sirainen }
6967fa47dde9f2726bd86019a50627dacf2d7509Timo Sirainen
6967fa47dde9f2726bd86019a50627dacf2d7509Timo Sirainen return TRUE;
6967fa47dde9f2726bd86019a50627dacf2d7509Timo Sirainen}
6967fa47dde9f2726bd86019a50627dacf2d7509Timo Sirainen