changeset 12642:46dc31d8769f

lib-index: Removed the old "mailbox list" type index, which is no longer used. It was rather overdesigned and fragile.
author Timo Sirainen <tss@iki.fi>
date Tue, 08 Feb 2011 01:36:19 +0200
parents ad002fdc6a6c
children f5f877ecd7f6
files src/lib-index/Makefile.am src/lib-index/mailbox-list-index-private.h src/lib-index/mailbox-list-index-sync.c src/lib-index/mailbox-list-index.c src/lib-index/mailbox-list-index.h src/util/Makefile.am src/util/listview.c
diffstat 7 files changed, 0 insertions(+), 2116 deletions(-) [+]
line wrap: on
line diff
--- a/src/lib-index/Makefile.am	Tue Feb 08 01:35:45 2011 +0200
+++ b/src/lib-index/Makefile.am	Tue Feb 08 01:36:19 2011 +0200
@@ -41,8 +41,6 @@
         mail-transaction-log-append.c \
         mail-transaction-log-file.c \
         mail-transaction-log-view.c \
-        mailbox-list-index.c \
-        mailbox-list-index-sync.c \
         mailbox-log.c
 
 headers = \
@@ -60,8 +58,6 @@
         mail-transaction-log.h \
 	mail-transaction-log-private.h \
 	mail-transaction-log-view-private.h \
-        mailbox-list-index.h \
-        mailbox-list-index-private.h \
         mailbox-log.h
 
 test_programs = \
