dovecot-2.0: Moved some code from mail-index-map.c to mail-index...

dovecot at dovecot.org dovecot at dovecot.org
Thu May 21 00:32:22 EEST 2009


details:   http://hg.dovecot.org/dovecot-2.0/rev/768b25cabd6c
changeset: 9331:768b25cabd6c
user:      Timo Sirainen <tss at iki.fi>
date:      Wed May 20 15:39:39 2009 -0400
description:
Moved some code from mail-index-map.c to mail-index-map-hdr.c

diffstat:

4 files changed, 302 insertions(+), 290 deletions(-)
src/lib-index/Makefile.am          |    1 
src/lib-index/mail-index-map-hdr.c |  293 ++++++++++++++++++++++++++++++++++++
src/lib-index/mail-index-map.c     |  292 -----------------------------------
src/lib-index/mail-index-private.h |    6 

diffs (truncated from 635 to 300 lines):

diff -r 94547703da25 -r 768b25cabd6c src/lib-index/Makefile.am
--- a/src/lib-index/Makefile.am	Wed May 20 14:04:25 2009 -0400
+++ b/src/lib-index/Makefile.am	Wed May 20 15:39:39 2009 -0400
@@ -18,6 +18,7 @@ libindex_la_SOURCES = \
         mail-index-fsck.c \
         mail-index-lock.c \
         mail-index-map.c \
+        mail-index-map-hdr.c \
         mail-index-modseq.c \
         mail-index-transaction.c \
         mail-index-transaction-export.c \
