mail-index.c revision 6403608174a11d00ad94bccb1dfb84e2ce720357
/* Copyright (C) 2002 Timo Sirainen */
#include "lib.h"
#include "ioloop.h"
#include "file-lock.h"
#include "file-set-size.h"
#include "mmap-util.h"
#include "mail-index.h"
#include "mail-index-data.h"
#include "mail-index-util.h"
#include "mail-tree.h"
#include "mail-modifylog.h"
#include "mail-custom-flags.h"
#include <unistd.h>
#include <fcntl.h>
#include <utime.h>
{
unsigned int extra;
index->mmap_used_length = 0;
return FALSE;
}
sizeof(MailIndexRecord);
if (extra != 0) {
/* partial write or corrupted -
truncate the file to valid length */
}
/* keep the header set even if we fail, so we can update the flags */
return FALSE;
}
sizeof(MailIndexRecord) != 0) {
return FALSE;
}
return FALSE;
}
return FALSE;
}
return TRUE;
}
{
return mmap_verify(index);
/* make sure file size hasn't changed */
i_panic("Index file size was grown without "
"updating sync_id");
}
return TRUE;
}
}
index->mmap_used_length = 0;
return FALSE;
}
return mmap_verify(index);
}
{
index->set_cache_fields = 0;
}
}
}
}
}
}
}
}
}
{
int failed;
return TRUE;
return FALSE;
}
}
/* keep index's modify stamp same as the sync file's stamp */
return !failed;
}
{
}
return TRUE;
}
{
}
if (index->set_cache_fields != 0) {
index->set_cache_fields = 0;
}
}
#define MAIL_LOCK_TO_FLOCK(lock_type) \
{
int ret;
return TRUE;
return TRUE;
if (ret < 0)
return ret > 0;
}
{
int failed;
/* use our own locking here so we don't mess up with any other
index states, like inconsistency. */
if (failed)
return !failed;
}
{
if (old_lock_type == MAIL_LOCK_SHARED) {
/* releasing shared lock. we may need to update some
flags in header. */
return mail_index_write_header_changes(index);
}
return TRUE;
}
{
/* shared -> exclusive isn't allowed */
if (index->inconsistent) {
/* index is in inconsistent state and nothing else than
free() is allowed for it. */
return FALSE;
}
if (!mail_index_mmap_update(index)) {
return FALSE;
}
/* index was rebuilt, there's no way we can maintain
consistency */
"%s was rebuilt while we had it open",
return FALSE;
}
if (lock_type == MAIL_LOCK_EXCLUSIVE) {
/* while holding exclusive lock, keep the FSCK flag on.
when the lock is released, the FSCK flag will also be
removed. */
return FALSE;
}
}
return TRUE;
}
{
int keep_fsck;
return TRUE;
/* anonymous mmaps are private and don't need any locking */
return TRUE;
}
/* dropping exclusive lock (either unlock or to shared) */
/* remove the FSCK flag only after successful fsync() */
MS_SYNC) < 0) {
/* we only failed to remove the fsck flag,
so this isn't fatal. */
}
}
}
if (lock_type == MAIL_LOCK_UNLOCK)
return mail_index_lock_remove(index);
else
}
{
unsigned int max_records;
if (hdr->first_hole_records == 0)
return TRUE;
"first_hole_index points outside file");
return FALSE;
}
/* check that first_hole_records is in valid range */
"first_hole_records points outside file");
return FALSE;
}
return TRUE;
}
{
}
{
const char *format;
unsigned int idx;
/* out of range */
return NULL;
}
return NULL;
/* easy, it's just at the expected index */
} else if (hdr->first_hole_records ==
/* only one hole in file, skip it and we're at
correct position */
} else {
/* find from binary tree */
if (idx == (unsigned int)-1) {
"binary tree (%u msgs says header)",
return NULL;
}
}
return NULL;
}
sizeof(MailIndexHeader)) + idx;
return NULL;
}
return rec;
}
{
return NULL;
/* go to the next non-deleted record */
return rec;
}
return NULL;
}
unsigned int first_uid,
unsigned int last_uid,
unsigned int *seq_r)
{
unsigned int idx;
if (idx == (unsigned int)-1)
return NULL;
"lookup returned index outside range "
return NULL;
}
sizeof(MailIndexHeader)) + idx;
"lookup returned offset to wrong UID "
return NULL;
}
return rec;
}
static MailIndexDataRecord *
{
/* first check if the field even could be in the file */
/* no, but make sure the future records will have it.
we don't immediately mark the index to cache this
field for old messages as some clients never ask
the info again */
} else {
/* this is at least the second time it's being asked,
make sure it'll be cached soon. */
}
return NULL;
}
}
{
return NULL;
/* index is corrupted, it will be rebuilt */
return NULL;
}
}
{
*size = 0;
return NULL;
}
}
{
/* unseen -> seen */
/* seen -> unseen */
/* this is the first unseen message */
"header is invalid");
} else {
}
}
if ((old_flags & MAIL_DELETED) == 0 &&
(new_flags & MAIL_DELETED)) {
/* undeleted -> deleted */
/* this is the first deleted message */
} else if ((old_flags & MAIL_DELETED) &&
(new_flags & MAIL_DELETED) == 0) {
/* deleted -> undeleted */
"header is invalid");
} else {
}
}
}
{
/* see if first_hole_records can be grown */
sizeof(MailIndexHeader)) +
rec++;
}
}
{
sizeof(MailIndexRecord);
if (!mail_index_truncate(index))
return FALSE;
/* all mail was deleted, truncate data file */
return FALSE;
}
return TRUE;
}
((records) > INDEX_MIN_RECORDS_COUNT && \
(hdr)->messages_count)
unsigned int seq, int external_change)
{
return FALSE;
/* setting UID to 0 is enough for deleting the mail from index */
/* update first hole */
if (hdr->first_hole_records == 0) {
/* first deleted message in index */
/* deleted the previous record before hole */
hdr->first_hole_index--;
/* deleted the next record after hole */
} else {
/* second hole coming to index file */
/* new hole before the old hole */
}
}
/* update message counts */
if (hdr->messages_count == 0) {
/* corrupted */
"while expunging");
return FALSE;
}
hdr->messages_count--;
/* the hole reaches end of file, truncate it */
(void)mail_index_truncate_hole(index);
} else {
}
/* expunge() may be called while index is being rebuilt and when
tree file hasn't been opened yet */
else {
/* make sure it also gets updated */
}
return FALSE;
}
return TRUE;
}
int external_change)
{
return TRUE; /* no changes */
}
{
unsigned int grow_count;
void *base;
INDEX_GROW_PERCENTAGE / 100;
if (grow_count < 16)
grow_count = 16;
if (base == MAP_FAILED)
return TRUE;
}
}
/* file size changed, let others know about it too by changing
sync_id in header. */
if (!mail_index_mmap_update(index))
return FALSE;
return TRUE;
}
{
if (!mail_index_grow(index))
return FALSE;
}
return TRUE;
}
{
}
return TRUE;
}
{
}
{
}
{
return index->inconsistent;
}