--- a/src/lib-index/mailbox-list-index-private.h	Tue Feb 08 01:35:45 2011 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,108 +0,0 @@
-#ifndef MAILBOX_LIST_INDEX_PRIVATE_H
-#define MAILBOX_LIST_INDEX_PRIVATE_H
-
-#include "file-dotlock.h"
-#include "mailbox-list-index.h"
-
-#define MAILBOX_LIST_INDEX_MAJOR_VERSION 1
-#define MAILBOX_LIST_INDEX_MINOR_VERSION 0
-
-#define MAILBOX_LIST_COMPRESS_PERCENTAGE 10
-#define MAILBOX_LIST_COMPRESS_MIN_SIZE 1024
-
-#define MAILBOX_LIST_INDEX_MMAP_MIN_SIZE (1024*32)
-
-struct mailbox_list_index_header {
-	uint8_t major_version;
-	uint8_t minor_version;
-	uint8_t unused[2];
-
-	uint32_t file_seq;
-	uint32_t header_size;
-	uint32_t uid_validity;
-
-	/* locking required to access the fields below: */
-	uint32_t next_uid;
-
-	uint32_t used_space;
-	uint32_t deleted_space;
-};
-
-struct mailbox_list_dir_record {
-	/* If non-zero, contains a pointer to updated directory list.
-	   Stored using mail_index_uint32_to_offset(). */
-	uint32_t next_offset;
-	/* Bytes required to be able to fully read this directory's records.
-	   This includes also bytes used by mailbox names that follow the
-	   records (but doesn't include bytes for mailbox names that point
-	   to earlier offsets in the file). */
-	uint32_t dir_size;
-
-	uint32_t count;
-	/* The records are sorted 1) by their name_hash, 2) the actual name */
-	/* struct mailbox_list_record records[count]; */
-};
-
-struct mailbox_list_record {
-	/* CRC32 hash of the name */
-	uint32_t name_hash;
-	unsigned int uid:31;
-	/* Set when this record has been marked as deleted. It will be removed
-	   permanently the next time a new record is added to this directory
-	   or on the next index compression. */
-	unsigned int deleted:1;
-
-	/* Points to a NUL-terminated record name */
-	uint32_t name_offset;
-	/* Pointer to child mailboxes or 0 if there are no children.
-	   The offset is stored using mail_index_uint32_to_offset()
-	   since it may change while we're reading */
-	uint32_t dir_offset;
-};
-
-struct mailbox_list_index {
-	char *filepath;
-	char separator;
-	struct mail_index *mail_index;
-	struct file_cache *file_cache;
-	struct dotlock_settings dotlock_set;
-
-	int fd;
-
-	void *mmap_base;
-	const void *const_mmap_base;
-	size_t mmap_size;
-	const struct mailbox_list_index_header *hdr;
-
-	unsigned int mmap_disable:1;
-};
-
-#define MAILBOX_LIST_RECORDS(dir) \
-	((const struct mailbox_list_record *)(dir + 1))
-#define MAILBOX_LIST_RECORDS_MODIFIABLE(dir) \
-	((struct mailbox_list_record *)(dir + 1))
-#define MAILBOX_LIST_RECORD_IDX(dir, rec) \
-	((rec) - MAILBOX_LIST_RECORDS(dir))
-
-int mailbox_list_index_set_syscall_error(struct mailbox_list_index *index,
-					 const char *function);
-
-int mailbox_list_index_dir_lookup_rec(struct mailbox_list_index *index,
-				      const struct mailbox_list_dir_record *dir,
-				      const char *name,
-				      const struct mailbox_list_record **rec_r);
-int mailbox_list_index_get_dir(struct mailbox_list_index_view *view,
-			       uint32_t *offset,
-			       const struct mailbox_list_dir_record **dir_r);
-int mailbox_list_index_map(struct mailbox_list_index *index);
-
-int mailbox_list_index_file_create(struct mailbox_list_index *index,
-				   uint32_t uid_validity);
-void mailbox_list_index_file_close(struct mailbox_list_index *index);
-
-int mailbox_list_index_refresh(struct mailbox_list_index *index);
-
-int mailbox_list_index_set_corrupted(struct mailbox_list_index *index,
-				     const char *str);
-
-#endif
--- a/src/lib-index/mailbox-list-index-sync.c	Tue Feb 08 01:35:45 2011 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,991 +0,0 @@
-/* Copyright (c) 2006-2010 Dovecot authors, see the included COPYING file */
-
-#include "lib.h"
-#include "array.h"
-#include "bsearch-insert-pos.h"
-#include "crc32.h"
-#include "file-cache.h"
-#include "file-set-size.h"
-#include "mmap-util.h"
-#include "nfs-workarounds.h"
-#include "ostream.h"
-#include "mail-index-private.h"
-#include "mailbox-list-index-private.h"
-
-#include <stddef.h>
-
-#define ROOT_INIT_COUNT 128
-#define DIR_ALLOC_MORE_COUNT 4
-#define MAILBOX_LIST_INDEX_GROW_PERCENTAGE 10
-#define MAILBOX_LIST_INDEX_MIN_SIZE 512
-
-struct mailbox_list_sync_record {
-	uint32_t name_hash;
-	uint32_t seq;
-	uint32_t uid;
-	const char *name;
-
-	/* dir is used if it's non-NULL, otherwise dir_offset is used */
-	struct mailbox_list_sync_dir *dir;
-	uint32_t dir_offset;
-
-	uint32_t created:1;
-	/* This record was seen while syncing, either as parent or as leaf */
-	uint32_t seen:1;
-	/* This record was seen as leaf while syncing, so it exists */
-	uint32_t exists:1;
-};
-
-struct mailbox_list_sync_dir {
-	/* The records are sorted by their name_hash */
-	ARRAY_DEFINE(records, struct mailbox_list_sync_record);
-
-	/* Offset to the original location in the index, or 0 for new dirs */
-	uint32_t offset;
-	unsigned int seen_records_count;
-	unsigned int new_records_count;
-};
-
-struct mailbox_list_index_sync_ctx {
-	struct mailbox_list_index *index;
-	struct mailbox_list_index_view *view;
-	pool_t pool;
-
-	enum mailbox_list_sync_flags flags;
-	const char *sync_path;
-	struct mail_index_sync_ctx *mail_sync_ctx;
-	struct mail_index_view *mail_view;
-	struct mail_index_transaction *trans;
-
-	struct mailbox_list_index_header hdr;
-	struct mailbox_list_sync_dir *root, *sync_root;
-
-	struct ostream *output;
-	buffer_t *output_buf;
-
-	unsigned int failed:1;
-	unsigned int changed:1;
-	unsigned int restart:1;
-	unsigned int partial:1;
-	unsigned int seen_sync_root:1;
-};
-
-struct mailbox_list_sync_lookup_key {
-	uint32_t name_hash;
-	const char *name;
-};
-
-static bool mailbox_list_index_need_compress(struct mailbox_list_index *index);
-static int mailbox_list_index_compress(struct mailbox_list_index_sync_ctx *ctx);
-
-static struct mailbox_list_sync_dir *
-mailbox_list_alloc_sync_dir(struct mailbox_list_index_sync_ctx *ctx,
-			    unsigned int initial_count)
-{
-	struct mailbox_list_sync_dir *sync_dir;
-
-	sync_dir = p_new(ctx->pool, struct mailbox_list_sync_dir, 1);
-	p_array_init(&sync_dir->records, ctx->pool, initial_count);
-	return sync_dir;
-}
-
-static int
-mailbox_list_copy_sync_dir(struct mailbox_list_index_sync_ctx *ctx,
-			   uint32_t offset,
-			   struct mailbox_list_sync_dir **sync_dir_r)
-{
-	const struct mailbox_list_dir_record *dir;
-	const struct mailbox_list_record *recs;
-	struct mailbox_list_sync_dir *sync_dir;
-	struct mailbox_list_sync_record *sync_rec;
-	const char *name;
-	size_t max_len;
-	unsigned int i;
-
-	if (mailbox_list_index_get_dir(ctx->view, &offset, &dir) < 0)
-		return -1;
-
-	sync_dir = mailbox_list_alloc_sync_dir(ctx, dir->count +
-					       DIR_ALLOC_MORE_COUNT);
-	sync_dir->offset = offset;
-
-	recs = MAILBOX_LIST_RECORDS(dir);
-	for (i = 0; i < dir->count; i++) {
-		if (recs[i].deleted)
-			continue;
-
-		if (recs[i].uid == 0) {
-			return mailbox_list_index_set_corrupted(ctx->index,
-							"Record with UID=0");
-		}
-
-		sync_rec = array_append_space(&sync_dir->records);
-		sync_rec->name_hash = recs[i].name_hash;
-		sync_rec->uid = recs[i].uid;
-		sync_rec->dir_offset =
-			mail_index_offset_to_uint32(recs[i].dir_offset);
-
-		max_len = ctx->index->mmap_size - recs[i].name_offset;
-		name = CONST_PTR_OFFSET(ctx->index->const_mmap_base,
-					recs[i].name_offset);
-
-		sync_rec->name = p_strndup(ctx->pool, name, max_len);
-	}
-
-	*sync_dir_r = sync_dir;
-	return 0;
-}
-
-static int
-mailbox_list_sync_record_cmp(const struct mailbox_list_sync_lookup_key *key,
-			     const struct mailbox_list_sync_record *rec)
-{
-	if (key->name_hash < rec->name_hash)
-		return -1;
-	if (key->name_hash > rec->name_hash)
-		return 1;
-
-	return strcmp(key->name, rec->name);
-}
-
-static struct mailbox_list_sync_record *
-mailbox_list_sync_dir_lookup(struct mailbox_list_sync_dir *dir,
-			     const char *name, unsigned int *idx_r)
-{
-	struct mailbox_list_sync_lookup_key key;
-
-	/* binary search the current hierarchy level name. the values are
-	   sorted primarily by their hash value and secondarily by the actual
-	   name */
-	key.name = name;
-	key.name_hash = crc32_str(name);
-
-	if (!array_bsearch_insert_pos(&dir->records, &key,
-				      mailbox_list_sync_record_cmp, idx_r))
-		return NULL;
-
-	return array_idx_modifiable(&dir->records, *idx_r);
-}
-
-static struct mailbox_list_sync_record *
-mailbox_list_alloc_add_record(struct mailbox_list_index_sync_ctx *ctx,
-			      struct mailbox_list_sync_dir *dir,
-			      const char *name, unsigned int idx)
-{
-	struct mailbox_list_sync_record *rec;
-
-	ctx->changed = TRUE;
-
-	rec = array_insert_space(&dir->records, idx);
-	rec->name_hash = crc32_str(name);
-	rec->name = p_strdup(ctx->pool, name);
-	rec->uid = ctx->hdr.next_uid++;
-	rec->created = TRUE;
-	mail_index_append(ctx->trans, rec->uid, &rec->seq);
-
-	dir->new_records_count++;
-	return rec;
-}
-
-static int
-mailbox_list_index_sync_get_seq(struct mailbox_list_index_sync_ctx *ctx,
-				struct mailbox_list_sync_record *rec)
-{
-	const struct mail_index_header *mail_hdr;
-
-	if (rec->uid == 0) {
-		return mailbox_list_index_set_corrupted(ctx->index,
-							"Record with UID=0");
-	}
-	if (!mail_index_lookup_seq(ctx->mail_view, rec->uid, &rec->seq)) {
-		mail_hdr = mail_index_get_header(ctx->mail_view);
-		if (rec->uid < mail_hdr->next_uid) {
-			i_warning("%s: Desync: Record uid=%u "
-				  "expunged from mail index",
-				  ctx->index->mail_index->filepath, rec->uid);
-			ctx->restart = TRUE;
-			return -1;
-		}
-		mail_index_append(ctx->trans, rec->uid, &rec->seq);
-	}
-	return 0;
-}
-
-static int
-mailbox_list_index_sync_int(struct mailbox_list_index_sync_ctx *ctx,
-			    const char *name,
-			    struct mailbox_list_sync_dir **dir_r,
-			    uint32_t *seq_r)
-{
-	const char *p, *hier_name;
-	struct mailbox_list_sync_dir *dir;
-	struct mailbox_list_sync_record *rec = NULL;
-	unsigned int idx, rec_flags;
-
-	if (ctx->failed)
-		return -1;
-
-	dir = ctx->sync_root;
-	rec_flags = MAILBOX_LIST_INDEX_FLAG_CHILDREN;
-
-	for (;;) {
-		p = strchr(name, ctx->index->separator);
-		hier_name = p == NULL ? name : t_strdup_until(name, p);
-
-		if (*hier_name == '\0') {
-			if (p == NULL) {
-				/* name ended with a separator */
-				break;
-			}
-			/* two separators adjacently, skip this */
-			name = p + 1;
-			continue;
-		}
-
-		if (rec != NULL) {
-			/* add CHILDREN flag to the parent and remove
-			   NOCHILDREN flag. if we happened to create the
-			   parent ourself, also add NONEXISTENT flag. */
-			mail_index_update_flags(ctx->trans, rec->seq,
-						MODIFY_ADD, rec_flags);
-			mail_index_update_flags(ctx->trans, rec->seq,
-					MODIFY_REMOVE,
-					(enum mail_flags)
-					MAILBOX_LIST_INDEX_FLAG_NOCHILDREN);
-		}
-
-		rec = mailbox_list_sync_dir_lookup(dir, hier_name, &idx);
-		if (rec == NULL) {
-			/* new record */
-			rec_flags |= MAILBOX_LIST_INDEX_FLAG_NONEXISTENT;
-			rec = mailbox_list_alloc_add_record(ctx, dir,
-							    hier_name, idx);
-		} else if (rec->seq == 0) {
-			/* this record was copied from existing index.
-			   the uid is known, but the sequence isn't. */
-			if (mailbox_list_index_sync_get_seq(ctx, rec) < 0) {
-				ctx->failed = TRUE;
-				break;
-			}
-		}
-		*seq_r = rec->seq;
-
-		/* remember that we've seen this record */
-		if (!rec->seen) {
-			rec->seen = TRUE;
-			dir->seen_records_count++;
-		}
-
-		if (p == NULL) {
-			/* leaf */
-			rec->exists = TRUE;
-			mail_index_update_flags(ctx->trans, rec->seq,
-				MODIFY_REMOVE,
-				(enum mail_flags)
-				MAILBOX_LIST_INDEX_FLAG_NONEXISTENT);
-			break;
-		}
-
-		/* we were handling a parent, continue with its child */
-		if (!rec->exists) {
-			/* Mark this mailbox non-existent for now. If it
-			   exists, this flag is removed later. */
-			mail_index_update_flags(ctx->trans, rec->seq,
-				MODIFY_ADD,
-				(enum mail_flags)
-				MAILBOX_LIST_INDEX_FLAG_NONEXISTENT);
-		}
-
-		if (rec->dir == NULL) {
-			if (rec->dir_offset != 0) {
-				if (mailbox_list_copy_sync_dir(ctx,
-							       rec->dir_offset,
-							       &rec->dir) < 0) {
-					ctx->failed = TRUE;
-					break;
-				}
-			} else {
-				rec->dir = mailbox_list_alloc_sync_dir(ctx,
-						1 + DIR_ALLOC_MORE_COUNT);
-			}
-		}
-
-		name = p + 1;
-		dir = rec->dir;
-	}
-
-	i_assert(dir != NULL);
-	*dir_r = dir;
-	return ctx->failed ? -1 : 0;
-}
-
-static int mailbox_list_index_get_root(struct mailbox_list_index_sync_ctx *ctx)
-{
-	uint32_t seq;
-	int ret;
-
-	i_assert(ctx->index->mmap_size > 0);
-
-	if (ctx->index->mmap_size == sizeof(*ctx->index->hdr)) {
-		/* root doesn't exist in the file yet */
-		ctx->root = mailbox_list_alloc_sync_dir(ctx,
-							ROOT_INIT_COUNT);
-	} else {
-		if (mailbox_list_copy_sync_dir(ctx, sizeof(*ctx->index->hdr),
-					       &ctx->root) < 0)
-			return -1;
-	}
-
-	/* keep sync_root=root until we've built the sync_root path. */
-	ctx->sync_root = ctx->root;
-
-	if (*ctx->sync_path != '\0') {
-		if (mailbox_list_index_sync_more(ctx, ctx->sync_path, &seq) < 0)
-			return -1;
-	}
-
-	T_BEGIN {
-		ret = mailbox_list_index_sync_int(ctx, ctx->sync_path,
-						  &ctx->sync_root, &seq);
-	} T_END;
-	return ret;
-}
-
-static int sync_mail_sync_init(struct mailbox_list_index_sync_ctx *ctx)
-{
-	struct mail_index_sync_rec sync_rec;
-
-	if (mail_index_sync_begin(ctx->index->mail_index, &ctx->mail_sync_ctx,
-				  &ctx->mail_view, &ctx->trans,
-				  MAIL_INDEX_SYNC_FLAG_AVOID_FLAG_UPDATES) < 0)
-		return -1;
-
-	mail_index_flush_read_cache(ctx->index->mail_index, ctx->index->filepath,
-				    ctx->index->fd, FALSE);
-
-	/* we should have only external transactions in here, for which we
-	   don't need to do anything but write them to the index */
-	while (mail_index_sync_next(ctx->mail_sync_ctx, &sync_rec))
-		;
-	return 0;
-}
-
-static int sync_mail_sync_init2(struct mailbox_list_index_sync_ctx *ctx)
-{
-	const struct mail_index_header *mail_hdr;
-	uint32_t uid_validity;
-
-	ctx->hdr = *ctx->index->hdr;
-	mail_hdr = mail_index_get_header(ctx->mail_view);
-	uid_validity = mail_hdr->uid_validity;
-
-	if (uid_validity != 0 || mail_hdr->next_uid != 1) {
-		if (uid_validity != ctx->hdr.uid_validity) {
-			i_warning("%s: Desync: uid_validity changed %u -> %u",
-				  ctx->index->mail_index->filepath,
-				  uid_validity, ctx->hdr.uid_validity);
-			uid_validity = 0;
-			mail_index_reset(ctx->trans);
-		}
-	}
-
-	if (uid_validity != ctx->hdr.uid_validity ) {
-		mail_index_update_header(ctx->trans,
-			offsetof(struct mail_index_header, uid_validity),
-			&ctx->hdr.uid_validity, sizeof(ctx->hdr.uid_validity),
-			TRUE);
-	}
-
-	return 0;
-}
-
-int mailbox_list_index_sync_init(struct mailbox_list_index *index,
-				 const char *path,
-				 enum mailbox_list_sync_flags flags,
-				 struct mailbox_list_index_sync_ctx **ctx_r)
-{
-	struct mailbox_list_index_sync_ctx *ctx;
-	struct mailbox_list_index_view *view;
-	pool_t pool;
-	size_t len;
-
-	if (mailbox_list_index_view_init(index, NULL, &view) < 0)
-		return -1;
-
-	/* add separator to end of path if it isn't there */
-	len = strlen(path);
-	if (len > 0 && path[len-1] != index->separator)
-		path = t_strdup_printf("%s%c", path, index->separator);
-
-	pool = pool_alloconly_create(MEMPOOL_GROWING"mailbox list index sync",
-				     1024*32);
-
-	ctx = p_new(pool, struct mailbox_list_index_sync_ctx, 1);
-	ctx->pool = pool;
-	ctx->index = index;
-	ctx->view = view;
-	ctx->sync_path = p_strdup(pool, path);
-	ctx->flags = flags;
-
-	/* mail index syncing acts as the only locking for us */
-	if (sync_mail_sync_init(ctx) < 0 ||
-	    mailbox_list_index_refresh(index) < 0 ||
-	    sync_mail_sync_init2(ctx) < 0 ||
-	    mailbox_list_index_get_root(ctx) < 0) {
-		mailbox_list_index_sync_rollback(&ctx);
-		return -1;
-	}
-
-	*ctx_r = ctx;
-	return 0;
-}
-
-struct mail_index_view *
-mailbox_list_index_sync_get_view(struct mailbox_list_index_sync_ctx *ctx)
-{
-	return ctx->mail_view;
-}
-
-struct mail_index_transaction *
-mailbox_list_index_sync_get_transaction(struct mailbox_list_index_sync_ctx *ctx)
-{
-	return ctx->trans;
-}
-
-int mailbox_list_index_sync_more(struct mailbox_list_index_sync_ctx *ctx,
-				 const char *name, uint32_t *seq_r)
-{
-	struct mailbox_list_sync_dir *dir;
-	int ret;
-
-	T_BEGIN {
-		ret = mailbox_list_index_sync_int(ctx, name, &dir, seq_r);
-	} T_END;
-	return ret;
-}
-
-static int
-mailbox_list_index_sync_grow(struct mailbox_list_index_sync_ctx *ctx,
-			     uint32_t size)
-{
-	struct mailbox_list_index *index = ctx->index;
-	uoff_t new_fsize, grow_size;
-
-	new_fsize = ctx->hdr.used_space + size;
-	grow_size = new_fsize / 100 * MAILBOX_LIST_INDEX_GROW_PERCENTAGE;
-	if (grow_size < MAILBOX_LIST_INDEX_MIN_SIZE)
-		grow_size = MAILBOX_LIST_INDEX_MIN_SIZE;
-	new_fsize += grow_size;
-	new_fsize &= ~(512-1);
-
-	i_assert(new_fsize >= ctx->hdr.used_space + size);
-
-	if (file_set_size(index->fd, (off_t)new_fsize) < 0) {
-		mailbox_list_index_set_syscall_error(index, "file_set_size()");
-		return -1;
-	}
-
-	return mailbox_list_index_map(index);
-}
-
-static int
-mailbox_list_index_sync_alloc_space(struct mailbox_list_index_sync_ctx *ctx,
-				    uint32_t size, void **base_r,
-				    uint32_t *base_offset_r)
-{
-	size_t pos = ctx->hdr.used_space;
-
-	/* all allocations must be 32bit aligned */
-	pos = (pos + 3) & ~3;
-
-	if (ctx->index->mmap_base == NULL) {
-		/* write the data into temporary buffer first */
-		buffer_reset(ctx->output_buf);
-		*base_r = buffer_append_space_unsafe(ctx->output_buf, size);
-	} else {
-		if (pos + size > ctx->index->mmap_size) {
-			if (mailbox_list_index_sync_grow(ctx, size + 3) < 0)
-				return -1;
-
-			i_assert(pos + size < ctx->index->mmap_size);
-		}
-		*base_r = PTR_OFFSET(ctx->index->mmap_base, pos);
-		memset(*base_r, 0, size);
-	}
-
-	*base_offset_r = pos;
-	ctx->hdr.used_space = pos + size;
-	ctx->changed = TRUE;
-	return 0;
-}
-
-static int
-mailbox_list_index_sync_recreate_dir(struct mailbox_list_index_sync_ctx *ctx,
-				     struct mailbox_list_sync_dir *sync_dir,
-				     uint32_t offset_pos, bool partial)
-{
-	struct mailbox_list_index *index = ctx->index;
-	const struct mailbox_list_dir_record *dir;
-	const struct mailbox_list_record *recs;
-	struct mailbox_list_dir_record *new_dir;
-	struct mailbox_list_record *new_recs;
-	struct mailbox_list_sync_record *sync_recs;
-	unsigned int src, dest, orig, count, nondeleted_count;
-	unsigned int space_needed, deleted_space;
-	uint32_t base_offset, name_pos, size;
-	void *base;
-
-	i_assert((offset_pos % sizeof(uint32_t)) == 0);
-	i_assert(offset_pos < index->mmap_size);
-
-	/* count how much space we need and how much we wasted for deleted
-	   records */
-	nondeleted_count = 0; space_needed = 0;
-	sync_recs = array_get_modifiable(&sync_dir->records, &count);
-	for (src = 0; src < count; src++) {
-		if (sync_recs[src].seen || partial) {
-			nondeleted_count++;
-			if (sync_recs[src].created) {
-				/* new record */
-				space_needed += strlen(sync_recs[src].name) + 1;
-			}
-		}
-	}
-
-	/* @UNSAFE */
-	space_needed += sizeof(*dir) + nondeleted_count * sizeof(*new_recs);
-	if (mailbox_list_index_sync_alloc_space(ctx, space_needed,
-						&base, &base_offset) < 0)
-		return -1;
-	/* NOTE: any pointers to the index file may have been invalidated
-	   as a result of growing the the memory area */
-
-	if (sync_dir->offset == 0) {
-		dir = NULL;
-		recs = NULL;
-		deleted_space = 0;
-	} else {
-		/* the offset should have been verified already to be valid */
-		i_assert(sync_dir->offset == offset_pos);
-		i_assert(sync_dir->offset < index->mmap_size);
-		dir = CONST_PTR_OFFSET(index->const_mmap_base,
-				       sync_dir->offset);
-		recs = MAILBOX_LIST_RECORDS(dir);
-
-		/* approximate deleted_space. some of the mailbox names will be
-		   reused, but don't bother calculating them. */
-		deleted_space = sizeof(*dir) + dir->dir_size;
-	}
-
-	new_dir = base;
-	new_dir->count = nondeleted_count;
-	new_dir->dir_size = space_needed;
-
-	new_recs = MAILBOX_LIST_RECORDS_MODIFIABLE(new_dir);
-	name_pos = (const char *)(new_recs + nondeleted_count) -
-		(const char *)base;
-	for (src = dest = 0; src < count;) {
-		if (!sync_recs[src].seen && !partial) {
-			/* expunge from mail index */
-			uint32_t seq;
-
-			if (mail_index_lookup_seq(ctx->mail_view,
-						  sync_recs[src].uid, &seq))
-				mail_index_expunge(ctx->trans, seq);
-			// FIXME: expunge also NONEXISTENT parents
-
-			/* If we compress the file, the record must be removed
-			   from the array. */
-			array_delete(&sync_dir->records, src, 1);
-			sync_recs = array_get_modifiable(&sync_dir->records,
-							 &count);
-			continue;
-		}
-
-		new_recs[dest].name_hash = sync_recs[src].name_hash;
-		new_recs[dest].dir_offset =
-			mail_index_uint32_to_offset(sync_recs[src].dir_offset);
-		if (sync_recs[src].created) {
-			/* new record */
-			new_recs[dest].uid = sync_recs[src].uid;
-			new_recs[dest].name_offset = base_offset + name_pos;
-			size = strlen(sync_recs[src].name) + 1;
-			memcpy(PTR_OFFSET(base, name_pos), sync_recs[src].name,
-			       size);
-			name_pos += size;
-		} else {
-			/* existing record. need to find its name_offset */
-			i_assert(dir != NULL);
-			for (orig = 0; orig < dir->count; orig++) {
-				if (recs[orig].uid == sync_recs[src].uid)
-					break;
-			}
-			i_assert(orig < dir->count);
-
-			new_recs[dest].uid = sync_recs[src].uid;
-			new_recs[dest].name_offset = recs[orig].name_offset;
-		}
-		src++; dest++;
-	}
-	i_assert(dest == nondeleted_count);
-	i_assert(name_pos == space_needed);
-
-	if (index->mmap_base == NULL) {
-		file_cache_write(index->file_cache, ctx->output_buf->data,
-				 ctx->output_buf->used, ctx->output->offset);
-		o_stream_send(ctx->output, ctx->output_buf->data,
-			      ctx->output_buf->used);
-	}
-
-	if (offset_pos == 0) {
-		/* we're writing the root directory */
-		i_assert(base_offset == sizeof(*index->hdr));
-	} else {
-		/* add a link to this newly created directory. */
-		uint32_t data = mail_index_uint32_to_offset(base_offset);
-
-		if (index->mmap_base != NULL)  {
-			uint32_t *pos;
-
-			pos = PTR_OFFSET(index->mmap_base, offset_pos);
-			i_assert(mail_index_offset_to_uint32(*pos) == 0);
-			*pos = data;
-		} else {
-			uoff_t old_offset = ctx->output->offset;
-
-			file_cache_write(index->file_cache,
-					 &data, sizeof(data), offset_pos);
-
-			o_stream_seek(ctx->output, offset_pos);
-			o_stream_send(ctx->output, &data, sizeof(data));
-			o_stream_seek(ctx->output, old_offset);
-		}
-	}
-
-	if (index->mmap_base == NULL) {
-		/* file_cache_write() calls may have moved mmaping */
-		index->const_mmap_base = file_cache_get_map(index->file_cache,
-							    &index->mmap_size);
-		index->hdr = index->const_mmap_base;
-	}
-
-	ctx->hdr.deleted_space += deleted_space;
-	ctx->changed = TRUE;
-	sync_dir->offset = base_offset;
-	return 0;
-}
-
-static int
-mailbox_list_index_sync_update_dir(struct mailbox_list_index_sync_ctx *ctx,
-				   struct mailbox_list_sync_dir *sync_dir)
-{
-	const struct mailbox_list_dir_record *dir;
-	struct mailbox_list_record *recs;
-	const struct mailbox_list_sync_record *sync_recs;
-	unsigned int i, j, count;
-	uint32_t seq;
-
-	i_assert(sync_dir->offset != 0);
-
-	if (mailbox_list_index_get_dir(ctx->view, &sync_dir->offset, &dir) < 0)
-		return -1;
-
-	sync_recs = array_get(&sync_dir->records, &count);
-	i_assert(count <= dir->count);
-	i_assert(sync_dir->seen_records_count < count);
-
-	if (ctx->index->mmap_base != NULL)
-		recs = MAILBOX_LIST_RECORDS_MODIFIABLE(dir);
-	else {
-		/* @UNSAFE: copy the records into a temporary buffer that
-		   we modify and then write back to disk */
-		recs = t_new(struct mailbox_list_record, dir->count);
-		memcpy(recs, MAILBOX_LIST_RECORDS(dir),
-		       sizeof(struct mailbox_list_record) * dir->count);
-	}
-
-	/* records marked with deleted have been removed from sync_recs, so
-	   we need to skip those */
-	for (i = j = 0; i < count; ) {
-		while (recs[j].uid != sync_recs[i].uid) {
-			j++;
-			i_assert(j < dir->count);
-		}
-
-		if (!sync_recs[i].seen) {
-			recs[j].deleted = TRUE;
-
-			/* expunge from mail index */
-			if (mail_index_lookup_seq(ctx->mail_view,
-						  sync_recs[i].uid, &seq))
-				mail_index_expunge(ctx->trans, seq);
-
-			/* If we compress the file, the record must be removed
-			   from the array. */
-			array_delete(&sync_dir->records, i, 1);
-			sync_recs = array_get(&sync_dir->records, &count);
-		} else {
-			i++;
-		}
-	}
-	if (ctx->index->mmap_base == NULL) {
-		uoff_t offset, old_offset;
-		size_t size = sizeof(struct mailbox_list_record) * dir->count;
-
-		offset = sync_dir->offset +
-			sizeof(struct mailbox_list_dir_record);
-		file_cache_write(ctx->index->file_cache, recs, size, offset);
-
-		old_offset = ctx->output->offset;
-		o_stream_seek(ctx->output, offset);
-		o_stream_send(ctx->output, recs, size);
-		o_stream_seek(ctx->output, old_offset);
-	}
-	ctx->changed = TRUE;
-	return 0;
-}
-
-static int
-mailbox_list_index_sync_write_dir(struct mailbox_list_index_sync_ctx *ctx,
-				  struct mailbox_list_sync_dir *sync_dir,
-				  uint32_t offset_pos, bool partial)
-{
-	const struct mailbox_list_dir_record *dir;
-	const struct mailbox_list_record *recs;
-	const struct mailbox_list_sync_record *sync_recs;
-	uint32_t child_offset_pos;
-	unsigned int i, j, count;
-	int ret;
-
-	if (!ctx->seen_sync_root && ctx->sync_root == sync_dir) {
-		i_assert(partial);
-		ctx->seen_sync_root = TRUE;
-		partial = (ctx->flags & MAILBOX_LIST_SYNC_FLAG_PARTIAL) != 0;
-	}
-
-	if (sync_dir->offset != 0) {
-		/* point to latest dir entry's next_offset */
-		offset_pos = sync_dir->offset +
-			offsetof(struct mailbox_list_dir_record, next_offset);
-	}
-
-	if (sync_dir->new_records_count > 0) {
-		/* need to recreate the dir record */
-		if (mailbox_list_index_sync_recreate_dir(ctx, sync_dir,
-							 offset_pos,
-							 partial) < 0)
-			return -1;
-		/* NOTE: index may have been remaped here */
-	} else if (sync_dir->seen_records_count !=
-		   array_count(&sync_dir->records) && !partial) {
-		/* just mark the records deleted */
-		T_BEGIN {
-			ret = mailbox_list_index_sync_update_dir(ctx, sync_dir);
-		} T_END;
-		if (ret < 0)
-			return -1;
-	}
-
-	if (!partial && (ctx->flags & MAILBOX_LIST_SYNC_FLAG_RECURSIVE) == 0) {
-		/* we're doing a full sync only for the root */
-		partial = TRUE;
-	}
-
-	/* update child mailboxes */
-	sync_recs = array_get(&sync_dir->records, &count);
-	if (count == 0)
-		return 0;
-
-	i_assert(sync_dir->offset != 0 &&
-		 sync_dir->offset < ctx->index->mmap_size);
-	for (i = j = 0; i < count; i++) {
-		if (sync_recs[i].dir == NULL)
-			continue;
-
-		/* these may change after each sync_write_dir() call */
-		dir = CONST_PTR_OFFSET(ctx->index->const_mmap_base,
-				       sync_dir->offset);
-		recs = MAILBOX_LIST_RECORDS(dir);
-
-		/* child_offset_pos needs to point to record's dir_offset */
-		for (; j < dir->count; j++) {
-			if (recs[j].uid == sync_recs[i].uid)
-				break;
-		}
-		i_assert(j < dir->count);
-
-		child_offset_pos = (const char *)&recs[j].dir_offset -
-			(const char *)ctx->index->const_mmap_base;
-		if (mailbox_list_index_sync_write_dir(ctx, sync_recs[i].dir,
-						      child_offset_pos,
-						      partial) < 0)
-			return -1;
-	}
-	return 0;
-}
-
-static int
-mailbox_list_index_sync_write(struct mailbox_list_index_sync_ctx *ctx)
-{
-	struct mailbox_list_index_header *hdr;
-	bool partial;
-	int ret = 0;
-
-	if (ctx->index->mmap_base == NULL) {
-		ctx->output = o_stream_create_fd_file(ctx->index->fd, 0, FALSE);
-		ctx->output_buf = buffer_create_dynamic(default_pool, 4096);
-		o_stream_seek(ctx->output, ctx->hdr.used_space);
-	}
-
-	if (ctx->sync_root == ctx->root) {
-		ctx->seen_sync_root = TRUE;
-		partial = (ctx->flags & MAILBOX_LIST_SYNC_FLAG_PARTIAL) != 0;
-	} else {
-		/* until we've seen the sync root, we're doing only partial
-		   syncing */
-		partial = TRUE;
-	}
-
-	if (mailbox_list_index_sync_write_dir(ctx, ctx->root, 0, partial) < 0)
-		ret = -1;
-
-	if (!ctx->changed) {
-		/* nothing written */
-	} else if (ctx->index->mmap_base != NULL) {
-		/* update header */
-		hdr = ctx->index->mmap_base;
-		if (ret == 0)
-			memcpy(hdr, &ctx->hdr, sizeof(*hdr));
-
-		if (msync(ctx->index->mmap_base,
-			  hdr->used_space, MS_SYNC) < 0) {
-			mailbox_list_index_set_syscall_error(ctx->index,
-							     "msync()");
-			ret = -1;
-		}
-	} else {
-		if (ret == 0) {
-			o_stream_seek(ctx->output, 0);
-			o_stream_send(ctx->output, &ctx->hdr, sizeof(ctx->hdr));
-		}
-
-		if (o_stream_flush(ctx->output) < 0) {
-			mailbox_list_index_set_syscall_error(ctx->index,
-							"o_stream_flush()");
-			ret = -1;
-		}
-		if (ret == 0 &&
-		    ctx->index->mail_index->fsync_mode == FSYNC_MODE_ALWAYS &&
-		    fdatasync(ctx->index->fd) < 0) {
-			mailbox_list_index_set_syscall_error(ctx->index,
-							     "fdatasync()");
-			ret = -1;
-		}
-	}
-	if (ctx->index->mmap_base == NULL) {
-		o_stream_destroy(&ctx->output);
-		buffer_free(&ctx->output_buf);
-	}
-	return ret;
-}
-
-int mailbox_list_index_sync_commit(struct mailbox_list_index_sync_ctx **_ctx)
-{
-	struct mailbox_list_index_sync_ctx *ctx = *_ctx;
-	int ret = ctx->failed ? -1 : 0;
-
-	*_ctx = NULL;
-
-	if (!ctx->failed) {
-		/* write all the changes to the index */
-		ret = mailbox_list_index_sync_write(ctx);
-		if (ret == 0 && mailbox_list_index_need_compress(ctx->index))
-			ret = mailbox_list_index_compress(ctx);
-	}
-
-	if (ctx->mail_sync_ctx != NULL) {
-		if (ret < 0 && !ctx->restart)
-			mail_index_sync_rollback(&ctx->mail_sync_ctx);
-		else {
-			if (ctx->restart)
-				mail_index_reset(ctx->trans);
-			if (mail_index_sync_commit(&ctx->mail_sync_ctx) < 0)
-				ret = -1;
-		}
-	}
-
-	mailbox_list_index_view_deinit(&ctx->view);
-	pool_unref(&ctx->pool);
-	return ret;
-}
-
-void mailbox_list_index_sync_rollback(struct mailbox_list_index_sync_ctx **ctx)
-{
-	(*ctx)->failed = TRUE;
-	(void)mailbox_list_index_sync_commit(ctx);
-}
-
-static bool mailbox_list_index_need_compress(struct mailbox_list_index *index)
-{
-	uoff_t max_del_space;
-
-	max_del_space = index->hdr->used_space / 100 *
-		MAILBOX_LIST_COMPRESS_PERCENTAGE;
-	if (index->hdr->deleted_space >= max_del_space &&
-	    index->hdr->used_space >= MAILBOX_LIST_COMPRESS_MIN_SIZE)
-		return TRUE;
-
-	return FALSE;
-}
-
-static int mailbox_list_copy_to_mem_all(struct mailbox_list_index_sync_ctx *ctx,
-					struct mailbox_list_sync_dir *dir)
-{
-	struct mailbox_list_sync_record *recs;
-	unsigned int i, count;
-
-	/* mark the directories as new */
-	dir->offset = 0;
-	dir->new_records_count = 1;
-
-	recs = array_get_modifiable(&dir->records, &count);
-	for (i = 0; i < count; i++) {
-		recs[i].created = TRUE;
-		recs[i].seen = TRUE;
-
-		if (recs[i].dir == NULL) {
-			if (recs[i].dir_offset == 0)
-				continue;
-
-			if (mailbox_list_copy_sync_dir(ctx, recs[i].dir_offset,
-						       &recs[i].dir) < 0)
-				return -1;
-		}
-		recs[i].dir_offset = 0;
-
-		if (mailbox_list_copy_to_mem_all(ctx, recs[i].dir) < 0)
-			return -1;
-	}
-	return 0;
-}
-
-static int mailbox_list_index_compress(struct mailbox_list_index_sync_ctx *ctx)
-{
-	/* first read everything to memory */
-	if (mailbox_list_copy_to_mem_all(ctx, ctx->root) < 0)
-		return -1;
-
-	/* truncate the index file */
-	mailbox_list_index_file_close(ctx->index);
-	if (mailbox_list_index_file_create(ctx->index,
-					   ctx->hdr.uid_validity) < 0)
-		return -1;
-
-	/* reset header */
-	ctx->hdr.file_seq++;
-	ctx->hdr.used_space = sizeof(ctx->hdr);
-	ctx->hdr.deleted_space = 0;
-
-	/* and write everything back */
-	return mailbox_list_index_sync_write(ctx);
-}
--- a/src/lib-index/mailbox-list-index.c	Tue Feb 08 01:35:45 2011 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,770 +0,0 @@
-/* Copyright (c) 2006-2010 Dovecot authors, see the included COPYING file */
-
-#include "lib.h"
-#include "array.h"
-#include "crc32.h"
-#include "ioloop.h"
-#include "str.h"
-#include "file-cache.h"
-#include "file-dotlock.h"
-#include "mmap-util.h"
-#include "write-full.h"
-#include "nfs-workarounds.h"
-#include "mail-index-private.h"
-#include "mailbox-list-index-private.h"
-
-#include <stdlib.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <sys/stat.h>
-
-struct mailbox_list_iter_path {
-	const struct mailbox_list_dir_record *dir;
-	unsigned int pos;
-	unsigned int name_path_len;
-};
-
-struct mailbox_list_index_view {
-	struct mailbox_list_index *index;
-	struct mail_index_view *mail_view;
-};
-
-struct mailbox_list_iter_ctx {
-	struct mailbox_list_index_view *view;
-	unsigned int recurse_level;
-	uint32_t max_uid;
-
-	struct mailbox_list_iter_path cur;
-	ARRAY_DEFINE(path, struct mailbox_list_iter_path);
-	string_t *name_path;
-
-	unsigned int failed:1;
-};
-
-static const struct dotlock_settings default_dotlock_set = {
-	.timeout = 60,
-	.stale_timeout = 30
-};
-
-int mailbox_list_index_set_syscall_error(struct mailbox_list_index *index,
-					 const char *function)
-{
-	i_error("%s failed with file %s: %m", function, index->filepath);
-	return -1;
-}
-
-static void mailbox_list_index_unmap(struct mailbox_list_index *index)
-{
-	if (index->file_cache != NULL)
-		file_cache_invalidate(index->file_cache, 0, (uoff_t)-1);
-
-	if (index->mmap_base != NULL) {
-		if (munmap(index->mmap_base, index->mmap_size) < 0)
-			mailbox_list_index_set_syscall_error(index, "munmap()");
-		index->mmap_base = NULL;
-	}
-	index->const_mmap_base = NULL;
-	index->mmap_size = 0;
-
-	index->hdr = NULL;
-}
-
-void mailbox_list_index_file_close(struct mailbox_list_index *index)
-{
-	mailbox_list_index_unmap(index);
-
-	if (index->file_cache != NULL)
-		file_cache_free(&index->file_cache);
-	if (index->fd != -1) {
-		if (close(index->fd) < 0)
-			mailbox_list_index_set_syscall_error(index, "close()");
-		index->fd = -1;
-	}
-}
-
-int mailbox_list_index_set_corrupted(struct mailbox_list_index *index,
-				     const char *str)
-{
-	if (!index->mail_index->readonly)
-		(void)unlink(index->filepath);
-	mailbox_list_index_file_close(index);
-
-	i_error("Corrupted mailbox list index file %s: %s",
-		index->filepath, str);
-	return -1;
-}
-
-static int
-mailbox_list_index_check_header(struct mailbox_list_index *index,
-				const struct mailbox_list_index_header *hdr)
-{
-	if (hdr->major_version != MAILBOX_LIST_INDEX_MAJOR_VERSION)
-		return -1;
-
-	if (hdr->header_size < sizeof(*hdr)) {
-		return mailbox_list_index_set_corrupted(index,
-			"header_size is too small");
-	}
-	if (hdr->header_size > index->mmap_size) {
-		return mailbox_list_index_set_corrupted(index,
-			"header_size is too large");
-	}
-
-	if (hdr->uid_validity == 0) {
-		return mailbox_list_index_set_corrupted(index,
-							"uid_validity is 0");
-	}
-	if (hdr->next_uid == 0)
-		return mailbox_list_index_set_corrupted(index, "next_uid is 0");
-
-	if (index->mail_index->map == NULL) {
-		/* index already marked as corrupted */
-		return -1;
-	}
-	return 0;
-}
-
-int mailbox_list_index_map(struct mailbox_list_index *index)
-{
-	const struct mailbox_list_index_header *hdr;
-	struct stat st;
-	ssize_t ret;
-
-	mailbox_list_index_unmap(index);
-
-	if (!index->mmap_disable) {
-		if (fstat(index->fd, &st) < 0) {
-			mailbox_list_index_set_syscall_error(index, "fstat()");
-			return -1;
-		}
-	}
-
-	if (!index->mmap_disable &&
-	    st.st_size >= MAILBOX_LIST_INDEX_MMAP_MIN_SIZE) {
-		index->mmap_size = st.st_size;
-		index->mmap_base = mmap(NULL, index->mmap_size,
-					PROT_READ | PROT_WRITE,
-					MAP_SHARED, index->fd, 0);
-		if (index->mmap_base == MAP_FAILED) {
-			index->mmap_base = NULL;
-			mailbox_list_index_set_syscall_error(index, "mmap()");
-			return -1;
-		}
-
-		index->const_mmap_base = index->mmap_base;
-	} else {
-		if (index->file_cache == NULL)
-			index->file_cache = file_cache_new(index->fd);
-
-		ret = file_cache_read(index->file_cache, 0, SSIZE_T_MAX);
-		if (ret < 0) {
-			mailbox_list_index_set_syscall_error(index,
-				"file_cache_read()");
-			return -1;
-		}
-		index->const_mmap_base = file_cache_get_map(index->file_cache,
-							    &index->mmap_size);
-	}
-
-	if (index->mmap_size < sizeof(*hdr)) {
-		mailbox_list_index_set_corrupted(index, "File too small");
-		index->const_mmap_base = NULL;
-		return 0;
-	}
-
-	hdr = index->const_mmap_base;
-	if (mailbox_list_index_check_header(index, hdr) < 0) {
-		index->const_mmap_base = NULL;
-		return 0;
-	}
-
-	index->hdr = hdr;
-	return 1;
-}
-
-static int mailbox_list_index_map_area(struct mailbox_list_index *index,
-				       uoff_t offset, size_t size)
-{
-	if (offset < index->mmap_size && size <= index->mmap_size - offset)
-		return 1;
-
-	if (mailbox_list_index_map(index) <= 0)
-		return -1;
-
-	if (offset < index->mmap_size && size <= index->mmap_size - offset)
-		return 1;
-	/* outside the file */
-	return 0;
-}
-
-static void
-mailbox_list_index_init_header(struct mailbox_list_index *index,
-			       struct mailbox_list_index_header *hdr,
-			       uint32_t uid_validity)
-{
-	memset(hdr, 0, sizeof(*hdr));
-	hdr->major_version = MAILBOX_LIST_INDEX_MAJOR_VERSION;
-	hdr->minor_version = MAILBOX_LIST_INDEX_MINOR_VERSION;
-
-	hdr->file_seq = index->hdr == NULL ? 1 : index->hdr->file_seq + 1;
-	hdr->header_size = sizeof(*hdr);
-	hdr->used_space = hdr->header_size;
-
-	hdr->uid_validity = uid_validity;
-	hdr->next_uid = 1;
-}
-
-static int mailbox_list_index_is_recreated(struct mailbox_list_index *index)
-{
-	struct stat st1, st2;
-
-	if (index->fd == -1)
-		return 1;
-
-	if ((index->mail_index->flags & MAIL_INDEX_OPEN_FLAG_NFS_FLUSH) != 0)
-		nfs_flush_file_handle_cache(index->filepath);
-
-	if (nfs_safe_stat(index->filepath, &st1) < 0) {
-		if (errno == ENOENT || errno == ESTALE)
-			return 1;
-
-		mailbox_list_index_set_syscall_error(index, "stat()");
-		return -1;
-	}
-	if (fstat(index->fd, &st2) < 0) {
-		if (errno == ESTALE)
-			return 1;
-		mailbox_list_index_set_syscall_error(index, "fstat()");
-		return -1;
-	}
-
-	return st1.st_ino != st2.st_ino ||
-		!CMP_DEV_T(st1.st_dev, st2.st_dev);
-}
-
-int mailbox_list_index_file_create(struct mailbox_list_index *index,
-				   uint32_t uid_validity)
-{
-	struct mailbox_list_index_header hdr;
-	struct dotlock *dotlock;
-	int fd, ret;
-
-	fd = file_dotlock_open(&index->dotlock_set, index->filepath,
-			       0, &dotlock);
-	if (fd == -1) {
-		mailbox_list_index_set_syscall_error(index,
-						     "file_dotlock_open()");
-		return -1;
-	}
-
-	if (index->fd != -1) {
-		/* if the file has been recreated by someone else,
-		   retry opening it */
-		ret = mailbox_list_index_is_recreated(index);
-		if (ret != 0) {
-			(void)file_dotlock_delete(&dotlock);
-			return ret < 0 ? -1 : 0;
-		}
-	}
-
-	mailbox_list_index_init_header(index, &hdr, uid_validity);
-	if (write_full(fd, &hdr, sizeof(hdr)) < 0) {
-		mailbox_list_index_set_syscall_error(index, "write_full()");
-		(void)file_dotlock_delete(&dotlock);
-		return -1;
-	}
-
-	if (index->mail_index->fsync_mode == FSYNC_MODE_ALWAYS &&
-	    fdatasync(fd) < 0) {
-		mailbox_list_index_set_syscall_error(index, "fdatasync()");
-		(void)file_dotlock_delete(&dotlock);
-		return -1;
-	}
-
-	if (file_dotlock_replace(&dotlock,
-				 DOTLOCK_REPLACE_FLAG_DONT_CLOSE_FD) < 0) {
-		mailbox_list_index_set_syscall_error(index,
-						     "file_dotlock_replace()");
-		(void)close(fd);
-		return -1;
-	}
-
-	if (index->fd != -1)
-		mailbox_list_index_file_close(index);
-	index->fd = fd;
-
-	ret = mailbox_list_index_map(index);
-	if (ret == 0) {
-		i_error("Self-created mailbox list index file %s was corrupted",
-			index->filepath);
-		return -1;
-	}
-	return ret;
-}
-
-static int
-mailbox_list_index_file_try_open_or_create(struct mailbox_list_index *index)
-{
-	int ret;
-
-	i_assert(index->fd == -1);
-
-	index->fd = open(index->filepath, O_RDWR);
-	if (index->fd == -1) {
-		if (errno != ENOENT) {
-			mailbox_list_index_set_syscall_error(index, "open()");
-			return -1;
-		}
-	} else {
-		ret = mailbox_list_index_map(index);
-		if (ret != 0) {
-			if (ret < 0)
-				mailbox_list_index_file_close(index);
-			return ret;
-		}
-	}
-
-	ret = mailbox_list_index_file_create(index, ioloop_time);
-	if (ret <= 0)
-		mailbox_list_index_file_close(index);
-	return ret;
-}
-
-int mailbox_list_index_open_or_create(struct mailbox_list_index *index)
-{
-	int ret;
-
-	while ((ret = mailbox_list_index_file_try_open_or_create(index)) == 0) {
-		/* file was recreated by someone else, try reopening */
-	}
-	return ret < 0 ? -1 : 0;
-}
-
-struct mailbox_list_index *
-mailbox_list_index_alloc(const char *path, char separator,
-			 struct mail_index *mail_index)
-{
-	struct mailbox_list_index *index;
-
-	index = i_new(struct mailbox_list_index, 1);
-	index->filepath = i_strdup(path);
-	index->separator = separator;
-	index->mail_index = mail_index;
-	index->fd = -1;
-	index->mmap_disable =
-		(mail_index->flags & MAIL_INDEX_OPEN_FLAG_MMAP_DISABLE) != 0;
-	index->dotlock_set = default_dotlock_set;
-	index->dotlock_set.use_excl_lock =
-		(mail_index->flags & MAIL_INDEX_OPEN_FLAG_DOTLOCK_USE_EXCL) != 0;
-	index->dotlock_set.nfs_flush =
-		(mail_index->flags & MAIL_INDEX_OPEN_FLAG_NFS_FLUSH) != 0;
-	return index;
-}
-
-void mailbox_list_index_free(struct mailbox_list_index **_index)
-{
-	struct mailbox_list_index *index = *_index;
-
-	*_index = NULL;
-
-	mailbox_list_index_file_close(index);
-	i_free(index->filepath);
-	i_free(index);
-}
-
-struct mailbox_list_index_lookup_key {
-	uint32_t name_hash;
-
-	struct mailbox_list_index *index;
-	const char *name;
-
-	bool *failed;
-};
-
-static int
-mailbox_list_get_name(struct mailbox_list_index *index, pool_t pool,
-		      const struct mailbox_list_record *rec,
-		      const char **name_r)
-{
-	size_t max_len;
-	const char *name;
-
-	if (rec->name_offset >= index->mmap_size) {
-		mailbox_list_index_set_corrupted(index, t_strdup_printf(
-			"record name_offset (%u) points outside file "
-			"(%"PRIuSIZE_T")", rec->name_offset, index->mmap_size));
-		return -1;
-	}
-	max_len = index->mmap_size - rec->name_offset;
-	name = CONST_PTR_OFFSET(index->const_mmap_base, rec->name_offset);
-	/* get name length. don't bother checking if it's not NUL-terminated,
-	   because practically it always is even if the file is corrupted.
-	   just make sure we don't crash if it happens. */
-	*name_r = p_strndup(pool, name, max_len);
-	if (*name_r == '\0') {
-		mailbox_list_index_set_corrupted(index, "Empty mailbox name");
-		return -1;
-	}
-	return 0;
-}
-
-int mailbox_list_index_get_dir(struct mailbox_list_index_view *view,
-			       uint32_t *offset,
-			       const struct mailbox_list_dir_record **dir_r)
-{
-	struct mailbox_list_index *index = view->index;
-	const struct mailbox_list_dir_record *dir;
-	uint32_t next_offset, cur_offset = *offset;
-	int ret;
-
-	i_assert(index->mmap_size > 0);
-
-	do {
-		ret = mailbox_list_index_map_area(index, cur_offset,
-						  sizeof(*dir));
-		if (ret <= 0) {
-			if (ret < 0)
-				return -1;
-			return mailbox_list_index_set_corrupted(index,
-				"dir_offset points outside file");
-		}
-		if ((cur_offset % 4) != 0) {
-			return mailbox_list_index_set_corrupted(index,
-				"dir_offset not 32bit aligned");
-		}
-
-		dir = CONST_PTR_OFFSET(index->const_mmap_base, cur_offset);
-		next_offset = mail_index_offset_to_uint32(dir->next_offset);
-		if (next_offset != 0 && next_offset <= cur_offset) {
-			return mailbox_list_index_set_corrupted(index,
-				"next_offset points backwards");
-		}
-
-		if (dir->count >
-		    index->mmap_size / sizeof(struct mailbox_list_record)) {
-			return mailbox_list_index_set_corrupted(index,
-				"dir count too large");
-		}
-		if (dir->dir_size < sizeof(*dir) +
-		    dir->count * sizeof(struct mailbox_list_record)) {
-			return mailbox_list_index_set_corrupted(index,
-				"dir_size is smaller than record count");
-		}
-		cur_offset = next_offset;
-	} while (cur_offset != 0);
-
-	cur_offset = (const char *)dir - (const char *)index->const_mmap_base;
-	ret = mailbox_list_index_map_area(index, cur_offset, dir->dir_size);
-	if (ret <= 0) {
-		if (ret < 0)
-			return -1;
-		return mailbox_list_index_set_corrupted(index,
-			"dir points outside file");
-	}
-
-	*offset = cur_offset;
-	*dir_r = dir;
-	return 0;
-}
-
-static int mailbox_list_record_cmp(const void *_key, const void *_rec)
-{
-	const struct mailbox_list_index_lookup_key *key = _key;
-	const struct mailbox_list_record *rec = _rec;
-	int ret;
-
-	if (key->name_hash < rec->name_hash)
-		return -1;
-	if (key->name_hash > rec->name_hash)
-		return 1;
-
-	T_BEGIN {
-		const char *name;
-
-		if (mailbox_list_get_name(key->index, unsafe_data_stack_pool,
-					  rec, &name) < 0) {
-			*key->failed = TRUE;
-			ret = 0;
-		} else {
-			ret = strcmp(key->name, name);
-		}
-	} T_END;
-	return ret;
-}
-
-int mailbox_list_index_dir_lookup_rec(struct mailbox_list_index *index,
-				      const struct mailbox_list_dir_record *dir,
-				      const char *name,
-				      const struct mailbox_list_record **rec_r)
-{
-	const struct mailbox_list_record *rec;
-	struct mailbox_list_index_lookup_key key;
-	bool failed = FALSE;
-
-	/* binary search the current hierarchy level name. the values are
-	   sorted primarily by their hash value and secondarily by the actual
-	   name */
-	memset(&key, 0, sizeof(key));
-	key.index = index;
-	key.name = name;
-	key.name_hash = crc32_str(name);
-	key.failed = &failed;
-
-	rec = bsearch(&key, MAILBOX_LIST_RECORDS(dir), dir->count, sizeof(*rec),
-		      mailbox_list_record_cmp);
-	if (failed)
-		return -1;
-	if (rec == NULL)
-		return 0;
-
-	*rec_r = rec;
-	return 1;
-}
-
-static int
-mailbox_list_index_lookup_rec(struct mailbox_list_index_view *view,
-			      uint32_t dir_offset, const char *name,
-			      const struct mailbox_list_record **rec_r)
-{
-	struct mailbox_list_index *index = view->index;
-	const struct mailbox_list_dir_record *dir;
-	const char *p, *hier_name;
-	int ret;
-
-	if (dir_offset == sizeof(*index->hdr) &&
-	    index->mmap_size <= sizeof(*index->hdr)) {
-		/* root doesn't exist in the file yet */
-		return 0;
-	}
-
-	if (mailbox_list_index_get_dir(view, &dir_offset, &dir) < 0)
-		return -1;
-
-	p = strchr(name, index->separator);
-	hier_name = p == NULL ? name : t_strdup_until(name, p);
-
-	ret = mailbox_list_index_dir_lookup_rec(index, dir, hier_name, rec_r);
-	if (ret <= 0)
-		return ret;
-
-	if (p == NULL) {
-		/* found it */
-		return 1;
-	}
-
-	/* recurse to children */
-	dir_offset = mail_index_offset_to_uint32((*rec_r)->dir_offset);
-	if (dir_offset == 0)
-		return 0;
-
-	return mailbox_list_index_lookup_rec(view, dir_offset, p + 1, rec_r);
-}
-
-int mailbox_list_index_refresh(struct mailbox_list_index *index)
-{
-	int ret;
-
-	if ((ret = mailbox_list_index_is_recreated(index)) <= 0) {
-		if (ret < 0)
-			return -1;
-
-		if (mailbox_list_index_map(index) < 0)
-			ret = -1;
-		return ret;
-	}
-
-	mailbox_list_index_file_close(index);
-	return mailbox_list_index_open_or_create(index);
-}
-
-int mailbox_list_index_view_init(struct mailbox_list_index *index,
-				 struct mail_index_view *mail_view,
-				 struct mailbox_list_index_view **view_r)
-{
-	struct mailbox_list_index_view *view;
-	const struct mail_index_header *mail_hdr;
-
-	mail_hdr = mail_view != NULL ? mail_index_get_header(mail_view) : NULL;
-	if (mail_hdr != NULL && mail_hdr->uid_validity != 0 &&
-	    index->hdr != NULL &&
-	    mail_hdr->uid_validity != index->hdr->uid_validity) {
-		mail_index_set_error(index->mail_index,
-			"uid_validity mismatch in file %s: %u != %u",
-			index->filepath, index->hdr->uid_validity,
-			mail_hdr->uid_validity);
-		return -1;
-	}
-
-	view = *view_r = i_new(struct mailbox_list_index_view, 1);
-	view->index = index;
-	view->mail_view = mail_view;
-	return 0;
-}
-
-void mailbox_list_index_view_deinit(struct mailbox_list_index_view **_view)
-{
-	struct mailbox_list_index_view *view = *_view;
-
-	*_view = NULL;
-	i_free(view);
-}
-
-int mailbox_list_index_lookup(struct mailbox_list_index_view *view,
-			      const char *name, uint32_t *uid_r)
-{
-	const struct mailbox_list_record *rec;
-	uint32_t offset = sizeof(*view->index->hdr);
-	int ret;
-
-	ret = mailbox_list_index_lookup_rec(view, offset, name, &rec);
-	if (ret == 0) {
-		/* not found, see if it's found after a refresh */
-		if ((ret = mailbox_list_index_refresh(view->index)) <= 0)
-			return ret;
-
-		ret = mailbox_list_index_lookup_rec(view, offset, name, &rec);
-	}
-
-	*uid_r = ret <= 0 ? 0 : rec->uid;
-	return ret;
-}
-
-struct mailbox_list_iter_ctx *
-mailbox_list_index_iterate_init(struct mailbox_list_index_view *view,
-				const char *path, int recurse_level)
-{
-	struct mailbox_list_iter_ctx *ctx;
-	const struct mail_index_header *mail_hdr;
-	const struct mailbox_list_record *rec;
-	uint32_t offset = sizeof(*view->index->hdr);
-	int ret;
-
-	ctx = i_new(struct mailbox_list_iter_ctx, 1);
-	ctx->view = view;
-	ctx->recurse_level = recurse_level < 0 ? (unsigned int)-1 :
-		(unsigned int)recurse_level;
-	ctx->name_path = str_new(default_pool, 512);
-
-	if (view->mail_view != NULL) {
-		mail_hdr = mail_index_get_header(view->mail_view);
-		ctx->max_uid = mail_hdr->next_uid - 1;
-	} else {
-		ctx->max_uid = (uint32_t)-1;
-	}
-
-	if (mailbox_list_index_refresh(view->index) < 0)
-		ctx->failed = TRUE;
-	if (!ctx->failed && *path != '\0') {
-		ret = mailbox_list_index_lookup_rec(view, offset, path, &rec);
-		if (ret < 0)
-			ctx->failed = TRUE;
-		else {
-			offset = ret == 0 ? 0 :
-				mail_index_offset_to_uint32(rec->dir_offset);
-		}
-	}
-
-	if (view->index->mmap_size <= sizeof(*view->index->hdr)) {
-		/* root doesn't exist */
-	} else if (!ctx->failed && offset != 0) {
-		if (mailbox_list_index_get_dir(view, &offset,
-					       &ctx->cur.dir) < 0)
-			ctx->failed = TRUE;
-	}
-	i_array_init(&ctx->path, I_MIN(ctx->recurse_level, 16));
-	return ctx;
-}
-
-int mailbox_list_index_iterate_next(struct mailbox_list_iter_ctx *ctx,
-				    struct mailbox_list_index_info *info_r)
-{
-	const struct mailbox_list_iter_path *cur;
-	const struct mailbox_list_record *recs;
-	uint32_t dir_offset;
-	unsigned int count;
-
-	if (ctx->failed)
-		return -1;
-
-	if (ctx->cur.dir == NULL) {
-		/* no mailboxes */
-		i_assert(array_count(&ctx->path) == 0);
-		return 0;
-	}
-
-	for (;;) {
-		if (ctx->cur.pos == ctx->cur.dir->count) {
-			count = array_count(&ctx->path);
-			if (count == 0) {
-				/* we're done */
-				return 0;
-			}
-
-			/* go back to parent path */
-			cur = array_idx(&ctx->path, count-1);
-			ctx->cur = *cur;
-			array_delete(&ctx->path, count-1, 1);
-
-			ctx->cur.pos++;
-		} else {
-			recs = MAILBOX_LIST_RECORDS(ctx->cur.dir);
-			recs += ctx->cur.pos;
-
-			if (!recs->deleted && recs->uid <= ctx->max_uid)
-				break;
-
-			ctx->cur.pos++;
-		}
-	}
-
-	T_BEGIN {
-		const char *name;
-
-		if (mailbox_list_get_name(ctx->view->index,
-					  unsafe_data_stack_pool,
-					  recs, &name) < 0)
-			ctx->failed = TRUE;
-		else {
-			str_truncate(ctx->name_path, ctx->cur.name_path_len);
-			if (ctx->cur.name_path_len > 0) {
-				str_append_c(ctx->name_path,
-					     ctx->view->index->separator);
-			}
-			str_append(ctx->name_path, name);
-		}
-	} T_END;
-	if (ctx->failed)
-		return -1;
-
-	info_r->name = str_c(ctx->name_path);
-	info_r->uid = recs->uid;
-
-	dir_offset = mail_index_offset_to_uint32(recs->dir_offset);
-	if (dir_offset != 0 && array_count(&ctx->path) < ctx->recurse_level) {
-		/* recurse into children */
-		array_append(&ctx->path, &ctx->cur, 1);
-
-		ctx->cur.name_path_len = str_len(ctx->name_path);
-		ctx->cur.pos = 0;
-		if (mailbox_list_index_get_dir(ctx->view, &dir_offset,
-					       &ctx->cur.dir) < 0) {
-			ctx->failed = TRUE;
-			return -1;
-		}
-		recs = NULL; /* don't use anymore */
-	} else {
-		ctx->cur.pos++;
-	}
-	info_r->has_children = dir_offset != 0;
-	return 1;
-}
-
-void mailbox_list_index_iterate_deinit(struct mailbox_list_iter_ctx **_ctx)
-{
-	struct mailbox_list_iter_ctx *ctx = *_ctx;
-
-	*_ctx = NULL;
-	array_free(&ctx->path);
-	str_free(&ctx->name_path);
-	i_free(ctx);
-}
--- a/src/lib-index/mailbox-list-index.h	Tue Feb 08 01:35:45 2011 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,88 +0,0 @@
-#ifndef MAILBOX_LIST_INDEX_H
-#define MAILBOX_LIST_INDEX_H
-
-struct mailbox_list_index_view;
-struct mailbox_list_index_sync_ctx;
-
-/* Mailbox list index contains UID <-> mailbox name mapping. It also takes in
-   a mail_index index which contains UID -> metadata information for the
-   mailboxes. The mmap, in-memory and lock settings are taken from the
-   mail_index. */
-
-enum mailbox_list_index_flags {
-	/* Mailbox has children. They may not be indexed however, so
-	   mailbox_list_index_info.has_children=FALSE is possible. */
-	MAILBOX_LIST_INDEX_FLAG_CHILDREN	= 0x01,
-	/* Mailbox has no children. mailbox_list_index_info.has_children
-	   should be FALSE. */
-	MAILBOX_LIST_INDEX_FLAG_NOCHILDREN	= 0x02,
-	/* The mailbox isn't selectable (eg. a directory) */
-	MAILBOX_LIST_INDEX_FLAG_NOSELECT	= 0x04,
-	/* The mailbox doesn't exist at all. This is only a placeholder for
-	   a child mailbox. When the children are deleted, this mailbox will
-	   be automatically deleted as well. */
-	MAILBOX_LIST_INDEX_FLAG_NONEXISTENT	= 0x08
-};
-
-
-enum mailbox_list_sync_flags {
-	/* All the child mailboxes are also being synced */
-	MAILBOX_LIST_SYNC_FLAG_RECURSIVE	= 0x01,
-	/* New mailboxes may be added, but none are removed */
-	MAILBOX_LIST_SYNC_FLAG_PARTIAL		= 0x02
-};
-
-struct mailbox_list_index_info {
-	const char *name;
-	uint32_t uid;
-	bool has_children;
-};
-
-struct mailbox_list_index *
-mailbox_list_index_alloc(const char *path, char separator,
-			 struct mail_index *mail_index);
-void mailbox_list_index_free(struct mailbox_list_index **index);
-
-/* Open or create mailbox list index. */
-int mailbox_list_index_open_or_create(struct mailbox_list_index *index);
-
-/* Synchronize the index with the backend. */
-int mailbox_list_index_sync_init(struct mailbox_list_index *index,
-				 const char *path,
-				 enum mailbox_list_sync_flags flags,
-				 struct mailbox_list_index_sync_ctx **ctx_r);
-struct mail_index_view *
-mailbox_list_index_sync_get_view(struct mailbox_list_index_sync_ctx *ctx);
-struct mail_index_transaction *
-mailbox_list_index_sync_get_transaction(struct mailbox_list_index_sync_ctx*ctx);
-int mailbox_list_index_sync_more(struct mailbox_list_index_sync_ctx *ctx,
-				 const char *name, uint32_t *seq_r);
-int mailbox_list_index_sync_commit(struct mailbox_list_index_sync_ctx **ctx);
-void mailbox_list_index_sync_rollback(struct mailbox_list_index_sync_ctx **ctx);
-
-/* Mailbox list index and mail index must be kept in sync, so lookups and
-   iterations must know the mail index view. The mail_view can be set to NULL
-   to use the latest changes. Returns -1 if uidvalidity doesn't match. */
-int mailbox_list_index_view_init(struct mailbox_list_index *index,
-				 struct mail_index_view *mail_view,
-				 struct mailbox_list_index_view **view_r);
-void mailbox_list_index_view_deinit(struct mailbox_list_index_view **view);
-
-/* Get mailbox UID for a given name. Returns 1 if found, 0 if not,
-   -1 if error */
-int mailbox_list_index_lookup(struct mailbox_list_index_view *view,
-			      const char *name, uint32_t *uid_r);
-
-/* Iterate through all the mailboxes. If recurse_level is -1, all the child
-   mailboxes are returned, otherwise it's the number of levels to return
-   (0 = only the mailboxes directly under the path). Returned mailbox names
-   are allocated from name_pool. */
-struct mailbox_list_iter_ctx *
-mailbox_list_index_iterate_init(struct mailbox_list_index_view *view,
-				const char *path, int recurse_level);
-/* Returns 1 if mailbox was returned, 0 at the end of iteration, -1 if error */
-int mailbox_list_index_iterate_next(struct mailbox_list_iter_ctx *ctx,
-				    struct mailbox_list_index_info *info_r);
-void mailbox_list_index_iterate_deinit(struct mailbox_list_iter_ctx **ctx);
-
-#endif
--- a/src/util/Makefile.am	Tue Feb 08 01:35:45 2011 +0200
+++ b/src/util/Makefile.am	Tue Feb 08 01:36:19 2011 +0200
@@ -6,7 +6,6 @@
 	script-login \
 	$(TCPWRAP_BIN) \
 	gdbhelper \
