view src/lib-index/mail-index-fsck.c @ 276:406527c791c7 HEAD

fsck() now prints what differences it found
author Timo Sirainen <tss@iki.fi>
date Fri, 20 Sep 2002 08:20:11 +0300
parents cf4d065f2f85
children 6173b306d276
line wrap: on
line source

/* Copyright (C) 2002 Timo Sirainen */

#include "lib.h"
#include "mail-index.h"
#include "mail-index-util.h"

#define CHECK(field) \
	if (old_hdr->field != new_hdr->field) \
		i_warning("fsck: "#field" %u != %u", \
			  old_hdr->field, new_hdr->field);


static void print_differences(MailIndexHeader *old_hdr,
			      MailIndexHeader *new_hdr)
{
	if (old_hdr->first_hole_position != new_hdr->first_hole_position) {
		i_warning("fsck: first_hole_position %"PRIuUOFF_T
			  " != %"PRIuUOFF_T, old_hdr->first_hole_position,
			  new_hdr->first_hole_position);
	}
	CHECK(first_hole_records);

	CHECK(next_uid);

	CHECK(messages_count);
	CHECK(seen_messages_count);
	CHECK(deleted_messages_count);
	CHECK(last_nonrecent_uid);

	if (old_hdr->first_unseen_uid_lowwater >
	    new_hdr->first_unseen_uid_lowwater) {
		i_warning("fsck: first_unseen_uid_lowwater %u > %u",
			  old_hdr->first_unseen_uid_lowwater,
                          new_hdr->first_unseen_uid_lowwater);
	}

	if (old_hdr->first_deleted_uid_lowwater >
	    new_hdr->first_deleted_uid_lowwater) {
		i_warning("fsck: first_deleted_uid_lowwater %u > %u",
			  old_hdr->first_deleted_uid_lowwater,
                          new_hdr->first_deleted_uid_lowwater);
	}
}

int mail_index_fsck(MailIndex *index)
{
	/* we verify only the fields in the header. other problems will be
	   noticed and fixed while reading the messages. */
	MailIndexHeader old_hdr;
	MailIndexHeader *hdr;
	MailIndexRecord *rec, *end_rec;
	unsigned int max_uid;
	uoff_t pos;

	i_assert(index->lock_type != MAIL_LOCK_SHARED);

	if (!mail_index_set_lock(index, MAIL_LOCK_EXCLUSIVE))
		return FALSE;

	hdr = index->header;
	memcpy(&old_hdr, hdr, sizeof(MailIndexHeader));

	hdr->first_hole_position = 0;
	hdr->first_hole_records = 0;

	hdr->messages_count = 0;
	hdr->seen_messages_count = 0;
	hdr->deleted_messages_count = 0;

	hdr->first_unseen_uid_lowwater = 0;
	hdr->first_deleted_uid_lowwater = 0;

	rec = (MailIndexRecord *) ((char *) index->mmap_base +
				   sizeof(MailIndexHeader));
	end_rec = (MailIndexRecord *) ((char *) index->mmap_base +
				       index->mmap_used_length);

	max_uid = 0;
	for (; rec < end_rec; rec++) {
		if (rec->uid == 0) {
			/* expunged message */
			pos = INDEX_FILE_POSITION(index, rec);
			if (hdr->first_hole_position == 0) {
				hdr->first_hole_position = pos;
				hdr->first_hole_records = 1;
			} else if (hdr->first_hole_position +
				   (hdr->first_hole_records *
				    sizeof(MailIndexRecord)) == pos) {
				/* hole continues */
				hdr->first_hole_records++;
			}
			continue;
		}

		if (rec->uid < max_uid) {
			index_set_corrupted(index, "UIDs are not ordered "
					    "(%u < %u)", rec->uid, max_uid);
			return FALSE;
		}
		max_uid = rec->uid;

		if (rec->msg_flags & MAIL_SEEN)
			hdr->seen_messages_count++;
		else if (hdr->first_unseen_uid_lowwater)
			hdr->first_unseen_uid_lowwater = rec->uid;

		if (rec->msg_flags & MAIL_DELETED) {
			if (hdr->first_deleted_uid_lowwater == 0)
                                hdr->first_deleted_uid_lowwater = rec->uid;
			hdr->deleted_messages_count++;
		}
		hdr->messages_count++;
	}

	if (hdr->next_uid <= max_uid)
		hdr->next_uid = max_uid+1;
	if (hdr->last_nonrecent_uid >= hdr->next_uid)
		hdr->last_nonrecent_uid = hdr->next_uid-1;

	print_differences(&old_hdr, hdr);

	/* FSCK flag is removed automatically by set_lock() */
	return TRUE;
}