mail-index.c revision 73637408663279c5a3df51efcd573b9760ede15f
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen/* Copyright (C) 2002 Timo Sirainen */
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainenstatic const char *index_file_prefixes[] =
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen unsigned int extra;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen index->header = (MailIndexHeader *) index->mmap_base;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen (void)munmap(index->mmap_base, index->mmap_length);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen index->mmap_base = mmap_rw_file(index->fd, &index->mmap_length);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen index_set_error(index, "index: mmap() failed with file %s: %m",
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen if (index->mmap_length < sizeof(MailIndexHeader)) {
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen index_set_error(index, "truncated index file %s",
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen extra = (index->mmap_length - sizeof(MailIndexHeader)) %
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen /* partial write or corrupted -
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen truncate the file to valid length */
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen (void)ftruncate(index->fd, (off_t)index->mmap_length);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen index->header = (MailIndexHeader *) index->mmap_base;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen (void)munmap(index->mmap_base, index->mmap_length);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen if (msync(index->mmap_base, index->mmap_length, MS_SYNC) == -1) {
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen index_set_error(index, "msync() failed for %s: %m",
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen if (index->hash != NULL && !mail_hash_sync_file(index->hash))
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen /* keep index's modify stamp same as the sync file's stamp */
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen index_set_error(index, "utime() failed for %s: %m",
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen index_set_error(index, "fsync() failed for %s: %m",
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainenint mail_index_fmsync(MailIndex *index, size_t size)
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen i_assert(index->lock_type == MAIL_LOCK_EXCLUSIVE);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen if (msync(index->mmap_base, size, MS_SYNC) == -1) {
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen index_set_error(index, "msync() failed for %s: %m",
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen index_set_error(index, "fsync() failed for %s: %m",
5fb3bff645380804c9db2510940c41db6b8fdb01Timo Sirainenstatic void mail_index_update_header_changes(MailIndex *index)
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen i_assert(index->lock_type == MAIL_LOCK_EXCLUSIVE);
5fb3bff645380804c9db2510940c41db6b8fdb01Timo Sirainen index->header->cache_fields = index->set_cache_fields;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen ((lock_type) == MAIL_LOCK_UNLOCK ? F_UNLCK : \
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen (lock_type) == MAIL_LOCK_SHARED ? F_RDLCK : F_WRLCK)
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainenint mail_index_try_lock(MailIndex *index, MailLockType lock_type)
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen /* lock whole file */
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainenint mail_index_set_lock(MailIndex *index, MailLockType lock_type)
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen /* yeah, this function is a bit messy. besides locking, it keeps
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen the index synced and in a good shape. */
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen /* index is in inconsistent state and nothing else than
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen free() is allowed for it. */
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen /* shared -> exclusive isn't allowed */
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen if (index->lock_type == MAIL_LOCK_EXCLUSIVE) {
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen /* releasing exclusive lock */
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen index->header->flags &= ~MAIL_INDEX_FLAG_FSCK;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen /* sync mmaped memory */
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen index->lock_type == MAIL_LOCK_UNLOCK && !index->updating) {
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen /* unlock -> lock */
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen /* lock whole file */
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen while (fcntl(index->fd, F_SETLKW, &fl) == -1) {
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen /* reset last_lookup so rebuilds don't try to use it */
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen /* we're always mmap()ed when we're locked */
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen (void)mail_index_set_lock(index, MAIL_LOCK_UNLOCK);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen if (index->indexid != index->header->indexid) {
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen /* index was rebuilt, there's no way we can maintain
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen consistency */
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen index_set_error(index, "Warning: Inconsistency - Index "
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen "%s was rebuilt while we had it open",
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen } else if (old_lock_type == MAIL_LOCK_SHARED) {
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen /* releasing shared lock */
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen if ((old_flags | index->set_flags) != old_flags ||
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen (old_cache | index->set_cache_fields) != old_cache) {
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen /* need to update the header */
return FALSE;
return FALSE;
return ret;
return TRUE;
return FALSE;
return FALSE;
return TRUE;
int check_version)
return FALSE;
return FALSE;
return FALSE;
return compatible;
const char *name;
hostpid_init();
return name;
return name;
return NULL;
return FALSE;
return FALSE;
return FALSE;
return TRUE;
int update_recent)
const char *path;
return FALSE;
return FALSE;
} while (FALSE);
if (failed)
return !failed;
int update_recent)
const char *path;
return FALSE;
path);
return FALSE;
return FALSE;
hostpid_init();
return FALSE;
return FALSE;
return FALSE;
return FALSE;
return FALSE;
return TRUE;
const char *name;
return FALSE;
return FALSE;
return TRUE;
const char *name;
return TRUE;
return FALSE;
return FALSE;
if (failed)
return FALSE;
return TRUE;
return TRUE;
return FALSE;
return FALSE;
return FALSE;
return TRUE;
unsigned int lookup_seq)
unsigned int seq;
return NULL;
return NULL;
return NULL;
sizeof(MailIndexHeader));
sizeof(MailIndexRecord));
return NULL;
return rec;
seq++;
rec++;
return rec;
return NULL;
return NULL;
return rec;
return NULL;
unsigned int first_uid,
unsigned int last_uid)
return NULL;
return NULL;
sizeof(MailIndexHeader));
sizeof(MailIndexRecord));
return NULL;
if (pos != 0) {
return rec;
return NULL;
sizeof(MailIndexHeader));
return NULL;
return rec;
rec++;
return NULL;
static MailIndexDataRecord *
return NULL;
return NULL;
return datarec;
return NULL;
return NULL;
*size = 0;
return NULL;
unsigned int seq;
return INDEX_POSITION_INDEX(
return INDEX_POSITION_INDEX(
seq++;
return seq;
rec++;
return FALSE;
return FALSE;
return FALSE;
return TRUE;
return FALSE;
if (seq != 0) {
return FALSE;
return FALSE;
return TRUE;
int external_change)
if (pos < 0) {
return FALSE;
return FALSE;
return FALSE;
return TRUE;