diff src/lib-index/mail-index.c @ 3016:61c8d205d887 HEAD

Initial support for keywords. Syncing to mbox/maildir doesn't work yet.
author Timo Sirainen <tss@iki.fi>
date Sun, 26 Dec 2004 11:12:39 +0200
parents cd257e96a370
children 66c44404f9a1
line wrap: on
line diff
--- a/src/lib-index/mail-index.c	Sun Dec 26 11:10:20 2004 +0200
+++ b/src/lib-index/mail-index.c	Sun Dec 26 11:12:39 2004 +0200
@@ -34,6 +34,9 @@
 
 	index->mode = 0600;
 	index->gid = (gid_t)-1;
+
+	index->keywords_ext_id =
+		mail_index_ext_register(index, "keywords", 128, 2, 1);
 	return index;
 }
 
@@ -270,6 +273,92 @@
 	return 1;
 }
 
+int mail_index_map_read_keywords(struct mail_index *index,
+				 struct mail_index_map *map)
+{
+	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, **keywords_list;
+	unsigned int i, name_len;
+	uint32_t ext_id;
+
+	ext_id = mail_index_map_lookup_ext(map, "keywords");
+	if (ext_id == (uint32_t)-1) {
+		map->keywords = NULL;
+		map->keywords_count = 0;
+		return 0;
+	}
+
+	ext = map->extensions->data;
+	ext += ext_id;
+
+	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);
+
+	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;
+	}
+
+	/* make sure the header is valid */
+	name_len = (const char *)kw_hdr + ext->hdr_size - name;
+	for (i = 0; i < kw_hdr->keywords_count; i++) {
+		if (kw_rec[i].name_offset > name_len) {
+			mail_index_set_error(index, "Corrupted index file %s: "
+				"name_offset points outside allocated header",
+				index->filepath);
+			return -1;
+		}
+	}
+	if (name[name_len-1] != '\0') {
+		mail_index_set_error(index, "Corrupted index file %s: "
+				     "header doesn't end with NUL",
+				     index->filepath);
+		return -1;
+	}
+
+	if (map->keywords_pool == NULL)
+		map->keywords_pool = pool_alloconly_create("keywords", 1024);
+
+	/* Save keywords in memory. Only new keywords should come into the
+	   mapping, so keep the existing keyword strings in memory to allow
+	   mail_index_lookup_keywords() to safely return direct pointers
+	   into them. */
+	if (kw_hdr->keywords_count < map->keywords_count) {
+		mail_index_set_error(index, "Corrupted index file %s: "
+				     "Keywords removed unexpectedly",
+				     index->filepath);
+		return -1;
+	}
+	if (kw_hdr->keywords_count == map->keywords_count) {
+		/* nothing changed */
+		return 0;
+	}
+
+	/* @UNSAFE */
+	keywords_list = p_new(map->keywords_pool,
+			      const char *, kw_hdr->keywords_count + 1);
+	for (i = 0; i < map->keywords_count; i++)
+		keywords_list[i] = map->keywords[i];
+	for (; i < kw_hdr->keywords_count; i++) {
+		keywords_list[i] = p_strdup(map->keywords_pool,
+					    name + kw_rec[i].name_offset);
+	}
+	map->keywords = keywords_list;
+	map->keywords_count = kw_hdr->keywords_count;
+	return 0;
+}
+
+const char *const *mail_index_get_keywords(struct mail_index *index)
+{
+	(void)mail_index_map_read_keywords(index, index->map);
+	return index->map->keywords;
+}
+
 static int mail_index_check_header(struct mail_index *index,
 				   struct mail_index_map *map)
 {
@@ -305,14 +394,6 @@
 		return -1;
 	}
 
-	if (hdr->keywords_mask_size != sizeof(keywords_mask_t)) {
-		mail_index_set_error(index, "Corrupted index file %s: "
-				     "keywords_mask_size mismatch: %d != %d",
-				     index->filepath, hdr->keywords_mask_size,
-				     (int)sizeof(keywords_mask_t));
-		return -1;
-	}
-
 	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,
@@ -368,6 +449,8 @@
 	mail_index_map_clear(index, map);
 	if (map->extension_pool != NULL)
 		pool_unref(map->extension_pool);
+	if (map->keywords_pool != NULL)
+		pool_unref(map->keywords_pool);
 	buffer_free(map->hdr_copy_buf);
 	i_free(map);
 }
@@ -1080,7 +1163,6 @@
 	hdr->base_header_size = sizeof(*hdr);
 	hdr->header_size = sizeof(*hdr);
 	hdr->record_size = sizeof(struct mail_index_record);
-	hdr->keywords_mask_size = sizeof(keywords_mask_t);
 
 #ifndef WORDS_BIGENDIAN
 	hdr->compat_data[0] = MAIL_INDEX_COMPAT_LITTLE_ENDIAN;