diff -r 94547703da25 -r 768b25cabd6c src/lib-index/mail-index-map-hdr.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/lib-index/mail-index-map-hdr.c	Wed May 20 15:39:39 2009 -0400
@@ -0,0 +1,293 @@
+/* Copyright (c) 2003-2009 Dovecot authors, see the included COPYING file */
+
+#include "lib.h"
+#include "array.h"
+#include "mail-index-private.h"
+
+int mail_index_map_parse_extensions(struct mail_index_map *map)
+{
+	struct mail_index *index = map->index;
+	const struct mail_index_ext_header *ext_hdr;
+	unsigned int i, old_count, offset;
+	const char *name, *error;
+	uint32_t ext_id, ext_offset;
+
+	/* extension headers always start from 64bit offsets, so if base header
+	   doesn't happen to be 64bit aligned we'll skip some bytes */
+	offset = MAIL_INDEX_HEADER_SIZE_ALIGN(map->hdr.base_header_size);
+	if (offset >= map->hdr.header_size && map->extension_pool == NULL) {
+		/* nothing to do, skip allocatations and all */
+		return 0;
+	}
+
+	old_count = array_count(&index->extensions);
+	mail_index_map_init_extbufs(map, old_count + 5);
+
+	ext_id = (uint32_t)-1;
+	for (i = 0; i < old_count; i++)
+		array_append(&map->ext_id_map, &ext_id, 1);
+
+	for (i = 0; offset < map->hdr.header_size; i++) {
+		ext_offset = offset;
+
+		if (mail_index_map_ext_get_next(map, &offset,
+						&ext_hdr, &name) < 0) {
+			mail_index_set_error(index, "Corrupted index file %s: "
+				"Header extension #%d (%s) goes outside header",
+				index->filepath, i, name);
+			return -1;
+		}
+
+		if (mail_index_map_ext_hdr_check(&map->hdr, ext_hdr,
+						 name, &error) < 0) {
+			mail_index_set_error(index, "Corrupted index file %s: "
+					     "Broken extension #%d (%s): %s",
+					     index->filepath, i, name, error);
+			return -1;
+		}
+		if (mail_index_map_lookup_ext(map, name, NULL)) {
+			mail_index_set_error(index, "Corrupted index file %s: "
+				"Duplicate header extension %s",
+				index->filepath, name);
+			return -1;
+		}
+
+		mail_index_map_register_ext(map, name, ext_offset, ext_hdr);
+	}
+	return 0;
+}
+
+int mail_index_map_parse_keywords(struct mail_index_map *map)
+{
+	struct mail_index *index = map->index;
+	const struct mail_index_ext *ext;
+	const struct mail_index_keyword_header *kw_hdr;
+	const struct mail_index_keyword_header_rec *kw_rec;
+	const char *name;
+	unsigned int i, name_area_end_offset, old_count;
+	uint32_t idx;
+
+	if (!mail_index_map_lookup_ext(map, MAIL_INDEX_EXT_KEYWORDS, &idx)) {
+		if (array_is_created(&map->keyword_idx_map))
+			array_clear(&map->keyword_idx_map);
+		return 0;
+	}
+	ext = array_idx(&map->extensions, idx);
+
+	/* Extension header contains:
+	   - struct mail_index_keyword_header
+	   - struct mail_index_keyword_header_rec * keywords_count
+	   - const char names[] * keywords_count
+	*/
+	i_assert(ext->hdr_offset < map->hdr.header_size);
+	kw_hdr = CONST_PTR_OFFSET(map->hdr_base, ext->hdr_offset);
+	kw_rec = (const void *)(kw_hdr + 1);
+	name = (const char *)(kw_rec + kw_hdr->keywords_count);
+
+	old_count = !array_is_created(&map->keyword_idx_map) ? 0 :
+		array_count(&map->keyword_idx_map);
+
+	/* Keywords can only be added into same mapping. Removing requires a
+	   new mapping (recreating the index file) */
+	if (kw_hdr->keywords_count == old_count) {
+		/* nothing changed */
+		return 0;
+	}
+
+	/* make sure the header is valid */
+	if (kw_hdr->keywords_count < old_count) {
+		mail_index_set_error(index, "Corrupted index file %s: "
+				     "Keywords removed unexpectedly",
+				     index->filepath);
+		return -1;
+	}
+
+	if ((size_t)(name - (const char *)kw_hdr) > ext->hdr_size) {
+		mail_index_set_error(index, "Corrupted index file %s: "
+				     "keywords_count larger than header size",
+				     index->filepath);
+		return -1;
+	}
+
+	name_area_end_offset = (const char *)kw_hdr + ext->hdr_size - name;
+	for (i = 0; i < kw_hdr->keywords_count; i++) {
+		if (kw_rec[i].name_offset > name_area_end_offset) {
+			mail_index_set_error(index, "Corrupted index file %s: "
+				"name_offset points outside allocated header",
+				index->filepath);
+			return -1;
+		}
+	}
+	if (name[name_area_end_offset-1] != '\0') {
+		mail_index_set_error(index, "Corrupted index file %s: "
+				     "Keyword header doesn't end with NUL",
+				     index->filepath);
+		return -1;
+	}
+
+	/* create file -> index mapping */
+	if (!array_is_created(&map->keyword_idx_map)) 
+		i_array_init(&map->keyword_idx_map, kw_hdr->keywords_count);
+
+#ifdef DEBUG
+	/* Check that existing headers are still the same. It's behind DEBUG
+	   since it's pretty useless waste of CPU normally. */
+	for (i = 0; i < array_count(&map->keyword_idx_map); i++) {
+		const char *keyword = name + kw_rec[i].name_offset;
+		const unsigned int *old_idx;
+		unsigned int kw_idx;
+
+		old_idx = array_idx(&map->keyword_idx_map, i);
+		if (!mail_index_keyword_lookup(index, keyword, &kw_idx) ||
+		    kw_idx != *old_idx) {
+			mail_index_set_error(index, "Corrupted index file %s: "
+					     "Keywords changed unexpectedly",
+					     index->filepath);
+			return -1;
+		}
+	}
+#endif
+	/* Register the newly seen keywords */
+	i = array_count(&map->keyword_idx_map);
+	for (; i < kw_hdr->keywords_count; i++) {
+		const char *keyword = name + kw_rec[i].name_offset;
+		unsigned int kw_idx;
+
+		if (*keyword == '\0') {
+			mail_index_set_error(index, "Corrupted index file %s: "
+				"Empty keyword name in header",
+				index->filepath);
+			return -1;
+		}
+		mail_index_keyword_lookup_or_create(index, keyword, &kw_idx);
+		array_append(&map->keyword_idx_map, &kw_idx, 1);
+	}
+	return 0;
+}
+
+bool mail_index_check_header_compat(struct mail_index *index,
+				    const struct mail_index_header *hdr,
+				    uoff_t file_size)
+{
+        enum mail_index_header_compat_flags compat_flags = 0;
+
+#if !WORDS_BIGENDIAN
+	compat_flags |= MAIL_INDEX_COMPAT_LITTLE_ENDIAN;
+#endif
+
+	if (hdr->major_version != MAIL_INDEX_MAJOR_VERSION) {
+		/* major version change - handle silently(?) */
+		return FALSE;
+	}
+	if ((hdr->flags & MAIL_INDEX_HDR_FLAG_CORRUPTED) != 0) {
+		/* we've already complained about it */
+		return FALSE;
+	}
+
+	if (hdr->compat_flags != compat_flags) {
+		/* architecture change */
+		mail_index_set_error(index, "Rebuilding index file %s: "
+				     "CPU architecture changed",
+				     index->filepath);
+		return FALSE;
+	}
+
+	if (hdr->base_header_size < MAIL_INDEX_HEADER_MIN_SIZE ||
+	    hdr->header_size < hdr->base_header_size) {
+		mail_index_set_error(index, "Corrupted index file %s: "
+				     "Corrupted header sizes (base %u, full %u)",
+				     index->filepath, hdr->base_header_size,
+				     hdr->header_size);
+		return FALSE;
+	}
+	if (hdr->header_size > file_size) {
+		mail_index_set_error(index, "Corrupted index file %s: "
+				     "Corrupted header size (%u > %"PRIuUOFF_T")",
+				     index->filepath, hdr->header_size,
+				     file_size);
+		return FALSE;
+	}
+
+	if (hdr->indexid != index->indexid) {
+		if (index->indexid != 0) {
+			mail_index_set_error(index, "Index file %s: "
+					     "indexid changed: %u -> %u",
+					     index->filepath, index->indexid,
+					     hdr->indexid);
+		}
+		index->indexid = hdr->indexid;
+		mail_transaction_log_indexid_changed(index->log);
+	}
+
+	return TRUE;
+}
+
+static void mail_index_map_clear_recent_flags(struct mail_index_map *map)
+{
+	struct mail_index_record *rec;
+	unsigned int i;
+
+	for (i = 0; i < map->hdr.messages_count; i++) {
+		rec = MAIL_INDEX_MAP_IDX(map, i);
+		rec->flags &= ~MAIL_RECENT;
+	}
+}
+
+int mail_index_map_check_header(struct mail_index_map *map)
+{
+	struct mail_index *index = map->index;
+	const struct mail_index_header *hdr = &map->hdr;
+
+	if (!mail_index_check_header_compat(index, hdr, (uoff_t)-1))
+		return -1;
+
+	/* following some extra checks that only take a bit of CPU */
+	if (hdr->record_size < sizeof(struct mail_index_record)) {
+		mail_index_set_error(index, "Corrupted index file %s: "
+				     "record_size too small: %u < %"PRIuSIZE_T,
+				     index->filepath, hdr->record_size,
+				     sizeof(struct mail_index_record));
+		return -1;
+	}
+
+	if (hdr->uid_validity == 0 && hdr->next_uid != 1)
+		return 0;
+	if (hdr->next_uid == 0)
+		return 0;
+	if (hdr->messages_count > map->rec_map->records_count)
+		return 0;
+
+	if (hdr->seen_messages_count > hdr->messages_count ||
+	    hdr->deleted_messages_count > hdr->messages_count)
+		return 0;
+	switch (hdr->minor_version) {
+	case 0:
+		/* upgrade silently from v1.0 */
+		map->hdr.unused_old_recent_messages_count = 0;
+		if (hdr->first_recent_uid == 0)
+			map->hdr.first_recent_uid = 1;
+		index->need_recreate = TRUE;
+		/* fall through */
+	case 1:
+		/* pre-v1.1.rc6: make sure the \Recent flags are gone */
+		mail_index_map_clear_recent_flags(map);
+		map->hdr.minor_version = MAIL_INDEX_MINOR_VERSION;
+	}
+	if (hdr->first_recent_uid == 0 ||
+	    hdr->first_recent_uid > hdr->next_uid ||
+	    hdr->first_unseen_uid_lowwater > hdr->next_uid ||
+	    hdr->first_deleted_uid_lowwater > hdr->next_uid)
+		return 0;
+
+	if (hdr->messages_count > 0) {
+		/* last message's UID must be smaller than next_uid.
+		   also make sure it's not zero. */
+		const struct mail_index_record *rec;


More information about the dovecot-cvs mailing list