-	listview \
 	maildirlock
 
 AM_CPPFLAGS = \
@@ -52,11 +51,6 @@
 gdbhelper_SOURCES = \
 	gdbhelper.c
 
-listview_LDADD = $(LIBDOVECOT)
-listview_DEPENDENCIES = $(LIBDOVECOT_DEPS)
-listview_SOURCES = \
-	listview.c
-
 maildirlock_LDADD = $(LIBDOVECOT)
 maildirlock_DEPENDENCIES = $(LIBDOVECOT_DEPS)
 maildirlock_SOURCES = \
--- a/src/util/listview.c	Tue Feb 08 01:35:45 2011 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,149 +0,0 @@
-/* Copyright (c) 2007-2010 Dovecot authors, see the included COPYING file */
-
-#include "lib.h"
-#include "crc32.h"
-#include "mail-index.h"
-#include "mailbox-list-index-private.h"
-
-#include <stdio.h>
-#include <stdlib.h>
-
-static struct mailbox_list_index_header hdr;
-
-static uint32_t mail_index_offset_to_uint32(uint32_t offset)
-{
-	const unsigned char *buf = (const unsigned char *) &offset;
-
-	if ((offset & 0x80808080) != 0x80808080)
-		return 0;
-
-	return (((uint32_t)buf[3] & 0x7f) << 2) |
-		(((uint32_t)buf[2] & 0x7f) << 9) |
-		(((uint32_t)buf[1] & 0x7f) << 16) |
-		(((uint32_t)buf[0] & 0x7f) << 23);
-}
-
-static void dump_hdr(int fd)
-{
-	int ret;
-
-	ret = read(fd, &hdr, sizeof(hdr));
-	if (ret != sizeof(hdr)) {
-		i_fatal("file hdr read() %d != %"PRIuSIZE_T"\n",
-			ret, sizeof(hdr));
-	}
-
-	printf("version = %u.%u\n", hdr.major_version, hdr.minor_version);
-	printf("header size = %u\n", hdr.header_size);
-	printf("uid validity = %u\n", hdr.uid_validity);
-	printf("file seq = %u\n", hdr.file_seq);
-	printf("next uid = %u\n", hdr.next_uid);
-	printf("used space = %u\n", hdr.used_space);
-	printf("deleted space = %u\n", hdr.deleted_space);
-}
-
-static void dump_dir(int fd, unsigned int show_offset, const char *path)
-{
-	struct mailbox_list_dir_record dir;
-	struct mailbox_list_record rec;
-	off_t offset;
-	char name[1024];
-	unsigned int i;
-	int ret;
-
-	offset = lseek(fd, 0, SEEK_CUR);
-	ret = read(fd, &dir, sizeof(dir));
-	if (ret == 0) {
-		if (*path != '\0')
-			i_fatal("unexpected EOF when reading dir");
-		return;
-	}
-
-	if (ret != sizeof(dir))
-		i_fatal("dir read() %d != %"PRIuSIZE_T, ret, sizeof(dir));
-
-	dir.next_offset = mail_index_offset_to_uint32(dir.next_offset);
-	printf("%s: DIR: offset=%"PRIuUOFF_T" next_offset=%u count=%u dir_size=%u\n",
-	       path, offset, dir.next_offset, dir.count, dir.dir_size);
-
-	if (dir.next_offset != 0 && dir.next_offset != show_offset) {
-		lseek(fd, dir.next_offset, SEEK_SET);
-		dump_dir(fd, show_offset, path);
-		return;
-	}
-
-	offset += sizeof(dir);
-	for (i = 0; i < dir.count; i++) {
-		lseek(fd, offset, SEEK_SET);
-		ret = read(fd, &rec, sizeof(rec));
-		if (ret == 0)
-			i_fatal("unexpected EOF, %d/%d records", i, dir.count);
-
-		if (ret != sizeof(rec)) {
-			i_fatal("rec read() %d != %"PRIuSIZE_T,
-				ret, sizeof(rec));
-		}
-		rec.dir_offset = mail_index_offset_to_uint32(rec.dir_offset);
-
-		ret = pread(fd, name, sizeof(name)-1, rec.name_offset);
-		name[ret < 0 ? 0 : ret] = '\0';
-
-		printf("%s%s: offset=%"PRIuUOFF_T" uid=%u "
-		       "name_offset=%u name_hash=%u", path, name, offset,
-		       rec.uid, rec.name_offset, rec.name_hash);
-
-		if (rec.deleted != 0)
-			printf(" deleted=%u", rec.deleted);
-		if (rec.dir_offset != 0)
-			printf(" dir_offset=%u", rec.dir_offset);
-		printf("\n");
-
-		if (ret <= 0)
-			printf("%s%s: - invalid name_offset", path, name);
-		else if (strlen(name) == (size_t)ret) {
-			printf("%s%s: - name missing NUL terminator",
-			       path, name);
-		}
-
-		if (crc32_str(name) != rec.name_hash) {
-			printf("%s%s: - invalid name hash %u vs %u\n",
-			       path, name, crc32_str(name), rec.name_hash);
-		}
-
-		if (rec.dir_offset != 0) T_BEGIN {
-			const char *new_path;
-
-			lseek(fd, rec.dir_offset, SEEK_SET);
-			if (*path == '\0')
-				new_path = t_strdup_printf("%s/", name);
-			else
-				new_path = t_strdup_printf("%s%s/", path, name);
-			dump_dir(fd, show_offset, new_path);
-		} T_END;
-
-		offset += sizeof(rec);
-	}
-}
-
-int main(int argc ATTR_UNUSED, const char *argv[])
-{
-	int fd;
-
-	lib_init();
-
-	fd = open(argv[1], O_RDONLY);
-	if (fd < 0) {
-		i_error("open(): %m");
-		return 1;
-	}
-
-	printf("-- LIST INDEX: %s\n", argv[1]);
-
-	dump_hdr(fd);
-	lseek(fd, hdr.header_size, SEEK_SET);
-
-	printf("---------------\n");
-
-	dump_dir(fd, argv[2] == NULL ? 0 : atoi(argv[2]), "");
-	return 0;
-}