]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
removed out of the way of new index code
authorTimo Sirainen <tss@iki.fi>
Tue, 27 Apr 2004 20:14:15 +0000 (23:14 +0300)
committerTimo Sirainen <tss@iki.fi>
Tue, 27 Apr 2004 20:14:15 +0000 (23:14 +0300)
--HG--
branch : HEAD

35 files changed:
src/lib-index/mail-cache.c [deleted file]
src/lib-index/mail-cache.h [deleted file]
src/lib-index/mail-custom-flags.c [deleted file]
src/lib-index/mail-custom-flags.h [deleted file]
src/lib-index/mail-index-file.c [deleted file]
src/lib-index/mail-index-fsck.c [deleted file]
src/lib-index/mail-index-open.c [deleted file]
src/lib-index/mail-index-rebuild.c [deleted file]
src/lib-index/mail-index-util.c [deleted file]
src/lib-index/mail-index-util.h [deleted file]
src/lib-index/mail-index.c [deleted file]
src/lib-index/mail-index.h [deleted file]
src/lib-index/mail-modifylog.c [deleted file]
src/lib-index/mail-modifylog.h [deleted file]
src/lib-index/maildir/maildir-build.c [deleted file]
src/lib-index/maildir/maildir-clean.c [deleted file]
src/lib-index/maildir/maildir-expunge.c [deleted file]
src/lib-index/maildir/maildir-index.c [deleted file]
src/lib-index/maildir/maildir-index.h [deleted file]
src/lib-index/maildir/maildir-open.c [deleted file]
src/lib-index/maildir/maildir-sync.c [deleted file]
src/lib-index/maildir/maildir-uidlist.c [deleted file]
src/lib-index/maildir/maildir-uidlist.h [deleted file]
src/lib-index/maildir/maildir-update-flags.c [deleted file]
src/lib-index/mbox/istream-mbox.c [deleted file]
src/lib-index/mbox/mbox-append.c [deleted file]
src/lib-index/mbox/mbox-from.c [deleted file]
src/lib-index/mbox/mbox-index.c [deleted file]
src/lib-index/mbox/mbox-index.h [deleted file]
src/lib-index/mbox/mbox-lock.c [deleted file]
src/lib-index/mbox/mbox-lock.h [deleted file]
src/lib-index/mbox/mbox-open.c [deleted file]
src/lib-index/mbox/mbox-rewrite.c [deleted file]
src/lib-index/mbox/mbox-sync-full.c [deleted file]
src/lib-index/mbox/mbox-sync.c [deleted file]

diff --git a/src/lib-index/mail-cache.c b/src/lib-index/mail-cache.c
deleted file mode 100644 (file)
index 098b3bd..0000000
+++ /dev/null
@@ -1,1940 +0,0 @@
-/* Copyright (C) 2003 Timo Sirainen */
-
-#include "lib.h"
-#include "buffer.h"
-#include "byteorder.h"
-#include "file-lock.h"
-#include "file-set-size.h"
-#include "ioloop.h"
-#include "mmap-util.h"
-#include "write-full.h"
-#include "mail-index.h"
-#include "mail-index-util.h"
-#include "mail-cache.h"
-
-#include <stddef.h>
-#include <unistd.h>
-#include <sys/stat.h>
-
-/* Never compress the file if it's smaller than this */
-#define COMPRESS_MIN_SIZE (1024*50)
-
-/* Compress the file when deleted space reaches n% of total size */
-#define COMPRESS_PERCENTAGE 20
-
-/* Compress the file when n% of rows contain continued rows.
-   200% means that there's 2 continued rows per record. */
-#define COMPRESS_CONTINUED_PERCENTAGE 200
-
-/* Initial size for the file */
-#define MAIL_CACHE_INITIAL_SIZE (sizeof(struct mail_cache_header) + 10240)
-
-/* When more space is needed, grow the file n% larger than the previous size */
-#define MAIL_CACHE_GROW_PERCENTAGE 10
-
-#define MAIL_CACHE_LOCK_TIMEOUT 120
-#define MAIL_CACHE_LOCK_CHANGE_TIMEOUT 60
-#define MAIL_CACHE_LOCK_IMMEDIATE_TIMEOUT (5*60)
-
-#define CACHE_RECORD(cache, offset) \
-       ((struct mail_cache_record *) ((char *) (cache)->mmap_base + offset))
-
-struct mail_cache_header {
-       uint32_t indexid;
-       uint32_t sync_id;
-
-       uint32_t continued_record_count;
-
-       uint32_t used_file_size;
-       uint32_t deleted_space;
-
-       uint32_t used_fields; /* enum mail_cache_field */
-
-       uint32_t field_usage_start; /* time_t */
-       uint32_t field_usage_counts[32];
-
-       uint32_t header_offsets[MAIL_CACHE_HEADERS_COUNT];
-};
-
-struct mail_cache_record {
-       uint32_t fields; /* enum mail_cache_field */
-       uint32_t next_offset;
-       uint32_t size; /* full record size, including this header */
-};
-
-struct mail_cache {
-       struct mail_index *index;
-
-       char *filepath;
-       int fd;
-
-       void *mmap_base;
-       size_t mmap_length;
-       uint32_t used_file_size;
-       uint32_t sync_id;
-
-       struct mail_cache_header *header;
-
-       pool_t split_header_pool;
-       uint32_t split_offsets[MAIL_CACHE_HEADERS_COUNT];
-       const char *const *split_headers[MAIL_CACHE_HEADERS_COUNT];
-
-       enum mail_cache_field default_cache_fields;
-       enum mail_cache_field never_cache_fields;
-
-        struct mail_cache_transaction_ctx *trans_ctx;
-       unsigned int locks;
-
-       unsigned int anon_mmap:1;
-       unsigned int mmap_refresh:1;
-       unsigned int silent:1;
-};
-
-struct mail_cache_transaction_ctx {
-       struct mail_cache *cache;
-
-       unsigned int next_unused_header_lowwater;
-
-       unsigned int last_idx;
-       struct mail_cache_record cache_rec;
-       buffer_t *cache_data;
-
-       unsigned int first_uid, last_uid, prev_uid;
-       enum mail_cache_field prev_fields;
-       buffer_t *index_marks, *cache_marks;
-};
-
-unsigned int mail_cache_field_sizes[32] = {
-       sizeof(enum mail_index_record_flag),
-       sizeof(uoff_t),
-       16,
-       sizeof(struct mail_sent_date),
-       sizeof(time_t),
-       sizeof(uoff_t),
-       sizeof(uoff_t),
-
-       0, 0, 0, 0, 0,
-
-       /* variable sized */
-       (unsigned int)-1, (unsigned int)-1, (unsigned int)-1, (unsigned int)-1,
-       (unsigned int)-1, (unsigned int)-1, (unsigned int)-1, (unsigned int)-1,
-       (unsigned int)-1, (unsigned int)-1, (unsigned int)-1, (unsigned int)-1,
-       (unsigned int)-1, (unsigned int)-1, (unsigned int)-1, (unsigned int)-1,
-       (unsigned int)-1, (unsigned int)-1, (unsigned int)-1, (unsigned int)-1
-};
-
-enum mail_cache_field mail_cache_header_fields[MAIL_CACHE_HEADERS_COUNT] = {
-       MAIL_CACHE_HEADERS1,
-       MAIL_CACHE_HEADERS2,
-       MAIL_CACHE_HEADERS3,
-       MAIL_CACHE_HEADERS4
-};
-
-static const unsigned char *null4[] = { 0, 0, 0, 0 };
-
-static const char *
-mail_cache_get_header_fields_str(struct mail_cache *cache, unsigned int idx);
-static int mail_cache_write(struct mail_cache_transaction_ctx *ctx);
-static struct mail_cache_record *
-mail_cache_lookup(struct mail_cache *cache,
-                 const struct mail_index_record *rec,
-                 enum mail_cache_field fields);
-
-static uint32_t uint32_to_offset(uint32_t offset)
-{
-       unsigned char buf[4];
-
-       i_assert(offset < 0x40000000);
-       i_assert((offset & 3) == 0);
-
-       offset >>= 2;
-       buf[0] = 0x80 | ((offset & 0x0fe00000) >> 21);
-       buf[1] = 0x80 | ((offset & 0x001fc000) >> 14);
-       buf[2] = 0x80 | ((offset & 0x00003f80) >> 7);
-       buf[3] = 0x80 |  (offset & 0x0000007f);
-       return *((uint32_t *) buf);
-}
-
-static uint32_t 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 int mail_cache_set_syscall_error(struct mail_cache *cache,
-                                       const char *function)
-{
-       i_assert(function != NULL);
-
-       if (ENOSPACE(errno)) {
-               cache->index->nodiskspace = TRUE;
-               return FALSE;
-       }
-
-       index_set_error(cache->index, "%s failed with index cache file %s: %m",
-                       function, cache->filepath);
-       return FALSE;
-}
-
-static int mail_cache_create_memory(struct mail_cache *cache,
-                                   struct mail_cache_header *hdr)
-{
-       cache->mmap_length = MAIL_CACHE_INITIAL_SIZE;
-       cache->mmap_base = mmap_anon(cache->mmap_length);
-       if (cache->mmap_base == MAP_FAILED) {
-               index_set_error(cache->index, "mmap_anon(%"PRIuSIZE_T")",
-                               cache->mmap_length);
-               return FALSE;
-       }
-
-       cache->header = cache->mmap_base;
-       *cache->header = *hdr;
-
-       cache->anon_mmap = TRUE;
-       cache->filepath = i_strdup_printf("(in-memory index cache for %s)",
-                                         cache->index->mailbox_path);
-       return TRUE;
-}
-
-static void mail_cache_file_close(struct mail_cache *cache)
-{
-       if (cache->anon_mmap) {
-               if (munmap_anon(cache->mmap_base, cache->mmap_length) < 0)
-                       mail_cache_set_syscall_error(cache, "munmap_anon()");
-       } else if (cache->mmap_base != NULL) {
-               if (munmap(cache->mmap_base, cache->mmap_length) < 0)
-                       mail_cache_set_syscall_error(cache, "munmap()");
-       }
-
-       cache->mmap_base = NULL;
-       cache->header = NULL;
-       cache->mmap_length = 0;
-
-       if (cache->fd != -1) {
-               if (close(cache->fd) < 0)
-                       mail_cache_set_syscall_error(cache, "close()");
-               cache->fd = -1;
-       }
-}
-
-static int mail_cache_file_reopen(struct mail_cache *cache)
-{
-       int fd;
-
-       if (cache->anon_mmap) {
-               /* cache was set corrupted, we'll have to quit */
-               return FALSE;
-       }
-
-       fd = open(cache->filepath, O_RDWR);
-       if (fd == -1)
-               return mail_cache_set_syscall_error(cache, "open()");
-
-       mail_cache_file_close(cache);
-
-       cache->fd = fd;
-       return TRUE;
-}
-
-static int mmap_verify_header(struct mail_cache *cache)
-{
-       struct mail_cache_header *hdr;
-
-       /* check that the header is still ok */
-       if (cache->mmap_length < sizeof(struct mail_cache_header))
-               return mail_cache_set_corrupted(cache, "File too small");
-       cache->header = hdr = cache->mmap_base;
-       cache->sync_id = hdr->sync_id;
-
-       if (cache->header->indexid != cache->index->indexid) {
-               /* index id changed */
-               if (cache->header->indexid != 0)
-                       mail_cache_set_corrupted(cache, "indexid changed");
-               cache->index->inconsistent = TRUE; /* easiest way to rebuild */
-               return FALSE;
-       }
-
-       if (cache->trans_ctx != NULL) {
-               /* we've updated used_file_size, do nothing */
-               return TRUE;
-       }
-
-       cache->used_file_size = nbo_to_uint32(hdr->used_file_size);
-
-       /* only check the header if we're locked */
-       if (cache->locks == 0)
-               return TRUE;
-
-       if (cache->used_file_size < sizeof(struct mail_cache_header)) {
-               mail_cache_set_corrupted(cache, "used_file_size too small");
-               return FALSE;
-       }
-       if ((cache->used_file_size % sizeof(uint32_t)) != 0) {
-               mail_cache_set_corrupted(cache, "used_file_size not aligned");
-               return FALSE;
-       }
-
-       if (cache->used_file_size > cache->mmap_length) {
-               /* maybe a crash truncated the file - just fix it */
-               hdr->used_file_size = uint32_to_nbo(cache->mmap_length & ~3);
-               if (msync(cache->mmap_base, sizeof(*hdr), MS_SYNC) < 0) 
-                       return mail_cache_set_syscall_error(cache, "msync()");
-       }
-       return TRUE;
-}
-
-static int mmap_update_nocheck(struct mail_cache *cache,
-                              size_t offset, size_t size)
-{
-       struct stat st;
-
-       /* if sync id has changed, the file has to be reopened.
-          note that if main index isn't locked, it may change again */
-       if (cache->sync_id != cache->index->cache_sync_id &&
-           cache->mmap_base != NULL) {
-               if (!mail_cache_file_reopen(cache))
-                       return -1;
-       }
-
-       if (offset < cache->mmap_length &&
-           size <= cache->mmap_length - offset &&
-           !cache->mmap_refresh) {
-               /* already mapped */
-               if (size != 0 || cache->anon_mmap)
-                       return 1;
-
-               /* requesting the whole file - see if we need to
-                  re-mmap */
-               if (fstat(cache->fd, &st) < 0) {
-                       mail_cache_set_syscall_error(cache, "fstat()");
-                       return -1;
-               }
-               if ((uoff_t)st.st_size == cache->mmap_length)
-                       return 1;
-       }
-       cache->mmap_refresh = FALSE;
-
-       if (cache->anon_mmap)
-               return 1;
-
-       if (cache->mmap_base != NULL) {
-               if (cache->locks != 0) {
-                       /* in the middle of transaction - write the changes */
-                       if (msync(cache->mmap_base, cache->mmap_length,
-                                 MS_SYNC) < 0) {
-                               mail_cache_set_syscall_error(cache, "msync()");
-                               return -1;
-                       }
-               }
-
-               if (munmap(cache->mmap_base, cache->mmap_length) < 0)
-                       mail_cache_set_syscall_error(cache, "munmap()");
-       }
-
-       i_assert(cache->fd != -1);
-
-       /* map the whole file */
-       cache->header = NULL;
-       cache->mmap_length = 0;
-
-       cache->mmap_base = mmap_rw_file(cache->fd, &cache->mmap_length);
-       if (cache->mmap_base == MAP_FAILED) {
-               cache->mmap_base = NULL;
-               mail_cache_set_syscall_error(cache, "mmap()");
-               return -1;
-       }
-
-       /* re-mmaped, check header */
-       return 0;
-}
-
-static int mmap_update(struct mail_cache *cache, size_t offset, size_t size)
-{
-       int synced, ret;
-
-       for (synced = FALSE;; synced = TRUE) {
-               ret = mmap_update_nocheck(cache, offset, size);
-               if (ret > 0)
-                       return TRUE;
-               if (ret < 0)
-                       return FALSE;
-
-               if (!mmap_verify_header(cache))
-                       return FALSE;
-
-               /* see if cache file was rebuilt - do it only once to avoid
-                  infinite looping */
-               if (cache->header->sync_id == cache->index->cache_sync_id ||
-                   synced)
-                       break;
-
-               if (!mail_cache_file_reopen(cache))
-                       return FALSE;
-       }
-       return TRUE;
-}
-
-static int mail_cache_open_and_verify(struct mail_cache *cache, int silent)
-{
-       struct stat st;
-
-       mail_cache_file_close(cache);
-
-       cache->fd = open(cache->filepath, O_RDWR);
-       if (cache->fd == -1) {
-               if (errno == ENOENT)
-                       return 0;
-
-               mail_cache_set_syscall_error(cache, "open()");
-               return -1;
-       }
-
-       if (fstat(cache->fd, &st) < 0) {
-               mail_cache_set_syscall_error(cache, "fstat()");
-               return -1;
-       }
-
-       if (st.st_size < sizeof(struct mail_cache_header))
-               return 0;
-
-       cache->mmap_refresh = TRUE;
-       if (mmap_update_nocheck(cache, 0, sizeof(struct mail_cache_header)) < 0)
-               return -1;
-
-       /* verify that this really is the cache for wanted index */
-       cache->silent = silent;
-       if (!mmap_verify_header(cache)) {
-               cache->silent = FALSE;
-               return 0;
-       }
-
-       cache->silent = FALSE;
-       return 1;
-}
-
-static void mail_index_clear_cache_offsets(struct mail_index *index)
-{
-       struct mail_index_record *rec;
-
-       index->sync_stamp = 0;
-
-       rec = index->lookup(index, 1);
-       while (rec != NULL) {
-               rec->cache_offset = 0;
-               rec = index->next(index, rec);
-       }
-}
-
-static int mail_cache_open_or_create_file(struct mail_cache *cache,
-                                         struct mail_cache_header *hdr)
-{
-       int ret, fd;
-
-       cache->filepath = i_strconcat(cache->index->filepath,
-                                     MAIL_CACHE_FILE_PREFIX, NULL);
-
-       ret = mail_cache_open_and_verify(cache, FALSE);
-       if (ret != 0)
-               return ret > 0;
-
-       /* we'll have to clear cache_offsets which requires exclusive lock */
-       cache->index->inconsistent = FALSE;
-       if (!mail_index_set_lock(cache->index, MAIL_LOCK_EXCLUSIVE))
-               return FALSE;
-
-       /* maybe a rebuild.. */
-       fd = file_dotlock_open(cache->filepath, NULL, MAIL_CACHE_LOCK_TIMEOUT,
-                              MAIL_CACHE_LOCK_CHANGE_TIMEOUT,
-                              MAIL_CACHE_LOCK_IMMEDIATE_TIMEOUT, NULL, NULL);
-       if (fd == -1) {
-               mail_cache_set_syscall_error(cache, "file_dotlock_open()");
-               return FALSE;
-       }
-
-       /* see if someone else just created the cache file */
-       ret = mail_cache_open_and_verify(cache, TRUE);
-       if (ret != 0) {
-               (void)file_dotlock_delete(cache->filepath, fd);
-               return ret > 0;
-       }
-
-       /* rebuild then */
-       if (write_full(fd, hdr, sizeof(*hdr)) < 0) {
-               mail_cache_set_syscall_error(cache, "write_full()");
-               (void)file_dotlock_delete(cache->filepath, fd);
-               return FALSE;
-       }
-       if (file_set_size(fd, MAIL_CACHE_INITIAL_SIZE) < 0) {
-               mail_cache_set_syscall_error(cache, "file_set_size()");
-               (void)file_dotlock_delete(cache->filepath, fd);
-               return FALSE;
-       }
-
-       mail_index_clear_cache_offsets(cache->index);
-
-       mail_cache_file_close(cache);
-       cache->fd = dup(fd);
-
-       if (file_dotlock_replace(cache->filepath, fd, FALSE) < 0) {
-               mail_cache_set_syscall_error(cache, "file_dotlock_replace()");
-               return FALSE;
-       }
-
-       cache->mmap_refresh = TRUE;
-       if (!mmap_update(cache, 0, sizeof(struct mail_cache_header)))
-               return FALSE;
-
-       return TRUE;
-}
-
-int mail_cache_open_or_create(struct mail_index *index)
-{
-        struct mail_cache_header hdr;
-       struct mail_cache *cache;
-
-       memset(&hdr, 0, sizeof(hdr));
-       hdr.indexid = index->indexid;
-       hdr.sync_id = index->cache_sync_id;
-       hdr.used_file_size = uint32_to_nbo(sizeof(hdr));
-
-       cache = i_new(struct mail_cache, 1);
-       cache->index = index;
-       cache->fd = -1;
-        cache->split_header_pool = pool_alloconly_create("Headers", 512);
-
-       index->cache = cache;
-
-       /* we'll do anon-mmaping only if initially requested. if we fail
-          because of out of disk space, we'll just let the main index code
-          know it and fail. */
-       if (INDEX_IS_IN_MEMORY(index)) {
-               if (!mail_cache_create_memory(cache, &hdr)) {
-                       mail_cache_free(cache);
-                       return FALSE;
-               }
-       } else {
-               if (!mail_cache_open_or_create_file(cache, &hdr)) {
-                       mail_cache_free(cache);
-                       return FALSE;
-               }
-       }
-
-       /* unset inconsistency - we already rebuilt the cache file */
-       index->inconsistent = FALSE;
-
-       return TRUE;
-}
-
-void mail_cache_free(struct mail_cache *cache)
-{
-       i_assert(cache->trans_ctx == NULL);
-
-       cache->index->cache = NULL;
-
-       mail_cache_file_close(cache);
-
-       pool_unref(cache->split_header_pool);
-       i_free(cache->filepath);
-       i_free(cache);
-}
-
-void mail_cache_set_defaults(struct mail_cache *cache,
-                            enum mail_cache_field default_cache_fields,
-                            enum mail_cache_field never_cache_fields)
-{
-       cache->default_cache_fields = default_cache_fields;
-       cache->never_cache_fields = never_cache_fields;
-}
-
-static const struct mail_cache_record *
-mail_cache_compress_record(struct mail_cache *cache,
-                          struct mail_index_record *rec, int header_idx,
-                          uint32_t *size_r)
-{
-       enum mail_cache_field orig_cached_fields, cached_fields, field;
-       struct mail_cache_record cache_rec;
-       buffer_t *buffer;
-       const void *data;
-       size_t size, pos;
-       uint32_t nb_size;
-       int i;
-
-       memset(&cache_rec, 0, sizeof(cache_rec));
-       buffer = buffer_create_dynamic(pool_datastack_create(),
-                                      4096, (size_t)-1);
-
-        orig_cached_fields = mail_cache_get_fields(cache, rec);
-       cached_fields = orig_cached_fields & ~MAIL_CACHE_HEADERS_MASK;
-       buffer_append(buffer, &cache_rec, sizeof(cache_rec));
-       for (i = 0, field = 1; i < 31; i++, field <<= 1) {
-               if ((cached_fields & field) == 0)
-                       continue;
-
-               if (!mail_cache_lookup_field(cache, rec, field, &data, &size)) {
-                       cached_fields &= ~field;
-                       continue;
-               }
-
-               nb_size = uint32_to_nbo((uint32_t)size);
-
-               if ((field & MAIL_CACHE_FIXED_MASK) == 0)
-                       buffer_append(buffer, &nb_size, sizeof(nb_size));
-               buffer_append(buffer, data, size);
-               if ((size & 3) != 0)
-                       buffer_append(buffer, null4, 4 - (size & 3));
-       }
-
-       /* now merge all the headers if we have them all */
-       if ((orig_cached_fields & mail_cache_header_fields[header_idx]) != 0) {
-               nb_size = 0;
-               pos = buffer_get_used_size(buffer);
-               buffer_append(buffer, &nb_size, sizeof(nb_size));
-
-               for (i = 0; i <= header_idx; i++) {
-                       field = mail_cache_header_fields[i];
-                       if (mail_cache_lookup_field(cache, rec, field,
-                                                   &data, &size) && size > 1) {
-                               size--; /* terminating \0 */
-                               buffer_append(buffer, data, size);
-                               nb_size += size;
-                       }
-               }
-               buffer_append(buffer, "", 1);
-               nb_size++;
-               if ((nb_size & 3) != 0)
-                       buffer_append(buffer, null4, 4 - (nb_size & 3));
-
-               nb_size = uint32_to_nbo(nb_size);
-               buffer_write(buffer, pos, &nb_size, sizeof(nb_size));
-
-               cached_fields |= MAIL_CACHE_HEADERS1;
-       }
-
-       cache_rec.fields = cached_fields;
-       cache_rec.size = uint32_to_nbo(buffer_get_used_size(buffer));
-       buffer_write(buffer, 0, &cache_rec, sizeof(cache_rec));
-
-       data = buffer_get_data(buffer, &size);
-       *size_r = size;
-       return data;
-}
-
-static int mail_cache_copy(struct mail_cache *cache, int fd)
-{
-       struct mail_cache_header *hdr;
-       const struct mail_cache_record *cache_rec;
-       struct mail_index_record *rec;
-        enum mail_cache_field used_fields;
-       unsigned char *mmap_base;
-       const char *str;
-       uint32_t new_file_size, offset, size, nb_size;
-       int i, header_idx;
-
-       /* pick some reasonably good file size */
-       new_file_size = cache->used_file_size -
-               nbo_to_uint32(cache->header->deleted_space);
-       new_file_size = (new_file_size + 1023) & ~1023;
-       if (new_file_size < MAIL_CACHE_INITIAL_SIZE)
-               new_file_size = MAIL_CACHE_INITIAL_SIZE;
-
-       if (file_set_size(fd, new_file_size) < 0)
-               return mail_cache_set_syscall_error(cache, "file_set_size()");
-
-       mmap_base = mmap(NULL, new_file_size, PROT_READ | PROT_WRITE,
-                        MAP_SHARED, fd, 0);
-       if (mmap_base == MAP_FAILED)
-               return mail_cache_set_syscall_error(cache, "mmap()");
-
-       /* skip file's header */
-       hdr = (struct mail_cache_header *) mmap_base;
-       offset = sizeof(*hdr);
-
-       /* merge all the header pieces into one. if some message doesn't have
-          all the required pieces, we'll just have to drop them all. */
-       for (i = MAIL_CACHE_HEADERS_COUNT-1; i >= 0; i--) {
-               str = mail_cache_get_header_fields_str(cache, i);
-               if (str != NULL)
-                       break;
-       }
-
-       if (str == NULL)
-               header_idx = -1;
-       else {
-               hdr->header_offsets[0] = uint32_to_offset(offset);
-               header_idx = i;
-
-               size = strlen(str) + 1;
-               nb_size = uint32_to_nbo(size);
-
-               memcpy(mmap_base + offset, &nb_size, sizeof(nb_size));
-               offset += sizeof(nb_size);
-               memcpy(mmap_base + offset, str, size);
-               offset += (size + 3) & ~3;
-       }
-
-       used_fields = 0;
-       rec = cache->index->lookup(cache->index, 1);
-       while (rec != NULL) {
-               cache_rec = mail_cache_lookup(cache, rec, 0);
-               if (cache_rec == NULL)
-                       rec->cache_offset = 0;
-               else if (offset_to_uint32(cache_rec->next_offset) == 0) {
-                       /* just one unmodified block, copy it */
-                       size = nbo_to_uint32(cache_rec->size);
-                       i_assert(offset + size <= new_file_size);
-
-                       memcpy(mmap_base + offset, cache_rec, size);
-                       rec->cache_offset = uint32_to_offset(offset);
-
-                       size = (size + 3) & ~3;
-                       offset += size;
-               } else {
-                       /* multiple blocks, sort them into buffer */
-                       t_push();
-                       cache_rec = mail_cache_compress_record(cache, rec,
-                                                              header_idx,
-                                                              &size);
-                       i_assert(offset + size <= new_file_size);
-                       memcpy(mmap_base + offset, cache_rec, size);
-                       used_fields |= cache_rec->fields;
-                       t_pop();
-
-                       rec->cache_offset = uint32_to_offset(offset);
-                       offset += size;
-               }
-
-               rec = cache->index->next(cache->index, rec);
-       }
-
-       /* update header */
-       hdr->indexid = cache->index->indexid;
-       hdr->sync_id = cache->sync_id = cache->index->cache_sync_id =
-               ++cache->index->header->cache_sync_id;
-       hdr->used_file_size = uint32_to_nbo(offset);
-       hdr->used_fields = used_fields;
-       hdr->field_usage_start = uint32_to_nbo(ioloop_time);
-
-       /* write everything to disk */
-       if (msync(mmap_base, offset, MS_SYNC) < 0)
-               return mail_cache_set_syscall_error(cache, "msync()");
-
-       if (munmap(mmap_base, new_file_size) < 0)
-               return mail_cache_set_syscall_error(cache, "munmap()");
-
-       if (fdatasync(fd) < 0)
-               return mail_cache_set_syscall_error(cache, "fdatasync()");
-       return TRUE;
-}
-
-int mail_cache_compress(struct mail_cache *cache)
-{
-       int fd, ret = TRUE;
-
-       i_assert(cache->trans_ctx == NULL);
-
-       if (cache->anon_mmap)
-               return TRUE;
-
-       if (!cache->index->set_lock(cache->index, MAIL_LOCK_EXCLUSIVE))
-               return FALSE;
-
-       if (mail_cache_lock(cache, TRUE) <= 0)
-               return FALSE;
-
-#ifdef DEBUG
-       i_warning("Compressing cache file %s", cache->filepath);
-#endif
-
-       fd = file_dotlock_open(cache->filepath, NULL, MAIL_CACHE_LOCK_TIMEOUT,
-                              MAIL_CACHE_LOCK_CHANGE_TIMEOUT,
-                              MAIL_CACHE_LOCK_IMMEDIATE_TIMEOUT, NULL, NULL);
-       if (fd == -1) {
-               mail_cache_set_syscall_error(cache, "file_dotlock_open()");
-               return FALSE;
-       }
-
-       /* now we'll begin the actual moving. keep rebuild-flag on
-          while doing it. */
-       cache->index->header->flags |= MAIL_INDEX_HDR_FLAG_REBUILD;
-       if (!mail_index_fmdatasync(cache->index, cache->index->header_size))
-               return FALSE;
-
-       if (!mail_cache_copy(cache, fd)) {
-               (void)file_dotlock_delete(cache->filepath, fd);
-               ret = FALSE;
-       } else {
-               mail_cache_file_close(cache);
-               cache->fd = dup(fd);
-
-               if (file_dotlock_replace(cache->filepath, fd, FALSE) < 0) {
-                       mail_cache_set_syscall_error(cache,
-                                                    "file_dotlock_replace()");
-                       ret = FALSE;
-               }
-
-               if (!mmap_update(cache, 0, 0))
-                       ret = FALSE;
-       }
-
-       /* headers could have changed, reread them */
-       memset(cache->split_offsets, 0, sizeof(cache->split_offsets));
-       memset(cache->split_headers, 0, sizeof(cache->split_headers));
-
-       if (ret) {
-               cache->index->header->flags &=
-                       ~(MAIL_INDEX_HDR_FLAG_REBUILD |
-                         MAIL_INDEX_HDR_FLAG_COMPRESS_CACHE);
-       }
-
-       if (!mail_cache_unlock(cache))
-               ret = FALSE;
-
-       return ret;
-}
-
-int mail_cache_truncate(struct mail_cache *cache)
-{
-       struct mail_cache_header hdr;
-       int ret, fd;
-
-       i_assert(cache->index->lock_type == MAIL_LOCK_EXCLUSIVE);
-
-       memset(&hdr, 0, sizeof(hdr));
-       hdr.indexid = cache->index->indexid;
-       hdr.sync_id = cache->sync_id = cache->index->cache_sync_id =
-               ++cache->index->header->cache_sync_id;
-       hdr.used_file_size = uint32_to_nbo(sizeof(hdr));
-       cache->used_file_size = sizeof(hdr);
-
-       if (cache->anon_mmap) {
-               *cache->header = hdr;
-               return TRUE;
-       }
-
-       ret = mail_cache_open_and_verify(cache, TRUE);
-       if (ret != 0)
-               return ret > 0;
-
-       fd = file_dotlock_open(cache->filepath, NULL, MAIL_CACHE_LOCK_TIMEOUT,
-                              MAIL_CACHE_LOCK_CHANGE_TIMEOUT,
-                              MAIL_CACHE_LOCK_IMMEDIATE_TIMEOUT, NULL, NULL);
-       if (fd == -1) {
-               mail_cache_set_syscall_error(cache, "file_dotlock_open()");
-               return FALSE;
-       }
-
-       if (write_full(fd, &hdr, sizeof(hdr)) < 0) {
-               mail_cache_set_syscall_error(cache, "write_full()");
-               (void)file_dotlock_delete(cache->filepath, fd);
-               return FALSE;
-       }
-       if (file_set_size(fd, MAIL_CACHE_INITIAL_SIZE) < 0) {
-               mail_cache_set_syscall_error(cache, "file_set_size()");
-               (void)file_dotlock_delete(cache->filepath, fd);
-               return FALSE;
-       }
-
-       mail_cache_file_close(cache);
-       cache->fd = dup(fd);
-
-       if (file_dotlock_replace(cache->filepath, fd, FALSE) < 0) {
-               mail_cache_set_syscall_error(cache, "file_dotlock_replace()");
-               return FALSE;
-       }
-
-       cache->mmap_refresh = TRUE;
-       if (!mmap_update(cache, 0, sizeof(struct mail_cache_header)))
-               return FALSE;
-
-       return TRUE;
-}
-
-int mail_cache_mark_file_deleted(struct mail_cache *cache)
-{
-       uint32_t indexid = 0;
-
-       if (cache->anon_mmap)
-               cache->header->indexid = 0;
-       else {
-               if (pwrite(cache->fd, &indexid, sizeof(indexid), 0) < 0)
-                       return mail_cache_set_syscall_error(cache, "pwrite()");
-       }
-       return TRUE;
-}
-
-int mail_cache_lock(struct mail_cache *cache, int nonblock)
-{
-       int ret;
-
-       if (cache->locks++ != 0)
-               return TRUE;
-
-       if (cache->anon_mmap)
-               return TRUE;
-
-       if (nonblock) {
-               ret = file_try_lock(cache->fd, F_WRLCK);
-               if (ret < 0)
-                       mail_cache_set_syscall_error(cache, "file_try_lock()");
-       } else {
-               ret = file_wait_lock(cache->fd, F_WRLCK);
-               if (ret <= 0)
-                       mail_cache_set_syscall_error(cache, "file_wait_lock()");
-       }
-
-       if (ret > 0) {
-               if (!mmap_update(cache, 0, 0)) {
-                       (void)mail_cache_unlock(cache);
-                       return -1;
-               }
-               if (cache->sync_id != cache->index->cache_sync_id) {
-                       /* we have the cache file locked and sync_id still
-                          doesn't match. it means we crashed between updating
-                          cache file and updating sync_id in index header.
-                          just update the sync_ids so they match. */
-                       i_warning("Updating broken sync_id in cache file %s",
-                                 cache->filepath);
-                       cache->sync_id = cache->header->sync_id =
-                               cache->index->cache_sync_id;
-               }
-       }
-       return ret;
-}
-
-int mail_cache_unlock(struct mail_cache *cache)
-{
-       if (--cache->locks > 0)
-               return TRUE;
-
-       if (cache->anon_mmap)
-               return TRUE;
-
-       if (file_wait_lock(cache->fd, F_UNLCK) <= 0) {
-               mail_cache_set_syscall_error(cache, "file_wait_lock(F_UNLCK)");
-               return FALSE;
-       }
-
-       return TRUE;
-}
-
-void mail_cache_unlock_later(struct mail_cache *cache)
-{
-       cache->index->cache_later_locks++;
-}
-
-int mail_cache_is_locked(struct mail_cache *cache)
-{
-       return cache->locks > 0;
-}
-
-int mail_cache_transaction_begin(struct mail_cache *cache, int nonblock,
-                                struct mail_cache_transaction_ctx **ctx_r)
-{
-       int ret;
-
-       i_assert(cache->trans_ctx == NULL);
-
-       ret = mail_cache_lock(cache, nonblock);
-       if (ret <= 0)
-               return ret;
-
-       *ctx_r = i_new(struct mail_cache_transaction_ctx, 1);
-       (*ctx_r)->cache = cache;
-       (*ctx_r)->cache_data =
-               buffer_create_dynamic(system_pool, 8192, (size_t)-1);
-       (*ctx_r)->last_idx = (unsigned int)-1;
-
-       cache->trans_ctx = *ctx_r;
-       return 1;
-}
-
-int mail_cache_transaction_end(struct mail_cache_transaction_ctx *ctx)
-{
-       int ret = TRUE;
-
-       i_assert(ctx->cache->trans_ctx != NULL);
-
-       (void)mail_cache_transaction_rollback(ctx);
-
-       if (!mail_cache_unlock(ctx->cache))
-               ret = FALSE;
-
-       ctx->cache->trans_ctx = NULL;
-
-       if (ctx->cache_marks != NULL)
-               buffer_free(ctx->cache_marks);
-       if (ctx->index_marks != NULL)
-               buffer_free(ctx->index_marks);
-       buffer_free(ctx->cache_data);
-       i_free(ctx);
-       return ret;
-}
-
-static void mail_cache_transaction_flush(struct mail_cache_transaction_ctx *ctx)
-{
-       memset(&ctx->cache_rec, 0, sizeof(ctx->cache_rec));
-       ctx->last_idx = (unsigned int)-1;
-
-       ctx->next_unused_header_lowwater = 0;
-       ctx->first_uid = ctx->last_uid = ctx->prev_uid = 0;
-       ctx->prev_fields = 0;
-
-       if (ctx->cache_marks != NULL)
-               buffer_set_used_size(ctx->cache_marks, 0);
-       if (ctx->index_marks != NULL)
-               buffer_set_used_size(ctx->index_marks, 0);
-       buffer_set_used_size(ctx->cache_data, 0);
-}
-
-static void mark_update(buffer_t **buf, uint32_t offset, uint32_t data)
-{
-       if (*buf == NULL)
-               *buf = buffer_create_dynamic(system_pool, 1024, (size_t)-1);
-
-       /* data is in big endian, we want to update only the lowest byte */
-       buffer_append(*buf, &offset, sizeof(offset));
-       buffer_append(*buf, &data, sizeof(data));
-}
-
-static int write_mark_updates(struct mail_index *index, buffer_t *marks,
-                             const char *path, int fd)
-{
-       const uint32_t *data, *end;
-       size_t size;
-
-       data = buffer_get_data(marks, &size);
-       end = data + size/sizeof(uint32_t);
-
-       while (data < end) {
-               if (pwrite(fd, data+1, sizeof(*data), data[0]) < 0) {
-                       index_file_set_syscall_error(index, path, "pwrite()");
-                       return FALSE;
-               }
-               data += 2;
-       }
-       return TRUE;
-}
-
-static void write_mark_updates_in_memory(buffer_t *marks, void *mmap_base,
-                                        size_t mmap_length)
-{
-       const unsigned char *data, *end;
-       uint32_t offset;
-       size_t size;
-
-       data = buffer_get_data(marks, &size);
-       end = data + size;
-
-       while (data < end) {
-               memcpy(&offset, data, sizeof(offset));
-               data += sizeof(offset);
-
-               i_assert(offset <= mmap_length - sizeof(uint32_t));
-               memcpy((char *) mmap_base + offset, data, sizeof(uint32_t));
-               data += sizeof(uint32_t);
-       }
-}
-
-static void commit_all_changes_in_memory(struct mail_cache_transaction_ctx *ctx)
-{
-       struct mail_cache *cache = ctx->cache;
-
-       if (ctx->cache_marks != NULL) {
-               write_mark_updates_in_memory(ctx->cache_marks,
-                                            cache->mmap_base,
-                                            cache->mmap_length);
-       }
-       if (ctx->index_marks != NULL) {
-               write_mark_updates_in_memory(ctx->index_marks,
-                                            cache->index->mmap_base,
-                                            cache->index->mmap_used_length);
-       }
-}
-
-static int commit_all_changes(struct mail_cache_transaction_ctx *ctx)
-{
-       struct mail_cache *cache = ctx->cache;
-       uint32_t cont;
-
-       if (ctx->cache->anon_mmap) {
-               commit_all_changes_in_memory(ctx);
-               return TRUE;
-       }
-
-       /* write everything to disk */
-       if (msync(cache->mmap_base, cache->mmap_length, MS_SYNC) < 0)
-               return mail_cache_set_syscall_error(cache, "msync()");
-
-       if (fdatasync(cache->fd) < 0)
-               return mail_cache_set_syscall_error(cache, "fdatasync()");
-
-       if (ctx->cache_marks != NULL &&
-           buffer_get_used_size(ctx->cache_marks) != 0) {
-               /* now that we're sure it's there, set on all the used-bits */
-               if (!write_mark_updates(cache->index, ctx->cache_marks,
-                                       cache->filepath, cache->fd))
-                       return FALSE;
-
-               /* update continued records count */
-               cont = nbo_to_uint32(cache->header->continued_record_count);
-
-               cont += buffer_get_used_size(ctx->cache_marks) /
-                       (sizeof(uint32_t) * 2);
-
-               if (cont * 100 / cache->index->header->messages_count >=
-                   COMPRESS_CONTINUED_PERCENTAGE &&
-                   cache->used_file_size >= COMPRESS_MIN_SIZE) {
-                       /* too many continued rows, compress */
-                       cache->index->set_flags |=
-                               MAIL_INDEX_HDR_FLAG_COMPRESS_CACHE;
-               }
-
-               cache->header->continued_record_count = uint32_to_nbo(cont);
-       }
-
-       /* write index last */
-       if (ctx->index_marks != NULL &&
-           buffer_get_used_size(ctx->index_marks) != 0) {
-               if (!mail_index_fmdatasync(cache->index,
-                                          cache->index->mmap_used_length))
-                       return FALSE;
-
-               if (!write_mark_updates(cache->index, ctx->index_marks,
-                                       cache->index->filepath,
-                                       cache->index->fd))
-                       return FALSE;
-       }
-       return TRUE;
-}
-
-int mail_cache_transaction_commit(struct mail_cache_transaction_ctx *ctx)
-{
-       int ret = TRUE;
-
-       if (ctx->last_idx != (unsigned int)-1) {
-               if (!mail_cache_write(ctx))
-                       return FALSE;
-       }
-
-       ctx->cache->header->used_file_size =
-               uint32_to_nbo(ctx->cache->used_file_size);
-
-       if (!commit_all_changes(ctx))
-               ret = FALSE;
-
-       if (ctx->next_unused_header_lowwater == MAIL_CACHE_HEADERS_COUNT) {
-               /* they're all used - compress the cache to get more */
-               ctx->cache->index->set_flags |=
-                       MAIL_INDEX_HDR_FLAG_COMPRESS_CACHE;
-       }
-
-       mail_cache_transaction_flush(ctx);
-       return ret;
-}
-
-int mail_cache_transaction_rollback(struct mail_cache_transaction_ctx *ctx)
-{
-       struct mail_cache *cache = ctx->cache;
-       unsigned int i;
-
-       /* no need to actually modify the file - we just didn't update
-          used_file_size */
-       cache->used_file_size = nbo_to_uint32(cache->header->used_file_size);
-
-       /* make sure we don't cache the headers */
-       for (i = 0; i < ctx->next_unused_header_lowwater; i++) {
-               if (offset_to_uint32(cache->header->header_offsets[i]) == 0)
-                       cache->split_offsets[i] = 1;
-       }
-
-       mail_cache_transaction_flush(ctx);
-       return TRUE;
-}
-
-static int mail_cache_grow(struct mail_cache *cache, uint32_t size)
-{
-       struct stat st;
-       void *base;
-       uoff_t grow_size, new_fsize;
-
-       new_fsize = cache->used_file_size + size;
-       grow_size = new_fsize / 100 * MAIL_CACHE_GROW_PERCENTAGE;
-       if (grow_size < 16384)
-               grow_size = 16384;
-
-       new_fsize += grow_size;
-       new_fsize &= ~1023;
-
-       if (cache->anon_mmap) {
-               i_assert(new_fsize < SSIZE_T_MAX);
-
-               base = mremap_anon(cache->mmap_base, cache->mmap_length,
-                                  (size_t)new_fsize, MREMAP_MAYMOVE);
-               if (base == MAP_FAILED) {
-                       mail_cache_set_syscall_error(cache, "mremap_anon()");
-                       return FALSE;
-               }
-
-               cache->mmap_base = base;
-               cache->mmap_length = (size_t)new_fsize;
-               cache->header = cache->mmap_base;
-               return TRUE;
-       }
-
-       if (fstat(cache->fd, &st) < 0)
-               return mail_cache_set_syscall_error(cache, "fstat()");
-
-       if (cache->used_file_size + size <= (uoff_t)st.st_size) {
-               /* no need to grow, just update mmap */
-               if (!mmap_update(cache, 0, 0))
-                       return FALSE;
-
-               i_assert(cache->mmap_length >= (uoff_t)st.st_size);
-               return TRUE;
-       }
-
-       if (st.st_size < (off_t)sizeof(struct mail_cache_header))
-               return mail_cache_set_corrupted(cache, "Header is missing");
-
-       if (file_set_size(cache->fd, (off_t)new_fsize) < 0)
-               return mail_cache_set_syscall_error(cache, "file_set_size()");
-
-       return mmap_update(cache, 0, 0);
-}
-
-static uint32_t mail_cache_append_space(struct mail_cache_transaction_ctx *ctx,
-                                       uint32_t size)
-{
-       /* NOTE: must be done within transaction or rollback would break it */
-       uint32_t offset;
-
-       i_assert((size & 3) == 0);
-
-       offset = ctx->cache->used_file_size;
-       if (offset >= 0x40000000) {
-               index_set_error(ctx->cache->index, "Cache file too large: %s",
-                               ctx->cache->filepath);
-               return 0;
-       }
-
-       if (offset + size > ctx->cache->mmap_length) {
-               if (!mail_cache_grow(ctx->cache, size))
-                       return 0;
-       }
-
-       ctx->cache->used_file_size += size;
-       return offset;
-}
-
-static const char *
-mail_cache_get_header_fields_str(struct mail_cache *cache, unsigned int idx)
-{
-       uint32_t offset, data_size;
-       unsigned char *buf;
-
-       offset = offset_to_uint32(cache->header->header_offsets[idx]);
-
-       if (offset == 0)
-               return NULL;
-
-       if (!mmap_update(cache, offset, 1024))
-               return NULL;
-
-       if (offset + sizeof(data_size) > cache->mmap_length) {
-               mail_cache_set_corrupted(cache, "Header %u points outside file",
-                                        idx);
-               return NULL;
-       }
-
-       buf = cache->mmap_base;
-       memcpy(&data_size, buf + offset, sizeof(data_size));
-       data_size = nbo_to_uint32(data_size);
-       offset += sizeof(data_size);
-
-       if (data_size == 0) {
-               mail_cache_set_corrupted(cache,
-                       "Header %u points to empty string", idx);
-               return NULL;
-       }
-
-       if (!mmap_update(cache, offset, data_size))
-               return NULL;
-
-       if (offset + data_size > cache->mmap_length) {
-               mail_cache_set_corrupted(cache, "Header %u points outside file",
-                                        idx);
-               return NULL;
-       }
-
-       buf = cache->mmap_base;
-       if (buf[offset + data_size - 1] != '\0') {
-               mail_cache_set_corrupted(cache,
-                       "Header %u points to invalid string", idx);
-               return NULL;
-       }
-
-       return buf + offset;
-}
-
-static const char *const *
-split_header(struct mail_cache *cache, const char *header)
-{
-       const char *const *arr, *const *tmp;
-       const char *null = NULL;
-       char *str;
-       buffer_t *buf;
-
-       if (header == NULL)
-               return NULL;
-
-       arr = t_strsplit(header, "\n");
-       buf = buffer_create_dynamic(cache->split_header_pool, 32, (size_t)-1);
-       for (tmp = arr; *tmp != NULL; tmp++) {
-               str = p_strdup(cache->split_header_pool, *tmp);
-               buffer_append(buf, &str, sizeof(str));
-       }
-       buffer_append(buf, &null, sizeof(null));
-
-       return buffer_get_data(buf, NULL);
-}
-
-const char *const *mail_cache_get_header_fields(struct mail_cache *cache,
-                                               unsigned int idx)
-{
-       const char *str;
-       int i;
-
-       i_assert(idx < MAIL_CACHE_HEADERS_COUNT);
-
-       /* t_strsplit() is a bit slow, so we cache it */
-       if (cache->header->header_offsets[idx] != cache->split_offsets[idx]) {
-               p_clear(cache->split_header_pool);
-
-               t_push();
-               for (i = 0; i < MAIL_CACHE_HEADERS_COUNT; i++) {
-                       cache->split_offsets[i] =
-                               cache->header->header_offsets[i];
-
-                       str = mail_cache_get_header_fields_str(cache, i);
-                       cache->split_headers[i] = split_header(cache, str);
-               }
-               t_pop();
-       }
-
-       return cache->split_headers[idx];
-}
-
-static const char *write_header_string(const char *const headers[],
-                                      uint32_t *size_r)
-{
-       buffer_t *buffer;
-       size_t size;
-
-       buffer = buffer_create_dynamic(pool_datastack_create(),
-                                      512, (size_t)-1);
-
-       while (*headers != NULL) {
-               if (buffer_get_used_size(buffer) != 0)
-                       buffer_append(buffer, "\n", 1);
-               buffer_append(buffer, *headers, strlen(*headers));
-               headers++;
-       }
-       buffer_append(buffer, null4, 1);
-
-       size = buffer_get_used_size(buffer);
-       if ((size & 3) != 0) {
-               buffer_append(buffer, null4, 4 - (size & 3));
-               size += 4 - (size & 3);
-       }
-       *size_r = size;
-       return buffer_get_data(buffer, NULL);
-}
-
-int mail_cache_set_header_fields(struct mail_cache_transaction_ctx *ctx,
-                                unsigned int idx, const char *const headers[])
-{
-       struct mail_cache *cache = ctx->cache;
-       uint32_t offset, update_offset, size;
-       const char *header_str, *prev_str;
-
-       i_assert(*headers != NULL);
-       i_assert(idx < MAIL_CACHE_HEADERS_COUNT);
-       i_assert(idx >= ctx->next_unused_header_lowwater);
-       i_assert(offset_to_uint32(cache->header->header_offsets[idx]) == 0);
-
-       t_push();
-
-       header_str = write_header_string(headers, &size);
-       if (idx != 0) {
-               prev_str = mail_cache_get_header_fields_str(cache, idx-1);
-               if (prev_str == NULL) {
-                       t_pop();
-                       return FALSE;
-               }
-
-               i_assert(strcmp(header_str, prev_str) != 0);
-       }
-
-       offset = mail_cache_append_space(ctx, size + sizeof(uint32_t));
-       if (offset != 0) {
-               memcpy((char *) cache->mmap_base + offset + sizeof(uint32_t),
-                      header_str, size);
-
-               size = uint32_to_nbo(size);
-               memcpy((char *) cache->mmap_base + offset,
-                      &size, sizeof(uint32_t));
-
-               /* update cached headers */
-               cache->split_offsets[idx] = cache->header->header_offsets[idx];
-               cache->split_headers[idx] = split_header(cache, header_str);
-
-               /* mark used-bit to be updated later. not really needed for
-                  read-safety, but if transaction get rolled back we can't let
-                  this point to invalid location. */
-               update_offset = (char *) &cache->header->header_offsets[idx] -
-                       (char *) cache->mmap_base;
-               mark_update(&ctx->cache_marks, update_offset,
-                           uint32_to_offset(offset));
-
-               /* make sure get_header_fields() still works for this header
-                  while the transaction isn't yet committed. */
-               ctx->next_unused_header_lowwater = idx + 1;
-       }
-
-       t_pop();
-       return offset > 0;
-}
-
-static struct mail_cache_record *
-cache_get_record(struct mail_cache *cache, uint32_t offset)
-{
-#define CACHE_PREFETCH 1024
-       struct mail_cache_record *cache_rec;
-       size_t size;
-
-       offset = offset_to_uint32(offset);
-       if (offset == 0)
-               return NULL;
-
-       if (!mmap_update(cache, offset, sizeof(*cache_rec) + CACHE_PREFETCH))
-               return NULL;
-
-       if (offset + sizeof(*cache_rec) > cache->mmap_length) {
-               mail_cache_set_corrupted(cache, "record points outside file");
-               return NULL;
-       }
-       cache_rec = CACHE_RECORD(cache, offset);
-
-       size = nbo_to_uint32(cache_rec->size);
-       if (size < sizeof(*cache_rec)) {
-               mail_cache_set_corrupted(cache, "invalid record size");
-               return NULL;
-       }
-       if (size > CACHE_PREFETCH) {
-               if (!mmap_update(cache, offset, size))
-                       return NULL;
-       }
-
-       if (offset + size > cache->mmap_length) {
-               mail_cache_set_corrupted(cache, "record points outside file");
-               return NULL;
-       }
-       return cache_rec;
-}
-
-static struct mail_cache_record *
-cache_get_next_record(struct mail_cache *cache, struct mail_cache_record *rec)
-{
-       struct mail_cache_record *next;
-
-       next = cache_get_record(cache, rec->next_offset);
-       if (next != NULL && next <= rec) {
-               mail_cache_set_corrupted(cache, "next_offset points backwards");
-               return NULL;
-       }
-       return next;
-}
-
-static int mail_cache_write(struct mail_cache_transaction_ctx *ctx)
-{
-       struct mail_cache *cache = ctx->cache;
-       struct mail_cache_record *cache_rec, *next;
-       struct mail_index_record *rec;
-       uint32_t write_offset, update_offset;
-       const void *buf;
-       size_t size, buf_size;
-
-       buf = buffer_get_data(ctx->cache_data, &buf_size);
-
-       size = sizeof(*cache_rec) + buf_size;
-       ctx->cache_rec.size = uint32_to_nbo(size);
-
-       write_offset = mail_cache_append_space(ctx, size);
-       if (write_offset == 0)
-               return FALSE;
-
-       rec = INDEX_RECORD_AT(ctx->cache->index, ctx->last_idx);
-       ctx->last_idx = (unsigned int)-1;
-
-       cache_rec = cache_get_record(cache, rec->cache_offset);
-       if (cache_rec == NULL) {
-               /* first cache record - update offset in index file */
-               i_assert(cache->index->lock_type == MAIL_LOCK_EXCLUSIVE);
-
-               /* mark cache_offset to be updated later */
-               update_offset = (char *) &rec->cache_offset -
-                       (char *) cache->index->mmap_base;
-               mark_update(&ctx->index_marks, update_offset,
-                           uint32_to_offset(write_offset));
-       } else {
-               /* find the last cache record */
-               while ((next = cache_get_next_record(cache, cache_rec)) != NULL)
-                       cache_rec = next;
-
-               /* mark next_offset to be updated later */
-               update_offset = (char *) &cache_rec->next_offset -
-                       (char *) cache->mmap_base;
-               mark_update(&ctx->cache_marks, update_offset,
-                           uint32_to_offset(write_offset));
-       }
-
-       memcpy((char *) cache->mmap_base + write_offset,
-              &ctx->cache_rec, sizeof(ctx->cache_rec));
-       memcpy((char *) cache->mmap_base + write_offset +
-              sizeof(ctx->cache_rec), buf, buf_size);
-
-       /* reset the write context */
-       memset(&ctx->cache_rec, 0, sizeof(ctx->cache_rec));
-       buffer_set_used_size(ctx->cache_data, 0);
-       return TRUE;
-}
-
-static struct mail_cache_record *
-mail_cache_lookup(struct mail_cache *cache, const struct mail_index_record *rec,
-                 enum mail_cache_field fields)
-{
-       struct mail_cache_record *cache_rec;
-       unsigned int idx;
-
-       if (cache->trans_ctx != NULL &&
-           cache->trans_ctx->first_uid <= rec->uid &&
-           cache->trans_ctx->last_uid >= rec->uid &&
-           (cache->trans_ctx->prev_uid != rec->uid || fields == 0 ||
-            (cache->trans_ctx->prev_fields & fields) != 0)) {
-               /* we have to auto-commit since we're not capable of looking
-                  into uncommitted records. it would be possible by checking
-                  index_marks and cache_marks, but it's just more trouble
-                  than worth. */
-               idx = INDEX_RECORD_INDEX(cache->index, rec);
-               if (cache->trans_ctx->last_idx == idx) {
-                       if (!mail_cache_write(cache->trans_ctx))
-                               return NULL;
-               }
-
-               if (!mail_cache_transaction_commit(cache->trans_ctx))
-                       return NULL;
-       }
-
-       cache_rec = cache_get_record(cache, rec->cache_offset);
-       if (cache_rec == NULL)
-               return NULL;
-
-       return cache_rec;
-}
-
-static int get_field_num(enum mail_cache_field field)
-{
-       unsigned int mask;
-       int i;
-
-       for (i = 0, mask = 1; i < 31; i++, mask <<= 1) {
-               if ((field & mask) != 0)
-                       return i;
-       }
-
-       return -1;
-}
-
-static size_t get_insert_offset(struct mail_cache_transaction_ctx *ctx,
-                               enum mail_cache_field field)
-{
-       const unsigned char *buf;
-       unsigned int mask;
-       uint32_t data_size;
-       size_t offset = 0;
-       int i;
-
-       buf = buffer_get_data(ctx->cache_data, NULL);
-
-       for (i = 0, mask = 1; i < 31; i++, mask <<= 1) {
-               if ((field & mask) != 0)
-                       return offset;
-
-               if ((ctx->cache_rec.fields & mask) != 0) {
-                       if ((mask & MAIL_CACHE_FIXED_MASK) != 0)
-                               data_size = mail_cache_field_sizes[i];
-                       else {
-                               memcpy(&data_size, buf + offset,
-                                      sizeof(data_size));
-                               data_size = nbo_to_uint32(data_size);
-                               offset += sizeof(data_size);
-                       }
-                       offset += (data_size + 3) & ~3;
-               }
-       }
-
-       i_unreached();
-       return offset;
-}
-
-int mail_cache_add(struct mail_cache_transaction_ctx *ctx,
-                  struct mail_index_record *rec, enum mail_cache_field field,
-                  const void *data, size_t data_size)
-{
-       uint32_t nb_data_size;
-       size_t full_size, offset;
-       unsigned char *buf;
-       unsigned int idx;
-       int field_num;
-
-       i_assert(data_size > 0);
-       i_assert(data_size < (uint32_t)-1);
-
-       nb_data_size = uint32_to_nbo((uint32_t)data_size);
-
-       if ((field & MAIL_CACHE_FIXED_MASK) != 0) {
-               field_num = get_field_num(field);
-               i_assert(field_num != -1);
-               i_assert(mail_cache_field_sizes[field_num] == data_size);
-       } else if ((field & MAIL_CACHE_STRING_MASK) != 0) {
-               i_assert(((char *) data)[data_size-1] == '\0');
-       }
-
-       /* NOTE: we use index because the record pointer might not last. */
-        idx = INDEX_RECORD_INDEX(ctx->cache->index, rec);
-       if (ctx->last_idx != idx && ctx->last_idx != (unsigned int)-1) {
-               if (!mail_cache_write(ctx))
-                       return FALSE;
-       }
-       ctx->last_idx = idx;
-
-       i_assert((ctx->cache_rec.fields & field) == 0);
-
-       full_size = (data_size + 3) & ~3;
-       if ((field & MAIL_CACHE_FIXED_MASK) == 0)
-               full_size += sizeof(nb_data_size);
-
-       /* fields must be ordered. find where to insert it. */
-       if (field > ctx->cache_rec.fields)
-                buf = buffer_append_space_unsafe(ctx->cache_data, full_size);
-       else {
-               offset = get_insert_offset(ctx, field);
-               buffer_copy(ctx->cache_data, offset + full_size,
-                           ctx->cache_data, offset, (size_t)-1);
-               buf = buffer_get_space_unsafe(ctx->cache_data,
-                                             offset, full_size);
-       }
-       ctx->cache_rec.fields |= field;
-
-       /* @UNSAFE */
-       if ((field & MAIL_CACHE_FIXED_MASK) == 0) {
-               memcpy(buf, &nb_data_size, sizeof(nb_data_size));
-               buf += sizeof(nb_data_size);
-       }
-       memcpy(buf, data, data_size); buf += data_size;
-       if ((data_size & 3) != 0)
-               memset(buf, 0, 4 - (data_size & 3));
-
-       /* remember the transaction uid range */
-       if (rec->uid < ctx->first_uid || ctx->first_uid == 0)
-               ctx->first_uid = rec->uid;
-       if (rec->uid > ctx->last_uid)
-               ctx->last_uid = rec->uid;
-
-       if (ctx->prev_uid != rec->uid) {
-               ctx->prev_uid = rec->uid;
-               ctx->prev_fields = 0;
-       }
-       ctx->prev_fields |= field;
-
-       return TRUE;
-}
-
-int mail_cache_delete(struct mail_cache_transaction_ctx *ctx,
-                     struct mail_index_record *rec)
-{
-       struct mail_cache *cache = ctx->cache;
-       struct mail_cache_record *cache_rec;
-       uint32_t deleted_space;
-       uoff_t max_del_space;
-
-       cache_rec = mail_cache_lookup(cache, rec, 0);
-       if (cache_rec == NULL)
-               return TRUE;
-
-       /* NOTE: it would be nice to erase the cached data for the record,
-          but some other processes might still be using them. So, we just
-          update the deleted_space in header */
-       deleted_space = nbo_to_uint32(cache->header->deleted_space);
-
-       do {
-               deleted_space -= nbo_to_uint32(cache_rec->size);
-               cache_rec = cache_get_next_record(cache, cache_rec);
-       } while (cache_rec != NULL);
-
-       /* see if we've reached the max. deleted space in file */
-       max_del_space = cache->used_file_size / 100 * COMPRESS_PERCENTAGE;
-       if (deleted_space >= max_del_space &&
-           cache->used_file_size >= COMPRESS_MIN_SIZE)
-               cache->index->set_flags |= MAIL_INDEX_HDR_FLAG_COMPRESS_CACHE;
-
-       cache->header->deleted_space = uint32_to_nbo(deleted_space);
-
-       return TRUE;
-}
-
-enum mail_cache_field
-mail_cache_get_fields(struct mail_cache *cache,
-                     const struct mail_index_record *rec)
-{
-       struct mail_cache_record *cache_rec;
-        enum mail_cache_field fields = 0;
-
-       cache_rec = mail_cache_lookup(cache, rec, 0);
-       while (cache_rec != NULL) {
-               fields |= cache_rec->fields;
-               cache_rec = cache_get_next_record(cache, cache_rec);
-       }
-
-       return fields;
-}
-
-static int cache_get_field(struct mail_cache *cache,
-                          struct mail_cache_record *cache_rec,
-                          enum mail_cache_field field,
-                          void **data_r, size_t *size_r)
-{
-       unsigned char *buf;
-       unsigned int mask;
-       uint32_t rec_size, data_size;
-       size_t offset, next_offset;
-       int i;
-
-       rec_size = nbo_to_uint32(cache_rec->size);
-       buf = (unsigned char *) cache_rec;
-       offset = sizeof(*cache_rec);
-
-       for (i = 0, mask = 1; i < 31; i++, mask <<= 1) {
-               if ((cache_rec->fields & mask) == 0)
-                       continue;
-
-               /* all records are at least 32bit. we have to check this
-                  before getting data_size. */
-               if (offset + sizeof(uint32_t) > rec_size) {
-                       mail_cache_set_corrupted(cache,
-                               "Record continues outside it's allocated size");
-                       return FALSE;
-               }
-
-               if ((mask & MAIL_CACHE_FIXED_MASK) != 0)
-                       data_size = mail_cache_field_sizes[i];
-               else {
-                       memcpy(&data_size, buf + offset, sizeof(data_size));
-                       data_size = nbo_to_uint32(data_size);
-                       offset += sizeof(data_size);
-               }
-
-               next_offset = offset + ((data_size + 3) & ~3);
-               if (next_offset > rec_size) {
-                       mail_cache_set_corrupted(cache,
-                               "Record continues outside it's allocated size");
-                       return FALSE;
-               }
-
-               if (field == mask) {
-                       if (data_size == 0) {
-                               mail_cache_set_corrupted(cache,
-                                                        "Field size is 0");
-                               return FALSE;
-                       }
-                       *data_r = buf + offset;
-                       *size_r = data_size;
-                       return TRUE;
-               }
-               offset = next_offset;
-       }
-
-       i_unreached();
-       return FALSE;
-}
-
-static int cache_lookup_field(struct mail_cache *cache,
-                             const struct mail_index_record *rec,
-                             enum mail_cache_field field,
-                             void **data_r, size_t *size_r)
-{
-       struct mail_cache_record *cache_rec;
-
-       cache_rec = mail_cache_lookup(cache, rec, field);
-       while (cache_rec != NULL) {
-               if ((cache_rec->fields & field) != 0) {
-                       return cache_get_field(cache, cache_rec, field,
-                                              data_r, size_r);
-               }
-               cache_rec = cache_get_next_record(cache, cache_rec);
-       }
-
-       return FALSE;
-}
-
-int mail_cache_lookup_field(struct mail_cache *cache,
-                           const struct mail_index_record *rec,
-                           enum mail_cache_field field,
-                           const void **data_r, size_t *size_r)
-{
-       void *data;
-
-       if (!cache_lookup_field(cache, rec, field, &data, size_r))
-               return FALSE;
-
-       *data_r = data;
-       return TRUE;
-}
-
-const char *mail_cache_lookup_string_field(struct mail_cache *cache,
-                                          const struct mail_index_record *rec,
-                                          enum mail_cache_field field)
-{
-       const void *data;
-       size_t size;
-
-       i_assert((field & MAIL_CACHE_STRING_MASK) != 0);
-
-       if (!mail_cache_lookup_field(cache, rec, field, &data, &size))
-               return NULL;
-
-       if (((const char *) data)[size-1] != '\0') {
-               mail_cache_set_corrupted(cache,
-                       "String field %x doesn't end with NUL", field);
-               return NULL;
-       }
-       return data;
-}
-
-int mail_cache_copy_fixed_field(struct mail_cache *cache,
-                               const struct mail_index_record *rec,
-                               enum mail_cache_field field,
-                               void *buffer, size_t buffer_size)
-{
-       const void *data;
-       size_t size;
-
-       i_assert((field & MAIL_CACHE_FIXED_MASK) != 0);
-
-       if (!mail_cache_lookup_field(cache, rec, field, &data, &size))
-               return FALSE;
-
-       if (buffer_size != size) {
-               i_panic("cache: fixed field %x wrong size "
-                       "(%"PRIuSIZE_T" vs %"PRIuSIZE_T")",
-                       field, size, buffer_size);
-       }
-
-       memcpy(buffer, data, buffer_size);
-       return TRUE;
-}
-
-void mail_cache_mark_missing(struct mail_cache *cache,
-                            enum mail_cache_field fields)
-{
-       // FIXME: count these
-}
-
-enum mail_index_record_flag
-mail_cache_get_index_flags(struct mail_cache *cache,
-                          const struct mail_index_record *rec)
-{
-       enum mail_index_record_flag flags;
-
-       if (!mail_cache_copy_fixed_field(cache, rec, MAIL_CACHE_INDEX_FLAGS,
-                                        &flags, sizeof(flags)))
-               return 0;
-
-       return flags;
-}
-
-int mail_cache_update_index_flags(struct mail_cache *cache,
-                                 struct mail_index_record *rec,
-                                 enum mail_index_record_flag flags)
-{
-       void *data;
-       size_t size;
-
-       i_assert(cache->locks > 0);
-
-       if (!cache_lookup_field(cache, rec, MAIL_CACHE_INDEX_FLAGS,
-                               &data, &size)) {
-               mail_cache_set_corrupted(cache,
-                       "Missing index flags for record %u", rec->uid);
-               return FALSE;
-       }
-
-       memcpy(data, &flags, sizeof(flags));
-       return TRUE;
-}
-
-int mail_cache_update_location_offset(struct mail_cache *cache,
-                                     struct mail_index_record *rec,
-                                     uoff_t offset)
-{
-       void *data;
-       size_t size;
-
-       i_assert(cache->locks > 0);
-
-       if (!cache_lookup_field(cache, rec, MAIL_CACHE_LOCATION_OFFSET,
-                               &data, &size)) {
-               mail_cache_set_corrupted(cache,
-                       "Missing location offset for record %u", rec->uid);
-               return FALSE;
-       }
-
-       memcpy(data, &offset, sizeof(offset));
-       return TRUE;
-}
-
-void *mail_cache_get_mmaped(struct mail_cache *cache, size_t *size)
-{
-       if (!mmap_update(cache, 0, 0))
-               return NULL;
-
-       *size = cache->mmap_length;
-       return cache->mmap_base;
-}
-
-int mail_cache_set_corrupted(struct mail_cache *cache, const char *fmt, ...)
-{
-       va_list va;
-
-       mail_cache_mark_file_deleted(cache);
-       cache->index->inconsistent = TRUE; /* easiest way to rebuild */
-
-       if (cache->silent)
-               return FALSE;
-
-       va_start(va, fmt);
-       t_push();
-       index_set_error(cache->index, "Corrupted index cache file %s: %s",
-                       cache->filepath, t_strdup_vprintf(fmt, va));
-       t_pop();
-       va_end(va);
-
-       return FALSE;
-}
diff --git a/src/lib-index/mail-cache.h b/src/lib-index/mail-cache.h
deleted file mode 100644 (file)
index 3b2a305..0000000
+++ /dev/null
@@ -1,175 +0,0 @@
-#ifndef __MAIL_CACHE_H
-#define __MAIL_CACHE_H
-
-#include "mail-index.h"
-
-#define MAIL_CACHE_FILE_PREFIX ".cache"
-
-#define MAIL_CACHE_HEADERS_COUNT 4
-
-struct mail_cache_transaction_ctx;
-
-enum mail_cache_field {
-       /* fixed size fields */
-       MAIL_CACHE_INDEX_FLAGS          = 0x00000001,
-       MAIL_CACHE_LOCATION_OFFSET      = 0x00000002,
-       MAIL_CACHE_MD5                  = 0x00000004,
-       MAIL_CACHE_SENT_DATE            = 0x00000008,
-       MAIL_CACHE_RECEIVED_DATE        = 0x00000010,
-       MAIL_CACHE_VIRTUAL_FULL_SIZE    = 0x00000020,
-       MAIL_CACHE_PHYSICAL_BODY_SIZE   = 0x00000040,
-
-       /* variable sized field */
-       MAIL_CACHE_HEADERS1             = 0x40000000,
-       MAIL_CACHE_HEADERS2             = 0x20000000,
-       MAIL_CACHE_HEADERS3             = 0x10000000,
-       MAIL_CACHE_HEADERS4             = 0x08000000,
-       MAIL_CACHE_LOCATION             = 0x04000000,
-       MAIL_CACHE_BODY                 = 0x02000000,
-       MAIL_CACHE_BODYSTRUCTURE        = 0x01000000,
-       MAIL_CACHE_ENVELOPE             = 0x00800000,
-       MAIL_CACHE_MESSAGEPART          = 0x00400000,
-
-       MAIL_CACHE_FIXED_MASK           = MAIL_CACHE_INDEX_FLAGS |
-                                         MAIL_CACHE_LOCATION_OFFSET |
-                                         MAIL_CACHE_MD5 |
-                                         MAIL_CACHE_SENT_DATE |
-                                         MAIL_CACHE_RECEIVED_DATE |
-                                         MAIL_CACHE_VIRTUAL_FULL_SIZE |
-                                         MAIL_CACHE_PHYSICAL_BODY_SIZE,
-       MAIL_CACHE_HEADERS_MASK         = MAIL_CACHE_HEADERS1 |
-                                         MAIL_CACHE_HEADERS2 |
-                                         MAIL_CACHE_HEADERS3 |
-                                         MAIL_CACHE_HEADERS4,
-       MAIL_CACHE_STRING_MASK          = MAIL_CACHE_HEADERS_MASK |
-                                         MAIL_CACHE_LOCATION |
-                                         MAIL_CACHE_BODY |
-                                         MAIL_CACHE_BODYSTRUCTURE |
-                                         MAIL_CACHE_ENVELOPE,
-       MAIL_CACHE_BODYSTRUCTURE_MASK   = MAIL_CACHE_BODY |
-                                         MAIL_CACHE_BODYSTRUCTURE |
-                                          MAIL_CACHE_MESSAGEPART
-};
-
-struct mail_sent_date {
-       time_t time;
-       int32_t timezone;
-};
-
-extern enum mail_cache_field mail_cache_header_fields[MAIL_CACHE_HEADERS_COUNT];
-
-int mail_cache_open_or_create(struct mail_index *index);
-void mail_cache_free(struct mail_cache *cache);
-
-void mail_cache_set_defaults(struct mail_cache *cache,
-                            enum mail_cache_field default_cache_fields,
-                            enum mail_cache_field never_cache_fields);
-
-/* Compress cache file. */
-int mail_cache_compress(struct mail_cache *cache);
-
-/* Truncate the cache file and update it's indexid */
-int mail_cache_truncate(struct mail_cache *cache);
-
-/* Set indexid to 0 to notify other processes using this file that they should
-   re-open it. */
-int mail_cache_mark_file_deleted(struct mail_cache *cache);
-
-/* Explicitly lock the cache file. Returns 1 if ok, 0 if nonblock is TRUE and
-   we couldn't immediately get a lock, or -1 if error. */
-int mail_cache_lock(struct mail_cache *cache, int nonblock);
-int mail_cache_unlock(struct mail_cache *cache);
-
-/* Mark the lock to be removed when unlocking index file. */
-void mail_cache_unlock_later(struct mail_cache *cache);
-
-/* Returns TRUE if cache file is locked. */
-int mail_cache_is_locked(struct mail_cache *cache);
-
-/* Begin transaction. Returns same as mail_cache_lock(). Note that if you
-   call lookup functions for messages within first and last message in
-   transaction, the transaction will be automatically committed. */
-int mail_cache_transaction_begin(struct mail_cache *cache, int nonblock,
-                                struct mail_cache_transaction_ctx **ctx_r);
-/* End transaction. Single transaction can have multiple commits/rollbacks.
-   If there's any pending changes, they will be rolled back. */
-int mail_cache_transaction_end(struct mail_cache_transaction_ctx *ctx);
-
-int mail_cache_transaction_commit(struct mail_cache_transaction_ctx *ctx);
-int mail_cache_transaction_rollback(struct mail_cache_transaction_ctx *ctx);
-
-/* Return NULL-terminated list of headers for given index, or NULL if
-   header index isn't used. */
-const char *const *mail_cache_get_header_fields(struct mail_cache *cache,
-                                               unsigned int idx);
-/* Set list of headers for given index. */
-int mail_cache_set_header_fields(struct mail_cache_transaction_ctx *ctx,
-                                unsigned int idx, const char *const headers[]);
-
-/* Add new field to given record. Updates are not allowed. Fixed size fields
-   must be exactly the expected size and they're converted to network byte
-   order in disk. */
-int mail_cache_add(struct mail_cache_transaction_ctx *ctx,
-                  struct mail_index_record *rec, enum mail_cache_field field,
-                  const void *data, size_t data_size);
-
-/* Mark the given record deleted. */
-int mail_cache_delete(struct mail_cache_transaction_ctx *ctx,
-                     struct mail_index_record *rec);
-
-/* Return all fields that are currently cached for record. */
-enum mail_cache_field
-mail_cache_get_fields(struct mail_cache *cache,
-                     const struct mail_index_record *rec);
-
-/* Set data_r and size_r to point to wanted field in cache file.
-   Returns TRUE if field was found. If field contains multiple fields,
-   first one found is returned. This is mostly useful for finding headers. */
-int mail_cache_lookup_field(struct mail_cache *cache,
-                           const struct mail_index_record *rec,
-                           enum mail_cache_field field,
-                           const void **data_r, size_t *size_r);
-
-/* Return string field. */
-const char *mail_cache_lookup_string_field(struct mail_cache *cache,
-                                          const struct mail_index_record *rec,
-                                          enum mail_cache_field field);
-
-
-/* Copy fixed size field to given buffer. buffer_size must be exactly the
-   expected size. The result will be converted to host byte order.
-   Returns TRUE if field was found. */
-int mail_cache_copy_fixed_field(struct mail_cache *cache,
-                               const struct mail_index_record *rec,
-                               enum mail_cache_field field,
-                               void *buffer, size_t buffer_size);
-
-/* Mark given fields as missing, ie. they should be cached when possible. */
-void mail_cache_mark_missing(struct mail_cache *cache,
-                            enum mail_cache_field fields);
-
-/* Return index flags. */
-enum mail_index_record_flag
-mail_cache_get_index_flags(struct mail_cache *cache,
-                          const struct mail_index_record *rec);
-
-/* Update index flags. The cache file must be locked and the flags must be
-   already inserted to the record. */
-int mail_cache_update_index_flags(struct mail_cache *cache,
-                                 struct mail_index_record *rec,
-                                 enum mail_index_record_flag flags);
-
-/* Update location offset. External locking is assumed to take care of locking
-   readers out to prevent race conditions. */
-int mail_cache_update_location_offset(struct mail_cache *cache,
-                                     struct mail_index_record *rec,
-                                     uoff_t offset);
-
-/* Return the whole file mmaped. */
-void *mail_cache_get_mmaped(struct mail_cache *cache, size_t *size);
-
-/* "Error in index cache file %s: ...". */
-int mail_cache_set_corrupted(struct mail_cache *cache, const char *fmt, ...)
-       __attr_format__(2, 3);
-
-#endif
diff --git a/src/lib-index/mail-custom-flags.c b/src/lib-index/mail-custom-flags.c
deleted file mode 100644 (file)
index e0db24d..0000000
+++ /dev/null
@@ -1,592 +0,0 @@
-/* Copyright (C) 2002 Timo Sirainen */
-
-#include "lib.h"
-#include "file-lock.h"
-#include "mmap-util.h"
-#include "write-full.h"
-#include "imap-util.h"
-#include "mail-index.h"
-#include "mail-index-util.h"
-#include "mail-custom-flags.h"
-
-#include <ctype.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <sys/stat.h>
-
-/* Header is simply a counter which is increased every time the file is
-   updated. This allows other processes to easily notice if there's been
-   any changes. */
-
-#define COUNTER_SIZE 4
-#define HEADER_SIZE (COUNTER_SIZE + 1) /* 0000\n */
-
-struct mail_custom_flags {
-       struct mail_index *index;
-       char *filepath;
-       int fd;
-       int lock_type;
-
-       char sync_counter[COUNTER_SIZE];
-       char *custom_flags[MAIL_CUSTOM_FLAGS_COUNT];
-
-       void *mmap_base;
-       size_t mmap_length;
-
-       unsigned int syncing:1;
-       unsigned int noupdate:1;
-       unsigned int changed:1;
-};
-
-static int lock_file(struct mail_custom_flags *mcf, int type);
-
-static int index_cf_set_syscall_error(struct mail_custom_flags *mcf,
-                                     const char *function)
-{
-       i_assert(function != NULL);
-
-       if (ENOSPACE(errno)) {
-               mcf->index->nodiskspace = TRUE;
-               return FALSE;
-       }
-
-       index_set_error(mcf->index, "%s failed with custom flags file %s: %m",
-                       function, mcf->filepath);
-       return FALSE;
-}
-
-static int update_mmap(struct mail_custom_flags *mcf)
-{
-       if (mcf->mmap_base != NULL) {
-               if (munmap(mcf->mmap_base, mcf->mmap_length) < 0)
-                       index_cf_set_syscall_error(mcf, "munmap()");
-       }
-
-
-       mcf->mmap_base = mcf->noupdate ?
-               mmap_ro_file(mcf->fd, &mcf->mmap_length) :
-               mmap_rw_file(mcf->fd, &mcf->mmap_length);
-       if (mcf->mmap_base == MAP_FAILED) {
-               mcf->mmap_base = NULL;
-               return index_cf_set_syscall_error(mcf, "mmap()");
-       }
-
-       (void)madvise(mcf->mmap_base, mcf->mmap_length, MADV_SEQUENTIAL);
-       return TRUE;
-}
-
-static int custom_flags_init(struct mail_custom_flags *mcf)
-{
-       static char buf[HEADER_SIZE] = "0000\n";
-       struct stat st;
-       int failed;
-
-       if (!lock_file(mcf, F_WRLCK))
-               return FALSE;
-
-       failed = FALSE;
-
-       /* make sure it's still empty after locking */
-       if (fstat(mcf->fd, &st) < 0) {
-               index_cf_set_syscall_error(mcf, "fstat()");
-               failed = TRUE;
-       } else if (st.st_size < HEADER_SIZE) {
-               /* write the header - it's a 4 byte counter as hex */
-               if (write_full(mcf->fd, buf, HEADER_SIZE) < 0) {
-                       index_cf_set_syscall_error(mcf, "write_full()");
-                       failed = TRUE;
-               }
-       }
-
-       if (!lock_file(mcf, F_UNLCK))
-               return FALSE;
-
-       return !failed;
-}
-
-static void custom_flags_sync(struct mail_custom_flags *mcf)
-{
-       char *data, *data_end, *line;
-       unsigned int num;
-       int i;
-
-       if (mcf->noupdate)
-               return;
-
-       memcpy(mcf->sync_counter, mcf->mmap_base, COUNTER_SIZE);
-
-       for (i = 0; i < MAIL_CUSTOM_FLAGS_COUNT; i++) {
-               if (mcf->custom_flags[i] != NULL) {
-                       i_free(mcf->custom_flags[i]);
-                        mcf->custom_flags[i] = NULL;
-               }
-       }
-
-       data = mcf->mmap_base;
-       data_end = data + mcf->mmap_length;
-
-       /* this loop skips the first line, which is the header */
-       while (data != data_end) {
-               if (*data != '\n') {
-                       data++;
-                       continue;
-               }
-
-               /* beginning of line, get the index */
-               if (data+1 == data_end)
-                       break;
-               data++;
-
-               if (!i_isdigit(*data))
-                       continue;
-
-               num = 0;
-               while (data != data_end && *data >= '0' && *data <= '9') {
-                       num = num*10 + (*data-'0');
-                       data++;
-               }
-
-               if (num < MAIL_CUSTOM_FLAGS_COUNT) {
-                       /* get the name */
-                       if (data == data_end || *data != ' ')
-                               continue;
-
-                       line = ++data;
-                       while (data != data_end && *data != '\n')
-                               data++;
-
-                       if (mcf->custom_flags[num] != NULL) {
-                               i_warning("Error in custom flags file %s: "
-                                         "Duplicated ID %u", mcf->filepath,
-                                         num);
-                               i_free(mcf->custom_flags[num]);
-                       }
-
-                       mcf->custom_flags[num] = i_strdup_until(line, data);
-               }
-       }
-}
-
-static int custom_flags_check_sync(struct mail_custom_flags *mcf)
-{
-       if (mcf->fd == -1)
-               return TRUE;
-
-       if (mcf->mmap_length != 0 &&
-           memcmp(mcf->sync_counter, mcf->mmap_base, COUNTER_SIZE) == 0)
-               return TRUE;
-
-       /* file modified, resync */
-       if (!update_mmap(mcf))
-               return FALSE;
-
-       if (mcf->mmap_length < HEADER_SIZE && !mcf->noupdate) {
-               /* it's broken, rewrite header */
-               if (mcf->lock_type == F_RDLCK)
-                       (void)lock_file(mcf, F_UNLCK);
-
-               if (lseek(mcf->fd, 0, SEEK_SET) < 0) {
-                       index_cf_set_syscall_error(mcf, "lseek()");
-                       return FALSE;
-               }
-
-               if (!custom_flags_init(mcf))
-                       return FALSE;
-
-               if (!update_mmap(mcf))
-                       return FALSE;
-       }
-
-       custom_flags_sync(mcf);
-       mcf->changed = TRUE;
-       return TRUE;
-}
-
-static int lock_file(struct mail_custom_flags *mcf, int type)
-{
-       if (mcf->lock_type == type)
-               return TRUE;
-
-       if (mcf->fd != -1) {
-               /* FIXME: possibility to use .lock file instead */
-               if (file_wait_lock(mcf->fd, type) <= 0) {
-                       index_cf_set_syscall_error(mcf, "file_wait_lock()");
-                       return FALSE;
-               }
-       }
-
-       mcf->lock_type = type;
-
-       if (type != F_UNLCK && !mcf->syncing) {
-               mcf->syncing = TRUE;
-               if (!custom_flags_check_sync(mcf)) {
-                       mcf->syncing = FALSE;
-                       return FALSE;
-               }
-
-               /* syncing may have changed locking, do it again */
-               if (!lock_file(mcf, type)) {
-                       mcf->syncing = FALSE;
-                       return FALSE;
-               }
-
-               mcf->syncing = FALSE;
-       }
-       return TRUE;
-}
-
-int mail_custom_flags_open_or_create(struct mail_index *index)
-{
-       struct mail_custom_flags *mcf;
-       const char *path;
-       int fd, readonly;
-
-       readonly = index->mailbox_readonly;
-
-       if (index->control_dir != NULL) {
-               path = t_strconcat(index->control_dir, "/",
-                                  CUSTOM_FLAGS_FILE_NAME, NULL);
-               fd = !readonly ? open(path, O_RDWR | O_CREAT, 0660) :
-                       open(path, O_RDONLY);
-               if (fd == -1 && errno == EACCES) {
-                       fd = open(path, O_RDONLY);
-                       readonly = TRUE;
-               }
-               if (fd == -1 && errno != EACCES && errno != ENOENT &&
-                   !ENOSPACE(errno)) {
-                       index_file_set_syscall_error(index, path, "open()");
-                       return FALSE;
-               }
-       } else {
-               path = NULL;
-               fd = -1;
-       }
-
-       mcf = i_new(struct mail_custom_flags, 1);
-       mcf->index = index;
-       mcf->filepath = fd != -1 ? i_strdup(path) :
-               i_strdup_printf("(in-memory custom flags for %s)",
-                               index->mailbox_path);
-       mcf->fd = fd;
-       mcf->noupdate = mcf->fd == -1 || readonly;
-
-       if (fd != -1) {
-               if (!update_mmap(mcf)) {
-                       (void)close(mcf->fd);
-                       mcf->fd = -1;
-                       mcf->noupdate = TRUE;
-               }
-
-               if (mcf->mmap_length < HEADER_SIZE && !mcf->noupdate) {
-                       /* we just created it, write the header */
-                       mcf->syncing = TRUE;
-                       if (!custom_flags_init(mcf) || !update_mmap(mcf)) {
-                               (void)close(mcf->fd);
-                               mcf->fd = -1;
-                               mcf->noupdate = TRUE;
-                       }
-                       mcf->syncing = FALSE;
-               }
-       }
-
-       mcf->index->allow_new_custom_flags = mcf->fd != -1;
-
-       custom_flags_sync(mcf);
-
-       index->custom_flags = mcf;
-       return TRUE;
-}
-
-void mail_custom_flags_free(struct mail_custom_flags *mcf)
-{
-       int i;
-
-       for (i = 0; i < MAIL_CUSTOM_FLAGS_COUNT; i++)
-               i_free(mcf->custom_flags[i]);
-
-       if (mcf->mmap_base != NULL) {
-               if (munmap(mcf->mmap_base, mcf->mmap_length) < 0)
-                       index_cf_set_syscall_error(mcf, "munmap()");
-       }
-
-       if (mcf->fd != -1) {
-               if (close(mcf->fd) < 0)
-                       index_cf_set_syscall_error(mcf, "close()");
-       }
-
-       i_free(mcf->filepath);
-       i_free(mcf);
-}
-
-static int custom_flags_update_counter(struct mail_custom_flags *mcf)
-{
-       int i;
-
-       if (lseek(mcf->fd, 0, SEEK_SET) < 0)
-               return index_cf_set_syscall_error(mcf, "lseek()");
-
-       for (i = COUNTER_SIZE-1; i >= 0; i--) {
-               if (mcf->sync_counter[i] == '9') {
-                       mcf->sync_counter[i] = 'A';
-                       break;
-               }
-
-               if (mcf->sync_counter[i] == 'F') {
-                       /* digit wrapped, update next one */
-                       mcf->sync_counter[i] = '0';
-               } else {
-                       mcf->sync_counter[i]++;
-                       break;
-               }
-       }
-
-       if (write_full(mcf->fd, mcf->sync_counter, COUNTER_SIZE) < 0)
-               return index_cf_set_syscall_error(mcf, "write_full()");
-
-       mcf->changed = TRUE;
-       return TRUE;
-}
-
-static int custom_flags_add(struct mail_custom_flags *mcf,
-                           int idx, const char *name)
-{
-       const char *buf;
-       size_t len;
-       off_t pos;
-
-       i_assert(idx < MAIL_CUSTOM_FLAGS_COUNT);
-
-       /* first update the sync counter */
-       if (!custom_flags_update_counter(mcf))
-               return FALSE;
-
-       /* add the flag */
-       pos = lseek(mcf->fd, 0, SEEK_END);
-       if (pos < 0)
-               return index_cf_set_syscall_error(mcf, "lseek()");
-
-       if (pos != (off_t)mcf->mmap_length) {
-               index_set_error(mcf->index, "Custom flags file %s was "
-                               "changed by someone while we were"
-                               "trying to modify it", mcf->filepath);
-               return FALSE;
-       }
-
-       buf = t_strdup_printf("\n%d %s\n", idx, name);
-       len = strlen(buf);
-
-       if (((char *) mcf->mmap_base)[mcf->mmap_length-1] == '\n') {
-               /* don't add the \n prefix */
-               buf++;
-               len--;
-       }
-
-       if (write_full(mcf->fd, buf, len) < 0)
-               return index_cf_set_syscall_error(mcf, "write_full()");
-
-       if (!update_mmap(mcf))
-               return FALSE;
-
-       return TRUE;
-}
-
-static int custom_flags_remove(struct mail_custom_flags *mcf, unsigned int idx)
-{
-       char *data, *data_end, *line;
-       unsigned int num;
-       int pos, linelen;
-
-       data = mcf->mmap_base;
-       data_end = data + mcf->mmap_length;
-
-       while (data != data_end) {
-               if (*data != '\n') {
-                       data++;
-                       continue;
-               }
-
-               /* beginning of line, get the index */
-               if (data+1 == data_end)
-                       break;
-               line = ++data;
-
-               num = 0;
-               while (data != data_end && *data >= '0' && *data <= '9') {
-                       num = num*10 + (*data-'0');
-                       data++;
-               }
-
-               if (num == idx) {
-                       /* remove this line */
-                       while (data != data_end && data[-1] != '\n')
-                               data++;
-
-                       linelen = (int) (data - line);
-                       pos = (int) (data - (char *) mcf->mmap_base);
-                       memmove(line, data, mcf->mmap_length - pos);
-
-                       mcf->mmap_length -= linelen;
-                       if (ftruncate(mcf->fd, (off_t) mcf->mmap_length) < 0) {
-                               index_cf_set_syscall_error(mcf, "ftruncate()");
-                               return FALSE;
-                       }
-
-                       return TRUE;
-               }
-       }
-
-       return FALSE;
-}
-
-static int find_first_unused_flag(struct mail_custom_flags *mcf)
-{
-       int i;
-
-       for (i = 0; i < MAIL_CUSTOM_FLAGS_COUNT; i++) {
-               if (mcf->custom_flags[i] == NULL)
-                       return i;
-       }
-
-       return -1;
-}
-
-static void remove_unused_custom_flags(struct mail_custom_flags *mcf,
-                                      enum mail_flags used_flags)
-{
-       unsigned int i;
-
-       for (i = 0; i < MAIL_CUSTOM_FLAGS_COUNT; i++) {
-               if ((used_flags & (1 << (i + MAIL_CUSTOM_FLAG_1_BIT))) == 0) {
-                       i_free(mcf->custom_flags[i]);
-                       mcf->custom_flags[i] = NULL;
-
-                       custom_flags_remove(mcf, i);
-               }
-       }
-}
-
-static enum mail_flags get_used_flags(struct mail_custom_flags *mcf)
-{
-       struct mail_index_record *rec;
-       enum mail_flags used_flags;
-
-       used_flags = 0;
-
-       rec = mcf->index->lookup(mcf->index, 1);
-       while (rec != NULL) {
-               used_flags |= rec->msg_flags;
-               rec = mcf->index->next(mcf->index, rec);
-       }
-
-       return used_flags;
-}
-
-static int get_flag_index(struct mail_custom_flags *mcf, const char *flag,
-                         int index_hint)
-{
-       int i, first_empty;
-
-       if (index_hint >= 0 && index_hint < MAIL_CUSTOM_FLAGS_COUNT) {
-               if (mcf->custom_flags[index_hint] != NULL &&
-                   strcasecmp(mcf->custom_flags[index_hint], flag) == 0)
-                       return index_hint;
-       }
-
-       /* check existing flags */
-       for (i = 0; i < MAIL_CUSTOM_FLAGS_COUNT; i++) {
-               if (mcf->custom_flags[i] != NULL) {
-                       i_assert(mcf->custom_flags[i] != '\0');
-                       if (strcasecmp(mcf->custom_flags[i], flag) == 0)
-                               return i;
-               }
-       }
-
-       if (mcf->noupdate)
-               return -1;
-
-       if (mcf->lock_type != F_WRLCK) {
-               /* unlock + write lock, don't directly change from
-                  read -> write lock to prevent deadlocking */
-               if (!lock_file(mcf, F_UNLCK) || !lock_file(mcf, F_WRLCK))
-                       return -1;
-
-               /* list may have already changed between the lock changes,
-                  check again */
-               return get_flag_index(mcf, flag, -1);
-       }
-
-       /* new flag, add it. first find the first free flag, note that
-          unlock+lock might have just changed it. */
-       first_empty = find_first_unused_flag(mcf);
-       if (first_empty == -1) {
-               /* all custom flags are used, see if some of them are unused */
-               remove_unused_custom_flags(mcf, get_used_flags(mcf));
-
-               first_empty = find_first_unused_flag(mcf);
-               if (first_empty == -1) {
-                       /* everything is in use */
-                       return -1;
-               }
-       }
-
-       if (!custom_flags_add(mcf, first_empty, flag))
-               return -1;
-
-       mcf->index->set_flags |= MAIL_INDEX_HDR_FLAG_DIRTY_CUSTOMFLAGS;
-
-       mcf->custom_flags[first_empty] = i_strdup(flag);
-       return first_empty;
-}
-
-int mail_custom_flags_fix_list(struct mail_custom_flags *mcf,
-                              enum mail_flags *flags,
-                              const char *custom_flags[], unsigned int count)
-{
-       enum mail_flags oldflags, flag;
-       int i, idx;
-
-       i_assert(count < 32);
-
-       if ((*flags & MAIL_CUSTOM_FLAGS_MASK) == 0)
-               return 1;
-
-       if (!lock_file(mcf, F_RDLCK))
-               return -1;
-
-       oldflags = *flags;
-       *flags &= MAIL_SYSTEM_FLAGS_MASK;
-
-       flag = MAIL_CUSTOM_FLAG_1;
-       for (i = 0; i < (int)count; i++, flag <<= 1) {
-               if ((oldflags & flag) && custom_flags[i] != NULL) {
-                       i_assert(*custom_flags[i] != '\0');
-
-                       idx = get_flag_index(mcf, custom_flags[i], i);
-                       if (idx == -1) {
-                               (void)lock_file(mcf, F_UNLCK);
-                               return 0;
-                       }
-                       *flags |= 1 << (idx + MAIL_CUSTOM_FLAG_1_BIT);
-               }
-       }
-
-       if (!lock_file(mcf, F_UNLCK))
-               return -1;
-
-       return 1;
-}
-
-const char **mail_custom_flags_list_get(struct mail_custom_flags *mcf)
-{
-       return (const char **) mcf->custom_flags;
-}
-
-int mail_custom_flags_has_changes(struct mail_custom_flags *mcf)
-{
-       if (!mcf->changed)
-               return FALSE;
-       else {
-               mcf->changed = FALSE;
-               return TRUE;
-       }
-}
diff --git a/src/lib-index/mail-custom-flags.h b/src/lib-index/mail-custom-flags.h
deleted file mode 100644 (file)
index 9273bf4..0000000
+++ /dev/null
@@ -1,31 +0,0 @@
-#ifndef __MAIL_CUSTOM_FLAGS_H
-#define __MAIL_CUSTOM_FLAGS_H
-
-/* NOTE: Contains it's own locking, unrelated to index locks. */
-
-#include "mail-index.h"
-
-#define CUSTOM_FLAGS_FILE_NAME ".customflags"
-
-int mail_custom_flags_open_or_create(struct mail_index *index);
-void mail_custom_flags_free(struct mail_custom_flags *mcf);
-
-/* Change custom flags so that they reflect the real flag numbers in
-   the file. Initially flags contains the custom flags in the order of the
-   specified list, it's modified to reflect the actual list. Returns 1 if ok,
-   0 if number of custom flags exceeded or -1 if error */
-int mail_custom_flags_fix_list(struct mail_custom_flags *mcf,
-                              enum mail_flags *flags,
-                              const char *custom_flags[], unsigned int count);
-
-/* Returns a pointer to list of flags. Note that calls to
-   mail_cutom_flags_fix_list() may modify the flags in the returned list.
-   It can modify only the flags that aren't in use anywhere, so this should
-   be safe. */
-const char **mail_custom_flags_list_get(struct mail_custom_flags *mcf);
-
-/* Returns TRUE if there's been any changes since this function was
-   called last time, or since open if this is the first call. */
-int mail_custom_flags_has_changes(struct mail_custom_flags *mcf);
-
-#endif
diff --git a/src/lib-index/mail-index-file.c b/src/lib-index/mail-index-file.c
deleted file mode 100644 (file)
index 87fb733..0000000
+++ /dev/null
@@ -1,208 +0,0 @@
-/* Copyright (C) 2003 Timo Sirainen */
-
-#include "lib.h"
-#include "file-set-size.h"
-#include "mail-index.h"
-#include "mail-index-util.h"
-
-#include <unistd.h>
-
-struct mail_index_record *mail_index_next(struct mail_index *index,
-                                         struct mail_index_record *rec)
-{
-       i_assert(index->lock_type != MAIL_LOCK_UNLOCK);
-       i_assert(rec >= INDEX_RECORD_AT(index, 0));
-
-       return rec+1 == INDEX_END_RECORD(index) ? NULL : rec+1;
-}
-
-static int compress(struct mail_index *index, unsigned int remove_first_idx,
-                   unsigned int remove_last_idx)
-{
-       struct mail_index_record *rec = INDEX_RECORD_AT(index, 0);
-       unsigned int idx_limit, count;
-
-       idx_limit = MAIL_INDEX_RECORD_COUNT(index);
-       count = remove_last_idx - remove_first_idx + 1;
-
-       memmove(rec + remove_first_idx, rec + remove_last_idx + 1,
-               (idx_limit - remove_last_idx - 1) * sizeof(*rec));
-
-       index->header->used_file_size -= sizeof(*rec) * count;
-       index->mmap_used_length -= sizeof(*rec) * count;
-
-       /* not really needed since append() will initialize it as well,
-          but may help preventing problems if change is only partially
-          written to disk */
-       memset((char *) rec + index->mmap_used_length, 0, sizeof(*rec) * count);
-
-       return mail_index_truncate(index);
-}
-
-int mail_index_expunge_record_range(struct mail_index *index,
-                                   struct mail_index_record *first_rec,
-                                   struct mail_index_record *last_rec)
-{
-       struct mail_index_record *rec;
-       unsigned int first_idx, last_idx, idx_limit;
-
-        i_assert(index->lock_type == MAIL_LOCK_EXCLUSIVE);
-
-       first_idx = INDEX_RECORD_INDEX(index, first_rec);
-       last_idx = INDEX_RECORD_INDEX(index, last_rec);
-       idx_limit = MAIL_INDEX_RECORD_COUNT(index);
-
-       i_assert(first_idx <= last_idx);
-       i_assert(last_idx < idx_limit);
-
-       index->header->messages_count -= last_idx - first_idx + 1;
-       for (rec = first_rec; rec <= last_rec; rec++)
-               mail_index_mark_flag_changes(index, rec, rec->msg_flags, 0);
-
-       return compress(index, first_idx, last_idx);
-}
-
-struct mail_index_record *mail_index_lookup(struct mail_index *index,
-                                           unsigned int seq)
-{
-       i_assert(index->lock_type != MAIL_LOCK_UNLOCK);
-       i_assert(seq > 0);
-
-       if (seq > index->header->messages_count)
-               return NULL;
-
-       return INDEX_RECORD_AT(index, seq-1);
-}
-
-struct mail_index_record *
-mail_index_lookup_uid_range(struct mail_index *index, unsigned int first_uid,
-                           unsigned int last_uid, unsigned int *seq_r)
-{
-       struct mail_index_record *rec_p;
-       unsigned int idx_limit, idx, left_idx, right_idx;
-
-       i_assert(index->lock_type != MAIL_LOCK_UNLOCK);
-       i_assert(first_uid > 0);
-       i_assert(first_uid <= last_uid);
-
-       rec_p = INDEX_RECORD_AT(index, 0);
-       idx_limit = MAIL_INDEX_RECORD_COUNT(index);
-
-       idx = 0;
-       left_idx = 0;
-       right_idx = idx_limit;
-
-       while (left_idx < right_idx) {
-               idx = (left_idx + right_idx) / 2;
-
-               if (rec_p[idx].uid < first_uid)
-                       left_idx = idx+1;
-               else if (rec_p[idx].uid > first_uid)
-                       right_idx = idx;
-               else
-                       break;
-       }
-
-       if (rec_p[idx].uid < first_uid || rec_p[idx].uid > last_uid) {
-               /* could still be the next one */
-               idx++;
-               if (idx == idx_limit ||
-                   rec_p[idx].uid < first_uid || rec_p[idx].uid > last_uid) {
-                       if (seq_r != NULL) *seq_r = 0;
-                       return NULL;
-               }
-       }
-
-       if (seq_r != NULL)
-               *seq_r = idx + 1;
-       return rec_p + idx;
-}
-
-int mail_index_compress(struct mail_index *index)
-{
-       size_t diff;
-       off_t new_file_size;
-
-       if (index->header_size >= sizeof(struct mail_index_header))
-               return TRUE;
-
-       if (!index->set_lock(index, MAIL_LOCK_EXCLUSIVE))
-               return FALSE;
-
-       /* make sure the file is large enough */
-       diff = sizeof(struct mail_index_header) - index->header_size;
-       if (index->mmap_used_length + diff > index->mmap_full_length) {
-               /* mmap_update ftruncates the file to multiples of
-                  mail_index_record, make sure we grow it enough here. */
-               new_file_size = index->mmap_used_length + diff +
-                       (sizeof(struct mail_index_record) -
-                        (diff % sizeof(struct mail_index_record)));
-               if (file_set_size(index->fd, new_file_size) < 0) {
-                       index_set_syscall_error(index, "file_set_size()");
-                       return FALSE;
-               }
-
-               index->header->master_sync_id++;
-               if (!mail_index_mmap_update(index))
-                       return FALSE;
-       }
-
-       /* if we break, we'll have to rebuild it completely */
-       index->header->flags |= MAIL_INDEX_HDR_FLAG_REBUILD;
-       if (!mail_index_fmdatasync(index, index->header_size))
-               return FALSE;
-
-       memmove((char *) index->mmap_base + sizeof(struct mail_index_header),
-               (char *) index->mmap_base + index->header_size,
-               index->mmap_used_length - index->header_size);
-       memset((char *) index->mmap_base + index->header_size, 0, diff);
-
-       index->mmap_used_length += diff;
-       index->header_size = sizeof(struct mail_index_header);
-
-       index->header->header_size = sizeof(struct mail_index_header);
-       index->header->used_file_size += diff;
-       index->header->master_sync_id++;
-       if (!mail_index_fmdatasync(index, index->mmap_used_length))
-               return FALSE;
-
-       index->header->flags &= ~MAIL_INDEX_HDR_FLAG_REBUILD;
-       return mail_index_mmap_update(index);
-}
-
-int mail_index_truncate(struct mail_index *index)
-{
-       uoff_t empty_space, truncate_threshold;
-
-       i_assert(index->lock_type == MAIL_LOCK_EXCLUSIVE);
-
-       if (index->mmap_full_length <= INDEX_FILE_MIN_SIZE(index) ||
-           index->anon_mmap)
-               return TRUE;
-
-       /* really truncate the file only when it's almost empty */
-       empty_space = index->mmap_full_length - index->mmap_used_length;
-       truncate_threshold =
-               index->mmap_full_length / 100 * INDEX_TRUNCATE_PERCENTAGE;
-
-       if (empty_space > truncate_threshold) {
-               index->mmap_full_length = index->mmap_used_length +
-                       (empty_space * INDEX_TRUNCATE_KEEP_PERCENTAGE / 100);
-
-               /* keep the size record-aligned */
-               index->mmap_full_length -= (index->mmap_full_length -
-                                           index->header_size) %
-                       sizeof(struct mail_index_record);
-
-               if (index->mmap_full_length < INDEX_FILE_MIN_SIZE(index))
-                        index->mmap_full_length = INDEX_FILE_MIN_SIZE(index);
-
-               if (ftruncate(index->fd, (off_t)index->mmap_full_length) < 0)
-                       return index_set_syscall_error(index, "ftruncate()");
-
-               index->header->master_sync_id++;
-       }
-
-       return TRUE;
-}
diff --git a/src/lib-index/mail-index-fsck.c b/src/lib-index/mail-index-fsck.c
deleted file mode 100644 (file)
index 1367671..0000000
+++ /dev/null
@@ -1,103 +0,0 @@
-/* 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 %s: "#field" %u != %u", \
-                         index->filepath, old_hdr->field, new_hdr->field);
-
-
-static void print_differences(struct mail_index *index,
-                             struct mail_index_header *old_hdr,
-                             struct mail_index_header *new_hdr)
-{
-       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 %s: first_unseen_uid_lowwater %u > %u",
-                         index->filepath,
-                         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 %s: first_deleted_uid_lowwater %u > %u",
-                         index->filepath,
-                         old_hdr->first_deleted_uid_lowwater,
-                          new_hdr->first_deleted_uid_lowwater);
-       }
-}
-
-int mail_index_fsck(struct mail_index *index)
-{
-       struct mail_index_header old_hdr, *hdr;
-       struct mail_index_record *rec, *end_rec;
-       unsigned int max_uid;
-
-       i_assert(index->lock_type != MAIL_LOCK_SHARED);
-
-       if (!mail_index_compress(index))
-               return FALSE;
-
-       /* then we verify only the fields in the header. other problems will
-          be noticed and fixed while reading the messages. */
-       hdr = index->header;
-       memcpy(&old_hdr, hdr, sizeof(struct mail_index_header));
-
-       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 = INDEX_RECORD_AT(index, 0);
-       end_rec = INDEX_END_RECORD(index);
-
-       max_uid = 0;
-       for (; rec < end_rec; rec++) {
-               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 == 0)
-                       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;
-
-       if (hdr->first_unseen_uid_lowwater == 0)
-               hdr->first_unseen_uid_lowwater = hdr->next_uid;
-       if (hdr->first_deleted_uid_lowwater == 0)
-               hdr->first_deleted_uid_lowwater = hdr->next_uid;
-
-       print_differences(index, &old_hdr, hdr);
-
-       /* FSCK flag is removed automatically by set_lock() */
-       return TRUE;
-}
diff --git a/src/lib-index/mail-index-open.c b/src/lib-index/mail-index-open.c
deleted file mode 100644 (file)
index e91af87..0000000
+++ /dev/null
@@ -1,397 +0,0 @@
-/* Copyright (C) 2002-2003 Timo Sirainen */
-
-#include "lib.h"
-#include "ioloop.h"
-#include "file-lock.h"
-#include "file-set-size.h"
-#include "hostpid.h"
-#include "mmap-util.h"
-#include "unlink-lockfiles.h"
-#include "write-full.h"
-#include "mail-index.h"
-#include "mail-index-util.h"
-#include "mail-cache.h"
-#include "mail-modifylog.h"
-#include "mail-custom-flags.h"
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <fcntl.h>
-
-static int mail_index_open_init(struct mail_index *index,
-                               enum mail_index_open_flags flags)
-{
-       struct mail_index_header *hdr;
-
-       hdr = index->header;
-
-       index->maildir_have_new =
-               (hdr->flags & MAIL_INDEX_FLAG_MAILDIR_NEW) != 0;
-
-       if ((hdr->flags & MAIL_INDEX_HDR_FLAG_DIRTY_MESSAGES) != 0)
-               index->next_dirty_flags_flush = ioloop_time;
-
-       /* update \Recent message counters */
-       if ((flags & MAIL_INDEX_OPEN_FLAG_UPDATE_RECENT) != 0 &&
-           hdr->last_nonrecent_uid != hdr->next_uid-1) {
-               /* keep last_recent_uid to next_uid-1 */
-               if (index->lock_type == MAIL_LOCK_SHARED) {
-                       if (!index->set_lock(index, MAIL_LOCK_UNLOCK))
-                               return FALSE;
-               }
-
-               if (!index->set_lock(index, MAIL_LOCK_EXCLUSIVE))
-                       return FALSE;
-
-               index->first_recent_uid = index->header->last_nonrecent_uid+1;
-               index->header->last_nonrecent_uid = index->header->next_uid-1;
-       } else {
-               index->first_recent_uid = hdr->last_nonrecent_uid+1;
-       }
-
-       if (hdr->next_uid >= MAX_ALLOWED_UID - 1000) {
-               /* UID values are getting too high, rebuild index */
-               index->set_flags |= MAIL_INDEX_HDR_FLAG_REBUILD;
-       }
-
-       if (index->lock_type == MAIL_LOCK_EXCLUSIVE) {
-               /* finally reset the modify log marks, fsck or syncing might
-                  have deleted some messages, and since we're only just
-                  opening the index, there's no need to remember them */
-               if (!mail_modifylog_mark_synced(index->modifylog))
-                       return FALSE;
-       }
-
-       return TRUE;
-}
-
-static int index_open_and_fix(struct mail_index *index,
-                             enum mail_index_open_flags flags)
-{
-       int rebuilt;
-
-       if (index->header_size < sizeof(struct mail_index_header)) {
-               /* upgrading from older index file. */
-               if (!mail_index_compress(index))
-                       return FALSE;
-       }
-
-       if (!mail_cache_open_or_create(index))
-               return FALSE;
-
-       /* custom flags file needs to be open before rebuilding index */
-       if (!mail_custom_flags_open_or_create(index))
-               return FALSE;
-
-       if ((index->header->flags & MAIL_INDEX_HDR_FLAG_REBUILD) != 0 ||
-           (index->set_flags & MAIL_INDEX_HDR_FLAG_REBUILD) != 0) {
-
-               if (!index->rebuild(index))
-                       return FALSE;
-
-               if ((index->header->flags & MAIL_INDEX_HDR_FLAG_REBUILD) != 0)
-                       return FALSE;
-
-               /* no inconsistency problems since we're still opening
-                  the index */
-               index->inconsistent = FALSE;
-               rebuilt = TRUE;
-       } else {
-               rebuilt = FALSE;
-       }
-
-       if ((flags & _MAIL_INDEX_OPEN_FLAG_CREATING) == 0) {
-               if (!mail_modifylog_open_or_create(index))
-                       return FALSE;
-       } else {
-               if (!mail_modifylog_create(index))
-                       return FALSE;
-       }
-
-       if (index->header->flags & MAIL_INDEX_HDR_FLAG_FSCK) {
-               /* index needs fscking */
-               if (!index->fsck(index))
-                       return FALSE;
-       }
-
-       if (!rebuilt) {
-               /* sync ourself. do it before compression which may happen
-                  as a result of this. */
-               if (!index->sync_and_lock(index, FALSE,
-                                         MAIL_LOCK_SHARED, NULL) &&
-                   !index->nodiskspace)
-                       return FALSE;
-       }
-
-       /* we never want to keep shared lock if syncing happens to set it.
-          either exclusive or nothing (NOTE: drop it directly, not through
-          index->set_lock() so mbox lock won't be affected). */
-       if (index->lock_type == MAIL_LOCK_SHARED) {
-               if (!mail_index_set_lock(index, MAIL_LOCK_UNLOCK))
-                       return FALSE;
-       }
-
-       if ((flags & MAIL_INDEX_OPEN_FLAG_FAST) == 0) {
-               if (index->header->flags & MAIL_INDEX_HDR_FLAG_COMPRESS) {
-                       /* remove deleted blocks from index file */
-                       if (!mail_index_compress(index))
-                               return FALSE;
-               }
-
-               if (index->header->flags & MAIL_INDEX_HDR_FLAG_COMPRESS_CACHE) {
-                       /* remove unused space from index data file. */
-                       if (!mail_cache_compress(index->cache))
-                               return FALSE;
-               }
-       }
-
-       if (!mail_index_open_init(index, flags))
-               return FALSE;
-
-       return TRUE;
-}
-
-static int mail_index_read_header(struct mail_index *index,
-                                 struct mail_index_header *hdr)
-{
-       ssize_t ret;
-
-       if (lseek(index->fd, 0, SEEK_SET) < 0) {
-               index_set_syscall_error(index, "seek()");
-               return -1;
-       }
-
-       ret = read(index->fd, hdr, sizeof(*hdr));
-       if (ret < 0) {
-               index_set_syscall_error(index, "read()");
-               return -1;
-       }
-
-       if (ret != sizeof(*hdr)) {
-               /* missing data */
-               return 0;
-       }
-
-       return 1;
-}
-
-static int mail_index_init_file(struct mail_index *index,
-                               const struct mail_index_header *hdr)
-{
-       uoff_t file_size;
-
-       if (lseek(index->fd, 0, SEEK_SET) < 0) {
-               index_set_syscall_error(index, "lseek()");
-               return FALSE;
-       }
-
-       if (write_full(index->fd, hdr, sizeof(*hdr)) < 0) {
-               index_set_syscall_error(index, "write_full()");
-               return FALSE;
-       }
-
-       file_size = sizeof(*hdr) +
-               INDEX_MIN_RECORDS_COUNT * sizeof(struct mail_index_record);
-       if (file_set_size(index->fd, (off_t)file_size) < 0) {
-               index_set_syscall_error(index, "file_set_size()");
-               return FALSE;
-       }
-
-       return TRUE;
-}
-
-static void get_compat_data(unsigned char compat_data[4])
-{
-#ifndef WORDS_BIGENDIAN
-       compat_data[0] = MAIL_INDEX_COMPAT_LITTLE_ENDIAN;
-#else
-       compat_data[0] = 0;
-#endif
-       compat_data[1] = sizeof(uoff_t);
-       compat_data[2] = sizeof(time_t);
-       compat_data[3] = 0;
-}
-
-void mail_index_init_header(struct mail_index_header *hdr)
-{
-       i_assert(sizeof(struct mail_index_header) < 256);
-
-       memset(hdr, 0, sizeof(*hdr));
-       hdr->major_version = MAIL_INDEX_MAJOR_VERSION;
-       hdr->minor_version = MAIL_INDEX_MINOR_VERSION;
-       hdr->header_size = (uint8_t)sizeof(struct mail_index_header);
-       get_compat_data(hdr->compat_data);
-
-       hdr->indexid = ioloop_time;
-
-       /* mark the index requiring rebuild - rebuild() removes this flag
-          when it succeeds */
-       hdr->flags = MAIL_INDEX_HDR_FLAG_REBUILD;
-
-       hdr->used_file_size = sizeof(struct mail_index_header);
-       hdr->uid_validity = ioloop_time;
-       hdr->next_uid = 1;
-}
-
-static void mail_index_cleanup_temp_files(const char *dir)
-{
-       unlink_lockfiles(dir, t_strconcat(".temp.", my_hostname, ".", NULL),
-                        ".temp.", time(NULL) - TEMP_FILE_TIMEOUT);
-}
-
-void mail_index_init(struct mail_index *index, const char *dir)
-{
-       size_t len;
-
-       index->fd = -1;
-
-       if (dir != NULL) {
-               index->dir = i_strdup(dir);
-
-               len = strlen(index->dir);
-               if (index->dir[len-1] == '/')
-                       index->dir[len-1] = '\0';
-       }
-
-       index->mail_read_mmaped = getenv("MAIL_READ_MMAPED") != NULL;
-}
-
-static int mail_index_create_memory(struct mail_index *index,
-                                   enum mail_index_open_flags flags)
-{
-       if ((flags & MAIL_INDEX_OPEN_FLAG_CREATE) == 0)
-               return FALSE;
-
-       flags |= _MAIL_INDEX_OPEN_FLAG_CREATING;
-
-       index->header_size = sizeof(struct mail_index_header);
-       index->mmap_full_length = INDEX_FILE_MIN_SIZE(index);
-       index->mmap_base = mmap_anon(index->mmap_full_length);
-       if (index->mmap_base == MAP_FAILED) {
-               index->mmap_base = NULL;
-               return index_set_error(index, "mmap_anon() failed: %m");
-       }
-
-       mail_index_init_header(index->mmap_base);
-       index->header = index->mmap_base;
-       index->mmap_used_length = index->header->used_file_size;
-
-       index->anon_mmap = TRUE;
-       index->lock_type = MAIL_LOCK_EXCLUSIVE;
-       index->indexid = index->header->indexid;
-       index->filepath = i_strdup_printf("(in-memory index for %s)",
-                                         index->mailbox_path);
-
-       if (!index_open_and_fix(index, flags)) {
-               mail_index_close(index);
-               return FALSE;
-       }
-
-       index->opened = TRUE;
-       return TRUE;
-}
-
-static int mail_index_open_index(struct mail_index *index,
-                                enum mail_index_open_flags flags)
-{
-       struct mail_index_header hdr;
-       unsigned char compat_data[4];
-       int ret;
-
-       if ((flags & _MAIL_INDEX_OPEN_FLAG_CREATING) == 0)
-               index->lock_type = MAIL_LOCK_SHARED;
-       else
-               index->lock_type = MAIL_LOCK_EXCLUSIVE;
-
-       /* if index is being created, we'll wait here until it's finished */
-       if (!mail_index_wait_lock(index, MAIL_LOCK_TO_FLOCK(index->lock_type)))
-               return FALSE;
-#ifdef DEBUG
-       if (index->mmap_base != NULL) {
-               mprotect(index->mmap_base, index->mmap_used_length,
-                        PROT_READ|PROT_WRITE);
-       }
-#endif
-
-       if ((ret = mail_index_read_header(index, &hdr)) < 0)
-               return FALSE;
-       index->indexid = hdr.indexid;
-
-       get_compat_data(compat_data);
-       if (ret == 0 || hdr.major_version != MAIL_INDEX_MAJOR_VERSION ||
-           (hdr.flags & MAIL_INDEX_HDR_FLAG_REBUILD) != 0 ||
-           memcmp(compat_data, hdr.compat_data, sizeof(compat_data)) != 0 ||
-           !mail_index_mmap_update(index)) {
-               if ((flags & MAIL_INDEX_OPEN_FLAG_CREATE) == 0)
-                       return FALSE;
-
-               flags |= _MAIL_INDEX_OPEN_FLAG_CREATING;
-
-               /* so, we're creating the index */
-               if (index->lock_type != MAIL_LOCK_EXCLUSIVE) {
-                       /* have to get exclusive lock first */
-                       if (!mail_index_wait_lock(index, F_UNLCK))
-                               return FALSE;
-                       return mail_index_open_index(index, flags);
-               }
-
-               mail_index_init_header(&hdr);
-               if (!mail_index_init_file(index, &hdr))
-                       return FALSE;
-
-               if (!mail_index_mmap_update(index))
-                       return FALSE;
-       }
-
-       if (index->lock_type == MAIL_LOCK_SHARED) {
-               /* we don't want to keep the shared lock while opening
-                  indexes. opening should work unlocked and some
-                  things want exclusive lock */
-               if (!mail_index_wait_lock(index, F_UNLCK))
-                       return FALSE;
-               index->lock_type = MAIL_LOCK_UNLOCK;
-       }
-
-       if (!index_open_and_fix(index, flags))
-               return FALSE;
-
-       if (!index->set_lock(index, MAIL_LOCK_UNLOCK))
-               return FALSE;
-
-       index->opened = TRUE;
-       return TRUE;
-}
-
-int mail_index_open(struct mail_index *index, enum mail_index_open_flags flags)
-{
-       const char *path;
-
-       i_assert(!index->opened);
-
-       if (index->dir == NULL)
-               return mail_index_create_memory(index, flags);
-
-       mail_index_cleanup_temp_files(index->dir);
-
-       /* open/create the file */
-        path = t_strconcat(index->dir, "/", INDEX_FILE_PREFIX, NULL);
-       if ((flags & MAIL_INDEX_OPEN_FLAG_CREATE) != 0)
-               index->fd = open(path, O_RDWR | O_CREAT, 0660);
-       else
-               index->fd = open(path, O_RDWR);
-       if (index->fd == -1) {
-               if (errno != ENOENT)
-                       index_file_set_syscall_error(index, path, "open()");
-               return mail_index_create_memory(index, flags);
-       }
-
-       index->filepath = i_strdup(path);
-
-       if (!mail_index_open_index(index, flags)) {
-               mail_index_close(index);
-               return mail_index_create_memory(index, flags);
-       }
-
-       return TRUE;
-}
diff --git a/src/lib-index/mail-index-rebuild.c b/src/lib-index/mail-index-rebuild.c
deleted file mode 100644 (file)
index 25669bc..0000000
+++ /dev/null
@@ -1,47 +0,0 @@
-/* Copyright (C) 2002-2003 Timo Sirainen */
-
-#include "lib.h"
-#include "mail-index.h"
-#include "mail-index-util.h"
-#include "mail-cache.h"
-
-#include <sys/mman.h>
-
-int mail_index_rebuild(struct mail_index *index)
-{
-       if (!mail_index_set_lock(index, MAIL_LOCK_EXCLUSIVE))
-               return FALSE;
-
-       index->set_flags &= ~MAIL_INDEX_HDR_FLAG_REBUILD;
-
-       /* reset the header */
-       mail_index_init_header(index->header);
-       index->mmap_used_length = index->header->used_file_size;
-
-       /* update indexid, which also means that our state has completely
-          changed */
-       index->indexid = index->header->indexid;
-       index->inconsistent = TRUE;
-       index->rebuilding = TRUE;
-
-       if (!index->anon_mmap) {
-               if (msync(index->mmap_base, index->header_size, MS_SYNC) < 0)
-                       return index_set_syscall_error(index, "msync()");
-       }
-
-       if (!mail_cache_truncate(index->cache))
-               return FALSE;
-
-       /* read the mails by syncing */
-       if (!index->sync_and_lock(index, FALSE, MAIL_LOCK_UNLOCK, NULL))
-               return FALSE;
-
-       /* rebuild is complete - remove the flag */
-       index->header->flags &= ~(MAIL_INDEX_HDR_FLAG_REBUILD |
-                                 MAIL_INDEX_HDR_FLAG_FSCK);
-       index->header->flags |= index->set_flags;
-       index->set_flags = 0;
-
-       index->rebuilding = FALSE;
-       return TRUE;
-}
diff --git a/src/lib-index/mail-index-util.c b/src/lib-index/mail-index-util.c
deleted file mode 100644 (file)
index 62bf7aa..0000000
+++ /dev/null
@@ -1,154 +0,0 @@
-/* Copyright (C) 2002 Timo Sirainen */
-
-#include "lib.h"
-#include "istream.h"
-#include "hostpid.h"
-#include "file-lock.h"
-#include "message-size.h"
-#include "message-part-serialize.h"
-#include "mail-index.h"
-#include "mail-index-util.h"
-
-#include <unistd.h>
-#include <fcntl.h>
-
-int index_set_error(struct mail_index *index, const char *fmt, ...)
-{
-       va_list va;
-
-       i_free(index->error);
-
-       if (fmt == NULL)
-               index->error = NULL;
-       else {
-               va_start(va, fmt);
-               index->error = i_strdup_vprintf(fmt, va);
-               va_end(va);
-
-               i_error("%s", index->error);
-       }
-
-       return FALSE;
-}
-
-int index_set_corrupted(struct mail_index *index, const char *fmt, ...)
-{
-       va_list va;
-
-       INDEX_MARK_CORRUPTED(index);
-       index->inconsistent = TRUE;
-
-       va_start(va, fmt);
-       t_push();
-       index_set_error(index, "Corrupted index file %s: %s",
-                       index->filepath, t_strdup_vprintf(fmt, va));
-       t_pop();
-       va_end(va);
-
-       return FALSE;
-}
-
-int index_set_syscall_error(struct mail_index *index, const char *function)
-{
-       i_assert(function != NULL);
-
-       if (ENOSPACE(errno)) {
-               index->nodiskspace = TRUE;
-               return FALSE;
-       }
-
-       index_set_error(index, "%s failed with index file %s: %m",
-                       function, index->filepath);
-       return FALSE;
-}
-
-int index_file_set_syscall_error(struct mail_index *index, const char *filepath,
-                                const char *function)
-{
-       i_assert(filepath != NULL);
-       i_assert(function != NULL);
-
-       if (ENOSPACE(errno)) {
-               index->nodiskspace = TRUE;
-               return FALSE;
-       }
-
-       index_set_error(index, "%s failed with file %s: %m",
-                       function, filepath);
-
-       return FALSE;
-}
-
-void index_reset_error(struct mail_index *index)
-{
-       if (index->error != NULL) {
-               i_free(index->error);
-               index->error = NULL;
-       }
-
-       index->nodiskspace = FALSE;
-}
-
-int mail_index_create_temp_file(struct mail_index *index, const char **path)
-{
-       int fd;
-
-       /* use ".temp.host.pid" as temporary file name. unlink() it first,
-          just to be sure it's not symlinked somewhere for some reason..
-          FIXME: this function should rather be removed entirely. With
-          in-memory indexes index->dir is NULL, so we fallback to /tmp
-           so that mbox rewriting doesn't crash. */
-       *path = t_strconcat(index->dir != NULL ? index->dir : "/tmp",
-                           "/.temp.", my_hostname, ".", my_pid, NULL);
-       (void)unlink(*path);
-
-       /* usage of O_EXCL isn't exactly needed since the path should be
-          trusted, but it shouldn't hurt either - if creating file fails
-          because of it, it's because something must be wrong (race
-          condition). also, might not won't work through NFS but that
-          can't be helped. */
-       fd = open(*path, O_RDWR | O_CREAT | O_EXCL, 0660);
-       if (fd == -1) {
-               if (ENOSPACE(errno))
-                       index->nodiskspace = TRUE;
-               else {
-                       index_set_error(index, "Can't create temp index %s: %m",
-                                       *path);
-               }
-       }
-
-       return fd;
-}
-
-static void mail_index_lock_notify(unsigned int secs_left, void *context)
-{
-       struct mail_index *index = context;
-
-       if (index->lock_notify_cb == NULL)
-               return;
-
-       index->lock_notify_cb(MAIL_LOCK_NOTIFY_INDEX_ABORT, secs_left,
-                             index->lock_notify_context);
-}
-
-int mail_index_wait_lock(struct mail_index *index, int lock_type)
-{
-       int ret;
-
-       ret = file_wait_lock_full(index->fd, lock_type, DEFAULT_LOCK_TIMEOUT,
-                                 mail_index_lock_notify, index);
-       if (ret < 0)
-               return index_set_syscall_error(index, "file_wait_lock()");
-
-       if (ret == 0) {
-               index_set_error(index, "Timeout while waiting for release of "
-                               "%s fcntl() lock for index file %s",
-                               lock_type == F_WRLCK ? "exclusive" : "shared",
-                               index->filepath);
-               index->index_lock_timeout = TRUE;
-               return FALSE;
-       }
-
-       return TRUE;
-
-}
diff --git a/src/lib-index/mail-index-util.h b/src/lib-index/mail-index-util.h
deleted file mode 100644 (file)
index 203981f..0000000
+++ /dev/null
@@ -1,43 +0,0 @@
-#ifndef __MAIL_INDEX_UTIL_H
-#define __MAIL_INDEX_UTIL_H
-
-/* Get index's lock state as mprotect() argument */
-#define MAIL_INDEX_PROT(index) \
-       ((index)->lock_type == MAIL_LOCK_EXCLUSIVE ? (PROT_READ|PROT_WRITE) : \
-        (index)->lock_type == MAIL_LOCK_SHARED || !(index)->opened ? \
-        PROT_READ : PROT_NONE)
-
-/* DEBUG: Force mmap() locks with mprotect() */
-#ifdef DEBUG
-#  define debug_mprotect(mmap_base, mmap_length, index) \
-       mprotect(mmap_base, mmap_length, MAIL_INDEX_PROT(index))
-#else
-#  define debug_mprotect(mmap_base, mmap_length, index)
-#endif
-
-/* Set the current error message */
-int index_set_error(struct mail_index *index, const char *fmt, ...)
-       __attr_format__(2, 3);
-
-/* "Error in index file %s: ...". Also marks the index file as corrupted. */
-int index_set_corrupted(struct mail_index *index, const char *fmt, ...)
-       __attr_format__(2, 3);
-
-/* "%s failed with index file %s: %m" */
-int index_set_syscall_error(struct mail_index *index, const char *function);
-
-/* "%s failed with file %s: %m" */
-int index_file_set_syscall_error(struct mail_index *index, const char *filepath,
-                                const char *function);
-
-/* Reset the current error */
-void index_reset_error(struct mail_index *index);
-
-/* Create temporary file into index's directory. Returns opened file handle
-   and sets *path to the full path of the created file.  */
-int mail_index_create_temp_file(struct mail_index *index, const char **path);
-
-/* Wrapper to file_set_lock(), also calling index's lock notify callback. */
-int mail_index_wait_lock(struct mail_index *index, int lock_type);
-
-#endif
diff --git a/src/lib-index/mail-index.c b/src/lib-index/mail-index.c
deleted file mode 100644 (file)
index 83dba8b..0000000
+++ /dev/null
@@ -1,735 +0,0 @@
-/* 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-util.h"
-#include "mail-cache.h"
-#include "mail-modifylog.h"
-#include "mail-custom-flags.h"
-
-#include <unistd.h>
-#include <fcntl.h>
-
-static void update_header(struct mail_index *index)
-{
-       struct mail_index_header *hdr = index->header;
-
-       index->cache_sync_id = hdr->cache_sync_id;
-       index->log_sync_id = hdr->log_sync_id;
-       index->sync_stamp = hdr->sync_stamp;
-       index->sync_size = hdr->sync_size;
-}
-
-static int mmap_verify(struct mail_index *index)
-{
-       struct mail_index_header *hdr;
-       unsigned int extra;
-
-       index->mmap_used_length = 0;
-
-       if (index->mmap_full_length < sizeof(struct mail_index_header)) {
-                index_set_corrupted(index, "File too small");
-               return FALSE;
-       }
-
-       /* keep the header set even if we fail, so we can update the flags */
-       hdr = index->mmap_base;
-       index->header = hdr;
-       index->header_size = hdr->header_size;
-
-       if (index->header_size > index->mmap_full_length) {
-               index_set_corrupted(index, "Invalid header_size in header "
-                                   "(%"PRIuSIZE_T")", index->header_size);
-               return FALSE;
-       }
-
-       extra = (index->mmap_full_length - index->header_size) %
-               sizeof(struct mail_index_record);
-
-       if (extra != 0) {
-               /* partial write or corrupted -
-                  truncate the file to valid length */
-               i_assert(!index->anon_mmap);
-
-               index->mmap_full_length -= extra;
-               (void)ftruncate(index->fd, (off_t)index->mmap_full_length);
-       }
-
-       if (hdr->used_file_size > index->mmap_full_length) {
-               index_set_corrupted(index,
-                                   "used_file_size larger than real file size "
-                                   "(%u vs %"PRIuSIZE_T")",
-                                   hdr->used_file_size,
-                                   index->mmap_full_length);
-               return FALSE;
-       }
-
-       if (hdr->used_file_size < index->header_size ||
-           (hdr->used_file_size - index->header_size) %
-           sizeof(struct mail_index_record) != 0) {
-               index_set_corrupted(index, "Invalid used_file_size in header "
-                                   "(%u)", hdr->used_file_size);
-               return FALSE;
-       }
-
-       if (hdr->messages_count < hdr->seen_messages_count) {
-               index_set_corrupted(index, "Invalid seen messages count "
-                                   "(%u < %u)", hdr->messages_count,
-                                   hdr->seen_messages_count);
-               return FALSE;
-       }
-
-       if (hdr->messages_count < hdr->deleted_messages_count) {
-               index_set_corrupted(index, "Invalid deleted messages count "
-                                   "(%u < %u)", hdr->messages_count,
-                                   hdr->deleted_messages_count);
-               return FALSE;
-       }
-
-       index->master_sync_id = hdr->master_sync_id;
-       index->mmap_used_length = hdr->used_file_size;
-        update_header(index);
-       return TRUE;
-}
-
-int mail_index_mmap_update(struct mail_index *index)
-{
-       if (index->anon_mmap)
-               return mmap_verify(index);
-
-       if (index->mmap_base != NULL) {
-               index->header = (struct mail_index_header *) index->mmap_base;
-               update_header(index);
-
-               if (index->mmap_invalidate) {
-                       if (msync(index->mmap_base,
-                                 index->mmap_used_length,
-                                 MS_SYNC | MS_INVALIDATE) < 0) {
-                               index_set_syscall_error(index, "msync()");
-                               return FALSE;
-                       }
-               }
-
-               /* make sure file size hasn't changed */
-               if (index->header->master_sync_id == index->master_sync_id) {
-                       index->mmap_used_length = index->header->used_file_size;
-                       if (index->mmap_used_length > index->mmap_full_length) {
-                               i_panic("Index file size was grown without "
-                                       "updating sync_id");
-                       }
-                       return TRUE;
-               }
-
-               if (!index->mmap_invalidate) {
-                       if (msync(index->mmap_base,
-                                 index->mmap_used_length, MS_SYNC) < 0) {
-                               index_set_syscall_error(index, "msync()");
-                               return FALSE;
-                       }
-               }
-
-               if (munmap(index->mmap_base, index->mmap_full_length) < 0)
-                       return index_set_syscall_error(index, "munmap()");
-       }
-
-       index->mmap_base = mmap_rw_file(index->fd, &index->mmap_full_length);
-       if (index->mmap_base == MAP_FAILED) {
-               index->mmap_base = NULL;
-               index->mmap_used_length = 0;
-               index_set_syscall_error(index, "mmap()");
-               return FALSE;
-       }
-
-       return mmap_verify(index);
-}
-
-void mail_index_close(struct mail_index *index)
-{
-       if (index->set_flags != 0) {
-               if (index->header != NULL) {
-#ifdef DEBUG
-                       mprotect(index->mmap_base, index->mmap_used_length,
-                                PROT_READ|PROT_WRITE);
-#endif
-                       index->header->flags |= index->set_flags;
-                       (void)msync(index->mmap_base, index->header_size,
-                                   MS_SYNC);
-               }
-               index->set_flags = 0;
-       }
-
-       index->opened = FALSE;
-       index->inconsistent = FALSE;
-
-       index->lock_type = MAIL_LOCK_UNLOCK;
-       index->header = NULL;
-
-       if (index->fd != -1) {
-               if (close(index->fd) < 0)
-                       index_set_syscall_error(index, "close()");
-               index->fd = -1;
-       }
-
-       if (index->filepath != NULL) {
-               i_free(index->filepath);
-               index->filepath = NULL;
-       }
-
-       if (index->anon_mmap) {
-               if (munmap_anon(index->mmap_base, index->mmap_full_length) < 0)
-                       index_set_syscall_error(index, "munmap_anon()");
-               index->anon_mmap = FALSE;
-       } else if (index->mmap_base != NULL) {
-               if (munmap(index->mmap_base, index->mmap_full_length) < 0)
-                       index_set_syscall_error(index, "munmap()");
-       }
-       index->mmap_base = NULL;
-
-       if (index->cache != NULL) {
-                mail_cache_free(index->cache);
-               index->cache = NULL;
-       }
-
-       if (index->modifylog != NULL) {
-                mail_modifylog_free(index->modifylog);
-               index->modifylog = NULL;
-       }
-
-       if (index->custom_flags != NULL) {
-               mail_custom_flags_free(index->custom_flags);
-                index->custom_flags = NULL;
-       }
-
-       if (index->error != NULL) {
-               i_free(index->error);
-               index->error = NULL;
-       }
-}
-
-static int mail_index_sync_file(struct mail_index *index)
-{
-       unsigned int i;
-       int failed, fsync_fds[3];
-
-       if (index->anon_mmap)
-               return TRUE;
-
-       for (i = 0; i < sizeof(fsync_fds)/sizeof(fsync_fds[0]); i++)
-               fsync_fds[i] = -1;
-
-       if (msync(index->mmap_base, index->mmap_used_length, MS_SYNC) < 0)
-               return index_set_syscall_error(index, "msync()");
-
-       failed = FALSE;
-
-       if (index->modifylog != NULL) {
-               if (!mail_modifylog_sync_file(index->modifylog, &fsync_fds[2]))
-                       failed = TRUE;
-       }
-
-       for (i = 0; i < sizeof(fsync_fds)/sizeof(fsync_fds[0]); i++) {
-               if (fsync_fds[i] != -1 && fdatasync(fsync_fds[i]) < 0)
-                       index_set_error(index, "fdatasync(%u) failed: %m", i);
-       }
-
-       if (fdatasync(index->fd) < 0)
-               return index_set_syscall_error(index, "fdatasync()");
-
-       return !failed;
-}
-
-int mail_index_fmdatasync(struct mail_index *index, size_t size)
-{
-       i_assert(index->lock_type == MAIL_LOCK_EXCLUSIVE);
-
-       if (!index->anon_mmap) {
-               if (msync(index->mmap_base, size, MS_SYNC) < 0)
-                       return index_set_syscall_error(index, "msync()");
-               if (fdatasync(index->fd) < 0)
-                       return index_set_syscall_error(index, "fdatasync()");
-       }
-
-       return TRUE;
-}
-
-static void mail_index_update_header_changes(struct mail_index *index)
-{
-       if (index->set_flags != 0) {
-               index->header->flags |= index->set_flags;
-               index->set_flags = 0;
-       }
-}
-
-static int mail_index_write_header_changes(struct mail_index *index)
-{
-       int failed = FALSE;
-
-       /* use our own locking here so we don't mess up with any other
-          index states, like inconsistency. */
-       if (!mail_index_wait_lock(index, F_WRLCK))
-               return FALSE;
-
-#ifdef DEBUG
-       mprotect(index->mmap_base, index->mmap_used_length,
-                PROT_READ|PROT_WRITE);
-#endif
-
-       mail_index_update_header_changes(index);
-
-       if (!index->anon_mmap) {
-               if (msync(index->mmap_base, index->header_size, MS_SYNC) < 0) {
-                       index_set_syscall_error(index, "msync()");
-                       failed = TRUE;
-               }
-       }
-
-#ifdef DEBUG
-       mprotect(index->mmap_base, index->mmap_used_length, PROT_NONE);
-#endif
-
-       if (!mail_index_wait_lock(index, F_UNLCK))
-               return FALSE;
-
-       return !failed;
-}
-
-static int mail_index_lock_remove(struct mail_index *index)
-{
-       enum mail_lock_type old_lock_type;
-       int ret = TRUE;
-
-       while (index->cache_later_locks > 0) {
-               if (!mail_cache_unlock(index->cache))
-                       ret = FALSE;
-               index->cache_later_locks--;
-       }
-
-       if (!mail_index_wait_lock(index, F_UNLCK))
-               return FALSE;
-
-       old_lock_type = index->lock_type;
-       index->lock_type = MAIL_LOCK_UNLOCK;
-
-       if (old_lock_type == MAIL_LOCK_SHARED) {
-               /* releasing shared lock. we may need to update some
-                  flags in header. */
-               unsigned int old_flags;
-
-               old_flags = index->header->flags;
-
-               if ((old_flags | index->set_flags) != old_flags)
-                       return mail_index_write_header_changes(index);
-       }
-
-        debug_mprotect(index->mmap_base, index->mmap_full_length, index);
-       return ret;
-}
-
-static int mail_index_lock_change(struct mail_index *index,
-                                 enum mail_lock_type lock_type, int try_lock)
-{
-       int ret, fd_lock_type;
-
-       /* shared -> exclusive can deadlock */
-       i_assert(try_lock || lock_type != MAIL_LOCK_EXCLUSIVE ||
-                index->lock_type != MAIL_LOCK_SHARED);
-
-       /* locking index when cache is locked can deadlock */
-       i_assert(try_lock || index->lock_type == MAIL_LOCK_EXCLUSIVE ||
-                index->cache == NULL || !mail_cache_is_locked(index->cache));
-
-       if (index->inconsistent) {
-               /* index is in inconsistent state and nothing else than
-                  free() is allowed for it. */
-               if (index->error == NULL) {
-                       index->error =
-                               i_strdup("Index is in inconsistent state");
-               }
-               return FALSE;
-       }
-
-       fd_lock_type = MAIL_LOCK_TO_FLOCK(lock_type);
-       if (try_lock) {
-               ret = file_try_lock(index->fd, fd_lock_type);
-               if (ret < 0)
-                       index_set_syscall_error(index, "file_try_lock()");
-               if (ret <= 0)
-                       return FALSE;
-       } else {
-               if (!mail_index_wait_lock(index, fd_lock_type))
-                       return FALSE;
-       }
-
-       index->lock_type = lock_type;
-       debug_mprotect(index->mmap_base, index->mmap_full_length, index);
-
-       if (!mail_index_mmap_update(index)) {
-               (void)index->set_lock(index, MAIL_LOCK_UNLOCK);
-               return FALSE;
-       }
-
-       if (index->indexid != index->header->indexid) {
-               /* index was rebuilt, there's no way we can maintain
-                  consistency */
-               index_set_error(index, "Warning: Inconsistency - Index "
-                               "%s was rebuilt while we had it open",
-                               index->filepath);
-               index->inconsistent = TRUE;
-               return FALSE;
-       }
-
-       if (index->header->flags & MAIL_INDEX_HDR_FLAG_FSCK) {
-               /* someone just partially updated the index, need to fsck it */
-               if (lock_type == MAIL_LOCK_SHARED) {
-                       /* we need exclusive lock so fsck()'s set_lock() won't
-                          get us back here */
-                       if (!mail_index_lock_remove(index))
-                               return FALSE;
-
-                       if (!mail_index_wait_lock(index, F_WRLCK))
-                               return FALSE;
-                       index->lock_type = MAIL_LOCK_EXCLUSIVE;
-
-                       debug_mprotect(index->mmap_base,
-                                      index->mmap_full_length, index);
-               }
-
-               /* check again, in case it was already fscked while we had
-                  it unlocked for a while */
-               if (index->header->flags & MAIL_INDEX_HDR_FLAG_FSCK) {
-                       if (!index->fsck(index))
-                               return FALSE;
-               }
-
-               if (lock_type == MAIL_LOCK_SHARED) {
-                       /* drop exclusive lock */
-                       return index->set_lock(index, lock_type);
-               }
-       }
-
-       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. */
-               index->excl_lock_counter++;
-               index->header->flags |= MAIL_INDEX_HDR_FLAG_FSCK;
-               if (!mail_index_fmdatasync(index, index->header_size)) {
-                       (void)index->set_lock(index, MAIL_LOCK_UNLOCK);
-                       return FALSE;
-               }
-       }
-
-       return TRUE;
-}
-
-static int mail_index_lock_full(struct mail_index *index,
-                               enum mail_lock_type lock_type, int try_lock)
-{
-       int keep_fsck;
-
-       if (index->lock_type == lock_type)
-               return TRUE;
-
-       if (index->lock_type == MAIL_LOCK_EXCLUSIVE) {
-               index->excl_lock_counter++;
-               if (index->modifylog != NULL)
-                       mail_modifylog_notify_lock_drop(index->modifylog);
-       }
-
-       if (index->anon_mmap) {
-               /* anonymous mmaps are private and don't need any locking */
-#ifdef DEBUG
-               mprotect(index->mmap_base, index->mmap_used_length,
-                        PROT_READ|PROT_WRITE);
-#endif
-               mail_index_update_header_changes(index);
-
-               index->lock_type = lock_type;
-               debug_mprotect(index->mmap_base, index->mmap_full_length,
-                              index);
-               return TRUE;
-       }
-
-       if (index->lock_type == MAIL_LOCK_EXCLUSIVE) {
-               /* dropping exclusive lock (either unlock or to shared) */
-               keep_fsck = (index->set_flags & MAIL_INDEX_HDR_FLAG_FSCK) != 0;
-               mail_index_update_header_changes(index);
-
-               if (index->sync_dirty_stamp == 0) {
-                       index->header->sync_stamp = index->sync_stamp;
-                       index->header->sync_size = index->sync_size;
-               }
-
-               /* remove the FSCK flag only after successful fsync() */
-               if (mail_index_sync_file(index) && !keep_fsck) {
-                       index->header->flags &= ~MAIL_INDEX_HDR_FLAG_FSCK;
-                       if (msync(index->mmap_base, index->header_size,
-                                 MS_SYNC) < 0) {
-                               /* we only failed to remove the fsck flag,
-                                  so this isn't fatal. */
-                               index_set_syscall_error(index, "msync()");
-                       }
-               }
-       }
-
-       if (lock_type == MAIL_LOCK_UNLOCK)
-               return mail_index_lock_remove(index);
-       else
-               return mail_index_lock_change(index, lock_type, try_lock);
-}
-
-int mail_index_set_lock(struct mail_index *index, enum mail_lock_type lock_type)
-{
-       return mail_index_lock_full(index, lock_type, FALSE);
-}
-
-int mail_index_try_lock(struct mail_index *index, enum mail_lock_type lock_type)
-{
-       return mail_index_lock_full(index, lock_type, TRUE);
-}
-
-void mail_index_set_lock_notify_callback(struct mail_index *index,
-                                        mail_lock_notify_callback_t callback,
-                                        void *context)
-{
-       index->lock_notify_cb = callback;
-       index->lock_notify_context = context;
-}
-
-struct mail_index_header *mail_index_get_header(struct mail_index *index)
-{
-       i_assert(index->lock_type != MAIL_LOCK_UNLOCK);
-
-       return index->header;
-}
-
-void mail_index_mark_flag_changes(struct mail_index *index,
-                                 struct mail_index_record *rec,
-                                 enum mail_flags old_flags,
-                                 enum mail_flags new_flags)
-{
-       if ((old_flags & MAIL_SEEN) == 0 && (new_flags & MAIL_SEEN)) {
-               /* unseen -> seen */
-               index->header->seen_messages_count++;
-               if (index->header->first_unseen_uid_lowwater == rec->uid)
-                       index->header->first_unseen_uid_lowwater++;
-       } else if ((old_flags & MAIL_SEEN) && (new_flags & MAIL_SEEN) == 0) {
-               /* seen -> unseen */
-               if (index->header->seen_messages_count ==
-                   index->header->messages_count) {
-                       /* this is the first unseen message */
-                        index->header->first_unseen_uid_lowwater = rec->uid;
-               } else if (rec->uid < index->header->first_unseen_uid_lowwater)
-                       index->header->first_unseen_uid_lowwater = rec->uid;
-
-               if (index->header->seen_messages_count == 0) {
-                       index_set_corrupted(index,
-                               "seen_messages_count in header is invalid");
-               } else {
-                       index->header->seen_messages_count--;
-               }
-       }
-
-       if ((old_flags & MAIL_DELETED) == 0 && (new_flags & MAIL_DELETED)) {
-               /* undeleted -> deleted */
-               index->header->deleted_messages_count++;
-
-               if (index->header->deleted_messages_count == 1) {
-                       /* this is the first deleted message */
-                       index->header->first_deleted_uid_lowwater = rec->uid;
-               } else if (rec->uid < index->header->first_deleted_uid_lowwater)
-                       index->header->first_deleted_uid_lowwater = rec->uid;
-       } else if ((old_flags & MAIL_DELETED) &&
-                  (new_flags & MAIL_DELETED) == 0) {
-               /* deleted -> undeleted */
-               if (index->header->first_deleted_uid_lowwater == rec->uid)
-                       index->header->first_deleted_uid_lowwater++;
-               if (index->header->deleted_messages_count == 0) {
-                       index_set_corrupted(index,
-                               "deleted_messages_count in header is invalid");
-               } else {
-                       index->header->deleted_messages_count--;
-               }
-       }
-}
-
-#define INDEX_NEED_COMPRESS(records, hdr) \
-       ((records) > INDEX_MIN_RECORDS_COUNT && \
-        (records) * (100-INDEX_COMPRESS_PERCENTAGE) / 100 > \
-               (hdr)->messages_count)
-
-int mail_index_expunge(struct mail_index *index,
-                      struct mail_index_record *first_rec,
-                      struct mail_index_record *last_rec,
-                      unsigned int first_seq, unsigned int last_seq,
-                      int external_change)
-{
-       unsigned int first_uid, last_uid;
-
-       i_assert(index->lock_type == MAIL_LOCK_EXCLUSIVE);
-       i_assert(first_seq != 0);
-       i_assert(first_seq <= last_seq);
-
-       index->expunge_counter++;
-
-       first_uid = first_rec->uid;
-       last_uid = last_rec->uid;
-
-       if (!mail_index_expunge_record_range(index, first_rec, last_rec))
-               return FALSE;
-
-       if (index->modifylog != NULL) {
-               if (!mail_modifylog_add_expunges(index->modifylog,
-                                                first_seq, last_seq,
-                                                first_uid, last_uid,
-                                                external_change))
-                       return FALSE;
-       }
-
-       if (index->header->messages_count == 0) {
-               /* all mail was deleted, truncate cache file */
-               if (!mail_cache_truncate(index->cache))
-                       return FALSE;
-       }
-
-       return TRUE;
-}
-
-int mail_index_update_flags(struct mail_index *index,
-                           struct mail_index_record *rec, unsigned int seq,
-                           enum modify_type modify_type, enum mail_flags flags,
-                           int external_change)
-{
-       enum mail_flags new_flags;
-
-       i_assert(index->lock_type == MAIL_LOCK_EXCLUSIVE);
-       i_assert(seq != 0);
-
-       switch (modify_type) {
-       case MODIFY_ADD:
-               new_flags = rec->msg_flags | flags;
-               break;
-       case MODIFY_REMOVE:
-               new_flags = rec->msg_flags & ~flags;
-               break;
-       case MODIFY_REPLACE:
-               new_flags = flags;
-               break;
-       default:
-               new_flags = 0;
-               i_unreached();
-       }
-
-       if (new_flags == rec->msg_flags)
-               return TRUE; /* no changes */
-
-        mail_index_mark_flag_changes(index, rec, rec->msg_flags, new_flags);
-
-       rec->msg_flags = new_flags;
-       return index->modifylog == NULL ? TRUE :
-               mail_modifylog_add_flags(index->modifylog, seq,
-                                        rec->uid, external_change);
-}
-
-static int mail_index_grow(struct mail_index *index)
-{
-       uoff_t pos;
-       unsigned int grow_count;
-       void *base;
-
-       grow_count = index->header->messages_count *
-               INDEX_GROW_PERCENTAGE / 100;
-       if (grow_count < 16)
-               grow_count = 16;
-
-       pos = index->mmap_full_length +
-               (grow_count * sizeof(struct mail_index_record));
-       i_assert(pos < OFF_T_MAX);
-
-       if (index->anon_mmap) {
-               i_assert(pos < SSIZE_T_MAX);
-
-               base = mremap_anon(index->mmap_base, index->mmap_full_length,
-                                  (size_t)pos, MREMAP_MAYMOVE);
-               if (base == MAP_FAILED)
-                       return index_set_syscall_error(index, "mremap_anon()");
-
-               index->mmap_base = base;
-               index->mmap_full_length = (size_t)pos;
-               return mmap_verify(index);
-       }
-
-       if (file_set_size(index->fd, (off_t)pos) < 0)
-               return index_set_syscall_error(index, "file_set_size()");
-
-       /* file size changed, let others know about it too by changing
-          sync_id in header. */
-       index->header->master_sync_id++;
-
-       if (!mail_index_mmap_update(index))
-               return FALSE;
-
-       return TRUE;
-}
-
-struct mail_index_record *mail_index_append(struct mail_index *index)
-{
-       struct mail_index_record *rec;
-
-       i_assert(index->lock_type == MAIL_LOCK_EXCLUSIVE);
-
-       if (index->header->next_uid == MAX_ALLOWED_UID) {
-               index->set_flags |= MAIL_INDEX_HDR_FLAG_REBUILD;
-               index_set_error(index, "Reached maximum UID in mailbox %s, "
-                               "rebuilding index", index->filepath);
-               return NULL;
-       }
-
-       if (index->mmap_used_length == index->mmap_full_length) {
-               if (!mail_index_grow(index))
-                       return NULL;
-       }
-
-       i_assert(index->header->used_file_size == index->mmap_used_length);
-       i_assert(index->mmap_used_length + sizeof(struct mail_index_record) <=
-                index->mmap_full_length);
-
-       index->header->messages_count++;
-
-       rec = (struct mail_index_record *) ((char *) index->mmap_base +
-                                           index->mmap_used_length);
-       rec->uid = index->header->next_uid++;
-       rec->msg_flags = 0;
-       rec->cache_offset = 0;
-
-       index->header->used_file_size += sizeof(*rec);
-       index->mmap_used_length += sizeof(*rec);
-
-       return rec;
-}
-
-enum mail_index_error mail_index_get_last_error(struct mail_index *index)
-{
-       if (index->inconsistent)
-               return MAIL_INDEX_ERROR_INCONSISTENT;
-       if (index->nodiskspace)
-               return MAIL_INDEX_ERROR_DISKSPACE;
-       if (index->index_lock_timeout)
-               return MAIL_INDEX_ERROR_INDEX_LOCK_TIMEOUT;
-       if (index->mailbox_lock_timeout)
-               return MAIL_INDEX_ERROR_MAILBOX_LOCK_TIMEOUT;
-
-       if (index->error != NULL)
-               return MAIL_INDEX_ERROR_INTERNAL;
-
-       return MAIL_INDEX_ERROR_NONE;
-}
-
-const char *mail_index_get_last_error_text(struct mail_index *index)
-{
-       return index->error;
-}
diff --git a/src/lib-index/mail-index.h b/src/lib-index/mail-index.h
deleted file mode 100644 (file)
index 699a190..0000000
+++ /dev/null
@@ -1,496 +0,0 @@
-#ifndef __MAIL_INDEX_H
-#define __MAIL_INDEX_H
-
-#include "file-dotlock.h"
-#include "message-parser.h"
-#include "imap-util.h"
-
-#define MAIL_INDEX_MAJOR_VERSION 3
-#define MAIL_INDEX_MINOR_VERSION 0
-
-#define INDEX_FILE_PREFIX ".imap.index"
-
-enum mail_index_open_flags {
-       /* Create index if it doesn't exist */
-       MAIL_INDEX_OPEN_FLAG_CREATE             = 0x01,
-       /* Update \Recent flag counters */
-       MAIL_INDEX_OPEN_FLAG_UPDATE_RECENT      = 0x02,
-       /* Compressing and cache updates are not performed */
-       MAIL_INDEX_OPEN_FLAG_FAST               = 0x04,
-       /* Invalidate memory maps before accessing them */
-       MAIL_INDEX_OPEN_FLAG_MMAP_INVALIDATE    = 0x08,
-
-       /* internal: we're creating the index */
-       _MAIL_INDEX_OPEN_FLAG_CREATING          = 0x100
-};
-
-enum mail_index_header_compat_flags {
-       MAIL_INDEX_COMPAT_LITTLE_ENDIAN         = 0x01
-};
-
-enum mail_index_header_flag {
-       /* Rebuild flag is set while index is being rebuilt or when
-          some error is noticed in the index file. If this flag is set,
-          the index shouldn't be used before rebuilding it. */
-       MAIL_INDEX_HDR_FLAG_FSCK                = 0x0001,
-       MAIL_INDEX_HDR_FLAG_REBUILD             = 0x0002,
-       MAIL_INDEX_HDR_FLAG_COMPRESS            = 0x0004,
-       MAIL_INDEX_HDR_FLAG_COMPRESS_CACHE      = 0x0008,
-       MAIL_INDEX_HDR_FLAG_DIRTY_MESSAGES      = 0x0010,
-       MAIL_INDEX_HDR_FLAG_DIRTY_CUSTOMFLAGS   = 0x0020,
-       MAIL_INDEX_HDR_FLAG_MAILDIR_NEW         = 0x0040
-};
-
-enum mail_index_record_flag {
-       /* If binary flags are set, it's not checked whether mail is
-          missing CRs. So this flag may be set as an optimization for
-          regular non-binary mails as well if it's known that it contains
-          valid CR+LF line breaks. */
-       MAIL_INDEX_FLAG_BINARY_HEADER           = 0x0001,
-       MAIL_INDEX_FLAG_BINARY_BODY             = 0x0002,
-
-       /* Mail flags have been changed in index, but not written into
-          actual mailbox yet. */
-       MAIL_INDEX_FLAG_DIRTY                   = 0x0004,
-
-       /* Maildir: Mail file is in new/ dir instead of cur/ */
-       MAIL_INDEX_FLAG_MAILDIR_NEW             = 0x0008,
-
-       /* Mail header or body is known to contain NUL characters. */
-       MAIL_INDEX_FLAG_HAS_NULS                = 0x0010,
-       /* Mail header or body is known to not contain NUL characters. */
-       MAIL_INDEX_FLAG_HAS_NO_NULS             = 0x0020
-};
-
-enum mail_lock_type {
-       MAIL_LOCK_UNLOCK = 0,
-       MAIL_LOCK_SHARED,
-       MAIL_LOCK_EXCLUSIVE
-};
-
-enum mail_lock_notify_type {
-       /* Mailbox is locked, will abort in secs_left */
-       MAIL_LOCK_NOTIFY_MAILBOX_ABORT,
-       /* Mailbox lock looks stale, will override in secs_left */
-       MAIL_LOCK_NOTIFY_MAILBOX_OVERRIDE,
-       /* Index is locked, will abort in secs_left */
-       MAIL_LOCK_NOTIFY_INDEX_ABORT
-};
-
-enum mail_index_error {
-       /* No errors */
-       MAIL_INDEX_ERROR_NONE,
-       /* Internal error, see get_error_text() for more information. */
-       MAIL_INDEX_ERROR_INTERNAL,
-       /* Index is now in inconsistent state with the previous known state,
-          meaning that the message IDs etc. may have changed - only way to
-          recover this would be to fully close the mailbox and reopen it.
-          With IMAP this would mean a forced disconnection since we can't do
-          forced CLOSE. */
-       MAIL_INDEX_ERROR_INCONSISTENT,
-       /* We ran out of available disk space. */
-       MAIL_INDEX_ERROR_DISKSPACE,
-       /* Mail index locking timeouted */
-       MAIL_INDEX_ERROR_INDEX_LOCK_TIMEOUT,
-       /* Mailbox locking timeouted */
-       MAIL_INDEX_ERROR_MAILBOX_LOCK_TIMEOUT
-};
-
-typedef void mail_lock_notify_callback_t(enum mail_lock_notify_type notify_type,
-                                        unsigned int secs_left, void *context);
-
-struct mail_index_header {
-       /* major version is increased only when you can't have backwards
-          compatibility. minor version is increased when header size is
-          increased to contain new non-critical fields. */
-       uint8_t major_version;
-       uint8_t minor_version;
-       uint8_t header_size;
-       uint8_t reserved;
-
-       /* 0 = flags
-          1 = sizeof(uoff_t)
-          2 = sizeof(time_t)
-          3 = reserved, 0 for now */
-       uint8_t compat_data[4];
-
-       uint32_t indexid;
-       uint32_t used_file_size;
-
-       /* file needs to be reopened if sync_ids change. */
-       uint32_t master_sync_id;
-       uint32_t cache_sync_id;
-       uint32_t log_sync_id;
-
-       uint32_t flags;
-
-       uint32_t uid_validity;
-       uint32_t next_uid;
-
-       uint32_t messages_count;
-       uint32_t seen_messages_count;
-       uint32_t deleted_messages_count;
-       uint32_t last_nonrecent_uid;
-
-       /* these UIDs may not exist and may not even be unseen */
-       uint32_t first_unseen_uid_lowwater;
-       uint32_t first_deleted_uid_lowwater;
-
-       uint64_t sync_size;
-       uint32_t sync_stamp;
-};
-
-struct mail_index_record {
-       uint32_t uid;
-       uint32_t msg_flags;
-       uint32_t cache_offset;
-};
-
-struct mail_index {
-       /* Note that opening same index twice in the same process is a bad
-          idea since they share the same file locks. As soon one of the
-          indexes is closed, the locks in second index are dropped which
-          especially hurts modify log since it keeps locks all the time. */
-       int (*open)(struct mail_index *index, enum mail_index_open_flags flags);
-
-       /* Free index from memory. */
-       void (*free)(struct mail_index *index);
-
-       /* Lock/unlock index. May block. Note that unlocking must not
-          reset error from get_last_error() as unlocking can be done as
-          a cleanup after some other function failed. Index is always
-          mmap()ed after set_lock() succeeds.
-
-          Trying to change a shared lock into exclusive lock is a fatal
-          error, since it may create a deadlock. Even though operating
-          system should detect it and fail, it's not a good idea to even
-          let it happen. Better ways to do this would be to a) mark the
-          data to be updated later, b) use try_lock() if the update is
-          preferred but not required, c) unlock + lock again, but make
-          sure that won't create race conditions. */
-       int (*set_lock)(struct mail_index *index,
-                       enum mail_lock_type lock_type);
-
-       /* Try locking the index. Returns TRUE if the lock was got and
-          FALSE if lock isn't possible to get currently or some other error
-          occured. Never blocks. */
-       int (*try_lock)(struct mail_index *index,
-                       enum mail_lock_type lock_type);
-
-       /* If we have to wait for the lock, the given lock notify function
-          is called once in a while. */
-       void (*set_lock_notify_callback)(struct mail_index *index,
-                                        mail_lock_notify_callback_t *callback,
-                                        void *context);
-
-       /* Rebuild the whole index. Note that this changes the indexid
-          so all the other files must also be rebuilt after this call.
-          Index MUST NOT have shared lock, but exclusive lock or no lock at
-          all is fine. Note that this function may leave the index
-          exclusively locked, and always sets index->inconsistent = TRUE. */
-       int (*rebuild)(struct mail_index *index);
-
-       /* Verify that the index is valid. If anything invalid is found,
-          index is set inconsistent and to be rebuilt at next open.
-          Same locking issues as with rebuild(). */
-       int (*fsck)(struct mail_index *index);
-
-       /* Synchronize the index with the mailbox. Index must not have shared
-          lock when calling this function. The data_lock_type specifies what
-          lock should be set to data file (mbox file). This function may
-          leave the index in ANY locking state. If changes is non-NULL, it's
-          set to TRUE if any changes were noticed. If minimal_sync is TRUE,
-          we do as little as possible to get data file locked (ie. noop with
-          maildir). */
-       int (*sync_and_lock)(struct mail_index *index, int minimal_sync,
-                            enum mail_lock_type data_lock_type, int *changes);
-
-       /* Returns the index header (never fails). The index needs to be
-          locked before calling this function, and must be kept locked as
-          long as you keep using the returned structure. */
-       struct mail_index_header *(*get_header)(struct mail_index *index);
-
-       /* sequence -> data lookup. The index needs to be locked before calling
-          this function, and must be kept locked as long as you keep using
-          the returned structure. */
-       struct mail_index_record *(*lookup)(struct mail_index *index,
-                                           unsigned int seq);
-
-       /* Return the next record after specified record, or NULL if it was
-          last record. The index must be locked all the time between
-          lookup() and last next() call. rec must not have been expunged. */
-       struct mail_index_record *(*next)(struct mail_index *index,
-                                         struct mail_index_record *rec);
-
-       /* Find first existing UID in range. Sequence number is also retrieved
-          if seq_r is non-NULL. */
-       struct mail_index_record *(*lookup_uid_range)(struct mail_index *index,
-                                                     unsigned int first_uid,
-                                                     unsigned int last_uid,
-                                                     unsigned int *seq_r);
-
-       /* Open mail file and return it as mmap()ed IStream. If we fail,
-          we return NULL and set deleted = TRUE if failure was because the
-          mail was just deleted (ie. not an error). received_date is set
-          if it's non-NULL. */
-       struct istream *(*open_mail)(struct mail_index *index,
-                                    struct mail_index_record *rec,
-                                    time_t *received_date, int *deleted);
-
-       /* Returns received date of message, or (time_t)-1 if error occured. */
-       time_t (*get_received_date)(struct mail_index *index,
-                                   struct mail_index_record *rec);
-
-       /* Expunge mails from index. Modifylog is also updated. The
-          index must be exclusively locked before calling this function.
-
-          first_rec+1 .. last_rec-1 range may contain already expunged
-          records.
-
-          Note that all record pointers are invalidated after this call as
-          expunging may radically modify the file. */
-       int (*expunge)(struct mail_index *index,
-                      struct mail_index_record *first_rec,
-                      struct mail_index_record *last_rec,
-                      unsigned int first_seq, unsigned int last_seq,
-                      int external_change);
-
-       /* Update mail flags. The index must be exclusively locked before
-          calling this function. */
-       int (*update_flags)(struct mail_index *index,
-                           struct mail_index_record *rec, unsigned int seq,
-                           enum modify_type modify_type, enum mail_flags flags,
-                           int external_change);
-
-       /* Append a new record to index. The index must be exclusively
-          locked before calling this function. */
-       struct mail_index_record *(*append)(struct mail_index *index);
-
-       /* Returns the last error code. */
-       enum mail_index_error (*get_last_error)(struct mail_index *index);
-
-       /* Returns the full error message for last error. This message may
-          contain paths etc. so it shouldn't be shown to users. */
-       const char *(*get_last_error_text)(struct mail_index *index);
-
-/* private: */
-       struct mail_cache *cache;
-       struct mail_modify_log *modifylog;
-       struct mail_custom_flags *custom_flags;
-
-       char *dir; /* directory where to place the index files */
-       char *filepath; /* index file path */
-       char *mailbox_path; /* file/directory for mailbox location */
-       char *control_dir; /* destination for control files */
-       unsigned int indexid;
-       unsigned int master_sync_id, cache_sync_id, log_sync_id;
-
-        /* updated whenever exclusive lock is set/unset */
-       unsigned int excl_lock_counter;
-       /* updated whenever expunge() is called */
-       unsigned int expunge_counter;
-
-       int mbox_fd;
-       struct istream *mbox_stream;
-       enum mail_lock_type mbox_lock_type;
-       struct dotlock mbox_dotlock;
-
-       /* these counters can be used to check that we've synced the mailbox
-          after locking it */
-       unsigned int mbox_lock_counter;
-       unsigned int mbox_sync_counter;
-
-       /* last mbox sync: */
-       dev_t mbox_dev;
-       ino_t mbox_ino;
-
-       /* last maildir sync: */
-       time_t last_new_mtime, last_uidlist_mtime;
-       int maildir_lock_fd;
-       pool_t new_filename_pool;
-       struct hash_table *new_filenames;
-
-       int fd; /* opened index file */
-       char *error; /* last error message */
-
-       void *mmap_base;
-       size_t mmap_used_length;
-       size_t mmap_full_length;
-
-       struct mail_index_header *header;
-       size_t header_size;
-
-        enum mail_lock_type lock_type;
-       time_t sync_stamp, sync_dirty_stamp;
-       uoff_t sync_size;
-       time_t next_dirty_flags_flush;
-       unsigned int first_recent_uid;
-
-       mail_lock_notify_callback_t *lock_notify_cb;
-       void *lock_notify_context;
-
-        mode_t mail_create_mode;
-       unsigned int private_flags_mask;
-
-       /* these fields are OR'ed to the fields in index header once we
-          get around grabbing exclusive lock */
-       unsigned int set_flags;
-       unsigned int cache_later_locks;
-
-       unsigned int anon_mmap:1;
-       unsigned int mmap_invalidate:1;
-       unsigned int mbox_rewritten:1;
-       unsigned int opened:1;
-       unsigned int rebuilding:1;
-       unsigned int mail_read_mmaped:1;
-       unsigned int inconsistent:1;
-       unsigned int nodiskspace:1;
-       unsigned int index_lock_timeout:1;
-       unsigned int allow_new_custom_flags:1;
-       unsigned int mailbox_readonly:1;
-       unsigned int mailbox_lock_timeout:1;
-       unsigned int maildir_keep_new:1;
-       unsigned int maildir_have_new:1;
-       unsigned int maildir_synced_once:1;
-};
-
-#ifdef DEV_T_STRUCT
-/* we can't initialize dev_t as 0, and we don't know what it actually
-   contains, so don't initialize them. gcc's -W option should be disabled
-   with this or we get warnings.. */
-#  define MAIL_INDEX_PRIVATE_FILL 0
-#else
-/* needed to remove annoying warnings about not initializing all struct
-   members.. */
-#define MAIL_INDEX_PRIVATE_FILL \
-       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
-       0, 0, 0, 0, 0, 0, { 0, 0, 0 }, 0, \
-       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
-       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
-       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
-       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
-       0, 0
-#endif
-
-/* defaults - same as above but prefixed with mail_index_. */
-int mail_index_open(struct mail_index *index, enum mail_index_open_flags flags);
-int mail_index_set_lock(struct mail_index *index,
-                       enum mail_lock_type lock_type);
-int mail_index_try_lock(struct mail_index *index,
-                       enum mail_lock_type lock_type);
-void mail_index_set_lock_notify_callback(struct mail_index *index,
-                                        mail_lock_notify_callback_t *callback,
-                                        void *context);
-int mail_index_fsck(struct mail_index *index);
-struct mail_index_header *mail_index_get_header(struct mail_index *index);
-struct mail_index_record *mail_index_lookup(struct mail_index *index,
-                                           unsigned int seq);
-struct mail_index_record *mail_index_next(struct mail_index *index,
-                                         struct mail_index_record *rec);
-struct mail_index_record *
-mail_index_lookup_uid_range(struct mail_index *index, unsigned int first_uid,
-                           unsigned int last_uid, unsigned int *seq_r);
-int mail_index_expunge(struct mail_index *index,
-                      struct mail_index_record *first_rec,
-                      struct mail_index_record *last_rec,
-                      unsigned int first_seq, unsigned int last_seq,
-                      int external_change);
-int mail_index_update_flags(struct mail_index *index,
-                           struct mail_index_record *rec, unsigned int seq,
-                           enum modify_type modify_type, enum mail_flags flags,
-                           int external_change);
-struct mail_index_record *mail_index_append(struct mail_index *index);
-enum mail_index_error mail_index_get_last_error(struct mail_index *index);
-const char *mail_index_get_last_error_text(struct mail_index *index);
-
-/* INTERNAL: */
-void mail_index_init(struct mail_index *index, const char *dir);
-int mail_index_mmap_update(struct mail_index *index);
-void mail_index_init_header(struct mail_index_header *hdr);
-void mail_index_close(struct mail_index *index);
-int mail_index_fmdatasync(struct mail_index *index, size_t size);
-void mail_index_mark_flag_changes(struct mail_index *index,
-                                 struct mail_index_record *rec,
-                                 enum mail_flags old_flags,
-                                 enum mail_flags new_flags);
-int mail_index_rebuild(struct mail_index *index);
-int mail_index_compress(struct mail_index *index);
-int mail_index_truncate(struct mail_index *index);
-int mail_index_expunge_record_range(struct mail_index *index,
-                                   struct mail_index_record *first_rec,
-                                   struct mail_index_record *last_rec);
-
-/* Maximum allowed UID number. */
-#define MAX_ALLOWED_UID 4294967295U /* 2^32 - 1 */
-
-/* Max. mmap()ed size for a message */
-#define MAIL_MMAP_BLOCK_SIZE (1024*256)
-/* Block size when read()ing message. */
-#define MAIL_READ_BLOCK_SIZE (1024*8)
-
-/* Delete unused non-local temp files after 24h. Just to be sure we don't
-   delete it too early. The temp files don't harm much anyway. */
-#define TEMP_FILE_TIMEOUT (60*24)
-
-/* number of records to always keep allocated in index file,
-   either used or unused */
-#define INDEX_MIN_RECORDS_COUNT 64
-/* when empty space in index file gets full, grow the file n% larger */
-#define INDEX_GROW_PERCENTAGE 10
-/* ftruncate() the index file when only n% of it is in use */
-#define INDEX_TRUNCATE_PERCENTAGE 30
-/* don't truncate whole file anyway, keep n% of the empty space */
-#define INDEX_TRUNCATE_KEEP_PERCENTAGE 10
-/* Compress the file when deleted space reaches n% of total size */
-#define INDEX_COMPRESS_PERCENTAGE 50
-/* Compress the file when searching deleted records tree has to go this deep */
-#define INDEX_COMPRESS_DEPTH 10
-
-/* uoff_t to index file for given record */
-#define INDEX_FILE_POSITION(index, ptr) \
-       ((uoff_t) ((char *) (ptr) - (char *) ((index)->mmap_base)))
-
-/* record for given index */
-#define INDEX_RECORD_AT(index, idx) \
-       ((struct mail_index_record *) \
-        ((char *) index->mmap_base + (index)->header_size) + (idx))
-
-/* returns the next record after last one */
-#define INDEX_END_RECORD(index) \
-       ((struct mail_index_record *) \
-        ((char *) (index)->mmap_base + (index)->mmap_used_length))
-
-/* index number for uoff_t position */
-#define INDEX_POSITION_INDEX(index, pos) \
-       (((pos) - (index)->header_size) / \
-        sizeof(struct mail_index_record))
-
-/* index number for given record */
-#define INDEX_RECORD_INDEX(index, ptr) \
-       INDEX_POSITION_INDEX(index, INDEX_FILE_POSITION(index, ptr))
-
-/* mark the index corrupted */
-#define INDEX_MARK_CORRUPTED(index) \
-       STMT_START { \
-               (index)->set_flags |= MAIL_INDEX_HDR_FLAG_REBUILD; \
-       } STMT_END
-
-/* get number of records in mmaped index */
-#define MAIL_INDEX_RECORD_COUNT(index) \
-       ((index->mmap_used_length - (index)->header_size) / \
-        sizeof(struct mail_index_record))
-
-/* minimum size for index file */
-#define INDEX_FILE_MIN_SIZE(index) \
-       ((index)->header_size + \
-        INDEX_MIN_RECORDS_COUNT * sizeof(struct mail_index_record))
-
-/* enum mail_lock_type to fcntl() lock type */
-#define MAIL_LOCK_TO_FLOCK(lock_type) \
-        ((lock_type) == MAIL_LOCK_EXCLUSIVE ? F_WRLCK : \
-               (lock_type) == MAIL_LOCK_SHARED ? F_RDLCK : F_UNLCK)
-
-#define INDEX_IS_IN_MEMORY(index) \
-       ((index)->anon_mmap)
-
-#endif
diff --git a/src/lib-index/mail-modifylog.c b/src/lib-index/mail-modifylog.c
deleted file mode 100644 (file)
index 57af13a..0000000
+++ /dev/null
@@ -1,1298 +0,0 @@
-/* Copyright (C) 2002 Timo Sirainen */
-
-#include "lib.h"
-#include "buffer.h"
-#include "file-lock.h"
-#include "file-set-size.h"
-#include "mmap-util.h"
-#include "write-full.h"
-#include "mail-index.h"
-#include "mail-index-util.h"
-#include "mail-modifylog.h"
-
-#include <stddef.h>
-#include <stdlib.h>
-#include <fcntl.h>
-
-/* Maximum size for modify log (isn't exact) */
-#define MAX_MODIFYLOG_SIZE (4096*8)
-
-/* How large chunks to use to grow log file */
-#define MODIFYLOG_GROW_SIZE (sizeof(struct modify_log_record) * 128)
-
-#define MODIFY_LOG_INITIAL_SIZE \
-       (sizeof(struct modify_log_header) + MODIFYLOG_GROW_SIZE)
-
-#define MODIFYLOG_FILE_POSITION(log, ptr) \
-       ((size_t) ((char *) (ptr) - (char *) (log)->mmap_base))
-
-/* FIXME: not ANSI-C */
-#define IS_PTR_IN_RANGE(ptr, area_ptr, area_size) \
-       ((char *) (ptr) >= (char *) (area_ptr) && \
-        (char *) (ptr) < (char *) (area_ptr) + (area_size))
-
-struct modify_log_file {
-       struct mail_modify_log *log;
-
-       int fd;
-       char *filepath;
-
-       void *mmap_base;
-       size_t mmap_used_length;
-       size_t mmap_full_length;
-
-       struct modify_log_record *last_expunge, *last_flags;
-       int last_expunge_external, last_flags_external;
-
-       struct modify_log_header *header;
-       uoff_t synced_position;
-       unsigned int synced_id;
-
-       unsigned int anon_mmap:1;
-       unsigned int modified:1;
-       unsigned int second_log:1;
-};
-
-struct mail_modify_log {
-       struct mail_index *index;
-
-       struct modify_log_record *iterator_end;
-
-       struct modify_log_file file1, file2;
-       struct modify_log_file *head, *tail;
-
-       int cache_have_others;
-       unsigned int cache_lock_counter;
-};
-
-static const struct modify_log_expunge no_expunges = { 0, 0, 0 };
-
-static int modifylog_set_syscall_error(struct modify_log_file *file,
-                                      const char *function)
-{
-       i_assert(function != NULL);
-
-       if (ENOSPACE(errno)) {
-               file->log->index->nodiskspace = TRUE;
-               return FALSE;
-       }
-
-       index_set_error(file->log->index,
-                       "%s failed with modify log file %s: %m",
-                       function, file->filepath);
-       return FALSE;
-}
-
-static int modifylog_set_corrupted(struct modify_log_file *file,
-                                  const char *fmt, ...)
-{
-       va_list va;
-
-       va_start(va, fmt);
-       t_push();
-
-       index_set_error(file->log->index, "Corrupted modify log file %s: %s",
-                       file->filepath, t_strdup_vprintf(fmt, va));
-
-       t_pop();
-       va_end(va);
-
-       /* make sure we don't get back here */
-       file->log->index->inconsistent = TRUE;
-       (void)unlink(file->filepath);
-
-       return FALSE;
-}
-
-static int modifylog_drop_lock(struct modify_log_file *file)
-{
-       int ret;
-
-       /* revert back to shared lock */
-       ret = file_try_lock(file->fd, F_RDLCK);
-       if (ret < 0) {
-               modifylog_set_syscall_error(file, "file_try_lock()");
-               return -1;
-       }
-
-       if (ret == 0) {
-               /* shouldn't happen */
-               index_set_error(file->log->index,
-                               "file_try_lock(F_WRLCK -> F_RDLCK) "
-                               "failed with file %s", file->filepath);
-               return -1;
-       }
-
-       return 1;
-}
-
-static int modifylog_file_have_other_users(struct modify_log_file *file,
-                                          int keep_lock)
-{
-       int ret;
-
-       if (file->anon_mmap)
-               return 0;
-
-       /* try grabbing exclusive lock */
-       ret = file_try_lock(file->fd, F_WRLCK);
-       if (ret <= 0) {
-               if (ret < 0)
-                       modifylog_set_syscall_error(file, "file_try_lock()");
-               return ret < 0 ? -1 : 1;
-       }
-
-       if (keep_lock)
-               return 0;
-       else
-               return modifylog_drop_lock(file) < 0 ? -1 : 0;
-}
-
-/* returns 1 = yes, 0 = no, -1 = error */
-static int modifylog_have_other_users(struct mail_modify_log *log,
-                                     int keep_lock)
-{
-       struct modify_log_file *file;
-       int ret;
-
-       ret = modifylog_file_have_other_users(log->head, keep_lock);
-       if (ret == 0) {
-               /* check the other file too */
-               file = log->head == &log->file1 ? &log->file2 : &log->file1;
-
-               ret = file->fd == -1 ? 0 :
-                       modifylog_file_have_other_users(file, FALSE);
-               if (keep_lock && ret != 0) {
-                       if (modifylog_drop_lock(log->head) < 0)
-                               return -1;
-               }
-       }
-
-       return ret;
-}
-
-static int mmap_update(struct modify_log_file *file, int forced)
-{
-       struct modify_log_header *hdr;
-       unsigned int extra;
-
-       if (file->log->index->mmap_invalidate && file->mmap_base != NULL) {
-               if (msync(file->mmap_base, file->mmap_used_length,
-                         MS_SYNC | MS_INVALIDATE) < 0)
-                       return modifylog_set_syscall_error(file, "msync()");
-       }
-
-       if (!forced && file->header != NULL &&
-           file->mmap_full_length >= file->header->used_file_size) {
-               file->mmap_used_length = file->header->used_file_size;
-               debug_mprotect(file->mmap_base, file->mmap_full_length,
-                              file->log->index);
-               return TRUE;
-       }
-
-       i_assert(!file->anon_mmap);
-
-       if (file->mmap_base != NULL) {
-               /* make sure we're synced before munmap() */
-               if (file->modified &&
-                   msync(file->mmap_base, file->mmap_used_length, MS_SYNC) < 0)
-                       return modifylog_set_syscall_error(file, "msync()");
-               file->modified = FALSE;
-
-               if (munmap(file->mmap_base, file->mmap_full_length) < 0)
-                       modifylog_set_syscall_error(file, "munmap()");
-       }
-
-       file->log->iterator_end = NULL;
-
-       file->mmap_used_length = 0;
-       file->header = NULL;
-
-       file->last_expunge = NULL;
-       file->last_flags = NULL;
-
-       file->mmap_base = mmap_rw_file(file->fd, &file->mmap_full_length);
-       if (file->mmap_base == MAP_FAILED) {
-               file->mmap_base = NULL;
-               return modifylog_set_syscall_error(file, "mmap()");
-       }
-
-       if (file->mmap_full_length < sizeof(struct modify_log_header)) {
-               index_set_error(file->log->index, "Too small modify log %s",
-                               file->filepath);
-               (void)unlink(file->filepath);
-               return FALSE;
-       }
-
-       extra = (file->mmap_full_length - sizeof(struct modify_log_header)) %
-               sizeof(struct modify_log_record);
-
-       if (extra != 0) {
-               /* partial write or corrupted -
-                  truncate the file to valid length */
-               file->mmap_full_length -= extra;
-               if (ftruncate(file->fd, (off_t)file->mmap_full_length) < 0)
-                       modifylog_set_syscall_error(file, "ftruncate()");
-       }
-
-       hdr = file->mmap_base;
-       if (hdr->used_file_size > file->mmap_full_length) {
-               modifylog_set_corrupted(file,
-                       "used_file_size larger than real file size "
-                       "(%"PRIuUOFF_T" vs %"PRIuSIZE_T")",
-                       hdr->used_file_size, file->mmap_full_length);
-               return FALSE;
-       }
-
-       if (hdr->used_file_size < sizeof(struct modify_log_header) ||
-           (hdr->used_file_size - sizeof(struct modify_log_header)) %
-           sizeof(struct modify_log_record) != 0) {
-               modifylog_set_corrupted(file,
-                       "Invalid used_file_size in header (%"PRIuUOFF_T")",
-                       hdr->used_file_size);
-               return FALSE;
-       }
-
-       file->header = file->mmap_base;
-       file->mmap_used_length = hdr->used_file_size;
-       debug_mprotect(file->mmap_base, file->mmap_full_length,
-                      file->log->index);
-       return TRUE;
-}
-
-static int mmap_init_update(struct modify_log_file *file)
-{
-       if (!mmap_update(file, TRUE))
-               return FALSE;
-
-       file->synced_id = file->header->sync_id;
-       file->synced_position = file->mmap_used_length;
-       return TRUE;
-}
-
-static struct mail_modify_log *mail_modifylog_new(struct mail_index *index)
-{
-       struct mail_modify_log *log;
-
-       log = i_new(struct mail_modify_log, 1);
-       log->index = index;
-
-       log->file1.fd = -1;
-       log->file2.fd = -1;
-
-       log->file1.log = log;
-       log->file2.log = log;
-
-       log->file1.filepath = i_strconcat(index->filepath, ".log", NULL);
-       log->file2.filepath = i_strconcat(index->filepath, ".log.2", NULL);
-
-       index->modifylog = log;
-       return log;
-}
-
-static void modifylog_munmap(struct modify_log_file *file)
-{
-       if (file->anon_mmap) {
-               if (munmap_anon(file->mmap_base, file->mmap_full_length) < 0)
-                       modifylog_set_syscall_error(file, "munmap_anon()");
-       } else if (file->mmap_base != NULL) {
-               if (munmap(file->mmap_base, file->mmap_full_length) < 0)
-                       modifylog_set_syscall_error(file, "munmap()");
-       }
-       file->mmap_base = NULL;
-       file->mmap_full_length = 0;
-       file->mmap_used_length = 0;
-       file->header = NULL;
-
-       file->last_expunge = NULL;
-       file->last_flags = NULL;
-}
-
-static void modifylog_close_file(struct modify_log_file *file)
-{
-       modifylog_munmap(file);
-
-       if (file->fd != -1) {
-               if (close(file->fd) < 0)
-                       modifylog_set_syscall_error(file, "close()");
-               file->fd = -1;
-       }
-}
-
-static void mail_modifylog_init_header(struct mail_modify_log *log,
-                                      struct modify_log_header *hdr)
-{
-       memset(hdr, 0, sizeof(struct modify_log_header));
-       hdr->indexid = log->index->indexid;
-       hdr->used_file_size = sizeof(struct modify_log_header);
-}
-
-static int mail_modifylog_init_fd(struct modify_log_file *file, int fd)
-{
-        struct modify_log_header hdr;
-
-        mail_modifylog_init_header(file->log, &hdr);
-
-       if (write_full(fd, &hdr, sizeof(hdr)) < 0)
-               return modifylog_set_syscall_error(file, "write_full()");
-
-       if (file_set_size(fd, MODIFY_LOG_INITIAL_SIZE) < 0)
-               return modifylog_set_syscall_error(file, "file_set_size()");
-
-       return TRUE;
-}
-
-static int modifylog_mark_full(struct modify_log_file *file)
-{
-       unsigned int sync_id = SYNC_ID_FULL;
-
-       if (file->mmap_base != NULL) {
-               file->header->sync_id = SYNC_ID_FULL;
-
-               if (msync(file->mmap_base, sizeof(struct modify_log_header),
-                         MS_SYNC) < 0)
-                       return modifylog_set_syscall_error(file, "msync()");
-       } else {
-               off_t offset = offsetof(struct modify_log_header, sync_id);
-
-               if (lseek(file->fd, offset, SEEK_SET) < 0)
-                       return modifylog_set_syscall_error(file, "lseek()");
-
-               if (write_full(file->fd, &sync_id, sizeof(sync_id)) < 0) {
-                       modifylog_set_syscall_error(file, "write_full()");
-                       return FALSE;
-               }
-       }
-
-       return TRUE;
-}
-
-/* Returns 1 = ok, 0 = can't lock file, -1 = error */
-static int modifylog_reuse_or_create_file(struct modify_log_file *file)
-{
-       struct mail_index *index = file->log->index;
-       int fd, ret;
-
-       if (INDEX_IS_IN_MEMORY(index))
-               return -1;
-
-       fd = open(file->filepath, O_RDWR | O_CREAT, 0660);
-       if (fd == -1) {
-               modifylog_set_syscall_error(file, "open()");
-               return -1;
-       }
-
-       /* 1) there's race condition between open() and file_try_lock(), so
-             if we can't get a lock it means the other process did
-          2) this function is also called by try_switch_log() which uses
-             this check to make sure it's not locked by others. */
-       ret = file_try_lock(fd, F_WRLCK);
-       if (ret < 0)
-               modifylog_set_syscall_error(file, "file_try_lock()");
-
-       if (ret > 0 && mail_modifylog_init_fd(file, fd)) {
-               /* drop back to read lock */
-               if (file_try_lock(fd, F_RDLCK) <= 0) {
-                       modifylog_set_syscall_error(file, "file_try_lock()");
-                       ret = -1;
-               }
-
-               if (ret > 0) {
-                       file->fd = fd;
-                       return 1;
-               }
-       }
-
-       if (close(fd) < 0)
-               modifylog_set_syscall_error(file, "close()");
-       return ret;
-}
-
-/* Returns 1 = ok, 0 = full, -1 = error */
-static int mail_modifylog_open_and_verify(struct modify_log_file *file)
-{
-       struct mail_index *index = file->log->index;
-       struct modify_log_header hdr;
-       ssize_t ret;
-       int fd;
-
-       fd = open(file->filepath, O_RDWR);
-       if (fd == -1) {
-               if (errno != ENOENT)
-                       modifylog_set_syscall_error(file, "open()");
-               return -1;
-       }
-
-       if (file_wait_lock(fd, F_RDLCK) <= 0) {
-               modifylog_set_syscall_error(file, "file_wait_lock()");
-               (void)close(fd);
-               return -1;
-       }
-
-       ret = read(fd, &hdr, sizeof(hdr));
-       if (ret < 0)
-               modifylog_set_syscall_error(file, "read()");
-       else if (ret != sizeof(hdr)) {
-               index_set_error(index, "Corrupted modify log %s: "
-                               "File too small", file->filepath);
-               ret = -1;
-
-               (void)unlink(file->filepath);
-       } else {
-               ret = 1;
-       }
-
-       if (ret > 0 && hdr.indexid != index->indexid) {
-               index_set_error(index, "IndexID mismatch for modify log file "
-                               "%s", file->filepath);
-               ret = -1;
-
-               /* we have to rebuild it, make sure it's deleted. */
-               (void)unlink(file->filepath);
-       }
-
-       if (ret > 0 && hdr.sync_id == SYNC_ID_FULL) {
-               /* full */
-               ret = 0;
-       }
-
-       if (ret > 0)
-               file->fd = fd;
-       else
-               (void)close(fd);
-
-       return ret;
-}
-
-static int modifylog_files_open_or_create(struct mail_modify_log *log)
-{
-       int i, ret1, ret2;
-
-       for (i = 0; i < 2; i++) {
-               ret1 = mail_modifylog_open_and_verify(&log->file1);
-               ret2 = mail_modifylog_open_and_verify(&log->file2);
-
-               if (ret1 == 1 && ret2 != 1) {
-                       log->head = log->tail = &log->file1;
-                       return TRUE;
-               }
-
-               if (ret1 != 1 && ret2 == 1) {
-                       log->head = log->tail = &log->file2;
-                       return TRUE;
-               }
-
-               if (ret1 == 1 && ret2 == 1) {
-                       /* both logs were opened ok, which shouldn't happen.
-                          safest thing to do is to mark both closed,
-                          delete them and recreate */
-                       index_set_error(log->index,
-                                       "Index %s has both modify logs open",
-                                       log->index->filepath);
-                       (void)modifylog_mark_full(&log->file1);
-                       (void)modifylog_mark_full(&log->file2);
-
-                       (void)unlink(log->file1.filepath);
-                       (void)unlink(log->file2.filepath);
-
-                       modifylog_close_file(&log->file1);
-                       modifylog_close_file(&log->file2);
-               }
-
-               ret1 = modifylog_reuse_or_create_file(&log->file1);
-               if (ret1 == 1) {
-                       log->head = log->tail = &log->file1;
-                       return TRUE;
-               }
-               if (ret1 == -1)
-                       break;
-
-               /* someone else probably just created the file */
-       }
-
-       if (ret1 == 0) {
-               /* we tried twice */
-               index_set_error(log->index, "Couldn't lock modify log file %s",
-                               log->file1.filepath);
-       }
-       return FALSE;
-}
-
-static int modifylog_create_anon(struct modify_log_file *file)
-{
-       file->mmap_full_length = MODIFY_LOG_INITIAL_SIZE;
-       file->mmap_base = mmap_anon(file->mmap_full_length);
-       file->header = file->mmap_base;
-
-       if (file->mmap_base == MAP_FAILED)
-               return modifylog_set_syscall_error(file, "mmap_anon()");
-
-       mail_modifylog_init_header(file->log, file->mmap_base);
-
-       file->mmap_used_length = file->header->used_file_size;
-       file->synced_position = file->mmap_used_length;
-
-       file->anon_mmap = TRUE;
-       file->filepath = i_strdup_printf("(in-memory modify log for %s)",
-                                        file->log->index->mailbox_path);
-       return TRUE;
-}
-
-int mail_modifylog_create(struct mail_index *index)
-{
-       struct mail_modify_log *log;
-       int ret;
-
-       i_assert(index->lock_type == MAIL_LOCK_EXCLUSIVE);
-
-       log = mail_modifylog_new(index);
-
-       if (INDEX_IS_IN_MEMORY(index)) {
-               if (!modifylog_create_anon(&log->file1)) {
-                       mail_modifylog_free(log);
-                       return FALSE;
-               }
-       } else {
-               ret = modifylog_reuse_or_create_file(&log->file1);
-               if (ret == 0) {
-                       index_set_error(log->index,
-                               "Couldn't lock created modify log file %s",
-                               log->file1.filepath);
-               }
-
-               if (ret <= 0 || !mmap_init_update(&log->file1)) {
-                       /* fatal failure */
-                       mail_modifylog_free(log);
-                       return FALSE;
-               }
-       }
-
-       log->head = log->tail = &log->file1;
-       return TRUE;
-}
-
-int mail_modifylog_open_or_create(struct mail_index *index)
-{
-       struct mail_modify_log *log;
-
-       log = mail_modifylog_new(index);
-
-       if (!modifylog_files_open_or_create(log) ||
-           !mmap_init_update(log->head)) {
-               /* fatal failure */
-               mail_modifylog_free(log);
-               return FALSE;
-       }
-
-       return TRUE;
-}
-
-void mail_modifylog_free(struct mail_modify_log *log)
-{
-       log->index->modifylog = NULL;
-
-       modifylog_close_file(&log->file1);
-       modifylog_close_file(&log->file2);
-
-       i_free(log->file1.filepath);
-       i_free(log->file2.filepath);
-       i_free(log);
-}
-
-int mail_modifylog_sync_file(struct mail_modify_log *log, int *fsync_fd)
-{
-       struct modify_log_file *file = log->head;
-
-       *fsync_fd = -1;
-
-       if (!file->modified || file->anon_mmap)
-               return TRUE;
-
-       i_assert(file->mmap_base != NULL);
-
-       if (msync(file->mmap_base, file->mmap_used_length, MS_SYNC) < 0)
-               return modifylog_set_syscall_error(file, "msync()");
-
-       *fsync_fd = file->fd;
-       file->modified = FALSE;
-       return TRUE;
-}
-
-void mail_modifylog_notify_lock_drop(struct mail_modify_log *log)
-{
-       log->head->last_expunge = NULL;
-       log->head->last_flags = NULL;
-}
-
-/* if head file is closed, change it */
-static int modifylog_update_head(struct mail_modify_log *log)
-{
-       struct modify_log_file *file;
-
-       if (!mmap_update(log->head, FALSE))
-               return FALSE;
-
-       if (log->head->header->sync_id != SYNC_ID_FULL)
-               return TRUE;
-
-       i_assert(log->head == log->tail);
-
-       /* switch file */
-       file = log->head == &log->file1 ? &log->file2 : &log->file1;
-       if (file->fd == -1) {
-               if (mail_modifylog_open_and_verify(file) <= 0) {
-                       modifylog_set_corrupted(file,
-                               "Can't switch to open log file");
-                       return FALSE;
-               }
-       }
-
-       if (!mmap_update(file, TRUE))
-               return FALSE;
-
-       /* we're non-synced */
-       file->synced_id = 0;
-       file->synced_position = sizeof(struct modify_log_header);
-       log->head = file;
-       return TRUE;
-}
-
-static int mmap_update_both(struct mail_modify_log *log)
-{
-       if (!modifylog_update_head(log))
-               return FALSE;
-
-       if (log->head != log->tail) {
-               if (!mmap_update(log->tail, FALSE))
-                       return FALSE;
-       }
-
-       return TRUE;
-}
-
-static int mail_modifylog_grow(struct modify_log_file *file)
-{
-       uoff_t new_fsize;
-       void *base;
-
-       new_fsize = (uoff_t)file->mmap_full_length + MODIFYLOG_GROW_SIZE;
-       i_assert(new_fsize < OFF_T_MAX);
-
-       if (file->anon_mmap) {
-               i_assert(new_fsize < SSIZE_T_MAX);
-
-               base = mremap_anon(file->mmap_base, file->mmap_full_length,
-                                  (size_t)new_fsize, MREMAP_MAYMOVE);
-               if (base == MAP_FAILED) {
-                       modifylog_set_syscall_error(file, "mremap_anon()");
-                       return FALSE;
-               }
-
-               file->mmap_base = base;
-               file->mmap_full_length = (size_t)new_fsize;
-               return TRUE;
-       }
-
-       if (file_set_size(file->fd, (off_t)new_fsize) < 0)
-               return modifylog_set_syscall_error(file, "file_set_size()");
-
-       if (!mmap_update(file, TRUE))
-               return FALSE;
-
-       return TRUE;
-}
-
-static int mail_modifylog_append(struct modify_log_file *file,
-                                struct modify_log_record **rec,
-                                int external_change)
-{
-       struct modify_log_record *destrec;
-
-       i_assert(file->log->index->lock_type == MAIL_LOCK_EXCLUSIVE);
-       i_assert(file->header->sync_id != SYNC_ID_FULL);
-       i_assert((*rec)->seq1 != 0);
-       i_assert((*rec)->uid1 != 0);
-
-       if (!external_change) {
-               if (file->log->cache_lock_counter !=
-                   file->log->index->excl_lock_counter) {
-                       switch (modifylog_have_other_users(file->log, FALSE)) {
-                       case 0:
-                               /* we're the only one having this log open,
-                                  no need for modify log. */
-                               file->log->cache_have_others = FALSE;
-                               file->log->cache_lock_counter =
-                                       file->log->index->excl_lock_counter;
-
-                               *rec = NULL;
-                               return TRUE;
-                       case -1:
-                               return FALSE;
-                       default:
-                               file->log->cache_have_others = TRUE;
-                               file->log->cache_lock_counter =
-                                       file->log->index->excl_lock_counter;
-                               break;
-                       }
-               }
-
-               if (!file->log->cache_have_others) {
-                       *rec = NULL;
-                       return TRUE;
-               }
-       }
-
-       if (file->mmap_used_length == file->mmap_full_length) {
-               if (!mail_modifylog_grow(file))
-                       return FALSE;
-       }
-
-       i_assert(file->header->used_file_size == file->mmap_used_length);
-       i_assert(file->mmap_used_length + sizeof(struct modify_log_record) <=
-                file->mmap_full_length);
-
-       destrec = (struct modify_log_record *) ((char *) file->mmap_base +
-                                               file->mmap_used_length);
-       memcpy(destrec, *rec, sizeof(struct modify_log_record));
-
-       if (!external_change && file->header->sync_id == file->synced_id) {
-               file->synced_position += sizeof(struct modify_log_record);
-               file->synced_id++;
-       }
-
-       file->header->used_file_size += sizeof(struct modify_log_record);
-       file->mmap_used_length += sizeof(struct modify_log_record);
-
-       file->header->sync_id++;
-       file->modified = TRUE;
-
-       *rec = destrec;
-       return TRUE;
-}
-
-int mail_modifylog_add_expunges(struct mail_modify_log *log,
-                               unsigned int first_seq, unsigned int last_seq,
-                               unsigned int first_uid, unsigned int last_uid,
-                               int external_change)
-{
-       struct modify_log_file *file;
-       struct modify_log_record rec, *recp;
-
-       if (!modifylog_update_head(log))
-               return FALSE;
-
-       file = log->head;
-
-       /* expunges must not be added when log isn't synced */
-       i_assert(external_change || file->synced_id == file->header->sync_id);
-
-       if (file->last_expunge != NULL &&
-           file->last_expunge_external == external_change) {
-               if (last_seq+1 == file->last_expunge->seq1) {
-                       i_assert(last_uid < file->last_expunge->uid1);
-                       file->last_expunge->seq1 = first_seq;
-                       file->last_expunge->uid1 = first_uid;
-                       return TRUE;
-               } else if (first_seq == file->last_expunge->seq1) {
-                       /* note that the weird looking logic above is correct.
-                          it's because of reordered seq numbers. */
-                       i_assert(first_uid > file->last_expunge->uid2);
-                       file->last_expunge->seq2 += (last_seq - first_seq) + 1;
-                       file->last_expunge->uid2 = last_uid;
-                       return TRUE;
-               }
-       }
-
-       rec.type = RECORD_TYPE_EXPUNGE;
-       rec.seq1 = first_seq; rec.seq2 = last_seq;
-       rec.uid1 = first_uid; rec.uid2 = last_uid;
-
-       recp = &rec;
-       if (!mail_modifylog_append(file, &recp, external_change))
-               return FALSE;
-
-        file->last_expunge_external = external_change;
-       file->last_expunge = recp;
-       return TRUE;
-}
-
-int mail_modifylog_add_flags(struct mail_modify_log *log, unsigned int seq,
-                            unsigned int uid, int external_change)
-{
-       struct modify_log_file *file;
-       struct modify_log_record rec, *recp;
-
-       if (!modifylog_update_head(log))
-               return FALSE;
-
-       file = log->head;
-
-       if (file->last_flags != NULL &&
-           file->last_flags_external == external_change) {
-               if (seq+1 == file->last_flags->seq1) {
-                       file->last_flags->seq1 = seq;
-                       file->last_flags->uid1 = uid;
-                       return TRUE;
-               } else if (seq-1 == file->last_flags->seq2) {
-                       file->last_flags->seq2 = seq;
-                       file->last_flags->uid2 = uid;
-                       return TRUE;
-               }
-       }
-
-       rec.type = RECORD_TYPE_FLAGS_CHANGED;
-       rec.seq1 = rec.seq2 = seq;
-       rec.uid1 = rec.uid2 = uid;
-
-       recp = &rec;
-       if (!mail_modifylog_append(file, &recp, external_change))
-               return FALSE;
-
-        file->last_flags_external = external_change;
-       file->last_flags = recp;
-       return TRUE;
-}
-
-static void
-mail_modifylog_get_nonsynced_file(struct modify_log_file *file,
-                                 const struct modify_log_record **arr,
-                                 unsigned int *count)
-{
-       struct modify_log_record *end_rec;
-
-       i_assert(file->synced_position <= file->mmap_used_length);
-       i_assert(file->synced_position >= sizeof(struct modify_log_header));
-
-       *arr = (struct modify_log_record *) ((char *) file->mmap_base +
-                                            file->synced_position);
-       end_rec = (struct modify_log_record *) ((char *) file->mmap_base +
-                                               file->mmap_used_length);
-       *count = (unsigned int) (end_rec - *arr);
-}
-
-int mail_modifylog_get_nonsynced(struct mail_modify_log *log,
-                                const struct modify_log_record **arr1,
-                                unsigned int *count1,
-                                const struct modify_log_record **arr2,
-                                unsigned int *count2)
-{
-       i_assert(log->index->lock_type != MAIL_LOCK_UNLOCK);
-
-       *arr1 = *arr2 = NULL;
-       *count1 = *count2 = 0;
-
-       if (!mmap_update_both(log))
-               return FALSE;
-
-       mail_modifylog_get_nonsynced_file(log->tail, arr1, count1);
-       if (log->head != log->tail)
-               mail_modifylog_get_nonsynced_file(log->head, arr2, count2);
-
-       return TRUE;
-}
-
-static int mail_modifylog_try_truncate(struct modify_log_file *file)
-{
-       if (modifylog_have_other_users(file->log, TRUE) != 0)
-               return FALSE;
-
-#ifdef DEBUG
-       mprotect(file->mmap_base, sizeof(struct modify_log_header),
-                PROT_READ | PROT_WRITE);
-#endif
-       file->header->sync_id = 0;
-       file->header->used_file_size = sizeof(struct modify_log_header);
-
-       if (msync(file->mmap_base,
-                 sizeof(struct modify_log_header), MS_SYNC) < 0) {
-               modifylog_set_syscall_error(file, "msync()");
-               return FALSE;
-       }
-
-       file->synced_id = 0;
-       file->synced_position = sizeof(struct modify_log_header);
-
-       if (file_set_size(file->fd, MODIFY_LOG_INITIAL_SIZE) < 0)
-               modifylog_set_syscall_error(file, "file_set_size()");
-
-       return TRUE;
-}
-
-/* switches to active modify log, updating our sync mark to end of it */
-static int mail_modifylog_switch_file(struct mail_modify_log *log)
-{
-       struct modify_log_file *file;
-
-       (void)mail_modifylog_try_truncate(log->tail);
-
-       file = log->tail == &log->file1 ? &log->file2 : &log->file1;
-       if (file->fd == -1) {
-               if (mail_modifylog_open_and_verify(file) <= 0) {
-                       modifylog_set_corrupted(file,
-                               "Can't switch to open log file");
-                       return FALSE;
-               }
-       }
-
-       modifylog_munmap(log->tail);
-
-       log->head = log->tail = file;
-       return mmap_init_update(log->head);
-}
-
-static int mail_modifylog_try_switch_file(struct mail_modify_log *log)
-{
-       struct modify_log_file *file;
-
-       if (log->head->anon_mmap)
-               return TRUE;
-
-       if (mail_modifylog_try_truncate(log->tail)) {
-               /* no need to switch, we're the only user and we just
-                  truncated it  */
-               return TRUE;
-       }
-
-       file = log->head == &log->file1 ? &log->file2 : &log->file1;
-       if (modifylog_reuse_or_create_file(file) != 1) {
-               /* locked or error, keep using the old log */
-               return TRUE;
-       }
-
-       if (!modifylog_mark_full(log->head))
-               return FALSE;
-
-       modifylog_munmap(log->head);
-
-       log->head = log->tail = file;
-       return mmap_init_update(log->head);
-}
-
-int mail_modifylog_mark_synced(struct mail_modify_log *log)
-{
-       i_assert(log->index->lock_type != MAIL_LOCK_UNLOCK);
-
-       if (!mmap_update_both(log))
-               return FALSE;
-
-       if (log->tail->header->sync_id == SYNC_ID_FULL) {
-               /* tail file is full, switch to next one */
-               return mail_modifylog_switch_file(log);
-       }
-
-       log->tail = log->head;
-       if (log->head->synced_id != log->head->header->sync_id) {
-               log->head->synced_id = log->head->header->sync_id;
-               log->head->synced_position = log->head->mmap_used_length;
-       }
-
-       if (log->head->mmap_used_length > MAX_MODIFYLOG_SIZE) {
-               /* if the other file isn't locked, switch to it */
-               return mail_modifylog_try_switch_file(log);
-       }
-
-       return TRUE;
-}
-
-static int compare_expunge(const void *p1, const void *p2)
-{
-       const struct modify_log_expunge *e1 = p1;
-       const struct modify_log_expunge *e2 = p2;
-
-       return e1->uid1 < e2->uid1 ? -1 : e1->uid1 > e2->uid1 ? 1 : 0;
-}
-
-static struct modify_log_record *modifylog_first(struct mail_modify_log *log)
-{
-       struct modify_log_file *file;
-        struct modify_log_record *rec;
-
-       file = log->tail;
-       rec = (struct modify_log_record *) ((char *) file->mmap_base +
-                                           file->synced_position);
-       log->iterator_end = (struct modify_log_record *)
-               ((char *) file->mmap_base + file->mmap_used_length);
-       return rec < log->iterator_end ? rec : NULL;
-}
-
-static struct modify_log_record *
-modifylog_next(struct mail_modify_log *log, struct modify_log_record *rec)
-{
-       struct modify_log_file *file;
-
-       rec++;
-       if (rec < log->iterator_end)
-               return rec;
-
-       file = log->head;
-       if ((char *) rec == (char *) file->mmap_base + file->mmap_used_length)
-               return NULL; /* end of head */
-
-       /* end of tail, jump to beginning of head */
-       rec = (struct modify_log_record *) ((char *) file->mmap_base +
-                                           sizeof(struct modify_log_header));
-       log->iterator_end = (struct modify_log_record *)
-               ((char *) file->mmap_base + file->mmap_used_length);
-       return rec < log->iterator_end ? rec : NULL;
-}
-
-static unsigned int
-modifylog_get_record_count_after(struct mail_modify_log *log,
-                                struct modify_log_record *rec)
-{
-       unsigned int count = 0;
-
-       if (log->head == log->tail ||
-           IS_PTR_IN_RANGE(rec, log->head->mmap_base,
-                           log->head->mmap_used_length)) {
-               /* only head */
-               count = (log->head->mmap_used_length -
-                        MODIFYLOG_FILE_POSITION(log->head, rec)) /
-                       sizeof(struct modify_log_record);
-       } else {
-               /* tail */
-               count = (log->tail->mmap_used_length -
-                        MODIFYLOG_FILE_POSITION(log->tail, rec)) /
-                       sizeof(struct modify_log_record);
-
-               if (log->head != log->tail) {
-                       /* + head */
-                       count += (log->tail->mmap_used_length -
-                                 sizeof(struct modify_log_header)) /
-                               sizeof(struct modify_log_record);
-               }
-       }
-
-       return count;
-}
-
-const struct modify_log_expunge *
-mail_modifylog_seq_get_expunges(struct mail_modify_log *log,
-                               unsigned int first_seq,
-                               unsigned int last_seq,
-                               unsigned int *expunges_before)
-{
-       struct modify_log_record *rec;
-       struct modify_log_expunge expunge, *expunges;
-       buffer_t *buf;
-       size_t count;
-       unsigned int before, max_records;
-
-       i_assert(log->index->lock_type != MAIL_LOCK_UNLOCK);
-
-       *expunges_before = 0;
-
-       if (!mmap_update_both(log))
-               return NULL;
-
-       /* find the first expunged message that affects our range */
-       rec = modifylog_first(log);
-       while (rec != NULL) {
-               if (rec->type == RECORD_TYPE_EXPUNGE && rec->seq1 <= last_seq)
-                       break;
-
-               rec = modifylog_next(log, rec);
-       }
-
-       if (rec == NULL) {
-               /* none found */
-               return &no_expunges;
-       }
-
-       /* allocate memory for the returned array. the file size - synced
-          position should be quite near the amount of memory we need, unless
-          there's lots of FLAGS_CHANGED records which is why there's the
-          second check to make sure it's not unneededly large. */
-       max_records = modifylog_get_record_count_after(log, rec);
-       if (max_records > last_seq - first_seq + 1)
-               max_records = last_seq - first_seq + 1;
-
-       i_assert((max_records+1) <
-                SSIZE_T_MAX / sizeof(struct modify_log_expunge));
-       buf = buffer_create_static_hard(pool_datastack_create(),
-                                       (max_records+1) *
-                                       sizeof(struct modify_log_expunge));
-
-       before = 0;
-       for (; rec != NULL; rec = modifylog_next(log, rec)) {
-               if (rec->type != RECORD_TYPE_EXPUNGE)
-                       continue;
-
-               if (rec->seq2 < first_seq) {
-                       /* before our range */
-                       before += rec->seq2 - rec->seq1 + 1;
-               } else if (rec->seq1 <= last_seq && rec->seq2 >= first_seq) {
-                       /* within our range, at least partially */
-                       if (max_records-- == 0) {
-                               /* log contains more data than it should
-                                  have - must be corrupted. */
-                               modifylog_set_corrupted(log->tail,
-                                       "Contains more data than expected");
-                               return NULL;
-                       }
-
-                       if (rec->seq1 < first_seq) {
-                               /* partial initial match, update
-                                  before-counter */
-                               before += first_seq - rec->seq1;
-                               expunge.seq_count = rec->seq2 - first_seq + 1;
-                       } else {
-                               expunge.seq_count = rec->seq2 - rec->seq1 + 1;
-                       }
-
-                       expunge.uid1 = rec->uid1;
-                       expunge.uid2 = rec->uid2;
-                       buffer_append(buf, &expunge, sizeof(expunge));
-               }
-
-               if (rec->seq1 <= last_seq) {
-                       /* update the seq. numbers so they can be compared */
-                       last_seq -= I_MIN(rec->seq2, last_seq) -
-                               rec->seq1 + 1;
-
-                       if (rec->seq1 < first_seq) {
-                               first_seq -= I_MIN(rec->seq2, first_seq-1) -
-                                       rec->seq1 + 1;
-                       }
-               }
-       }
-
-       /* terminate the array */
-       buffer_set_used_size(buf, buffer_get_used_size(buf) + sizeof(expunge));
-
-       /* extract the array from buffer */
-       count = buffer_get_used_size(buf) / sizeof(expunge);
-       expunges = buffer_free_without_data(buf);
-
-       /* sort the UID array, not including the terminating 0 */
-       qsort(expunges, count-1, sizeof(expunge), compare_expunge);
-
-       *expunges_before = before;
-       return expunges;
-}
-
-const struct modify_log_expunge *
-mail_modifylog_uid_get_expunges(struct mail_modify_log *log,
-                               unsigned int first_uid,
-                               unsigned int last_uid,
-                               unsigned int *expunges_before)
-{
-       /* pretty much copy&pasted from sequence code above ..
-          kind of annoying */
-       struct modify_log_record *rec;
-       struct modify_log_expunge expunge, *expunges;
-       buffer_t *buf;
-       size_t count;
-       unsigned int before, max_records;
-
-       i_assert(log->index->lock_type != MAIL_LOCK_UNLOCK);
-
-       *expunges_before = 0;
-
-       if (!mmap_update_both(log))
-               return NULL;
-
-       /* find the first expunged message that affects our range */
-       rec = modifylog_first(log);
-       while (rec != NULL) {
-               if (rec->type == RECORD_TYPE_EXPUNGE && rec->uid1 <= last_uid)
-                       break;
-
-               rec = modifylog_next(log, rec);
-       }
-
-       if (rec == NULL) {
-               /* none found */
-               return &no_expunges;
-       }
-
-       /* allocate memory for the returned array. the file size - synced
-          position should be quite near the amount of memory we need, unless
-          there's lots of FLAGS_CHANGED records which is why there's the
-          second check to make sure it's not unneededly large. */
-       max_records = modifylog_get_record_count_after(log, rec);
-       if (max_records > last_uid - first_uid + 1)
-               max_records = last_uid - first_uid + 1;
-
-       i_assert((max_records+1) <
-                SSIZE_T_MAX / sizeof(struct modify_log_expunge));
-       buf = buffer_create_static_hard(pool_datastack_create(),
-                                       (max_records+1) *
-                                       sizeof(struct modify_log_expunge));
-
-       before = 0;
-       for (; rec != NULL; rec = modifylog_next(log, rec)) {
-               if (rec->type != RECORD_TYPE_EXPUNGE)
-                       continue;
-
-                if (rec->uid2 < first_uid) {
-                       /* before our range */
-                       before += rec->seq2 - rec->seq1 + 1;
-               } else if (rec->uid1 <= last_uid && rec->uid2 >= first_uid) {
-                       /* within our range, at least partially */
-                       if (max_records-- == 0) {
-                               /* log contains more data than it should
-                                  have - must be corrupted. */
-                               modifylog_set_corrupted(log->tail,
-                                       "Contains more data than expected");
-                               return NULL;
-                       }
-
-                       expunge.uid1 = rec->uid1;
-                       expunge.uid2 = rec->uid2;
-                       expunge.seq_count = rec->seq2 -rec->seq1 + 1;
-                       buffer_append(buf, &expunge, sizeof(expunge));
-               }
-       }
-
-       /* terminate the array */
-       buffer_set_used_size(buf, buffer_get_used_size(buf) + sizeof(expunge));
-
-       /* extract the array from buffer */
-       count = buffer_get_used_size(buf) / sizeof(expunge);
-       expunges = buffer_free_without_data(buf);
-
-       /* sort the UID array, not including the terminating 0 */
-       qsort(expunges, count-1, sizeof(expunge), compare_expunge);
-
-       *expunges_before = before;
-       return expunges;
-}
-
-static unsigned int
-modifylog_file_get_expunge_count(struct modify_log_file *file)
-{
-       struct modify_log_record *rec, *end_rec;
-       unsigned int expunges;
-
-       /* find the first expunged message that affects our range */
-       rec = (struct modify_log_record *) ((char *) file->mmap_base +
-                                           file->synced_position);
-       end_rec = (struct modify_log_record *) ((char *) file->mmap_base +
-                                               file->mmap_used_length);
-
-       expunges = 0;
-       while (rec < end_rec) {
-               if (rec->type == RECORD_TYPE_EXPUNGE)
-                       expunges += rec->seq2 - rec->seq1 + 1;
-               rec++;
-       }
-
-       return expunges;
-}
-
-unsigned int mail_modifylog_get_expunge_count(struct mail_modify_log *log)
-{
-       unsigned int expunges;
-
-       i_assert(log->index->lock_type != MAIL_LOCK_UNLOCK);
-
-       if (!mmap_update_both(log))
-               return 0;
-
-       expunges = modifylog_file_get_expunge_count(log->tail);
-       if (log->tail != log->head)
-               expunges += modifylog_file_get_expunge_count(log->head);
-
-       return expunges;
-}
diff --git a/src/lib-index/mail-modifylog.h b/src/lib-index/mail-modifylog.h
deleted file mode 100644 (file)
index 1589e6c..0000000
+++ /dev/null
@@ -1,97 +0,0 @@
-#ifndef __MAIL_MODIFYLOG_H
-#define __MAIL_MODIFYLOG_H
-
-enum modify_log_record_type {
-       RECORD_TYPE_EXPUNGE,
-       RECORD_TYPE_FLAGS_CHANGED
-};
-
-/* if sync_id has this value, the log file is full and should be
-   deleted or reused. */
-#define SYNC_ID_FULL ((unsigned int)-1)
-
-struct modify_log_header {
-       unsigned int indexid;
-       unsigned int sync_id;
-       uoff_t used_file_size;
-};
-
-struct modify_log_record {
-       unsigned int type;
-       unsigned int seq1, seq2;
-       unsigned int uid1, uid2;
-};
-
-/* for mail_modifylog_*_get_expunges() */
-struct modify_log_expunge {
-       unsigned int uid1, uid2; /* NOTE: may be outside wanted range */
-       unsigned int seq_count;
-};
-
-/* NOTE: All these functions require the index file to be locked. */
-
-int mail_modifylog_create(struct mail_index *index);
-int mail_modifylog_open_or_create(struct mail_index *index);
-void mail_modifylog_free(struct mail_modify_log *log);
-
-/* Append EXPUGE or FLAGS entry to modify log. Index must be exclusively
-   locked before calling these functions, and modifylog must have been
-   marked synced within the same lock. */
-int mail_modifylog_add_expunges(struct mail_modify_log *log,
-                               unsigned int first_seq, unsigned int last_seq,
-                               unsigned int first_uid, unsigned int last_uid,
-                               int external_change);
-int mail_modifylog_add_flags(struct mail_modify_log *log, unsigned int seq,
-                            unsigned int uid, int external_change);
-
-/* Synchronize the data into disk */
-int mail_modifylog_sync_file(struct mail_modify_log *log, int *fsync_fd);
-
-/* Must be called when exclusive lock is dropped from index. */
-void mail_modifylog_notify_lock_drop(struct mail_modify_log *log);
-
-/* Updates arr and count parameters to list nonsynced log entries.
-   Returns TRUE if successful. */
-int mail_modifylog_get_nonsynced(struct mail_modify_log *log,
-                                const struct modify_log_record **arr1,
-                                unsigned int *count1,
-                                const struct modify_log_record **arr2,
-                                unsigned int *count2);
-
-/* Marks the modify log as being synced with in-memory state. */
-int mail_modifylog_mark_synced(struct mail_modify_log *log);
-
-/* Finds expunged messages for the given sequence range, and number of
-   expunged messages before the range. Returns 0,0 terminated list of
-   expunged UIDs, or NULL if error occured.
-
-   Note that returned UID range may not be exact for first returned
-   expunge record. For example fetching range 9:10 may return
-   expunges_before=8, {uid1=1, uid2=9, seq_count=1} if only message 10
-   exists.
-
-   Also the last expunge record's both uid and seq_count ranges may go
-   past last_seq */
-const struct modify_log_expunge *
-mail_modifylog_seq_get_expunges(struct mail_modify_log *log,
-                               unsigned int first_seq,
-                               unsigned int last_seq,
-                               unsigned int *expunges_before);
-
-/* Like above, but for given UID range. expunges_before is treated a bit
-   differently however. It specifies the number of messages deleted before
-   the first returned expunge-record, which may partially be before our
-   wanted range. For example fetching range 9:10 may return
-   expunges_before=0, {uid1=1, uid2=9, seq_count=9} if only message 10
-   exists. This is because we have no idea how many messages there are
-   between UIDs since they're not guaranteed to be contiguous. */
-const struct modify_log_expunge *
-mail_modifylog_uid_get_expunges(struct mail_modify_log *log,
-                               unsigned int first_uid,
-                               unsigned int last_uid,
-                               unsigned int *expunges_before);
-
-/* Get number of non-synced expunges in modify log. */
-unsigned int mail_modifylog_get_expunge_count(struct mail_modify_log *log);
-
-#endif
diff --git a/src/lib-index/maildir/maildir-build.c b/src/lib-index/maildir/maildir-build.c
deleted file mode 100644 (file)
index 0fcc262..0000000
+++ /dev/null
@@ -1,76 +0,0 @@
-/* Copyright (C) 2002-2003 Timo Sirainen */
-
-#include "lib.h"
-#include "maildir-index.h"
-#include "mail-cache.h"
-
-int maildir_cache_update_file(struct mail_cache_transaction_ctx **trans_ctx,
-                             struct mail_index *index,
-                             struct mail_index_record *rec, const char *fname,
-                             int new_dir)
-{
-       enum mail_cache_field cached_fields;
-        enum mail_index_record_flag index_flags;
-       uoff_t virtual_size;
-       const char *p;
-
-       if (*trans_ctx == NULL) {
-               if (mail_cache_transaction_begin(index->cache,
-                                                TRUE, trans_ctx) <= 0)
-                       return FALSE;
-       }
-
-       cached_fields = mail_cache_get_fields(index->cache, rec);
-       if ((cached_fields & MAIL_CACHE_INDEX_FLAGS) == 0) {
-               /* always set index flags */
-               index_flags = new_dir ? MAIL_INDEX_FLAG_MAILDIR_NEW : 0;
-               if (!mail_cache_add(*trans_ctx, rec, MAIL_CACHE_INDEX_FLAGS,
-                                   &index_flags, sizeof(index_flags)))
-                       return FALSE;
-       }
-
-       /* set virtual size if found from file name */
-       p = strstr(fname, ",W=");
-       if (p != NULL && (cached_fields & MAIL_CACHE_VIRTUAL_FULL_SIZE) == 0) {
-               p += 3;
-               virtual_size = 0;
-               while (*p >= '0' && *p <= '9') {
-                       virtual_size = virtual_size * 10 + (*p - '0');
-                       p++;
-               }
-
-               if (*p == ':' || *p == ',' || *p != '\0') {
-                       if (!mail_cache_add(*trans_ctx, rec,
-                                           MAIL_CACHE_VIRTUAL_FULL_SIZE,
-                                           &virtual_size,
-                                           sizeof(virtual_size)))
-                               return FALSE;
-               }
-       }
-
-       if ((cached_fields & MAIL_CACHE_LOCATION) == 0) {
-               /* always set location */
-               if (!mail_cache_add(*trans_ctx, rec, MAIL_CACHE_LOCATION,
-                                   fname, strlen(fname)+1))
-                       return FALSE;
-       }
-
-       return TRUE;
-}
-
-int maildir_index_append_file(struct mail_cache_transaction_ctx **trans_ctx,
-                             struct mail_index *index, const char *fname,
-                             int new_dir)
-{
-       struct mail_index_record *rec;
-
-       rec = index->append(index);
-       if (rec == NULL)
-               return FALSE;
-
-       /* set message flags from file name */
-       rec->msg_flags = maildir_filename_get_flags(fname, 0);
-       mail_index_mark_flag_changes(index, rec, 0, rec->msg_flags);
-
-        return maildir_cache_update_file(trans_ctx, index, rec, fname, new_dir);
-}
diff --git a/src/lib-index/maildir/maildir-clean.c b/src/lib-index/maildir/maildir-clean.c
deleted file mode 100644 (file)
index ee0f935..0000000
+++ /dev/null
@@ -1,49 +0,0 @@
-/* Copyright (C) 2002 Timo Sirainen */
-
-#include "lib.h"
-#include "ioloop.h"
-#include "maildir-index.h"
-
-#include <dirent.h>
-#include <unistd.h>
-#include <sys/stat.h>
-
-/* Clean files from tmp/ if they're older than 36 hours */
-#define MAILDIR_CLEANUP_TIME (60 * 60 * 36)
-
-void maildir_clean_tmp(const char *dir)
-{
-       time_t cleanup_time = ioloop_time - MAILDIR_CLEANUP_TIME;
-       DIR *dirp;
-       struct dirent *d;
-       struct stat st;
-       const char *path;
-
-       dirp = opendir(dir);
-       if (dirp == NULL) {
-               i_error("opendir(%s) failed: %m", dir);
-               return;
-       }
-
-       while ((d = readdir(dirp)) != NULL) {
-               if (strcmp(d->d_name, ".") == 0 ||
-                   strcmp(d->d_name, "..") == 0)
-                       continue;
-
-               t_push();
-               path = t_strconcat(dir, "/", d->d_name, NULL);
-               if (stat(path, &st) < 0) {
-                       if (errno != ENOENT)
-                               i_error("stat(%s) failed: %m", path);
-               } else if (st.st_mtime < cleanup_time &&
-                          st.st_atime < cleanup_time &&
-                          !S_ISDIR(st.st_mode)) {
-                       if (unlink(path) < 0 && errno != ENOENT)
-                               i_error("unlink(%s) failed: %m", path);
-               }
-               t_pop();
-       }
-
-       if (closedir(dirp) < 0)
-               i_error("closedir(%s) failed: %m", dir);
-}
diff --git a/src/lib-index/maildir/maildir-expunge.c b/src/lib-index/maildir/maildir-expunge.c
deleted file mode 100644 (file)
index 7371127..0000000
+++ /dev/null
@@ -1,50 +0,0 @@
-/* Copyright (C) 2002 Timo Sirainen */
-
-#include "lib.h"
-#include "ioloop.h"
-#include "maildir-index.h"
-#include "mail-index-util.h"
-
-#include <unistd.h>
-
-static int do_expunge(struct mail_index *index, const char *path, void *context)
-{
-       int *found = context;
-
-       if (unlink(path) < 0) {
-               if (errno == ENOENT)
-                       return 0;
-               if (errno == EACCES) {
-                       index->mailbox_readonly = TRUE;
-                       return 1;
-               }
-
-               index_set_error(index, "unlink(%s) failed: %m", path);
-               return -1;
-       }
-
-       *found = TRUE;
-       return 1;
-}
-
-int maildir_expunge_mail(struct mail_index *index,
-                        struct mail_index_record *rec)
-{
-       int found = FALSE;
-
-       if (!maildir_file_do(index, rec, do_expunge, &found))
-               return FALSE;
-
-       if (found) {
-               /* if we're in out-of-space condition, reset it since we'll
-                  probably have enough space now. */
-               index->maildir_keep_new = FALSE;
-               if (index->next_dirty_flags_flush != 0)
-                       index->next_dirty_flags_flush = ioloop_time;
-
-               /* cur/ was updated, set it dirty-synced */
-               index->sync_dirty_stamp = ioloop_time;
-               index->sync_stamp = ioloop_time;
-       }
-       return TRUE;
-}
diff --git a/src/lib-index/maildir/maildir-index.c b/src/lib-index/maildir/maildir-index.c
deleted file mode 100644 (file)
index 7a24eb7..0000000
+++ /dev/null
@@ -1,413 +0,0 @@
-/* Copyright (C) 2002 Timo Sirainen */
-
-#include "lib.h"
-#include "ioloop.h"
-#include "hash.h"
-#include "hostpid.h"
-#include "str.h"
-#include "maildir-index.h"
-#include "mail-index-util.h"
-#include "mail-cache.h"
-
-#include <stdio.h>
-#include <sys/stat.h>
-#include <sys/time.h>
-#include <time.h>
-
-extern struct mail_index maildir_index;
-
-static int maildir_index_open(struct mail_index *index,
-                             enum mail_index_open_flags flags)
-{
-       maildir_clean_tmp(t_strconcat(index->mailbox_path, "/tmp", NULL));
-       return mail_index_open(index, flags);
-}
-
-const char *maildir_get_location(struct mail_index *index,
-                                struct mail_index_record *rec, int *new_dir)
-{
-       const char *fname, *new_fname;
-
-       if (new_dir != NULL)
-               *new_dir = FALSE;
-
-       if (index->new_filenames != NULL) {
-               /* this has the most up-to-date filename */
-               new_fname = hash_lookup(index->new_filenames,
-                                       POINTER_CAST(rec->uid));
-               if (new_fname != NULL) {
-                       if (*new_fname == '/') {
-                               new_fname++;
-                               if (new_dir != NULL)
-                                       *new_dir = TRUE;
-                       }
-                       return new_fname;
-               }
-       }
-
-       /* cache file file should give us at least the base name. */
-       fname = mail_cache_lookup_string_field(index->cache, rec,
-                                              MAIL_CACHE_LOCATION);
-       if (fname == NULL) {
-               /* Not cached, we'll have to resync the directory. */
-               return NULL;
-       }
-
-       if (new_dir != NULL) {
-               *new_dir = (mail_cache_get_index_flags(index->cache, rec) &
-                           MAIL_INDEX_FLAG_MAILDIR_NEW) != 0;
-       }
-
-       return fname;
-}
-
-static int
-maildir_file_do_try(struct mail_index *index, struct mail_index_record *rec,
-                   const char **fname,
-                   maildir_file_do_func *func, void *context)
-{
-       const char *path;
-       int ret, new_dir;
-
-       *fname = maildir_get_location(index, rec, &new_dir);
-       if (*fname == NULL)
-               return 0;
-
-       if (new_dir) {
-               /* probably in new/ dir */
-               path = t_strconcat(index->mailbox_path, "/new/", *fname, NULL);
-               ret = func(index, path, context);
-               if (ret != 0)
-                       return ret;
-       }
-
-       path = t_strconcat(index->mailbox_path, "/cur/", *fname, NULL);
-       return func(index, path, context);
-}
-
-int maildir_file_do(struct mail_index *index, struct mail_index_record *rec,
-                   maildir_file_do_func *func, void *context)
-{
-       const char *fname;
-       int i, ret, found;
-
-       ret = maildir_file_do_try(index, rec, &fname, func, context);
-       for (i = 0; i < 10 && ret == 0; i++) {
-               /* file is either renamed or deleted. sync the maildir and
-                  see which one. if file appears to be renamed constantly,
-                  don't try to open it more than 10 times. */
-               fname = t_strdup(fname);
-               if (!maildir_index_sync_readonly(index, fname, &found))
-                       return FALSE;
-
-               if (!found && fname != NULL)
-                       return TRUE;
-
-               ret = maildir_file_do_try(index, rec, &fname, func, context);
-       }
-
-       return ret >= 0;
-}
-
-const char *maildir_generate_tmp_filename(const struct timeval *tv)
-{
-       static unsigned int create_count = 0;
-       static time_t first_stamp = 0;
-
-       if (first_stamp == 0 || first_stamp == ioloop_time) {
-               /* it's possible that within last second another process had
-                  the same UID as us. Use usecs to make sure we don't create
-                  duplicate base name. */
-               first_stamp = ioloop_time;
-               return t_strdup_printf("%s.P%sQ%uM%s.%s",
-                                      dec2str(tv->tv_sec), my_pid,
-                                      create_count++,
-                                      dec2str(tv->tv_usec), my_hostname);
-       } else {
-               /* Don't bother with usecs. Saves a bit space :) */
-               return t_strdup_printf("%s.P%sQ%u.%s",
-                                      dec2str(tv->tv_sec), my_pid,
-                                      create_count++, my_hostname);
-       }
-}
-
-int maildir_create_tmp(struct mail_index *index, const char *dir, mode_t mode,
-                      const char **fname)
-{
-       const char *path, *tmp_fname;
-       struct stat st;
-       struct timeval *tv, tv_now;
-       pool_t pool;
-       int fd;
-
-       tv = &ioloop_timeval;
-       pool = pool_alloconly_create("maildir_tmp", 4096);
-       for (;;) {
-               p_clear(pool);
-               tmp_fname = maildir_generate_tmp_filename(tv);
-
-               path = p_strconcat(pool, dir, "/", tmp_fname, NULL);
-               if (stat(path, &st) < 0 && errno == ENOENT) {
-                       /* doesn't exist */
-                       mode_t old_mask = umask(0);
-                       fd = open(path, O_WRONLY | O_CREAT | O_EXCL, mode);
-                       umask(old_mask);
-                       if (fd != -1 || errno != EEXIST)
-                               break;
-               }
-
-               /* wait and try again - very unlikely */
-               sleep(2);
-               tv = &tv_now;
-               if (gettimeofday(&tv_now, NULL) < 0)
-                       i_fatal("gettimeofday(): %m");
-       }
-
-       *fname = t_strdup(path);
-       if (fd == -1)
-               index_file_set_syscall_error(index, path, "open()");
-
-       pool_unref(pool);
-       return fd;
-}
-
-enum mail_flags maildir_filename_get_flags(const char *fname,
-                                          enum mail_flags default_flags)
-{
-       const char *info;
-       enum mail_flags flags;
-
-       info = strchr(fname, ':');
-       if (info == NULL || info[1] != '2' || info[2] != ',')
-               return default_flags;
-
-       flags = 0;
-       for (info += 3; *info != '\0' && *info != ','; info++) {
-               switch (*info) {
-               case 'R': /* replied */
-                       flags |= MAIL_ANSWERED;
-                       break;
-               case 'S': /* seen */
-                       flags |= MAIL_SEEN;
-                       break;
-               case 'T': /* trashed */
-                       flags |= MAIL_DELETED;
-                       break;
-               case 'D': /* draft */
-                       flags |= MAIL_DRAFT;
-                       break;
-               case 'F': /* flagged */
-                       flags |= MAIL_FLAGGED;
-                       break;
-               default:
-                       if (*info >= 'a' && *info <= 'z') {
-                               /* custom flag */
-                               flags |= 1 << (MAIL_CUSTOM_FLAG_1_BIT +
-                                              *info-'a');
-                               break;
-                       }
-
-                       /* unknown flag - ignore */
-                       break;
-               }
-       }
-
-       return flags;
-}
-
-const char *maildir_filename_set_flags(const char *fname, enum mail_flags flags)
-{
-       string_t *flags_str;
-       const char *info, *oldflags;
-       int i, nextflag;
-
-       /* remove the old :info from file name, and get the old flags */
-       info = strrchr(fname, ':');
-       if (info != NULL && strrchr(fname, '/') > info)
-               info = NULL;
-
-       oldflags = "";
-       if (info != NULL) {
-               fname = t_strdup_until(fname, info);
-               if (info[1] == '2' && info[2] == ',')
-                       oldflags = info+3;
-       }
-
-       /* insert the new flags between old flags. flags must be sorted by
-          their ASCII code. unknown flags are kept. */
-       flags_str = t_str_new(256);
-       str_append(flags_str, fname);
-       str_append(flags_str, ":2,");
-       for (;;) {
-               /* skip all known flags */
-               while (*oldflags == 'D' || *oldflags == 'F' ||
-                      *oldflags == 'R' || *oldflags == 'S' ||
-                      *oldflags == 'T' ||
-                      (*oldflags >= 'a' && *oldflags <= 'z'))
-                       oldflags++;
-
-               nextflag = *oldflags == '\0' || *oldflags == ',' ? 256 :
-                       (unsigned char) *oldflags;
-
-               if ((flags & MAIL_DRAFT) && nextflag > 'D') {
-                       str_append_c(flags_str, 'D');
-                       flags &= ~MAIL_DRAFT;
-               }
-               if ((flags & MAIL_FLAGGED) && nextflag > 'F') {
-                       str_append_c(flags_str, 'F');
-                       flags &= ~MAIL_FLAGGED;
-               }
-               if ((flags & MAIL_ANSWERED) && nextflag > 'R') {
-                       str_append_c(flags_str, 'R');
-                       flags &= ~MAIL_ANSWERED;
-               }
-               if ((flags & MAIL_SEEN) && nextflag > 'S') {
-                       str_append_c(flags_str, 'S');
-                       flags &= ~MAIL_SEEN;
-               }
-               if ((flags & MAIL_DELETED) && nextflag > 'T') {
-                       str_append_c(flags_str, 'T');
-                       flags &= ~MAIL_DELETED;
-               }
-
-               if ((flags & MAIL_CUSTOM_FLAGS_MASK) && nextflag > 'a') {
-                       for (i = 0; i < MAIL_CUSTOM_FLAGS_COUNT; i++) {
-                               if (flags & (1 << (i + MAIL_CUSTOM_FLAG_1_BIT)))
-                                       str_append_c(flags_str, 'a' + i);
-                       }
-                       flags &= ~MAIL_CUSTOM_FLAGS_MASK;
-               }
-
-               if (*oldflags == '\0' || *oldflags == ',')
-                       break;
-
-               str_append_c(flags_str, *oldflags);
-               oldflags++;
-       }
-
-       if (*oldflags == ',') {
-               /* another flagset, we don't know about these, just keep them */
-               while (*oldflags != '\0')
-                       str_append_c(flags_str, *oldflags++);
-       }
-
-       return str_c(flags_str);
-}
-
-void maildir_index_update_filename(struct mail_index *index, unsigned int uid,
-                                  const char *fname, int new_dir)
-{
-       const char *new_fname, *old_fname;
-
-       if (index->new_filename_pool == NULL) {
-               index->new_filename_pool =
-                       pool_alloconly_create("Maildir filenames", 10240);
-       }
-       if (index->new_filenames == NULL) {
-               index->new_filenames =
-                       hash_create(system_pool, index->new_filename_pool, 0,
-                                   NULL, NULL);
-       }
-
-       t_push();
-       new_fname = !new_dir ? fname : t_strconcat("/", fname, NULL);
-       old_fname = hash_lookup(index->new_filenames, POINTER_CAST(uid));
-       if (old_fname == NULL || strcmp(old_fname, new_fname) != 0) {
-               hash_insert(index->new_filenames, POINTER_CAST(uid),
-                            p_strdup(index->new_filename_pool, new_fname));
-       }
-       t_pop();
-}
-
-struct mail_index *
-maildir_index_alloc(const char *maildir, const char *index_dir,
-                   const char *control_dir)
-{
-       struct mail_index *index;
-
-       i_assert(maildir != NULL);
-       i_assert(control_dir != NULL);
-
-       index = i_new(struct mail_index, 1);
-       memcpy(index, &maildir_index, sizeof(struct mail_index));
-
-       index->maildir_lock_fd = -1;
-       index->mailbox_path = i_strdup(maildir);
-       index->control_dir = i_strdup(control_dir);
-       index->mailbox_readonly = access(maildir, W_OK) < 0;
-       mail_index_init(index, index_dir);
-       return index;
-}
-
-static void maildir_index_free(struct mail_index *index)
-{
-       if (index->new_filenames != NULL)
-               hash_destroy(index->new_filenames);
-       if (index->new_filename_pool != NULL)
-               pool_unref(index->new_filename_pool);
-
-       mail_index_close(index);
-       i_free(index->dir);
-       i_free(index->mailbox_path);
-       i_free(index->control_dir);
-       i_free(index);
-}
-
-static int do_get_received_date(struct mail_index *index,
-                               const char *path, void *context)
-{
-       time_t *date = context;
-       struct stat st;
-
-       if (stat(path, &st) < 0) {
-               if (errno == ENOENT)
-                       return 0;
-               index_file_set_syscall_error(index, path, "stat()");
-               return -1;
-       }
-
-       *date = st.st_mtime;
-       return 1;
-}
-
-static time_t maildir_get_received_date(struct mail_index *index,
-                                       struct mail_index_record *rec)
-{
-       time_t date;
-
-       /* try getting it from cache */
-       if (mail_cache_copy_fixed_field(index->cache, rec,
-                                       MAIL_CACHE_RECEIVED_DATE,
-                                       &date, sizeof(date)))
-               return date;
-
-       date = (time_t)-1;
-       if (!maildir_file_do(index, rec, do_get_received_date, &date))
-               return (time_t)-1;
-
-       return date;
-}
-
-struct mail_index maildir_index = {
-       maildir_index_open,
-       maildir_index_free,
-       mail_index_set_lock,
-       mail_index_try_lock,
-        mail_index_set_lock_notify_callback,
-       mail_index_rebuild,
-       mail_index_fsck,
-       maildir_index_sync,
-       mail_index_get_header,
-       mail_index_lookup,
-       mail_index_next,
-        mail_index_lookup_uid_range,
-       maildir_open_mail,
-       maildir_get_received_date,
-       mail_index_expunge,
-       maildir_index_update_flags,
-       mail_index_append,
-       mail_index_get_last_error,
-       mail_index_get_last_error_text,
-
-       MAIL_INDEX_PRIVATE_FILL
-};
diff --git a/src/lib-index/maildir/maildir-index.h b/src/lib-index/maildir/maildir-index.h
deleted file mode 100644 (file)
index a9fb302..0000000
+++ /dev/null
@@ -1,63 +0,0 @@
-#ifndef __MAILDIR_INDEX_H
-#define __MAILDIR_INDEX_H
-
-struct mail_cache_transaction_ctx;
-
-#include <sys/time.h>
-#include "mail-index.h"
-
-/* How often to try to flush dirty flags. */
-#define MAILDIR_DIRTY_FLUSH_TIMEOUT (60*5)
-
-/* Return -1 = error, 0 = file not found, 1 = ok */
-typedef int maildir_file_do_func(struct mail_index *index,
-                                const char *path, void *context);
-
-struct mail_index *
-maildir_index_alloc(const char *maildir, const char *index_dir,
-                   const char *control_dir);
-
-/* Return new filename base to save into tmp/ */
-const char *maildir_generate_tmp_filename(const struct timeval *tv);
-int maildir_create_tmp(struct mail_index *index, const char *dir, mode_t mode,
-                      const char **path);
-
-const char *maildir_get_location(struct mail_index *index,
-                                struct mail_index_record *rec, int *new_dir);
-int maildir_file_do(struct mail_index *index, struct mail_index_record *rec,
-                   maildir_file_do_func *func, void *context);
-enum mail_flags maildir_filename_get_flags(const char *fname,
-                                          enum mail_flags default_flags);
-const char *maildir_filename_set_flags(const char *fname,
-                                      enum mail_flags flags);
-void maildir_index_update_filename(struct mail_index *index, unsigned int uid,
-                                  const char *fname, int new_dir);
-
-int maildir_index_sync_readonly(struct mail_index *index,
-                               const char *fname, int *found);
-int maildir_index_sync(struct mail_index *index, int minimal_sync,
-                      enum mail_lock_type lock_type, int *changes);
-
-int maildir_cache_update_file(struct mail_cache_transaction_ctx **trans_ctx,
-                             struct mail_index *index,
-                             struct mail_index_record *rec, const char *fname,
-                             int new_dir);
-int maildir_index_append_file(struct mail_cache_transaction_ctx **trans_ctx,
-                             struct mail_index *index, const char *fname,
-                             int new_dir);
-int maildir_index_update_flags(struct mail_index *index,
-                              struct mail_index_record *rec, unsigned int seq,
-                              enum modify_type modify_type,
-                              enum mail_flags flags, int external_change);
-int maildir_try_flush_dirty_flags(struct mail_index *index, int force);
-
-struct istream *maildir_open_mail(struct mail_index *index,
-                                 struct mail_index_record *rec,
-                                 time_t *received_date, int *deleted);
-
-int maildir_expunge_mail(struct mail_index *index,
-                        struct mail_index_record *rec);
-
-void maildir_clean_tmp(const char *dir);
-
-#endif
diff --git a/src/lib-index/maildir/maildir-open.c b/src/lib-index/maildir/maildir-open.c
deleted file mode 100644 (file)
index 968c9e1..0000000
+++ /dev/null
@@ -1,63 +0,0 @@
-/* Copyright (C) 2002 Timo Sirainen */
-
-#include "lib.h"
-#include "istream.h"
-#include "maildir-index.h"
-#include "mail-index-util.h"
-#include "mail-cache.h"
-
-#include <unistd.h>
-#include <fcntl.h>
-#include <sys/stat.h>
-
-static int do_open(struct mail_index *index, const char *path, void *context)
-{
-       int *fd = context;
-
-       *fd = open(path, O_RDONLY);
-       if (*fd != -1)
-               return 1;
-       if (errno == ENOENT)
-               return 0;
-
-       index_file_set_syscall_error(index, path, "open()");
-       return -1;
-}
-
-struct istream *maildir_open_mail(struct mail_index *index,
-                                 struct mail_index_record *rec,
-                                 time_t *received_date, int *deleted)
-{
-       struct stat st;
-       int fd;
-
-       i_assert(index->lock_type != MAIL_LOCK_UNLOCK);
-
-       *deleted = FALSE;
-
-       /* check for inconsistency here, to avoid extra error messages */
-       if (index->inconsistent)
-               return NULL;
-
-       fd = -1;
-       if (!maildir_file_do(index, rec, do_open, &fd))
-               return NULL;
-
-       if (fd == -1) {
-               *deleted = TRUE;
-               return NULL;
-       }
-
-       if (received_date != NULL) {
-               if (fstat(fd, &st) == 0)
-                       *received_date = st.st_mtime;
-       }
-
-       if (index->mail_read_mmaped) {
-               return i_stream_create_mmap(fd, default_pool,
-                                           MAIL_MMAP_BLOCK_SIZE, 0, 0, TRUE);
-       } else {
-               return i_stream_create_file(fd, default_pool,
-                                           MAIL_READ_BLOCK_SIZE, TRUE);
-       }
-}
diff --git a/src/lib-index/maildir/maildir-sync.c b/src/lib-index/maildir/maildir-sync.c
deleted file mode 100644 (file)
index 24342b5..0000000
+++ /dev/null
@@ -1,1393 +0,0 @@
-/* Copyright (C) 2002-2003 Timo Sirainen */
-
-/*
-   Here's a description of how we handle Maildir synchronization and
-   it's problems:
-
-   We want to be as efficient as we can. The most efficient way to
-   check if changes have occured is to stat() the new/ and cur/
-   directories and uidlist file - if their mtimes haven't changed,
-   there's no changes and we don't need to do anything.
-
-   Problem 1: Multiple changes can happen within a single second -
-   nothing guarantees that once we synced it, someone else didn't just
-   then make a modification. Such modifications wouldn't get noticed
-   until a new modification occured later.
-
-   Problem 2: Syncing cur/ directory is much more costly than syncing
-   new/. Moving mails from new/ to cur/ will always change mtime of
-   cur/ causing us to sync it as well.
-
-   Problem 3: We may not be able to move mail from new/ to cur/
-   because we're out of quota, or simply because we're accessing a
-   read-only mailbox.
-
-
-   MAILDIR_SYNC_SECS
-   -----------------
-
-   Several checks below use MAILDIR_SYNC_SECS, which should be maximum
-   clock drift between all computers accessing the maildir (eg. via
-   NFS), rounded up to next second. Our default is 1 second, since
-   everyone should be using NTP.
-
-   Note that setting it to 0 works only if there's only one computer
-   accessing the maildir. It's practically impossible to make two
-   clocks _exactly_ synchronized.
-
-   It might be possible to only use file server's clock by looking at
-   the atime field, but I don't know how well that would actually work.
-
-   cur directory
-   -------------
-
-   We have maildir_cur_dirty variable which is set to cur/ directory's
-   mtime when it's >= time() - MAILDIR_SYNC_SECS and we _think_ we have
-   synchronized the directory.
-
-   When maildir_cur_dirty is non-zero, we don't synchronize the cur/
-   directory until
-
-      a) cur/'s mtime changes
-      b) opening a mail fails with ENOENT
-      c) time() > maildir_cur_dirty + MAILDIR_SYNC_SECS
-
-   This allows us to modify the maildir multiple times without having
-   to sync it at every change. The sync will eventually be done to
-   make sure we didn't miss any external changes.
-
-   The maildir_cur_dirty is set when:
-
-      - we change message flags
-      - we expunge messages
-      - we move mail from new/ to cur/
-      - we sync cur/ directory and it's mtime is
-        >= time() - MAILDIR_SYNC_SECS
-
-   It's unset when we do the final syncing, ie. when mtime is
-   older than time() - MAILDIR_SYNC_SECS.
-
-   new directory
-   -------------
-
-   If new/'s mtime is >= time() - MAILDIR_SYNC_SECS, always synchronize
-   it. maildir_cur_dirty-like feature might save us a few syncs, but
-   that might break a client which saves a mail in one connection and
-   tries to fetch it in another one. new/ directory is almost always
-   empty, so syncing it should be very fast anyway. Actually this can
-   still happen if we sync only new/ dir while another client is also
-   moving mails from it to cur/ - it takes us a while to see them.
-   That's pretty unlikely to happen however, and only way to fix it
-   would be to always synchronize cur/ after new/.
-
-   Normally we move all mails from new/ to cur/ whenever we sync it. If
-   it's not possible for some reason, we set maildir_have_new flag on
-   which instructs synchronization to check files in new/ directory as
-   well. maildir_keep_new flag is also set which instructs syncing to
-   not even try to move mails to cur/ anymore.
-
-   If client tries to change a flag for message in new/, we try to
-   rename() it into cur/. If it's successful, we clear the
-   maildir_keep_new flag so at next sync we'll try to move all of them
-   to cur/. When all of them have been moved, maildir_have_new flag is
-   cleared as well. Expunges will also clear maildir_keep_new flag.
-
-   If rename() still fails because of ENOSPC or EDQUOT, we still save
-   the flag changes in index with dirty-flag on. When moving the mail
-   to cur/ directory, or when we notice it's already moved there, we
-   apply the flag changes to the filename, rename it and remove the
-   dirty flag. If there's dirty flags, this should be tried every time
-   after expunge or when closing the mailbox.
-
-   uidlist
-   -------
-
-   This file contains UID <-> filename mappings. It's updated only when
-   new mail arrives, so it may contain filenames that have already been
-   deleted. Updating is done by getting uidlist.lock file, writing the
-   whole uidlist into it and rename()ing it over the old uidlist. This
-   means there's no need to lock the file for reading.
-
-   Whenever uidlist is rewritten, it's mtime must be larger than the old
-   one's. Use utime() before rename() if needed.
-
-   Only time you have to read this file is when assigning new UIDs for
-   messages, to see if they already have UIDs. If file's mtime hasn't
-   changed, you don't have to do even that.
-
-   broken clients
-   --------------
-
-   Originally the middle identifier in Maildir filename was specified
-   only as <process id>_<delivery counter>. That however created a
-   problem with randomized PIDs which made it possible that the same
-   PID was reused within one second.
-
-   So if within one second a mail was delivered, MUA moved it to cur/
-   and another mail was delivered by a new process using same PID as
-   the first one, we likely ended up overwriting the first mail when
-   the second mail was moved over it.
-
-   Nowadays everyone should be giving a bit more specific identifier,
-   for example include microseconds in it which Dovecot does.
-
-   There's a simple way to prevent this from happening in some cases:
-   Don't move the mail from new/ to cur/ if it's mtime is >= time() -
-   MAILDIR_SYNC_SECS. The second delivery's link() call then fails
-   because the file is already in new/, and it will then use a
-   different filename. There's a few problems with this however:
-
-      - while it's usually possible to read the mtime from beginning of
-        the file name, it is against the Maildir specs. stat()ing the
-       file then makes syncing slower.
-      - another MUA might still move the mail to cur/
-      - if first file's flags are modified by either Dovecot or another
-        MUA, it's moved to cur/ (you _could_ just do the dirty-flagging
-       but that'd be ugly)
-
-   Because this is useful only for very few people and it requires some
-   extra code, I decided not to implement it at least for now.
-
-   It's also possible to never accidentally overwrite a mail by using
-   link() + unlink() rather than rename(). This however isn't very
-   good idea as it introduces potential race conditions when multiple
-   clients are accessing the mailbox:
-
-   Trying to move the same mail from new/ to cur/ at the same time:
-
-      a) Client 1 uses slightly different filename than client 2,
-         for example one sets read-flag on but the other doesn't.
-        You have the same mail duplicated now.
-
-      b) Client 3 sees the mail between Client 1's and 2's link() calls
-         and changes it's flag. You have the same mail duplicated now.
-
-   And it gets worse when they're unlink()ing in cur/ directory:
-
-      c) Most other maildir clients use rename(). So if client 1 changes
-         mail's flag with link()+unlink() and client 2 using rename()
-        changes it back between 1's link() and unlink(), the mail gets
-        expunged.
-
-      d) If you try to deal with the duplicates by unlink()ing another
-         one of them, you might end up unlinking both of them.
-
-   So, what should we do then if we notice a duplicate? First of all,
-   it might not be a duplicate at all, readdir() might have just
-   returned it twice because it was just renamed. What we should do is
-   create a completely new base name for it and rename() it to that.
-   If the call fails with ENOENT, it only means that it wasn't a
-   duplicate after all.
-*/
-
-#include "lib.h"
-#include "buffer.h"
-#include "istream.h"
-#include "hash.h"
-#include "ioloop.h"
-#include "str.h"
-#include "maildir-index.h"
-#include "maildir-uidlist.h"
-#include "mail-index-util.h"
-#include "mail-cache.h"
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <dirent.h>
-#include <utime.h>
-#include <sys/stat.h>
-
-#define MAILDIR_SYNC_SECS 1
-
-enum maildir_file_action {
-       MAILDIR_FILE_ACTION_EXPUNGE,
-        MAILDIR_FILE_ACTION_UPDATE_FLAGS,
-       MAILDIR_FILE_ACTION_NEW,
-       MAILDIR_FILE_ACTION_NONE,
-
-       MAILDIR_FILE_FLAG_NEWDIR        = 0x1000,
-       MAILDIR_FILE_FLAG_ALLOCED       = 0x2000,
-        MAILDIR_FILE_FLAGS             = 0x3000
-};
-
-struct maildir_hash_context {
-       struct mail_index *index;
-       struct mail_index_record *new_mail;
-
-       int failed;
-};
-
-struct maildir_hash_rec {
-       struct mail_index_record *rec;
-       enum maildir_file_action action;
-};
-#define ACTION(hash) ((hash)->action & ~MAILDIR_FILE_FLAGS)
-
-struct maildir_sync_context {
-        struct mail_index *index;
-       const char *new_dir, *cur_dir;
-
-       pool_t pool;
-       struct hash_table *files;
-       unsigned int new_count;
-
-       DIR *new_dirp;
-       struct dirent *new_dent;
-
-       struct maildir_uidlist *uidlist;
-        struct mail_cache_transaction_ctx *trans_ctx;
-       unsigned int readonly_check:1;
-       unsigned int flag_updates:1;
-       unsigned int uidlist_rewrite:1;
-       unsigned int new_mails_new:1;
-       unsigned int new_mails_cur:1;
-       unsigned int have_uncached_filenames:1;
-};
-
-static int maildir_sync_cur_dir(struct maildir_sync_context *ctx);
-
-/* a char* hash function from ASU -- from glib */
-static unsigned int maildir_hash(const void *p)
-{
-        const unsigned char *s = p;
-       unsigned int g, h = 0;
-
-       while (*s != ':' && *s != '\0') {
-               h = (h << 4) + *s;
-               if ((g = h & 0xf0000000UL)) {
-                       h = h ^ (g >> 24);
-                       h = h ^ g;
-               }
-               s++;
-       }
-
-       return h;
-}
-
-static int maildir_cmp(const void *p1, const void *p2)
-{
-       const char *s1 = p1, *s2 = p2;
-
-       while (*s1 == *s2 && *s1 != ':' && *s1 != '\0') {
-               s1++; s2++;
-       }
-       if ((*s1 == '\0' || *s1 == ':') &&
-           (*s2 == '\0' || *s2 == ':'))
-               return 0;
-       return *s1 - *s2;
-}
-
-static int maildir_update_flags(struct maildir_sync_context *ctx,
-                               struct mail_index_record *rec,
-                               unsigned int seq, const char *new_fname)
-{
-       enum mail_flags flags;
-
-       if (ctx->index->lock_type != MAIL_LOCK_EXCLUSIVE)
-               return TRUE;
-
-       flags = maildir_filename_get_flags(new_fname, rec->msg_flags);
-       flags &= ~ctx->index->private_flags_mask;
-       flags |= rec->msg_flags & ctx->index->private_flags_mask;
-
-       if (flags != rec->msg_flags) {
-               if (!ctx->index->update_flags(ctx->index, rec,
-                                             seq, MODIFY_REPLACE, flags, TRUE))
-                       return FALSE;
-       }
-
-       return TRUE;
-}
-
-static int maildir_sync_open_uidlist(struct maildir_sync_context *ctx)
-{
-       struct mail_index *index = ctx->index;
-       struct stat st;
-       const char *path;
-
-       if (ctx->uidlist != NULL)
-               return TRUE;
-
-       /* open it only if it's changed since we last synced it,
-          or if we have uncached filenames. */
-       path = t_strconcat(index->control_dir, "/" MAILDIR_UIDLIST_NAME, NULL);
-       if (stat(path, &st) < 0) {
-               if (errno == ENOENT) {
-                       /* doesn't exist yet, create it */
-                       switch (maildir_uidlist_try_lock(ctx->index)) {
-                       case -1:
-                               return FALSE;
-                       case 1:
-                               ctx->uidlist_rewrite = TRUE;
-                               break;
-                       }
-
-                       return TRUE;
-               }
-               return index_file_set_syscall_error(index, path, "stat()");
-       }
-
-       /* FIXME: last_uidlist_mtime should be in index headers */
-       if (st.st_mtime == index->last_uidlist_mtime &&
-           !ctx->have_uncached_filenames)
-               return TRUE;
-
-       ctx->uidlist = maildir_uidlist_open(index);
-       if (ctx->uidlist == NULL)
-               return TRUE;
-
-       if (ctx->uidlist->uid_validity != index->header->uid_validity) {
-               /* uidvalidity changed */
-               if (!index->rebuilding && index->opened) {
-                       index_set_corrupted(index,
-                                           "UIDVALIDITY changed in uidlist");
-                       return FALSE;
-               }
-
-               index->header->uid_validity = ctx->uidlist->uid_validity;
-               i_assert(index->header->next_uid == 1);
-       }
-
-       if (index->header->next_uid > ctx->uidlist->next_uid) {
-               index_set_corrupted(index, "index.next_uid (%u) > "
-                                   "uidlist.next_uid (%u)",
-                                   index->header->next_uid,
-                                   ctx->uidlist->next_uid);
-               return FALSE;
-       }
-
-       return TRUE;
-}
-
-static int maildir_time_cmp(const void *p1, const void *p2)
-{
-       const char *s1 = *((const char **) p1);
-       const char *s2 = *((const char **) p2);
-       time_t t1 = 0, t2 = 0;
-
-       /* we have to do numeric comparision, strcmp() will break when
-          there's different amount of digits (mostly the 999999999 ->
-          1000000000 change in Sep 9 2001) */
-       while (*s1 >= '0' && *s1 <= '9') {
-               t1 = t1*10 + (*s1 - '0');
-               s1++;
-       }
-       while (*s2 >= '0' && *s2 <= '9') {
-               t2 = t2*10 + (*s2 - '0');
-               s2++;
-       }
-
-       return t1 < t2 ? -1 : t1 > t2 ? 1 : 0;
-}
-
-static int maildir_full_sync_finish_new_mails(struct maildir_sync_context *ctx)
-{
-       struct hash_iterate_context *iter;
-       void *key, *value;
-       const char *dir, **new_files;
-       buffer_t *buf;
-       unsigned int i;
-       int new_dir;
-
-       ctx->uidlist_rewrite = TRUE;
-
-       /* then there's the completely new mails. sort them by the filename
-          so we should get them to same order as they were created. */
-       buf = buffer_create_static_hard(ctx->pool,
-                                       ctx->new_count * sizeof(const char *));
-       iter = hash_iterate_init(ctx->files);
-       while (hash_iterate(iter, &key, &value)) {
-               struct maildir_hash_rec *hash_rec = value;
-
-               if (ACTION(hash_rec) == MAILDIR_FILE_ACTION_NEW) {
-                       buffer_append(buf, (const void *) &key,
-                                     sizeof(const char *));
-               }
-       }
-       hash_iterate_deinit(iter);
-       i_assert(buffer_get_used_size(buf) ==
-                ctx->new_count * sizeof(const char *));
-
-       new_files = buffer_get_modifyable_data(buf, NULL);
-       qsort(new_files, ctx->new_count, sizeof(const char *),
-             maildir_time_cmp);
-
-       if (!ctx->index->maildir_keep_new) {
-               dir = ctx->cur_dir;
-               new_dir = FALSE;
-       } else {
-               /* this is actually slightly wrong, because we don't really
-                  know if some of the new messages are in cur/ already.
-                  we could know that by saving it into buffer, but that'd
-                  require extra memory. luckily it doesn't really matter if
-                  we say it's in new/, but it's actually in cur/. we have
-                  to deal with such case anyway since another client might
-                  have just moved it. */
-               dir = ctx->new_dir;
-               new_dir = TRUE;
-               ctx->index->maildir_have_new = TRUE;
-       }
-
-       for (i = 0; i < ctx->new_count; i++) {
-               if (!maildir_index_append_file(&ctx->trans_ctx, ctx->index,
-                                              new_files[i], new_dir))
-                       return FALSE;
-       }
-       ctx->new_count = 0;
-
-       return TRUE;
-}
-
-static int maildir_full_sync_finish(struct maildir_sync_context *ctx)
-{
-       struct mail_index *index = ctx->index;
-        struct maildir_uidlist *uidlist;
-       struct mail_index_record *rec, *first_rec, *last_rec;
-       struct maildir_hash_rec *hash_rec;
-       struct maildir_uidlist_rec uid_rec;
-        enum maildir_file_action action;
-       const char *fname, *dir;
-       void *orig_key, *orig_value;
-       unsigned int seq, first_seq, last_seq, uid, last_uid, new_flag;
-       int new_dir, skip_next;
-
-       if (ctx->new_count > 0) {
-               /* new mails, either they're already in uidlist or we have
-                  to add them there. If we want to add them, we'll need to
-                  sync it locked. */
-               if (maildir_uidlist_try_lock(ctx->index) < 0)
-                       return FALSE;
-
-               if (!maildir_sync_open_uidlist(ctx))
-                       return FALSE;
-       }
-
-        seq = 1;
-       rec = index->lookup(index, 1);
-       uidlist = ctx->uidlist;
-
-       if (uidlist == NULL)
-               memset(&uid_rec, 0, sizeof(uid_rec));
-       else {
-               if (maildir_uidlist_next(uidlist, &uid_rec) < 0)
-                       return FALSE;
-       }
-
-       first_rec = last_rec = NULL;
-       first_seq = last_seq = 0;
-       skip_next = FALSE;
-       while (rec != NULL) {
-               uid = rec->uid;
-
-               /* skip over the expunged records in uidlist */
-               while (uid_rec.uid != 0 && uid_rec.uid < uid) {
-                       if (maildir_uidlist_next(uidlist, &uid_rec) < 0)
-                               return FALSE;
-               }
-
-               fname = maildir_get_location(index, rec, NULL);
-               if (fname == NULL) {
-                       /* filename not cached, it must be in uidlist or
-                          it's expunged */
-                       fname = uid_rec.uid == rec->uid ?
-                               uid_rec.filename : NULL;
-               }
-
-               if (fname == NULL) {
-                       hash_rec = NULL;
-                       action = MAILDIR_FILE_ACTION_EXPUNGE;
-               } else if (hash_lookup_full(ctx->files, fname,
-                                           &orig_key, &orig_value)) {
-                       hash_rec = orig_value;
-                       action = ACTION(hash_rec);
-               } else {
-                       /* none action */
-                       hash_rec = NULL;
-                       action = MAILDIR_FILE_ACTION_NONE;
-               }
-
-               if (uid_rec.uid == uid &&
-                   maildir_cmp(fname, uid_rec.filename) != 0) {
-                       index_set_corrupted(index,
-                               "Filename mismatch for UID %u: %s vs %s",
-                               uid, fname, uid_rec.filename);
-                       return FALSE;
-               }
-
-               if (uid_rec.uid > uid && hash_rec != NULL &&
-                   (action == MAILDIR_FILE_ACTION_UPDATE_FLAGS ||
-                    action == MAILDIR_FILE_ACTION_NONE)) {
-                       /* it's UID has changed. shouldn't happen. */
-                       index_set_corrupted(index,
-                                           "UID changed for %s/%s: %u -> %u",
-                                           index->mailbox_path, fname,
-                                           uid, uid_rec.uid);
-                       return FALSE;
-               }
-
-               switch (action) {
-               case MAILDIR_FILE_ACTION_EXPUNGE:
-                       if (first_rec == NULL) {
-                               first_rec = rec;
-                               first_seq = seq;
-                       }
-                       last_rec = rec;
-                       last_seq = seq;
-                       break;
-               case MAILDIR_FILE_ACTION_NEW:
-                       /* filename wasn't cached */
-                       new_flag = hash_rec->action & MAILDIR_FILE_FLAG_NEWDIR;
-                       hash_rec->action = MAILDIR_FILE_ACTION_NONE | new_flag;
-                       ctx->new_count--;
-
-                       if (!maildir_cache_update_file(&ctx->trans_ctx, index,
-                                                      rec, fname, new_flag))
-                               return FALSE;
-                       /* fall through */
-               case MAILDIR_FILE_ACTION_UPDATE_FLAGS:
-                       new_dir = (hash_rec->action &
-                                  MAILDIR_FILE_FLAG_NEWDIR) != 0;
-                       maildir_index_update_filename(index, rec->uid,
-                                                     orig_key, new_dir);
-                       if (!maildir_update_flags(ctx, rec, seq, orig_key))
-                               return FALSE;
-                       /* fall through */
-               case MAILDIR_FILE_ACTION_NONE:
-                       if (first_rec != NULL) {
-                               if (!index->expunge(index, first_rec, last_rec,
-                                                   first_seq, last_seq, TRUE))
-                                       return FALSE;
-                               first_rec = NULL;
-
-                               seq = first_seq;
-                               rec = index->lookup(index, seq);
-                               skip_next = TRUE;
-                       }
-                       break;
-               default:
-                       i_unreached();
-               }
-
-               if (uid_rec.uid == uid) {
-                       if (maildir_uidlist_next(uidlist, &uid_rec) < 0)
-                               return FALSE;
-               }
-
-               if (skip_next)
-                       skip_next = FALSE;
-               else {
-                       rec = index->next(index, rec);
-                       seq++;
-               }
-       }
-
-       if (first_rec != NULL) {
-               if (!index->expunge(index, first_rec, last_rec,
-                                   first_seq, last_seq, TRUE))
-                       return FALSE;
-               seq = first_seq;
-       }
-
-       if (seq-1 != index->header->messages_count) {
-               index_set_corrupted(index,
-                                   "Wrong messages_count in header (%u != %u)",
-                                   seq, index->header->messages_count);
-               return FALSE;
-       }
-
-       /* if there's new mails which are already in uidlist, get them */
-       last_uid = 0;
-       while (uid_rec.uid != 0) {
-               if (hash_lookup_full(ctx->files, uid_rec.filename,
-                                    &orig_key, &orig_value))
-                       hash_rec = orig_value;
-               else
-                       hash_rec = NULL;
-
-               if (hash_rec != NULL &&
-                   ACTION(hash_rec) == MAILDIR_FILE_ACTION_NONE) {
-                       /* it's a duplicate, shouldn't happen */
-                       i_error("%s: Found duplicate filename %s, rebuilding",
-                               ctx->uidlist->fname, uid_rec.filename);
-                       (void)unlink(ctx->uidlist->fname);
-
-                       if (INDEX_IS_UIDLIST_LOCKED(index))
-                               ctx->uidlist_rewrite = TRUE;
-                       hash_rec = NULL;
-               }
-
-               if (hash_rec != NULL) {
-                       i_assert(ACTION(hash_rec) == MAILDIR_FILE_ACTION_NEW);
-
-                       /* make sure we set the same UID for it. */
-                       if (index->header->next_uid > uid_rec.uid) {
-                               index_set_corrupted(index,
-                                                   "index.next_uid (%u) > "
-                                                   "uid_rec.uid (%u)",
-                                                   index->header->next_uid,
-                                                   uid_rec.uid);
-                               return FALSE;
-                       }
-                       index->header->next_uid = uid_rec.uid;
-
-                       new_flag = hash_rec->action & MAILDIR_FILE_FLAG_NEWDIR;
-                       hash_rec->action = MAILDIR_FILE_ACTION_NONE | new_flag;
-                       ctx->new_count--;
-
-                       if (new_flag != 0)
-                               ctx->index->maildir_have_new = TRUE;
-                       dir = new_flag != 0 ? ctx->new_dir : ctx->cur_dir;
-
-                       if (!maildir_index_append_file(&ctx->trans_ctx, index,
-                                                      orig_key, new_flag != 0))
-                               return FALSE;
-               }
-
-               if (maildir_uidlist_next(uidlist, &uid_rec) < 0)
-                       return FALSE;
-       }
-
-       if (ctx->uidlist != NULL) {
-               /* update our next_uid. it should have been checked for
-                  sanity already. */
-               struct stat st;
-
-               i_assert(index->header->next_uid <= ctx->uidlist->next_uid);
-                index->header->next_uid = ctx->uidlist->next_uid;
-
-               /* uidlist is now synced, remember that. */
-               if (fstat(i_stream_get_fd(ctx->uidlist->input), &st) < 0) {
-                       return index_file_set_syscall_error(index,
-                                                           ctx->uidlist->fname,
-                                                           "fstat()");
-               }
-               index->last_uidlist_mtime = st.st_mtime;
-       }
-
-       if (ctx->new_count > 0 && INDEX_IS_UIDLIST_LOCKED(index))
-                maildir_full_sync_finish_new_mails(ctx);
-
-       /* all done (or can't do it since we don't have lock) */
-       ctx->index->maildir_synced_once = TRUE;
-       if (ctx->trans_ctx != NULL)
-               mail_cache_transaction_commit(ctx->trans_ctx);
-       return TRUE;
-}
-
-static int maildir_full_sync_init(struct maildir_sync_context *ctx,
-                                 int only_new)
-{
-       struct mail_index *index = ctx->index;
-       struct mail_index_record *rec;
-       struct maildir_hash_rec *hash_rec;
-       const char *fname;
-       size_t size;
-       int new_dir, have_new;
-
-       if (index->header->messages_count >= INT_MAX/32) {
-               index_set_corrupted(index, "Header says %u messages",
-                                   index->header->messages_count);
-               return FALSE;
-       }
-
-       /* we're resyncing everything, so reset the filename hash */
-       if (index->new_filenames != NULL) {
-               hash_destroy(index->new_filenames);
-               index->new_filenames = NULL;
-       }
-
-       if (index->new_filename_pool != NULL)
-               p_clear(index->new_filename_pool);
-
-       /* reset synced-flag too, just in case something fails and we don't
-          have up-to-date new_filenames */
-       ctx->index->maildir_synced_once = FALSE;
-
-       /* read current messages in index into hash */
-       size = nearest_power(index->header->messages_count *
-                            sizeof(struct maildir_hash_rec) + 1024);
-       ctx->pool = pool_alloconly_create("maildir sync", I_MAX(size, 16384));
-       ctx->files = hash_create(default_pool, ctx->pool,
-                                index->header->messages_count * 2,
-                                maildir_hash, maildir_cmp);
-       ctx->new_count = 0;
-
-       have_new = FALSE;
-
-       /* Now we'll fill the hash with cached filenames. This is done mostly
-          just to save some memory since we can use pointers to mmaped cache
-          file. Note that all records may not have the filename cached.
-
-          WARNING: Cache file must not be modified as long as these pointers
-          exist, as modifying might change the mmap base address. The call
-          below makes sure that cache file is initially fully mmaped. */
-       if (mail_cache_get_mmaped(index->cache, &size) == NULL)
-               return FALSE;
-
-       rec = index->lookup(index, 1);
-       while (rec != NULL) {
-               fname = maildir_get_location(index, rec, &new_dir);
-               if (fname == NULL)
-                        ctx->have_uncached_filenames = TRUE;
-
-               if (new_dir)
-                       have_new = TRUE;
-
-               if ((!only_new || new_dir) && fname != NULL) {
-                       hash_rec = p_new(ctx->pool, struct maildir_hash_rec, 1);
-                       hash_rec->rec = rec;
-                       hash_rec->action = MAILDIR_FILE_ACTION_EXPUNGE;
-
-                       if (hash_lookup(ctx->files, fname) != NULL) {
-                               index_set_corrupted(index,
-                                       "Duplicated message %s", fname);
-                               return FALSE;
-                       }
-
-                       hash_insert(ctx->files, (void *) fname, hash_rec);
-               }
-
-               rec = index->next(index, rec);
-       }
-
-       index->maildir_have_new = have_new;
-       return TRUE;
-}
-
-static int maildir_fix_duplicate(struct mail_index *index,
-                                const char *old_fname, int new_dir)
-{
-       const char *new_fname, *old_path, *new_path;
-       int ret = TRUE;
-
-       t_push();
-
-       old_path = t_strconcat(index->mailbox_path, new_dir ? "/new/" : "/cur/",
-                              old_fname, NULL);
-
-       new_fname = maildir_generate_tmp_filename(&ioloop_timeval);
-       new_path = t_strconcat(index->mailbox_path, "/new/", new_fname, NULL);
-
-       if (rename(old_path, new_path) == 0) {
-               i_warning("Fixed duplicate in %s: %s -> %s",
-                         index->mailbox_path, old_fname, new_fname);
-       } else if (errno != ENOENT) {
-               index_set_error(index, "rename(%s, %s) failed: %m",
-                               old_path, new_path);
-               ret = FALSE;
-       }
-       t_pop();
-
-       return ret;
-}
-
-static int maildir_full_sync_dir(struct maildir_sync_context *ctx,
-                                int new_dir, DIR *dirp, struct dirent *d)
-{
-       struct hash_iterate_context *iter;
-       void *key, *value;
-       struct maildir_hash_rec *hash_rec;
-       void *orig_key, *orig_value;
-       int newflag;
-
-       newflag = new_dir ? MAILDIR_FILE_FLAG_NEWDIR : 0;
-
-       do {
-               if (d->d_name[0] == '.')
-                       continue;
-
-               if (!hash_lookup_full(ctx->files, d->d_name,
-                                     &orig_key, &orig_value)) {
-                       hash_rec = p_new(ctx->pool, struct maildir_hash_rec, 1);
-               } else {
-                       hash_rec = orig_value;
-                       if (ACTION(hash_rec) != MAILDIR_FILE_ACTION_EXPUNGE) {
-                               if (!maildir_fix_duplicate(ctx->index,
-                                                          d->d_name, new_dir))
-                                       return FALSE;
-                               continue;
-                       }
-               }
-
-               if (hash_rec->rec == NULL) {
-                       /* new message */
-                       if (ctx->readonly_check &&
-                           !ctx->have_uncached_filenames)
-                               continue;
-
-                       if (new_dir)
-                               ctx->new_mails_new = TRUE;
-                       else
-                               ctx->new_mails_cur = TRUE;
-
-                       ctx->new_count++;
-                       hash_rec->action = MAILDIR_FILE_ACTION_NEW | newflag;
-                       hash_insert(ctx->files, p_strdup(ctx->pool, d->d_name),
-                                   hash_rec);
-                       continue;
-               }
-
-               if (strcmp(orig_key, d->d_name) != 0) {
-                       hash_rec->action =
-                               MAILDIR_FILE_ACTION_UPDATE_FLAGS | newflag;
-
-                       hash_insert(ctx->files, p_strdup(ctx->pool, d->d_name),
-                                   hash_rec);
-                        ctx->flag_updates = TRUE;
-               } else {
-                       hash_rec->action = MAILDIR_FILE_ACTION_NONE | newflag;
-               }
-       } while ((d = readdir(dirp)) != NULL);
-
-       /* records that are left to hash must not have any (filename) pointers
-          to cache file. So remove none actions, and p_strdup() expunge
-          actions. */
-       iter = hash_iterate_init(ctx->files);
-       while (hash_iterate(iter, &key, &value)) {
-               struct maildir_hash_rec *hash_rec = value;
-
-               switch (ACTION(hash_rec)) {
-               case MAILDIR_FILE_ACTION_NONE:
-                       hash_remove(ctx->files, key);
-                       break;
-               case MAILDIR_FILE_ACTION_EXPUNGE:
-                       if (hash_rec->action & MAILDIR_FILE_FLAG_ALLOCED) {
-                               /* we're getting here because our recently
-                                  inserted node is traversed as well */
-                               break;
-                       }
-
-                       hash_rec->action |= MAILDIR_FILE_FLAG_ALLOCED;
-                       hash_insert(ctx->files,
-                                   p_strdup(ctx->pool, key), value);
-                       break;
-               default:
-                       break;
-               }
-       }
-       hash_iterate_deinit(iter);
-
-       return TRUE;
-}
-
-static int maildir_new_scan_first_file(struct maildir_sync_context *ctx)
-{
-       DIR *dirp;
-       struct dirent *d;
-
-       dirp = opendir(ctx->new_dir);
-       if (dirp == NULL) {
-               return index_file_set_syscall_error(ctx->index, ctx->new_dir,
-                                                   "opendir()");
-       }
-
-       /* find first file */
-       while ((d = readdir(dirp)) != NULL) {
-               if (d->d_name[0] != '.')
-                       break;
-       }
-
-       if (d == NULL) {
-               if (closedir(dirp) < 0) {
-                       index_file_set_syscall_error(ctx->index, ctx->new_dir,
-                                                    "closedir()");
-               }
-       } else {
-               ctx->new_dirp = dirp;
-               ctx->new_dent = d;
-       }
-
-       return TRUE;
-}
-
-static int maildir_full_sync_dirs(struct maildir_sync_context *ctx)
-{
-       DIR *dirp;
-       int failed;
-
-       if (ctx->new_dirp == NULL &&
-           (ctx->index->maildir_have_new || ctx->index->maildir_keep_new)) {
-               if (!maildir_new_scan_first_file(ctx))
-                       return FALSE;
-       }
-
-       if (ctx->new_dent != NULL) {
-               if (!maildir_full_sync_dir(ctx, TRUE, ctx->new_dirp,
-                                          ctx->new_dent))
-                       return FALSE;
-                ctx->new_dent = NULL;
-       }
-
-       dirp = opendir(ctx->cur_dir);
-       if (dirp == NULL) {
-               return index_file_set_syscall_error(ctx->index, ctx->cur_dir,
-                                                   "opendir()");
-       }
-
-       failed = !maildir_full_sync_dir(ctx, FALSE, dirp, readdir(dirp));
-
-       if (closedir(dirp) < 0) {
-               return index_file_set_syscall_error(ctx->index, ctx->cur_dir,
-                                                   "closedir()");
-       }
-
-       return !failed;
-}
-
-static int maildir_sync_new_dir_full(struct maildir_sync_context *ctx)
-{
-       if (!ctx->index->set_lock(ctx->index, MAIL_LOCK_EXCLUSIVE))
-               return FALSE;
-
-       if (!maildir_full_sync_init(ctx, TRUE))
-               return FALSE;
-
-       if (!maildir_full_sync_dir(ctx, TRUE, ctx->new_dirp, ctx->new_dent))
-               return FALSE;
-       ctx->new_dent = NULL;
-
-       if (!maildir_full_sync_finish(ctx))
-               return FALSE;
-
-       return TRUE;
-}
-
-static int maildir_sync_new_dir(struct maildir_sync_context *ctx,
-                               int move_to_cur, int append_index)
-{
-       struct dirent *d;
-       string_t *sourcepath, *destpath;
-       const char *final_dir;
-
-       if (append_index) {
-               if (ctx->index->maildir_have_new) {
-                       /* some of the mails in new/ are already indexed.
-                          we'll have to do a full sync. */
-                       return maildir_sync_new_dir_full(ctx);
-               }
-
-               if (!ctx->index->set_lock(ctx->index, MAIL_LOCK_EXCLUSIVE))
-                       return FALSE;
-
-               switch (maildir_uidlist_try_lock(ctx->index)) {
-               case -1:
-                       return FALSE;
-               case 0:
-                       /* couldn't get a lock.
-                          no point in doing more. */
-                       return TRUE;
-               }
-
-               /* make sure uidlist is up to date.
-                  if it's not, do a full sync. */
-               if (!maildir_sync_open_uidlist(ctx))
-                       return FALSE;
-
-               if (ctx->uidlist != NULL)
-                       return maildir_sync_cur_dir(ctx);
-
-               ctx->uidlist_rewrite = TRUE;
-       }
-
-       d = ctx->new_dent;
-       ctx->new_dent = NULL;
-
-       sourcepath = t_str_new(PATH_MAX);
-       destpath = t_str_new(PATH_MAX);
-
-       final_dir = move_to_cur ? ctx->cur_dir : ctx->new_dir;
-
-       do {
-               if (d->d_name[0] == '.')
-                       continue;
-
-               str_truncate(sourcepath, 0);
-               str_printfa(sourcepath, "%s/%s", ctx->new_dir, d->d_name);
-
-               if (move_to_cur) {
-                       str_truncate(destpath, 0);
-                       str_printfa(destpath, "%s/%s", ctx->cur_dir, d->d_name);
-
-                       if (rename(str_c(sourcepath), str_c(destpath)) < 0 &&
-                           errno != ENOENT) {
-                               if (ENOSPACE(errno))
-                                       ctx->index->nodiskspace = TRUE;
-                               else if (errno == EACCES)
-                                       ctx->index->mailbox_readonly = TRUE;
-                               else {
-                                       index_set_error(ctx->index,
-                                               "rename(%s, %s) failed: %m",
-                                               str_c(sourcepath),
-                                               str_c(destpath));
-                                       return FALSE;
-                               }
-
-                               ctx->index->maildir_keep_new = TRUE;
-                               if (!append_index) {
-                                       ctx->new_dent = d;
-                                       return TRUE;
-                               }
-
-                               /* continue by keeping them in new/ dir */
-                               final_dir = ctx->new_dir;
-                               move_to_cur = FALSE;
-                       }
-               }
-
-               if (append_index) {
-                       if (!move_to_cur)
-                               ctx->index->maildir_have_new = TRUE;
-
-                       t_push();
-                       if (!maildir_index_append_file(&ctx->trans_ctx,
-                                                      ctx->index, d->d_name,
-                                                      !move_to_cur)) {
-                               t_pop();
-                               return FALSE;
-                       }
-                       t_pop();
-               }
-       } while ((d = readdir(ctx->new_dirp)) != NULL);
-
-       return TRUE;
-}
-
-static int maildir_sync_cur_dir(struct maildir_sync_context *ctx)
-{
-       struct mail_index *index = ctx->index;
-
-       if (ctx->new_dent != NULL && !index->maildir_keep_new) {
-               /* there's also new mails. move them into cur/ first, if we
-                  can lock the uidlist */
-               switch (maildir_uidlist_try_lock(index)) {
-               case -1:
-                       return FALSE;
-               case 1:
-                       if (!maildir_sync_new_dir(ctx, TRUE, FALSE))
-                               return FALSE;
-               }
-       }
-
-       if (!index->set_lock(index, MAIL_LOCK_EXCLUSIVE))
-               return FALSE;
-
-       if (!maildir_full_sync_init(ctx, FALSE) ||
-           !maildir_full_sync_dirs(ctx) ||
-           !maildir_full_sync_finish(ctx))
-               return FALSE;
-
-       return TRUE;
-}
-
-static int maildir_index_sync_context(struct maildir_sync_context *ctx,
-                                     int *changes)
-
-{
-        struct mail_index *index = ctx->index;
-       struct stat st;
-       time_t new_mtime, cur_mtime;
-
-       if (!maildir_try_flush_dirty_flags(ctx->index, FALSE))
-               return FALSE;
-
-       if (stat(ctx->new_dir, &st) < 0) {
-               index_file_set_syscall_error(index, ctx->new_dir, "stat()");
-               return FALSE;
-       }
-       new_mtime = st.st_mtime;
-
-       if (stat(ctx->cur_dir, &st) < 0) {
-               index_file_set_syscall_error(index, ctx->cur_dir, "stat()");
-               return FALSE;
-       }
-       cur_mtime = st.st_mtime;
-
-       if (new_mtime != index->last_new_mtime ||
-           new_mtime >= ioloop_time - MAILDIR_SYNC_SECS) {
-               if (!maildir_new_scan_first_file(ctx))
-                       return FALSE;
-       }
-
-       if (cur_mtime != index->sync_stamp &&
-           index->sync_dirty_stamp == 0) {
-               /* update index->sync_stamp from header.
-                  set_lock() does it automatically. */
-               if (!index->set_lock(index, MAIL_LOCK_EXCLUSIVE))
-                       return FALSE;
-       }
-
-       if (cur_mtime != index->sync_stamp ||
-           (index->sync_dirty_stamp != 0 &&
-            index->sync_dirty_stamp < ioloop_time - MAILDIR_SYNC_SECS)) {
-               /* cur/ changed, or delayed cur/ check */
-               if (changes != NULL)
-                       *changes = TRUE;
-
-               if (!maildir_sync_cur_dir(ctx))
-                       return FALSE;
-       }
-
-       if (ctx->new_dent != NULL) {
-               if (changes != NULL)
-                       *changes = TRUE;
-
-               if (!maildir_sync_new_dir(ctx, !index->maildir_keep_new, TRUE))
-                       return FALSE;
-
-               /* this will set maildir_cur_dirty. it may actually be
-                  different from cur/'s mtime if we're unlucky, but that only
-                  causes extra sync and it's not worth the extra stat() */
-               if (ctx->new_dent == NULL &&
-                   (ctx->new_count == 0 || !ctx->new_mails_new))
-                       cur_mtime = time(NULL);
-       }
-
-       if (ctx->uidlist_rewrite) {
-               i_assert(INDEX_IS_UIDLIST_LOCKED(index));
-
-               if (!maildir_uidlist_rewrite(index, &index->last_uidlist_mtime))
-                       return FALSE;
-       }
-
-       if (index->lock_type == MAIL_LOCK_EXCLUSIVE) {
-               if (index->maildir_have_new)
-                       index->header->flags |= MAIL_INDEX_FLAG_MAILDIR_NEW;
-               else
-                       index->header->flags &= ~MAIL_INDEX_FLAG_MAILDIR_NEW;
-       }
-
-       if (index->sync_dirty_stamp == 0 ||
-           index->sync_dirty_stamp < ioloop_time - MAILDIR_SYNC_SECS) {
-               if (cur_mtime >= ioloop_time - MAILDIR_SYNC_SECS)
-                       index->sync_dirty_stamp = cur_mtime;
-               else if (ctx->new_count == 0 || !ctx->new_mails_cur)
-                       index->sync_dirty_stamp = 0;
-               else {
-                       /* uidlist is locked, wait for a while before
-                          trying again */
-                       index->sync_dirty_stamp = ioloop_time;
-               }
-       }
-
-       index->sync_stamp = cur_mtime;
-       if (ctx->new_dent == NULL &&
-           (ctx->new_count == 0 || !ctx->new_mails_new))
-               index->last_new_mtime = new_mtime;
-
-       return TRUE;
-}
-
-static int maildir_full_sync_finish_readonly(struct maildir_sync_context *ctx)
-{
-       struct mail_index *index = ctx->index;
-       struct mail_index_record *rec;
-       struct maildir_hash_rec *hash_rec;
-       struct maildir_uidlist *uidlist;
-       struct maildir_uidlist_rec uid_rec;
-       void *orig_key, *orig_value;
-       const char *fname;
-       unsigned int seq;
-       int new_dir, tried_uidlist;
-
-       if (!ctx->flag_updates && !ctx->have_uncached_filenames) {
-               ctx->index->maildir_synced_once = TRUE;
-               return TRUE;
-       }
-
-       memset(&uid_rec, 0, sizeof(uid_rec));
-       uidlist = ctx->uidlist;
-       tried_uidlist = FALSE;
-
-       rec = index->lookup(index, 1); seq = 1;
-       for (; rec != NULL; rec = index->next(index, rec), seq++) {
-               fname = maildir_get_location(index, rec, NULL);
-               if (fname == NULL) {
-                       /* not cached, get it from uidlist */
-                       if (uidlist == NULL && !tried_uidlist) {
-                               ctx->have_uncached_filenames = TRUE;
-                               if (!maildir_sync_open_uidlist(ctx))
-                                       return FALSE;
-
-                               uidlist = ctx->uidlist;
-                               tried_uidlist = TRUE;
-
-                               /* get the initial record */
-                               if (uidlist != NULL &&
-                                   maildir_uidlist_next(uidlist, &uid_rec) < 0)
-                                       return FALSE;
-                       }
-
-                       if (uidlist == NULL) {
-                               /* uidlist doesn't exist? shouldn't happen */
-                               continue;
-                       }
-
-                       while (uid_rec.uid != 0 && uid_rec.uid < rec->uid) {
-                               if (maildir_uidlist_next(uidlist, &uid_rec) < 0)
-                                       return FALSE;
-                       }
-
-                       if (uid_rec.uid != rec->uid) {
-                               /* not in uidlist, it's expunged */
-                               continue;
-                       }
-
-                       fname = uid_rec.filename;
-               }
-
-               if (!hash_lookup_full(ctx->files, fname,
-                                     &orig_key, &orig_value))
-                       continue;
-
-               hash_rec = orig_value;
-               if (ACTION(hash_rec) != MAILDIR_FILE_ACTION_UPDATE_FLAGS &&
-                   ACTION(hash_rec) != MAILDIR_FILE_ACTION_NEW)
-                       continue;
-
-               new_dir = (hash_rec->action & MAILDIR_FILE_FLAG_NEWDIR) != 0;
-               maildir_index_update_filename(index, rec->uid,
-                                             orig_key, new_dir);
-
-               if (!maildir_update_flags(ctx, rec, seq, orig_key))
-                       return FALSE;
-       }
-
-       ctx->index->maildir_synced_once = TRUE;
-       return TRUE;
-}
-
-static int maildir_index_sync_context_readonly(struct maildir_sync_context *ctx)
-{
-       struct mail_index *index = ctx->index;
-       struct stat st;
-       int cur_changed;
-
-       i_assert(index->lock_type != MAIL_LOCK_UNLOCK);
-
-       if (!index->maildir_synced_once) {
-               /* we haven't synced yet in this session. do it */
-               cur_changed = TRUE;
-       } else {
-               if (stat(ctx->cur_dir, &st) < 0) {
-                       index_file_set_syscall_error(index, ctx->cur_dir,
-                                                    "stat()");
-                       return FALSE;
-               }
-
-               cur_changed = st.st_mtime != index->sync_stamp ||
-                       index->sync_dirty_stamp != 0;
-       }
-
-       if (!cur_changed) {
-               if (!index->maildir_have_new) {
-                       /* no changes */
-                       return TRUE;
-               }
-
-               if (stat(ctx->new_dir, &st) < 0) {
-                       return index_file_set_syscall_error(index, ctx->new_dir,
-                                                           "stat()");
-               }
-               if (st.st_mtime == index->last_new_mtime &&
-                   st.st_mtime < ioloop_time - MAILDIR_SYNC_SECS) {
-                       /* no changes */
-                       return TRUE;
-               }
-
-               if (!maildir_new_scan_first_file(ctx))
-                       return FALSE;
-       }
-
-       /* ok, something's changed. check only changes in file names. */
-
-       /* if we can get exclusive lock, we can update the index
-          directly. but don't rely on it. */
-       (void)index->try_lock(index, MAIL_LOCK_EXCLUSIVE);
-
-       if (!maildir_full_sync_init(ctx, FALSE) ||
-           !maildir_full_sync_dirs(ctx) ||
-           !maildir_full_sync_finish_readonly(ctx))
-               return FALSE;
-
-       return TRUE;
-}
-
-static void maildir_index_sync_deinit(struct maildir_sync_context *ctx)
-{
-       // FIXME: remove new flags from cache if needed
-       if (ctx->trans_ctx != NULL)
-                mail_cache_transaction_end(ctx->trans_ctx);
-       if (ctx->uidlist != NULL)
-               maildir_uidlist_close(ctx->uidlist);
-       if (ctx->files != NULL)
-               hash_destroy(ctx->files);
-       if (ctx->pool != NULL)
-               pool_unref(ctx->pool);
-
-       if (ctx->new_dirp != NULL) {
-               if (closedir(ctx->new_dirp) < 0) {
-                       index_file_set_syscall_error(ctx->index, ctx->new_dir,
-                                                    "closedir()");
-               }
-       }
-
-       maildir_uidlist_unlock(ctx->index);
-}
-
-static struct maildir_sync_context *
-maildir_sync_context_new(struct mail_index *index)
-{
-        struct maildir_sync_context *ctx;
-
-       ctx = t_new(struct maildir_sync_context, 1);
-       ctx->index = index;
-       ctx->new_dir = t_strconcat(index->mailbox_path, "/new", NULL);
-       ctx->cur_dir = t_strconcat(index->mailbox_path, "/cur", NULL);
-       return ctx;
-}
-
-int maildir_index_sync_readonly(struct mail_index *index,
-                               const char *fname, int *found)
-{
-        struct maildir_sync_context *ctx;
-       struct maildir_hash_rec *hash_rec;
-       int ret;
-
-       ctx = maildir_sync_context_new(index);
-       ctx->readonly_check = TRUE;
-
-       ret = maildir_index_sync_context_readonly(ctx);
-
-       if (!ret || ctx->files == NULL || fname == NULL)
-               *found = FALSE;
-       else {
-               hash_rec = hash_lookup(ctx->files, fname);
-               *found = hash_rec != NULL &&
-                       hash_rec->action != MAILDIR_FILE_ACTION_EXPUNGE;
-       }
-       maildir_index_sync_deinit(ctx);
-       return ret;
-}
-
-int maildir_index_sync(struct mail_index *index, int minimal_sync,
-                      enum mail_lock_type data_lock_type __attr_unused__,
-                      int *changes)
-{
-        struct maildir_sync_context *ctx;
-       int ret;
-
-       i_assert(index->lock_type != MAIL_LOCK_SHARED);
-
-       if (changes != NULL)
-               *changes = FALSE;
-
-       if (minimal_sync)
-               return TRUE;
-
-       ctx = maildir_sync_context_new(index);
-       ret = maildir_index_sync_context(ctx, changes);
-        maildir_index_sync_deinit(ctx);
-       return ret;
-}
diff --git a/src/lib-index/maildir/maildir-uidlist.c b/src/lib-index/maildir/maildir-uidlist.c
deleted file mode 100644 (file)
index 1b3e0a3..0000000
+++ /dev/null
@@ -1,243 +0,0 @@
-/* Copyright (C) 2003 Timo Sirainen */
-
-#include "lib.h"
-#include "ioloop.h"
-#include "istream.h"
-#include "str.h"
-#include "write-full.h"
-#include "mail-index.h"
-#include "mail-index-util.h"
-#include "maildir-index.h"
-#include "maildir-uidlist.h"
-
-#include <stdio.h>
-#include <sys/stat.h>
-#include <utime.h>
-
-/* how many seconds to wait before overriding uidlist.lock */
-#define UIDLIST_LOCK_STALE_TIMEOUT (60*5)
-
-int maildir_uidlist_try_lock(struct mail_index *index)
-{
-       const char *path;
-       mode_t old_mask;
-       int fd;
-
-       if (INDEX_IS_UIDLIST_LOCKED(index))
-               return 1;
-
-       path = t_strconcat(index->control_dir, "/" MAILDIR_UIDLIST_NAME, NULL);
-        old_mask = umask(0777 & ~index->mail_create_mode);
-       fd = file_dotlock_open(path, NULL, 0, 0, UIDLIST_LOCK_STALE_TIMEOUT,
-                              NULL, NULL);
-       umask(old_mask);
-       if (fd == -1) {
-               if (errno == EAGAIN)
-                       return 0;
-               return -1;
-       }
-
-       index->maildir_lock_fd = fd;
-       return 1;
-}
-
-void maildir_uidlist_unlock(struct mail_index *index)
-{
-       const char *path;
-
-       if (!INDEX_IS_UIDLIST_LOCKED(index))
-               return;
-
-       path = t_strconcat(index->control_dir, "/" MAILDIR_UIDLIST_NAME, NULL);
-       (void)file_dotlock_delete(path, index->maildir_lock_fd);
-       index->maildir_lock_fd = -1;
-}
-
-struct maildir_uidlist *maildir_uidlist_open(struct mail_index *index)
-{
-       const char *path, *line;
-       struct maildir_uidlist *uidlist;
-       unsigned int version;
-       int fd;
-
-       path = t_strconcat(index->control_dir, "/" MAILDIR_UIDLIST_NAME, NULL);
-       fd = open(path, O_RDONLY);
-       if (fd == -1) {
-               if (errno != ENOENT)
-                       index_file_set_syscall_error(index, path, "open()");
-               return NULL;
-       }
-
-       uidlist = i_new(struct maildir_uidlist, 1);
-       uidlist->index = index;
-       uidlist->fname = i_strdup(path);
-       uidlist->input = i_stream_create_file(fd, default_pool, 4096, TRUE);
-
-       /* get header */
-       line = i_stream_read_next_line(uidlist->input);
-       if (line == NULL || sscanf(line, "%u %u %u", &version,
-                                  &uidlist->uid_validity,
-                                  &uidlist->next_uid) != 3 ||
-           version != 1) {
-               /* broken file */
-               (void)unlink(path);
-               maildir_uidlist_close(uidlist);
-               return NULL;
-       }
-
-       return uidlist;
-}
-
-int maildir_uidlist_next(struct maildir_uidlist *uidlist,
-                        struct maildir_uidlist_rec *uid_rec)
-{
-       const char *line;
-       unsigned int uid;
-
-       memset(uid_rec, 0, sizeof(*uid_rec));
-
-       line = i_stream_read_next_line(uidlist->input);
-       if (line == NULL)
-               return 0;
-
-       uid = 0;
-       while (*line >= '0' && *line <= '9') {
-               uid = uid*10 + (*line - '0');
-               line++;
-       }
-
-       if (uid == 0 || *line != ' ') {
-               /* invalid file */
-               index_set_error(uidlist->index, "Invalid data in file %s",
-                               uidlist->fname);
-               (void)unlink(uidlist->fname);
-               return -1;
-       }
-       if (uid <= uidlist->last_read_uid) {
-               index_set_error(uidlist->index,
-                               "UIDs not ordered in file %s (%u > %u)",
-                               uidlist->fname, uid, uidlist->last_read_uid);
-               (void)unlink(uidlist->fname);
-               return -1;
-       }
-       if (uid >= uidlist->next_uid) {
-               index_set_error(uidlist->index,
-                               "UID larger than next_uid in file %s "
-                               "(%u >= %u)", uidlist->fname,
-                               uid, uidlist->next_uid);
-               (void)unlink(uidlist->fname);
-               return -1;
-       }
-
-       while (*line == ' ') line++;
-
-       uid_rec->uid = uid;
-       uid_rec->filename = line;
-       return 1;
-}
-
-void maildir_uidlist_close(struct maildir_uidlist *uidlist)
-{
-       i_stream_unref(uidlist->input);
-       i_free(uidlist->fname);
-       i_free(uidlist);
-}
-
-static int maildir_uidlist_rewrite_fd(struct mail_index *index,
-                                     const char *temp_path, time_t *mtime)
-{
-       struct mail_index_record *rec;
-       struct utimbuf ut;
-       const char *p, *fname;
-       string_t *str;
-       size_t len;
-
-       str = t_str_new(4096);
-       str_printfa(str, "1 %u %u\n",
-                   index->header->uid_validity, index->header->next_uid);
-
-       rec = index->lookup(index, 1);
-       while (rec != NULL) {
-               fname = maildir_get_location(index, rec, NULL);
-               /* maildir should be synced, so above call should never fail */
-               i_assert(fname != NULL);
-
-               p = strchr(fname, ':');
-               len = p == NULL ? strlen(fname) : (size_t)(p-fname);
-
-               if (str_len(str) + MAX_INT_STRLEN + len + 2 >= 4096) {
-                       /* flush buffer */
-                       if (write_full(index->maildir_lock_fd,
-                                      str_data(str), str_len(str)) < 0) {
-                               index_file_set_syscall_error(index, temp_path,
-                                                            "write_full()");
-                               return FALSE;
-                       }
-                       str_truncate(str, 0);
-               }
-
-               str_printfa(str, "%u ", rec->uid);
-               str_append_n(str, fname, len);
-               str_append_c(str, '\n');
-
-               rec = index->next(index, rec);
-       }
-
-       if (write_full(index->maildir_lock_fd,
-                      str_data(str), str_len(str)) < 0) {
-               index_file_set_syscall_error(index, temp_path, "write_full()");
-               return FALSE;
-       }
-
-       /* uidlist's mtime must grow every time */
-       *mtime = ioloop_time > *mtime ? ioloop_time : *mtime + 1;
-       ut.actime = ioloop_time;
-       ut.modtime = *mtime;
-       if (utime(temp_path, &ut) < 0)
-               index_set_syscall_error(index, "utime()");
-
-       if (fsync(index->maildir_lock_fd) < 0) {
-               index_file_set_syscall_error(index, temp_path, "fsync()");
-               return FALSE;
-       }
-
-       return TRUE;
-}
-
-int maildir_uidlist_rewrite(struct mail_index *index, time_t *mtime)
-{
-       const char *temp_path, *db_path;
-       int failed = FALSE;
-
-       i_assert(INDEX_IS_UIDLIST_LOCKED(index));
-
-       if (index->lock_type == MAIL_LOCK_UNLOCK) {
-               if (!index->set_lock(index, MAIL_LOCK_SHARED))
-                       return FALSE;
-       }
-
-       temp_path = t_strconcat(index->control_dir,
-                               "/" MAILDIR_UIDLIST_NAME ".lock", NULL);
-
-       failed = !maildir_uidlist_rewrite_fd(index, temp_path, mtime);
-
-       if (!failed) {
-               db_path = t_strconcat(index->control_dir,
-                                     "/" MAILDIR_UIDLIST_NAME, NULL);
-
-               if (file_dotlock_replace(db_path, index->maildir_lock_fd,
-                                        FALSE) <= 0) {
-                       index_set_error(index,
-                                       "file_dotlock_replace(%s) failed: %m",
-                                       db_path);
-                       failed = TRUE;
-               }
-       } else {
-               (void)close(index->maildir_lock_fd);
-       }
-        index->maildir_lock_fd = -1;
-
-       if (failed)
-               (void)unlink(temp_path);
-       return !failed;
-}
diff --git a/src/lib-index/maildir/maildir-uidlist.h b/src/lib-index/maildir/maildir-uidlist.h
deleted file mode 100644 (file)
index 4b82908..0000000
+++ /dev/null
@@ -1,40 +0,0 @@
-#ifndef __MAILDIR_UIDLIST_H
-#define __MAILDIR_UIDLIST_H
-
-#define INDEX_IS_UIDLIST_LOCKED(index) \
-        ((index)->maildir_lock_fd != -1)
-
-#define MAILDIR_UIDLIST_NAME "dovecot-uidlist"
-
-struct maildir_uidlist {
-       struct mail_index *index;
-       char *fname;
-       struct istream *input;
-
-       unsigned int uid_validity, next_uid, last_read_uid;
-};
-
-struct maildir_uidlist_rec {
-       unsigned int uid;
-       const char *filename;
-};
-
-int maildir_uidlist_try_lock(struct mail_index *index);
-void maildir_uidlist_unlock(struct mail_index *index);
-int maildir_uidlist_rewrite(struct mail_index *index, time_t *mtime);
-
-struct maildir_uidlist *maildir_uidlist_open(struct mail_index *index);
-void maildir_uidlist_close(struct maildir_uidlist *uidlist);
-
-/* Returns -1 if error, 0 if end of file or 1 if found.
-   uid_rec.uid is also set to 0 at EOF. This function does sanity checks so
-   you can be sure that uid_rec.uid is always growing and smaller than
-   uidlist->next_uid. */
-int maildir_uidlist_next(struct maildir_uidlist *uidlist,
-                        struct maildir_uidlist_rec *uid_rec);
-
-/* Try to update cur/ stamp in  */
-int maildir_uidlist_update_cur_stamp(struct maildir_uidlist *uidlist,
-                                    time_t stamp);
-
-#endif
diff --git a/src/lib-index/maildir/maildir-update-flags.c b/src/lib-index/maildir/maildir-update-flags.c
deleted file mode 100644 (file)
index a9d8c87..0000000
+++ /dev/null
@@ -1,238 +0,0 @@
-/* Copyright (C) 2002 Timo Sirainen */
-
-#include "lib.h"
-#include "hash.h"
-#include "ioloop.h"
-#include "maildir-index.h"
-#include "mail-index-util.h"
-#include "mail-cache.h"
-
-#include <stdio.h>
-#include <sys/stat.h>
-
-struct update_flags_ctx {
-       const char *new_fname;
-       int found;
-
-        enum modify_type modify_type;
-       enum mail_flags flags;
-};
-
-static int update_filename(struct mail_index *index,
-                          struct mail_index_record *rec)
-{
-       const char *old_fname, *old_path, *new_fname, *new_path;
-       enum mail_index_record_flag flags;
-
-       old_fname = maildir_get_location(index, rec, NULL);
-       if (old_fname == NULL)
-               return -1;
-
-       flags = mail_cache_get_index_flags(index->cache, rec);
-
-       old_path = t_strconcat(index->mailbox_path,
-                              (flags & MAIL_INDEX_FLAG_MAILDIR_NEW) != 0 ?
-                              "/new/" : "/cur/", old_fname, NULL);
-
-       new_fname = maildir_filename_set_flags(old_fname, rec->msg_flags);
-       new_path = t_strconcat(index->mailbox_path, "/cur/", new_fname, NULL);
-
-       if (strcmp(old_path, new_path) == 0 ||
-           rename(old_path, new_path) == 0) {
-               flags &= ~(MAIL_INDEX_FLAG_DIRTY | MAIL_INDEX_FLAG_MAILDIR_NEW);
-               if (!mail_cache_update_index_flags(index->cache, rec, flags))
-                       return -1;
-               return 1;
-       } else {
-               if (errno != ENOENT && errno != EACCES &&
-                   !ENOSPACE(errno)) {
-                       index_set_error(index,
-                                       "rename(%s, %s) failed: %m",
-                                       old_path, new_path);
-                       return -1;
-               }
-               return 0;
-       }
-}
-
-int maildir_try_flush_dirty_flags(struct mail_index *index, int force)
-{
-       struct mail_index_record *rec;
-       int ret, dirty = FALSE;
-
-       if (index->next_dirty_flags_flush == 0 ||
-           (ioloop_time < index->next_dirty_flags_flush && !force))
-               return TRUE;
-
-       if (!index->set_lock(index, MAIL_LOCK_EXCLUSIVE))
-               return FALSE;
-
-       ret = mail_cache_lock(index->cache, !force);
-       if (ret <= 0)
-               return ret == 0;
-        mail_cache_unlock_later(index->cache);
-
-       rec = index->lookup(index, 1);
-       while (rec != NULL) {
-               if ((mail_cache_get_index_flags(index->cache, rec) &
-                    MAIL_INDEX_FLAG_DIRTY) != 0) {
-                       ret = update_filename(index, rec);
-                       if (ret < 0)
-                               break;
-                       if (ret == 0)
-                               dirty = TRUE;
-               }
-
-               rec = index->next(index, rec);
-       }
-
-       if (ret < 0)
-               return FALSE;
-
-       if (!dirty) {
-               index->header->flags &= ~MAIL_INDEX_HDR_FLAG_DIRTY_MESSAGES;
-               index->next_dirty_flags_flush = 0;
-       } else {
-               index->next_dirty_flags_flush =
-                       ioloop_time + MAILDIR_DIRTY_FLUSH_TIMEOUT;
-       }
-
-       return TRUE;
-}
-
-static int do_rename(struct mail_index *index, const char *path, void *context)
-{
-       struct update_flags_ctx *ctx = context;
-       const char *fname, *new_path;
-       enum mail_flags old_flags, new_flags;
-       int new_dir;
-
-        old_flags = maildir_filename_get_flags(path, 0);
-       switch (ctx->modify_type) {
-       case MODIFY_ADD:
-               new_flags = old_flags | ctx->flags;
-               break;
-       case MODIFY_REMOVE:
-               new_flags = old_flags & ~ctx->flags;
-               break;
-       case MODIFY_REPLACE:
-               new_flags = ctx->flags |
-                       (old_flags & index->private_flags_mask);
-               break;
-       default:
-               new_flags = 0;
-               i_unreached();
-       }
-
-       fname = strrchr(path, '/');
-       ctx->new_fname = maildir_filename_set_flags(fname != NULL ?
-                                                   fname+1 : path, new_flags);
-
-       if (old_flags == new_flags) {
-               /* it's what we wanted. verify that the file exists, but
-                  only if something actually could have changed
-                  (ie. do nothing with private flag changes in shared
-                  mailboxes). */
-               struct stat st;
-
-               if (ctx->flags != 0) {
-                       if (stat(path, &st) < 0) {
-                               if (errno == ENOENT)
-                                       return 0;
-                               index_file_set_syscall_error(index, path,
-                                                            "stat()");
-                               return -1;
-                       }
-               }
-               ctx->found = TRUE;
-               return 1;
-       }
-
-       new_dir = fname != NULL && path + 4 <= fname &&
-               strncmp(fname-4, "/new", 4) == 0;
-       if (new_dir) {
-               /* move from new/ to cur/ */
-               new_path = t_strconcat(t_strdup_until(path, fname-4),
-                                      "/cur/", ctx->new_fname, NULL);
-       } else {
-               new_path = maildir_filename_set_flags(path, new_flags);
-       }
-
-       if (rename(path, new_path) < 0) {
-               if (errno == ENOENT)
-                       return 0;
-
-               if (ENOSPACE(errno)) {
-                       index->nodiskspace = TRUE;
-                       return 1;
-               }
-
-               if (errno == EACCES) {
-                       index->mailbox_readonly = TRUE;
-                       return 1;
-               }
-
-               index_set_error(index, "rename(%s, %s) failed: %m",
-                               path, new_path);
-               return -1;
-       }
-
-       if (index->maildir_keep_new && new_dir) {
-               /* looks like we have some more space again, see if we could
-                  move mails from new/ to cur/ again */
-               index->maildir_keep_new = FALSE;
-       }
-
-       /* cur/ was updated, set it dirty-synced */
-       index->sync_stamp = ioloop_time;
-       index->sync_dirty_stamp = ioloop_time;
-       ctx->found = TRUE;
-       return 1;
-}
-
-int maildir_index_update_flags(struct mail_index *index,
-                              struct mail_index_record *rec, unsigned int seq,
-                              enum modify_type modify_type,
-                              enum mail_flags flags, int external_change)
-{
-       struct update_flags_ctx ctx;
-        enum mail_index_record_flag index_flags;
-
-       memset(&ctx, 0, sizeof(ctx));
-       ctx.modify_type = modify_type;
-       ctx.flags = flags & ~index->private_flags_mask;
-
-       t_push();
-       if (!maildir_file_do(index, rec, do_rename, &ctx)) {
-               t_pop();
-               return FALSE;
-       }
-
-       if (!ctx.found) {
-               /* we couldn't actually rename() the file now.
-                  leave it's flags dirty so they get changed later. */
-               index_flags = mail_cache_get_index_flags(index->cache, rec);
-               if ((index_flags & MAIL_INDEX_FLAG_DIRTY) == 0) {
-                       if (mail_cache_lock(index->cache, FALSE) <= 0)
-                               return FALSE;
-                       mail_cache_unlock_later(index->cache);
-
-                       index_flags |= MAIL_INDEX_FLAG_DIRTY;
-                       mail_cache_update_index_flags(index->cache, rec,
-                                                     index_flags);
-
-                       index->header->flags |=
-                               MAIL_INDEX_HDR_FLAG_DIRTY_MESSAGES;
-               }
-
-               index->next_dirty_flags_flush =
-                       ioloop_time + MAILDIR_DIRTY_FLUSH_TIMEOUT;
-       } else if (ctx.new_fname != NULL) {
-               maildir_index_update_filename(index, rec->uid,
-                                             ctx.new_fname, FALSE);
-       }
-       t_pop();
-
-       return mail_index_update_flags(index, rec, seq,
-                                      modify_type, flags, external_change);
-}
diff --git a/src/lib-index/mbox/istream-mbox.c b/src/lib-index/mbox/istream-mbox.c
deleted file mode 100644 (file)
index 27af5b6..0000000
+++ /dev/null
@@ -1,136 +0,0 @@
-/* Copyright (C) 2003 Timo Sirainen */
-
-#include "lib.h"
-#include "buffer.h"
-#include "message-parser.h"
-#include "istream-internal.h"
-#include "mbox-index.h"
-
-struct mbox_istream {
-       struct _istream istream;
-
-       struct istream *input;
-
-       buffer_t *headers;
-       uoff_t v_header_size, body_offset, body_size;
-};
-
-static void _close(struct _iostream *stream __attr_unused__)
-{
-}
-
-static void _destroy(struct _iostream *stream)
-{
-       struct mbox_istream *mstream = (struct mbox_istream *) stream;
-
-       i_stream_unref(mstream->input);
-       buffer_free(mstream->headers);
-}
-
-static void _set_max_buffer_size(struct _iostream *stream, size_t max_size)
-{
-       struct mbox_istream *mstream = (struct mbox_istream *) stream;
-
-       i_stream_set_max_buffer_size(mstream->input, max_size);
-}
-
-static void _set_blocking(struct _iostream *stream, int timeout_msecs,
-                         void (*timeout_cb)(void *), void *context)
-{
-       struct mbox_istream *mstream = (struct mbox_istream *) stream;
-
-       i_stream_set_blocking(mstream->input, timeout_msecs,
-                             timeout_cb, context);
-}
-
-static ssize_t _read(struct _istream *stream)
-{
-       struct mbox_istream *mstream = (struct mbox_istream *) stream;
-       ssize_t ret;
-       size_t pos;
-       uoff_t offset;
-
-       if (stream->istream.v_offset < mstream->v_header_size) {
-               /* we don't support mixing headers and body.
-                  it shouldn't be needed. */
-               return -2;
-       }
-
-       offset = stream->istream.v_offset - mstream->v_header_size;
-       if (mstream->input->v_offset != offset)
-               i_stream_seek(mstream->input, offset);
-
-       ret = i_stream_read(mstream->input);
-
-       stream->pos -= stream->skip;
-       stream->skip = 0;
-       stream->buffer = i_stream_get_data(mstream->input, &pos);
-
-       ret = pos <= stream->pos ? -1 :
-               (ssize_t) (pos - stream->pos);
-       mstream->istream.pos = pos;
-       return ret;
-}
-
-static void _seek(struct _istream *stream, uoff_t v_offset)
-{
-       struct mbox_istream *mstream = (struct mbox_istream *) stream;
-
-       stream->istream.v_offset = v_offset;
-       if (v_offset < mstream->v_header_size) {
-               /* still in headers */
-               stream->skip = v_offset;
-               stream->pos = mstream->v_header_size;
-               stream->buffer = buffer_get_data(mstream->headers, NULL);
-       } else {
-               /* body - use our real input stream */
-               stream->skip = stream->pos = 0;
-               stream->buffer = NULL;
-       }
-}
-
-struct istream *i_stream_create_mbox(pool_t pool, struct istream *input,
-                                    uoff_t offset, uoff_t body_size)
-{
-       struct mbox_istream *mstream;
-       struct istream *hdr_input;
-
-       mstream = p_new(pool, struct mbox_istream, 1);
-       mstream->body_size = body_size;
-
-       if (body_size == 0) {
-               /* possibly broken message, find the next From-line
-                  and make sure header parser won't pass it. */
-               mbox_skip_header(input);
-               hdr_input = i_stream_create_limit(pool, input,
-                                                 0, input->v_offset);
-       } else {
-               hdr_input = input;
-               i_stream_ref(input);
-       }
-
-       mstream->headers = buffer_create_dynamic(default_pool,
-                                                8192, (size_t)-1);
-       i_stream_seek(hdr_input, offset);
-       mbox_read_headers(hdr_input, mstream->headers);
-       mstream->v_header_size = buffer_get_used_size(mstream->headers);
-       mstream->body_offset = hdr_input->v_offset;
-       i_stream_unref(hdr_input);
-
-       mstream->input = i_stream_create_limit(pool, input,
-                                              mstream->body_offset, body_size);
-
-       mstream->istream.buffer = buffer_get_data(mstream->headers, NULL);
-       mstream->istream.pos = mstream->v_header_size;
-
-       mstream->istream.iostream.close = _close;
-       mstream->istream.iostream.destroy = _destroy;
-       mstream->istream.iostream.set_max_buffer_size = _set_max_buffer_size;
-       mstream->istream.iostream.set_blocking = _set_blocking;
-
-       mstream->istream.read = _read;
-       mstream->istream.seek = _seek;
-
-       return _i_stream_create(&mstream->istream, pool, -1,
-                               input->real_stream->abs_start_offset);
-}
diff --git a/src/lib-index/mbox/mbox-append.c b/src/lib-index/mbox/mbox-append.c
deleted file mode 100644 (file)
index 685b788..0000000
+++ /dev/null
@@ -1,238 +0,0 @@
-/* Copyright (C) 2002 Timo Sirainen */
-
-#include "lib.h"
-#include "ioloop.h"
-#include "istream.h"
-#include "hex-binary.h"
-#include "md5.h"
-#include "mbox-index.h"
-#include "mail-index-util.h"
-#include "mail-cache.h"
-
-static int mbox_index_append_next(struct mail_index *index,
-                                 struct mail_cache_transaction_ctx *trans_ctx,
-                                 struct istream *input)
-{
-       struct mail_index_record *rec;
-       struct mbox_header_context ctx;
-       struct istream *hdr_stream;
-       enum mail_index_record_flag index_flags;
-       time_t received_date;
-       uoff_t hdr_offset, body_offset, end_offset;
-       const unsigned char *data;
-       unsigned char md5_digest[16];
-       size_t size, pos;
-       int dirty, save_md5 = FALSE;
-
-       /* get the From-line */
-       pos = 0;
-       while (i_stream_read_data(input, &data, &size, pos) > 0) {
-               for (; pos < size; pos++) {
-                       if (data[pos] == '\n')
-                               break;
-               }
-
-               if (pos < size)
-                       break;
-       }
-
-       if (size == 0)
-               return -2;
-
-       if (pos == size || size <= 5 || memcmp(data, "From ", 5) != 0) {
-               /* a) no \n found, or line too long
-                  b) not a From-line */
-               index_set_error(index, "Error indexing mbox file %s: "
-                               "From-line not found where expected",
-                               index->mailbox_path);
-               index->set_flags |= MAIL_INDEX_HDR_FLAG_FSCK;
-               return -1;
-       }
-
-       /* parse the From-line */
-       received_date = mbox_from_parse_date(data + 5, size - 5);
-       if (received_date == (time_t)-1)
-               received_date = ioloop_time;
-
-       i_stream_skip(input, pos+1);
-       hdr_offset = input->v_offset;
-
-       /* now, find the end of header. also stops at "\nFrom " if it's
-          found (broken messages) */
-       mbox_skip_header(input);
-       body_offset = input->v_offset;
-
-       index_flags = 0;
-
-       /* parse the header and cache wanted fields. get the message flags
-          from Status and X-Status fields. temporarily limit the stream length
-          so the message body is parsed properly.
-
-          the stream length limit is raised again by mbox_header_cb after
-          reading the headers. it uses Content-Length if available or finds
-          the next From-line. */
-       mbox_header_init_context(&ctx, index, input);
-
-       hdr_stream = i_stream_create_limit(default_pool, input,
-                                          hdr_offset,
-                                          body_offset - hdr_offset);
-       i_stream_seek(hdr_stream, 0);
-       message_parse_header(NULL, hdr_stream, NULL, mbox_header_cb, &ctx);
-       i_stream_unref(hdr_stream);
-
-       dirty = FALSE;
-
-       /* try Content-Length */
-       end_offset = body_offset + ctx.content_length;
-       if (ctx.content_length == (uoff_t)-1 ||
-           !mbox_verify_end_of_body(input, end_offset)) {
-               /* failed, search for From-line */
-               if (ctx.content_length != (uoff_t)-1) {
-                       /* broken, rewrite it */
-                       dirty = TRUE;
-               }
-
-               i_stream_seek(input, body_offset);
-               mbox_skip_message(input);
-               ctx.content_length = input->v_offset - body_offset;
-       }
-
-       if (index->header->messages_count == 0 &&
-           ctx.uid_validity != index->header->uid_validity) {
-               /* UID validity is different */
-               if (ctx.uid_validity != 0) {
-                       /* change it in index */
-                       index->header->uid_validity = ctx.uid_validity;
-                       index->header->next_uid = 1;
-                       index->header->last_nonrecent_uid = 0;
-                       index->inconsistent = TRUE;
-               } else if (!index->mailbox_readonly) {
-                       /* we have to write it to mbox */
-                       if (index->mbox_lock_type != MAIL_LOCK_EXCLUSIVE) {
-                               /* try again */
-                               return 0;
-                       }
-
-                       dirty = TRUE;
-               }
-       }
-
-       if (ctx.uid >= index->header->next_uid) {
-               /* X-UID header looks ok */
-               index->header->next_uid = ctx.uid;
-       } else if (!index->mailbox_readonly) {
-               /* Write X-UID for it */
-               dirty = TRUE;
-       } else {
-               /* save MD5 */
-                save_md5 = TRUE;
-       }
-
-       if (dirty && !index->mailbox_readonly) {
-               if (index->mbox_lock_type != MAIL_LOCK_EXCLUSIVE) {
-                       /* try again */
-                       return 0;
-               }
-
-               index->header->flags |= MAIL_INDEX_HDR_FLAG_DIRTY_MESSAGES;
-               index_flags |= MAIL_INDEX_FLAG_DIRTY;
-       }
-
-       /* add message to index */
-       rec = index->append(index);
-       if (rec == NULL)
-               return -1;
-
-       /* save message flags */
-       rec->msg_flags = ctx.flags;
-       mail_index_mark_flag_changes(index, rec, 0, rec->msg_flags);
-
-       if (!mail_cache_add(trans_ctx, rec, MAIL_CACHE_INDEX_FLAGS,
-                           &index_flags, sizeof(index_flags)))
-               return -1;
-
-       /* location offset = beginning of headers in message */
-       if (!mail_cache_add(trans_ctx, rec, MAIL_CACHE_LOCATION_OFFSET,
-                           &hdr_offset, sizeof(hdr_offset)))
-               return -1;
-
-       if (!mail_cache_add(trans_ctx, rec, MAIL_CACHE_RECEIVED_DATE,
-                           &received_date, sizeof(received_date)))
-               return -1;
-
-       if (!mail_cache_add(trans_ctx, rec, MAIL_CACHE_PHYSICAL_BODY_SIZE,
-                           &ctx.content_length, sizeof(ctx.content_length)))
-               return -1;
-
-       if (save_md5) {
-               md5_final(&ctx.md5, md5_digest);
-
-               if (!mail_cache_add(trans_ctx, rec, MAIL_CACHE_MD5,
-                                   md5_digest, sizeof(md5_digest)))
-                       return -1;
-       }
-
-       return 1;
-}
-
-int mbox_index_append_stream(struct mail_index *index, struct istream *input)
-{
-       struct mail_cache_transaction_ctx *trans_ctx;
-       uoff_t offset;
-       int ret;
-
-       if (!index->set_lock(index, MAIL_LOCK_EXCLUSIVE))
-               return -1;
-
-       if (mail_cache_transaction_begin(index->cache, TRUE, &trans_ctx) <= 0)
-               return -1;
-
-       do {
-               offset = input->v_offset;
-               if (input->v_offset != 0) {
-                       /* we're at the [\r]\n before the From-line,
-                          skip it */
-                       if (!mbox_skip_crlf(input)) {
-                               index_set_error(index,
-                                               "Error indexing mbox file %s: "
-                                               "LF not found where expected",
-                                               index->mailbox_path);
-
-                               index->set_flags |= MAIL_INDEX_HDR_FLAG_FSCK;
-                               ret = -1;
-                               break;
-                       }
-               }
-
-               t_push();
-               ret = mbox_index_append_next(index, trans_ctx, input);
-               t_pop();
-
-               if (ret == -2) {
-                       /* EOF */
-                       ret = 1;
-                       break;
-               }
-
-               if (ret == 0) {
-                       /* we want to rescan this message with exclusive
-                          locking */
-                       i_stream_seek(input, offset);
-               }
-       } while (ret > 0);
-
-       if (ret >= 0 && index->mbox_lock_type == MAIL_LOCK_EXCLUSIVE) {
-               /* Write missing X-IMAPbase and new/changed X-UID headers */
-               if (!mbox_index_rewrite(index))
-                       ret = -1;
-       }
-
-       if (ret >= 0) {
-               if (!mail_cache_transaction_commit(trans_ctx))
-                       ret = -1;
-       }
-       if (!mail_cache_transaction_end(trans_ctx))
-               ret = -1;
-
-       return ret;
-}
diff --git a/src/lib-index/mbox/mbox-from.c b/src/lib-index/mbox/mbox-from.c
deleted file mode 100644 (file)
index 247f6ac..0000000
+++ /dev/null
@@ -1,197 +0,0 @@
-/* Copyright (C) 2002 Timo Sirainen */
-
-#include "lib.h"
-#include "str.h"
-#include "utc-mktime.h"
-#include "mbox-index.h"
-
-#include <time.h>
-#include <ctype.h>
-
-static const char *weekdays[] = {
-       "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
-};
-
-static const char *months[] = {
-       "Jan", "Feb", "Mar", "Apr", "May", "Jun",
-       "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
-};
-
-time_t mbox_from_parse_date(const unsigned char *msg, size_t size)
-{
-       const unsigned char *msg_end;
-       struct tm tm;
-       int i, timezone;
-       time_t t;
-
-       /* <sender> <date> <moreinfo> */
-       msg_end = msg + size;
-
-       /* skip sender */
-       while (msg < msg_end && *msg != ' ') {
-               if (*msg == '\r' || *msg == '\n')
-                       return (time_t)-1;
-               msg++;
-       }
-       while (msg < msg_end && *msg == ' ') msg++;
-
-       /* next 24 chars should be in the date in asctime() format, eg.
-          "Thu Nov 29 22:33:52 2001 +0300"
-
-          Some also include named timezone, which we ignore:
-
-          "Thu Nov 29 22:33:52 EEST 2001"
-       */
-       if (msg+24 > msg_end)
-               return (time_t)-1;
-
-       memset(&tm, 0, sizeof(tm));
-
-       /* skip weekday */
-       msg += 4;
-
-       /* month */
-       for (i = 0; i < 12; i++) {
-               if (memcasecmp(months[i], msg, 3) == 0) {
-                       tm.tm_mon = i;
-                       break;
-               }
-       }
-
-       if (i == 12 && memcmp(msg, "???", 3) == 0) {
-               /* just a hack to parse one special mbox I have :) */
-               i = 0;
-       }
-
-       if (i == 12 || msg[3] != ' ')
-               return (time_t)-1;
-       msg += 4;
-
-       /* day */
-       if (msg[0] == ' ') {
-               if (!i_isdigit(msg[1]) || msg[2] != ' ')
-                       return (time_t)-1;
-               tm.tm_mday = msg[1]-'0';
-       } else {
-               if (!i_isdigit(msg[0]) || !i_isdigit(msg[1]) || msg[2] != ' ')
-                       return (time_t)-1;
-               tm.tm_mday = (msg[0]-'0') * 10 + (msg[1]-'0');
-       }
-       if (tm.tm_mday == 0)
-               tm.tm_mday = 1;
-       msg += 3;
-
-       /* hour */
-       if (!i_isdigit(msg[0]) || !i_isdigit(msg[1]) || msg[2] != ':')
-               return (time_t)-1;
-       tm.tm_hour = (msg[0]-'0') * 10 + (msg[1]-'0');
-       msg += 3;
-
-       /* minute */
-       if (!i_isdigit(msg[0]) || !i_isdigit(msg[1]) || msg[2] != ':')
-               return (time_t)-1;
-       tm.tm_min = (msg[0]-'0') * 10 + (msg[1]-'0');
-       msg += 3;
-
-       /* second */
-       if (!i_isdigit(msg[0]) || !i_isdigit(msg[1]) || msg[2] != ' ')
-               return (time_t)-1;
-       tm.tm_sec = (msg[0]-'0') * 10 + (msg[1]-'0');
-       msg += 3;
-
-       /* optional named timezone */
-       if (!i_isdigit(msg[0]) || !i_isdigit(msg[1]) ||
-           !i_isdigit(msg[2]) || !i_isdigit(msg[3])) {
-               /* skip to next space */
-               while (msg < msg_end && *msg != ' ') {
-                       if (*msg == '\r' || *msg == '\n')
-                               return (time_t)-1;
-                       msg++;
-               }
-               if (msg+5 > msg_end)
-                       return (time_t)-1;
-               msg++;
-       }
-
-       /* year */
-       if (!i_isdigit(msg[0]) || !i_isdigit(msg[1]) ||
-           !i_isdigit(msg[2]) || !i_isdigit(msg[3]))
-               return (time_t)-1;
-
-       tm.tm_year = (msg[0]-'0') * 1000 + (msg[1]-'0') * 100 +
-               (msg[2]-'0') * 10 + (msg[3]-'0') - 1900;
-       msg += 4;
-
-       tm.tm_isdst = -1;
-       if (msg[0] == ' ' && (msg[1] == '-' || msg[1] == '+') &&
-           i_isdigit(msg[2]) && i_isdigit(msg[3]) &&
-           i_isdigit(msg[4]) && i_isdigit(msg[5])) {
-               timezone = (msg[2]-'0') * 1000 + (msg[3]-'0') * 100 +
-                       (msg[4]-'0') * 10 +(msg[5]-'0');
-               if (msg[1] == '-') timezone = -timezone;
-
-               t = utc_mktime(&tm);
-               if (t == (time_t)-1)
-                       return (time_t)-1;
-
-               t -= timezone * 60;
-               return t;
-       } else {
-               /* assume local timezone */
-               return mktime(&tm);
-       }
-}
-
-const char *mbox_from_create(const char *sender, time_t time)
-{
-       string_t *str;
-       struct tm *tm;
-       int year;
-
-       str = t_str_new(256);
-       str_append(str, "From ");
-       str_append(str, sender);
-       str_append(str, "  ");
-
-       /* we could use simply asctime(), but i18n etc. may break it.
-          Example: "Thu Nov 29 22:33:52 2001" */
-       tm = localtime(&time);
-
-       /* week day */
-       str_append(str, weekdays[tm->tm_wday]);
-       str_append_c(str, ' ');
-
-       /* month */
-       str_append(str, months[tm->tm_mon]);
-       str_append_c(str, ' ');
-
-       /* day */
-       str_append_c(str, (tm->tm_mday / 10) + '0');
-       str_append_c(str, (tm->tm_mday % 10) + '0');
-       str_append_c(str, ' ');
-
-       /* hour */
-       str_append_c(str, (tm->tm_hour / 10) + '0');
-       str_append_c(str, (tm->tm_hour % 10) + '0');
-       str_append_c(str, ':');
-
-       /* minute */
-       str_append_c(str, (tm->tm_min / 10) + '0');
-       str_append_c(str, (tm->tm_min % 10) + '0');
-       str_append_c(str, ':');
-
-       /* second */
-       str_append_c(str, (tm->tm_sec / 10) + '0');
-       str_append_c(str, (tm->tm_sec % 10) + '0');
-       str_append_c(str, ' ');
-
-       /* year */
-       year = tm->tm_year + 1900;
-       str_append_c(str, (year / 1000) + '0');
-       str_append_c(str, ((year / 100) % 10) + '0');
-       str_append_c(str, ((year / 10) % 10) + '0');
-       str_append_c(str, (year % 10) + '0');
-
-       str_append_c(str, '\n');
-       return str_c(str);
-}
diff --git a/src/lib-index/mbox/mbox-index.c b/src/lib-index/mbox/mbox-index.c
deleted file mode 100644 (file)
index 3712b36..0000000
+++ /dev/null
@@ -1,865 +0,0 @@
-/* Copyright (C) 2002 Timo Sirainen */
-
-#include "lib.h"
-#include "buffer.h"
-#include "istream.h"
-#include "message-part-serialize.h"
-#include "mbox-index.h"
-#include "mbox-lock.h"
-#include "mail-index-util.h"
-#include "mail-custom-flags.h"
-#include "mail-cache.h"
-
-#include <stdlib.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <sys/stat.h>
-
-/* Don't try reading more custom flags than this. */
-#define MAX_CUSTOM_FLAGS 1024
-
-extern struct mail_index mbox_index;
-
-int mbox_set_syscall_error(struct mail_index *index, const char *function)
-{
-       i_assert(function != NULL);
-
-       index_set_error(index, "%s failed with mbox file %s: %m",
-                       function, index->mailbox_path);
-       return FALSE;
-}
-
-int mbox_file_open(struct mail_index *index)
-{
-       struct stat st;
-       int fd;
-
-       i_assert(index->mbox_fd == -1);
-
-       fd = open(index->mailbox_path, index->mailbox_readonly ?
-                 O_RDONLY : O_RDWR);
-       if (fd == -1) {
-               mbox_set_syscall_error(index, "open()");
-               return FALSE;
-       }
-
-       if (fstat(fd, &st) < 0) {
-               mbox_set_syscall_error(index, "fstat()");
-               (void)close(fd);
-               return FALSE;
-       }
-
-       index->mbox_fd = fd;
-       index->mbox_dev = st.st_dev;
-       index->mbox_ino = st.st_ino;
-       return TRUE;
-}
-
-struct istream *mbox_get_stream(struct mail_index *index,
-                               enum mail_lock_type lock_type)
-{
-       switch (lock_type) {
-       case MAIL_LOCK_SHARED:
-       case MAIL_LOCK_EXCLUSIVE:
-               /* don't drop exclusive lock, it may be there for a reason */
-               if (index->mbox_lock_type != MAIL_LOCK_EXCLUSIVE) {
-                       if (!mbox_lock(index, lock_type))
-                               return NULL;
-               }
-               break;
-       default:
-               if (index->mbox_fd == -1) {
-                       if (!mbox_file_open(index))
-                               return NULL;
-               }
-               break;
-       }
-
-       if (index->mbox_stream == NULL) {
-               if (index->mail_read_mmaped) {
-                       index->mbox_stream =
-                               i_stream_create_mmap(index->mbox_fd,
-                                                    default_pool,
-                                                    MAIL_MMAP_BLOCK_SIZE,
-                                                    0, 0, FALSE);
-               } else {
-                       index->mbox_stream =
-                               i_stream_create_file(index->mbox_fd,
-                                                    default_pool,
-                                                    MAIL_READ_BLOCK_SIZE,
-                                                    FALSE);
-               }
-       }
-
-       i_stream_seek(index->mbox_stream, 0);
-       i_stream_ref(index->mbox_stream);
-       return index->mbox_stream;
-}
-
-void mbox_file_close_stream(struct mail_index *index)
-{
-       if (index->mbox_stream != NULL) {
-               i_stream_close(index->mbox_stream);
-               i_stream_unref(index->mbox_stream);
-               index->mbox_stream = NULL;
-       }
-}
-
-void mbox_file_close_fd(struct mail_index *index)
-{
-       mbox_file_close_stream(index);
-
-       if (index->mbox_fd != -1) {
-               if (close(index->mbox_fd) < 0)
-                       i_error("close(mbox) failed: %m");
-               index->mbox_fd = -1;
-       }
-}
-
-void mbox_header_init_context(struct mbox_header_context *ctx,
-                             struct mail_index *index,
-                             struct istream *input)
-{
-       memset(ctx, 0, sizeof(struct mbox_header_context));
-       md5_init(&ctx->md5);
-
-       ctx->index = index;
-       ctx->input = input;
-       ctx->custom_flags = mail_custom_flags_list_get(index->custom_flags);
-       ctx->content_length = (uoff_t)-1;
-}
-
-static enum mail_flags
-mbox_get_status_flags(const unsigned char *value, size_t len)
-{
-       enum mail_flags flags;
-       size_t i;
-
-       flags = 0;
-       for (i = 0; i < len; i++) {
-               switch (value[i]) {
-               case 'A':
-                       flags |= MAIL_ANSWERED;
-                       break;
-               case 'F':
-                       flags |= MAIL_FLAGGED;
-                       break;
-               case 'T':
-                       flags |= MAIL_DRAFT;
-                       break;
-               case 'R':
-                       flags |= MAIL_SEEN;
-                       break;
-               case 'D':
-                       flags |= MAIL_DELETED;
-                       break;
-               }
-       }
-
-       return flags;
-}
-
-static void mbox_update_custom_flags(const unsigned char *value __attr_unused__,
-                                    size_t len __attr_unused__,
-                                    int index, void *context)
-{
-       enum mail_flags *flags = context;
-
-       if (index >= 0)
-               *flags |= 1 << (index + MAIL_CUSTOM_FLAG_1_BIT);
-}
-
-static enum mail_flags
-mbox_get_keyword_flags(const unsigned char *value, size_t len,
-                      const char *custom_flags[MAIL_CUSTOM_FLAGS_COUNT])
-{
-       enum mail_flags flags;
-
-       flags = 0;
-       mbox_keywords_parse(value, len, custom_flags,
-                           mbox_update_custom_flags, &flags);
-       return flags;
-}
-
-static void mbox_parse_imapbase(const unsigned char *value, size_t len,
-                               struct mbox_header_context *ctx)
-{
-       const char *flag, *str;
-       char *end;
-       buffer_t *buf;
-       size_t pos, start;
-       enum mail_flags flags;
-       unsigned int count;
-       int ret;
-
-       t_push();
-
-       /* <uid validity> <last uid> */
-       str = t_strndup(value, len);
-       ctx->uid_validity = strtoul(str, &end, 10);
-       ctx->uid_last = strtoul(end, &end, 10);
-       pos = end - str;
-
-       while (pos < len && value[pos] == ' ')
-               pos++;
-
-       if (pos == len) {
-               t_pop();
-               return;
-       }
-
-       /* we're at the 3rd field now, which begins the list of custom flags */
-       buf = buffer_create_dynamic(pool_datastack_create(),
-                                   MAIL_CUSTOM_FLAGS_COUNT *
-                                   sizeof(const char *),
-                                   MAX_CUSTOM_FLAGS * sizeof(const char *));
-       for (start = pos; ; pos++) {
-               if (pos == len || value[pos] == ' ' || value[pos] == '\t') {
-                       if (start != pos) {
-                               flag = t_strdup_until(value+start, value+pos);
-                               if (buffer_append(buf, &flag,
-                                                 sizeof(flag)) == 0)
-                                       break;
-                       }
-                       start = pos+1;
-
-                       if (pos == len)
-                               break;
-               }
-       }
-
-       flags = MAIL_CUSTOM_FLAGS_MASK;
-       count = buffer_get_used_size(buf) / sizeof(const char *);
-       ret = mail_custom_flags_fix_list(ctx->index->custom_flags, &flags,
-                                        buffer_free_without_data(buf), count);
-
-       t_pop();
-}
-
-void mbox_header_cb(struct message_part *part __attr_unused__,
-                   struct message_header_line *hdr, void *context)
-{
-       struct mbox_header_context *ctx = context;
-       size_t i;
-       int fixed = FALSE;
-
-       if (hdr == NULL || hdr->eoh)
-               return;
-
-       /* Pretty much copy&pasted from popa3d by Solar Designer */
-       switch (*hdr->name) {
-       case 'R':
-       case 'r':
-               if (!ctx->received &&
-                   strcasecmp(hdr->name, "Received") == 0) {
-                       /* get only the first received-header */
-                       fixed = TRUE;
-                       if (!hdr->continues)
-                               ctx->received = TRUE;
-               }
-               break;
-
-       case 'C':
-       case 'c':
-               if (strcasecmp(hdr->name, "Content-Length") == 0) {
-                       /* manual parsing, so we can deal with uoff_t */
-                       ctx->content_length = 0;
-                       for (i = 0; i < hdr->value_len; i++) {
-                               if (hdr->value[i] < '0' ||
-                                   hdr->value[i] > '9') {
-                                       /* invalid */
-                                       ctx->content_length = 0;
-                                       break;
-                               }
-
-                               ctx->content_length = ctx->content_length * 10 +
-                                       (hdr->value[i] - '0');
-                       }
-               }
-               break;
-
-       case 'D':
-       case 'd':
-               if (strcasecmp(hdr->name, "Delivered-To") == 0)
-                       fixed = TRUE;
-               else if (!ctx->received && strcasecmp(hdr->name, "Date") == 0) {
-                       /* Received-header contains date too,
-                          and more trusted one */
-                       fixed = TRUE;
-               }
-               break;
-
-       case 'M':
-       case 'm':
-               if (!ctx->received &&
-                   strcasecmp(hdr->name, "Message-ID") == 0) {
-                       /* Received-header contains unique ID too,
-                          and more trusted one */
-                       fixed = TRUE;
-               }
-               break;
-
-       case 'S':
-       case 's':
-               if (strcasecmp(hdr->name, "Status") == 0) {
-                       /* update message flags */
-                       ctx->flags |= mbox_get_status_flags(hdr->value,
-                                                           hdr->value_len);
-               }
-               break;
-
-       case 'X':
-       case 'x':
-               if (strcasecmp(hdr->name, "X-Delivery-ID:") == 0) {
-                       /* Let the local delivery agent help generate unique
-                          ID's but don't blindly trust this header alone as
-                          it could just as easily come from the remote. */
-                       fixed = TRUE;
-               } else if (strcasecmp(hdr->name, "X-UID") == 0) {
-                       ctx->uid = 0;
-                       for (i = 0; i < hdr->value_len; i++) {
-                               if (hdr->value[i] < '0' ||
-                                   hdr->value[i] > '9')
-                                       break;
-                               ctx->uid = ctx->uid * 10 + (hdr->value[i]-'0');
-                       }
-               } else if (strcasecmp(hdr->name, "X-Status") == 0) {
-                       /* update message flags */
-                       ctx->flags |= mbox_get_status_flags(hdr->value,
-                                                           hdr->value_len);
-               } else if (strcasecmp(hdr->name, "X-Keywords") == 0) {
-                       /* update custom message flags */
-                       ctx->flags |= mbox_get_keyword_flags(hdr->value,
-                                                            hdr->value_len,
-                                                            ctx->custom_flags);
-               } else if (strcasecmp(hdr->name, "X-IMAPbase") == 0) {
-                       if (hdr->continues) {
-                               hdr->use_full_value = TRUE;
-                               break;
-                       }
-                       mbox_parse_imapbase(hdr->full_value,
-                                           hdr->full_value_len, ctx);
-               }
-               break;
-       }
-
-       if (fixed)
-               md5_update(&ctx->md5, hdr->value, hdr->value_len);
-}
-
-void mbox_keywords_parse(const unsigned char *value, size_t len,
-                        const char *custom_flags[MAIL_CUSTOM_FLAGS_COUNT],
-                        void (*func)(const unsigned char *, size_t,
-                                     int, void *),
-                        void *context)
-{
-       size_t custom_len[MAIL_CUSTOM_FLAGS_COUNT];
-       size_t item_len;
-       int i;
-
-       /* the value is often empty, so check that first */
-       while (len > 0 && IS_LWSP(*value)) {
-               value++;
-               len--;
-       }
-
-       if (len == 0)
-               return;
-
-       for (i = 0; i < MAIL_CUSTOM_FLAGS_COUNT; i++) {
-               custom_len[i] = custom_flags[i] != NULL ?
-                       strlen(custom_flags[i]) : 0;
-       }
-
-       for (;;) {
-               /* skip whitespace */
-               while (len > 0 && IS_LWSP(*value)) {
-                       value++;
-                       len--;
-               }
-
-               if (len == 0)
-                       break;
-
-               /* find the length of the item */
-               for (item_len = 0; item_len < len; item_len++) {
-                       if (IS_LWSP(value[item_len]))
-                               break;
-               }
-
-               /* check if it's found */
-               for (i = 0; i < MAIL_CUSTOM_FLAGS_COUNT; i++) {
-                       if (custom_len[i] == item_len &&
-                           memcasecmp(custom_flags[i], value, item_len) == 0)
-                               break;
-               }
-
-               if (i == MAIL_CUSTOM_FLAGS_COUNT)
-                       i = -1;
-
-               func(value, item_len, i, context);
-
-               value += item_len;
-               len -= item_len;
-       }
-}
-
-int mbox_skip_crlf(struct istream *input)
-{
-       const unsigned char *data;
-       size_t size, pos;
-
-       pos = 0;
-       while (i_stream_read_data(input, &data, &size, pos) > 0) {
-               if (pos == 0) {
-                       if (data[0] == '\n') {
-                               i_stream_skip(input, 1);
-                               return TRUE;
-                       }
-                       if (data[0] != '\r')
-                               return FALSE;
-
-                       pos++;
-               }
-
-               if (size > 1 && pos == 1) {
-                       if (data[1] != '\n')
-                               return FALSE;
-
-                       i_stream_skip(input, 2);
-                       return TRUE;
-               }
-       }
-
-       /* end of file */
-       return TRUE;
-}
-
-void mbox_skip_empty_lines(struct istream *input)
-{
-       const unsigned char *data;
-       size_t i, size;
-
-       /* skip empty lines at beginning */
-       while (i_stream_read_data(input, &data, &size, 0) > 0) {
-               for (i = 0; i < size; i++) {
-                       if (data[i] != '\r' && data[i] != '\n')
-                               break;
-               }
-
-               i_stream_skip(input, i);
-
-               if (i < size)
-                       break;
-       }
-}
-
-static int mbox_is_valid_from(struct istream *input, size_t startpos)
-{
-       const unsigned char *msg;
-       size_t i, size;
-
-       i = startpos;
-       while (i_stream_read_data(input, &msg, &size, i) > 0) {
-               for (; i < size; i++) {
-                       if (msg[i] == '\n') {
-                               msg += startpos;
-                               i -= startpos;
-                               return mbox_from_parse_date(msg, size) !=
-                                       (time_t)-1;
-                       }
-               }
-       }
-
-       return FALSE;
-}
-
-static void mbox_skip_forward(struct istream *input, int header)
-{
-       const unsigned char *msg;
-       size_t i, size, startpos, eoh;
-       int lastmsg, state, new_state;
-
-       /* read until "[\r]\nFrom " is found. assume '\n' at beginning of
-          buffer */
-       startpos = i = 0; eoh = 0; lastmsg = TRUE;
-       state = '\n';
-       while (i_stream_read_data(input, &msg, &size, startpos) > 0) {
-               for (i = startpos; i < size; i++) {
-                       new_state = 0;
-                       switch (state) {
-                       case '\n':
-                               if (msg[i] == 'F')
-                                       new_state = 'F';
-                               else if (header) {
-                                       if (msg[i] == '\n') {
-                                               /* \n\n, but if we have
-                                                  0-byte message body the
-                                                  following \n may belong
-                                                  to "From "-line */
-                                               eoh = i+1;
-                                               header = FALSE;
-                                               new_state = '\n';
-                                       } else if (msg[i] == '\r') {
-                                               /* possibly \n\r\n */
-                                               new_state = '\r';
-                                       }
-                               }
-                               break;
-                       case '\r':
-                               if (msg[i] == '\n') {
-                                       /* \n\r\n */
-                                       eoh = i+1;
-                                       header = FALSE;
-                                       new_state = '\n';
-                               }
-                               break;
-                       case 'F':
-                               if (msg[i] == 'r')
-                                       new_state = 'r';
-                               break;
-                       case 'r':
-                               if (msg[i] == 'o')
-                                       new_state = 'o';
-                               break;
-                       case 'o':
-                               if (msg[i] == 'm')
-                                       new_state = 'm';
-                               break;
-                       case 'm':
-                               if (msg[i] == ' ') {
-                                       int valid;
-
-                                       valid = mbox_is_valid_from(input, i+1);
-
-                                       /* we may have trashed msg above,
-                                          get it again */
-                                       msg = i_stream_get_data(input, &size);
-
-                                       if (valid) {
-                                               /* Go back "From" */
-                                               i -= 4;
-
-                                               /* Go back \n, unless we're at
-                                                  beginning of buffer */
-                                               if (i > 0)
-                                                       i--;
-
-                                               /* Go back \r if it's there */
-                                               if (i > 0 && msg[i-1] == '\r')
-                                                       i--;
-
-                                               i_stream_skip(input, i);
-                                               return;
-                                       }
-                               }
-                               break;
-                       }
-
-                       if (new_state != 0)
-                               state = new_state;
-                       else if (eoh == 0)
-                               state = msg[i] == '\n' ? '\n' : 0;
-                       else {
-                               /* end of header position confirmed */
-                               i_stream_skip(input, eoh);
-                               return;
-                       }
-               }
-
-               /* Leave enough space to go back "\r\nFrom" plus one for the
-                  end-of-headers check */
-               startpos = i < 7 ? i : 7;
-               i -= startpos;
-
-               if (eoh != 0) {
-                       i_assert(i < eoh);
-                       eoh -= i;
-               }
-
-               i_stream_skip(input, i);
-       }
-
-       if (eoh != 0) {
-               /* make sure we didn't end with \n\n or \n\r\n. In these
-                  cases the last [\r]\n doesn't belong to our message. */
-               if (eoh < size && (msg[eoh] != '\r' || eoh < size-1)) {
-                       i_stream_skip(input, eoh);
-                       return;
-               }
-       }
-
-       /* end of file, leave the last [\r]\n */
-       msg = i_stream_get_data(input, &size);
-       if (size == startpos && startpos > 0) {
-               if (msg[startpos-1] == '\n')
-                       startpos--;
-               if (startpos > 0 && msg[startpos-1] == '\r')
-                       startpos--;
-       }
-
-       i_stream_skip(input, startpos);
-}
-
-void mbox_skip_header(struct istream *input)
-{
-       mbox_skip_forward(input, TRUE);
-}
-
-void mbox_skip_message(struct istream *input)
-{
-       mbox_skip_forward(input, FALSE);
-}
-
-int mbox_verify_end_of_body(struct istream *input, uoff_t end_offset)
-{
-       const unsigned char *data;
-       size_t size;
-
-       i_stream_seek(input, end_offset);
-
-       /* read forward a bit */
-       if (i_stream_read_data(input, &data, &size, 6) < 0)
-               return FALSE;
-
-       /* either there should be the next From-line,
-          or [\r]\n at end of file */
-       if (size > 0 && data[0] == '\r') {
-               data++; size--;
-       }
-       if (size > 0) {
-               if (data[0] != '\n')
-                       return FALSE;
-
-               data++; size--;
-       }
-
-       return size == 0 ||
-               (size >= 5 && strncmp((const char *) data, "From ", 5) == 0);
-}
-
-int mbox_mail_get_location(struct mail_index *index,
-                          struct mail_index_record *rec,
-                          uoff_t *offset, uoff_t *body_size)
-{
-       struct message_size _body_size;
-       const void *data;
-       size_t size;
-
-       if (offset != NULL) {
-               if (!mail_cache_copy_fixed_field(index->cache, rec,
-                                                MAIL_CACHE_LOCATION_OFFSET,
-                                                offset, sizeof(*offset))) {
-                       mail_cache_set_corrupted(index->cache,
-                               "Missing location field for record %u",
-                               rec->uid);
-                       return FALSE;
-               }
-       }
-
-       if (body_size != NULL) {
-               if (mail_cache_copy_fixed_field(index->cache, rec,
-                                               MAIL_CACHE_PHYSICAL_BODY_SIZE,
-                                               body_size, sizeof(uoff_t)))
-                       return TRUE;
-
-               if (!mail_cache_lookup_field(index->cache, rec,
-                                            MAIL_CACHE_MESSAGEPART,
-                                            &data, &size)) {
-                       mail_cache_set_corrupted(index->cache,
-                               "No cached body_size or message_part for "
-                               "record %u", rec->uid);
-                       return FALSE;
-               }
-               if (!message_part_deserialize_size(data, size,
-                                                  NULL, &_body_size)) {
-                       mail_cache_set_corrupted(index->cache,
-                               "Corrupted message_part for record %u",
-                               rec->uid);
-                       return FALSE;
-               }
-
-               if (body_size != NULL)
-                       *body_size = _body_size.physical_size;
-       }
-
-       return TRUE;
-}
-
-void mbox_read_headers(struct istream *input, buffer_t *dest)
-{
-       struct message_header_parser_ctx *hdr_ctx;
-       struct message_header_line *hdr;
-
-       hdr_ctx = message_parse_header_init(input, NULL);
-       while ((hdr = message_parse_header_next(hdr_ctx)) != NULL) {
-               if (hdr->eoh) {
-                       buffer_append(dest, "\r\n", 2);
-                       break;
-               }
-
-               if ((*hdr->name == 'X' &&
-                    (strcasecmp(hdr->name, "X-UID") == 0 ||
-                     strcasecmp(hdr->name, "X-IMAPbase") == 0 ||
-                     strcasecmp(hdr->name, "X-Status") == 0 ||
-                     strcasecmp(hdr->name, "X-Keywords") == 0)) ||
-                   strcasecmp(hdr->name, "Content-Length") == 0 ||
-                   strcasecmp(hdr->name, "Status") == 0) {
-                       /* ignore */
-               } else {
-                       if (!hdr->continued) {
-                               buffer_append(dest, hdr->name, hdr->name_len);
-                               buffer_append(dest, ": ", 2);
-                       }
-                       buffer_append(dest, hdr->value, hdr->value_len);
-                       buffer_append(dest, "\r\n", 2);
-               }
-       }
-       message_parse_header_deinit(hdr_ctx);
-}
-
-struct mail_index *
-mbox_index_alloc(const char *mbox_path, const char *index_dir,
-                const char *control_dir)
-{
-       struct mail_index *index;
-
-       i_assert(mbox_path != NULL);
-
-       index = i_new(struct mail_index, 1);
-       memcpy(index, &mbox_index, sizeof(struct mail_index));
-
-       index->mbox_fd = -1;
-       index->mbox_sync_counter = (unsigned int)-1;
-       index->mailbox_readonly = access(mbox_path, W_OK) < 0;
-
-       index->mailbox_path = i_strdup(mbox_path);
-       index->control_dir = i_strdup(control_dir);
-       mail_index_init(index, index_dir);
-       return index;
-}
-
-static void mbox_index_free(struct mail_index *index)
-{
-        mbox_file_close_fd(index);
-       mail_index_close(index);
-       i_free(index->dir);
-       i_free(index->mailbox_path);
-       i_free(index->control_dir);
-       i_free(index);
-}
-
-static int mbox_index_set_lock(struct mail_index *index,
-                              enum mail_lock_type lock_type)
-{
-       if (lock_type == MAIL_LOCK_UNLOCK)
-               (void)mbox_unlock(index);
-       return mail_index_set_lock(index, lock_type);
-}
-
-static int mbox_index_try_lock(struct mail_index *index,
-                              enum mail_lock_type lock_type)
-{
-       if (lock_type == MAIL_LOCK_UNLOCK)
-               (void)mbox_unlock(index);
-       return mail_index_try_lock(index, lock_type);
-}
-
-static int mbox_index_expunge(struct mail_index *index,
-                             struct mail_index_record *first_rec,
-                             struct mail_index_record *last_rec,
-                             unsigned int first_seq, unsigned int last_seq,
-                             int external_change)
-{
-       if (!mail_index_expunge(index, first_rec, last_rec,
-                               first_seq, last_seq, external_change))
-               return FALSE;
-
-       if (first_seq == 1) {
-               /* Our message containing X-IMAPbase was deleted.
-                  Get it back there. */
-               index->header->flags |= MAIL_INDEX_HDR_FLAG_DIRTY_MESSAGES |
-                       MAIL_INDEX_HDR_FLAG_DIRTY_CUSTOMFLAGS;
-       }
-       return TRUE;
-}
-
-static int mbox_index_update_flags(struct mail_index *index,
-                                  struct mail_index_record *rec,
-                                  unsigned int seq,
-                                  enum modify_type modify_type,
-                                  enum mail_flags flags,
-                                  int external_change)
-{
-        enum mail_index_record_flag index_flags;
-
-       if (!mail_index_update_flags(index, rec, seq,
-                                    modify_type, flags, external_change))
-               return FALSE;
-
-       if (!external_change) {
-               /* we'll just mark the message as dirty */
-               index_flags = mail_cache_get_index_flags(index->cache, rec);
-               if ((index_flags & MAIL_INDEX_FLAG_DIRTY) == 0) {
-                       if (mail_cache_lock(index->cache, FALSE) <= 0)
-                               return FALSE;
-                       mail_cache_unlock_later(index->cache);
-
-                       index_flags |= MAIL_INDEX_FLAG_DIRTY;
-                       mail_cache_update_index_flags(index->cache, rec,
-                                                     index_flags);
-
-                       index->header->flags |=
-                               MAIL_INDEX_HDR_FLAG_DIRTY_MESSAGES;
-               }
-       }
-       return TRUE;
-}
-
-static struct mail_index_record *mbox_index_append(struct mail_index *index)
-{
-       /* update last_uid in X-IMAPbase */
-       index->header->flags |= MAIL_INDEX_HDR_FLAG_DIRTY_MESSAGES |
-               MAIL_INDEX_HDR_FLAG_DIRTY_CUSTOMFLAGS;
-
-       return mail_index_append(index);
-}
-
-static time_t mbox_get_received_date(struct mail_index *index,
-                                    struct mail_index_record *rec)
-{
-       time_t date;
-
-       if (mail_cache_copy_fixed_field(index->cache, rec,
-                                       MAIL_CACHE_RECEIVED_DATE,
-                                       &date, sizeof(date)))
-               return date;
-
-       mail_cache_set_corrupted(index->cache,
-               "Missing internal date for record %u", rec->uid);
-       return (time_t)-1;
-}
-
-struct mail_index mbox_index = {
-       mail_index_open,
-       mbox_index_free,
-       mbox_index_set_lock,
-       mbox_index_try_lock,
-        mail_index_set_lock_notify_callback,
-       mail_index_rebuild,
-       mail_index_fsck,
-       mbox_index_sync,
-       mail_index_get_header,
-       mail_index_lookup,
-       mail_index_next,
-        mail_index_lookup_uid_range,
-       mbox_open_mail,
-       mbox_get_received_date,
-       mbox_index_expunge,
-       mbox_index_update_flags,
-       mbox_index_append,
-       mail_index_get_last_error,
-       mail_index_get_last_error_text,
-
-       MAIL_INDEX_PRIVATE_FILL
-};
diff --git a/src/lib-index/mbox/mbox-index.h b/src/lib-index/mbox/mbox-index.h
deleted file mode 100644 (file)
index 8f1a71b..0000000
+++ /dev/null
@@ -1,74 +0,0 @@
-#ifndef __MBOX_INDEX_H
-#define __MBOX_INDEX_H
-
-#include "md5.h"
-#include "mail-index.h"
-
-/* Extra space to leave in X-Keywords header when rewriting mbox */
-#define MBOX_HEADER_EXTRA_SPACE 100
-
-struct mbox_header_context {
-       struct mail_index *index;
-       enum mail_flags flags;
-       const char **custom_flags;
-       struct md5_context md5;
-       int received;
-
-       unsigned int uid_validity, uid_last, uid;
-
-       struct istream *input;
-       uoff_t content_length;
-};
-
-int mbox_set_syscall_error(struct mail_index *index, const char *function);
-
-/* Make sure the mbox is opened. If reopen is TRUE, the file is closed first,
-   which is useful when you want to be sure you're not accessing a deleted
-   mbox file. */
-int mbox_file_open(struct mail_index *index);
-struct istream *mbox_get_stream(struct mail_index *index,
-                               enum mail_lock_type lock_type);
-void mbox_file_close_stream(struct mail_index *index);
-void mbox_file_close_fd(struct mail_index *index);
-
-void mbox_header_init_context(struct mbox_header_context *ctx,
-                             struct mail_index *index,
-                             struct istream *input);
-void mbox_header_cb(struct message_part *part,
-                   struct message_header_line *hdr, void *context);
-void mbox_keywords_parse(const unsigned char *value, size_t len,
-                        const char *custom_flags[MAIL_CUSTOM_FLAGS_COUNT],
-                        void (*func)(const unsigned char *, size_t,
-                                     int, void *),
-                        void *context);
-int mbox_skip_crlf(struct istream *input);
-void mbox_skip_empty_lines(struct istream *input);
-void mbox_skip_header(struct istream *input);
-void mbox_skip_message(struct istream *input);
-int mbox_verify_end_of_body(struct istream *input, uoff_t end_offset);
-int mbox_mail_get_location(struct mail_index *index,
-                          struct mail_index_record *rec,
-                          uoff_t *offset, uoff_t *body_size);
-void mbox_read_headers(struct istream *input, buffer_t *dest);
-
-struct mail_index *
-mbox_index_alloc(const char *mbox_path, const char *index_dir,
-                const char *control_dir);
-int mbox_index_sync(struct mail_index *index, int minimal_sync,
-                   enum mail_lock_type lock_type, int *changes);
-int mbox_sync_full(struct mail_index *index);
-struct istream *mbox_open_mail(struct mail_index *index,
-                              struct mail_index_record *rec,
-                              time_t *received_date, int *deleted);
-
-int mbox_index_append_stream(struct mail_index *index, struct istream *input);
-
-time_t mbox_from_parse_date(const unsigned char *msg, size_t size);
-const char *mbox_from_create(const char *sender, time_t time);
-
-int mbox_index_rewrite(struct mail_index *index);
-
-struct istream *i_stream_create_mbox(pool_t pool, struct istream *input,
-                                    uoff_t offset, uoff_t body_size);
-
-#endif
diff --git a/src/lib-index/mbox/mbox-lock.c b/src/lib-index/mbox/mbox-lock.c
deleted file mode 100644 (file)
index 2602890..0000000
+++ /dev/null
@@ -1,321 +0,0 @@
-/* Copyright (C) 2002 Timo Sirainen */
-
-#include "lib.h"
-#include "mbox-index.h"
-#include "mbox-lock.h"
-#include "mail-index-util.h"
-
-#include <time.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <sys/stat.h>
-
-#ifdef HAVE_FLOCK
-#  include <sys/file.h>
-#endif
-
-/* 0.1 .. 0.2msec */
-#define LOCK_RANDOM_USLEEP_TIME (100000 + (unsigned int)rand() % 100000)
-
-/* lock methods to use in wanted order */
-#define DEFAULT_LOCK_METHODS "dotlock fcntl"
-/* lock timeout */
-#define DEFAULT_LOCK_TIMEOUT 300
-/* assume stale dotlock if mbox file hasn't changed for n seconds */
-#define DEFAULT_DOTLOCK_CHANGE_TIMEOUT 30
-
-struct dotlock_context {
-       struct mail_index *index;
-        enum mail_lock_type lock_type;
-       int last_stale;
-};
-
-static int lock_settings_initialized = FALSE;
-static int use_dotlock, use_fcntl_lock, use_flock, fcntl_before_flock;
-static int use_read_dotlock, lock_timeout, dotlock_change_timeout;
-
-static void mbox_init_lock_settings(void)
-{
-       const char *str;
-       const char *const *lock;
-
-        use_dotlock = use_fcntl_lock = use_flock = fcntl_before_flock = FALSE;
-
-       str = getenv("MBOX_LOCKS");
-       if (str == NULL) str = DEFAULT_LOCK_METHODS;
-       for (lock = t_strsplit_spaces(str, " "); *lock != NULL; lock++) {
-               if (strcasecmp(*lock, "dotlock") == 0)
-                       use_dotlock = TRUE;
-               else if (strcasecmp(*lock, "fcntl") == 0) {
-                       use_fcntl_lock = TRUE;
-                       fcntl_before_flock = use_flock == FALSE;
-               } else if (strcasecmp(*lock, "flock") == 0)
-                       use_flock = TRUE;
-               else
-                       i_fatal("MBOX_LOCKS: Invalid value %s", *lock);
-       }
-
-       use_read_dotlock = getenv("MBOX_READ_DOTLOCK") != NULL;
-
-       str = getenv("MBOX_LOCK_TIMEOUT");
-       lock_timeout = str == NULL ? DEFAULT_LOCK_TIMEOUT : atoi(str);
-
-       str = getenv("MBOX_DOTLOCK_CHANGE_TIMEOUT");
-       dotlock_change_timeout = str == NULL ?
-               DEFAULT_DOTLOCK_CHANGE_TIMEOUT : atoi(str);
-
-        lock_settings_initialized = TRUE;
-}
-
-#ifdef HAVE_FLOCK
-static int mbox_lock_flock(struct mail_index *index,
-                          enum mail_lock_type lock_type, time_t max_wait_time)
-{
-       time_t now, last_notify;
-
-       if (lock_type == MAIL_LOCK_EXCLUSIVE)
-               lock_type = LOCK_EX;
-       else if (lock_type == MAIL_LOCK_SHARED)
-               lock_type = LOCK_SH;
-       else
-               lock_type = LOCK_UN;
-
-        last_notify = 0;
-       while (flock(index->mbox_fd, lock_type | LOCK_NB) < 0) {
-               if (errno != EWOULDBLOCK) {
-                        mbox_set_syscall_error(index, "flock()");
-                       return FALSE;
-               }
-
-               if (max_wait_time == 0)
-                       return FALSE;
-
-               now = time(NULL);
-               if (now >= max_wait_time) {
-                       index->mailbox_lock_timeout = TRUE;
-                       index_set_error(index, "Timeout while waiting for "
-                                       "release of flock() lock for mbox file "
-                                       "%s", index->mailbox_path);
-                       return FALSE;
-               }
-
-               if (now != last_notify && index->lock_notify_cb != NULL) {
-                       last_notify = now;
-                       index->lock_notify_cb(MAIL_LOCK_NOTIFY_MAILBOX_ABORT,
-                                             max_wait_time - now,
-                                             index->lock_notify_context);
-               }
-
-               usleep(LOCK_RANDOM_USLEEP_TIME);
-       }
-
-       return TRUE;
-}
-#endif
-
-static int mbox_lock_fcntl(struct mail_index *index,
-                          enum mail_lock_type lock_type, time_t max_wait_time)
-{
-       struct flock fl;
-       time_t now;
-       int wait_type;
-
-       fl.l_type = MAIL_LOCK_TO_FLOCK(lock_type);
-       fl.l_whence = SEEK_SET;
-       fl.l_start = 0;
-       fl.l_len = 0;
-
-        wait_type = max_wait_time == 0 ? F_SETLK : F_SETLKW;
-       while (fcntl(index->mbox_fd, wait_type, &fl) < 0) {
-               if (errno != EINTR) {
-                       if (errno != EAGAIN && errno != EACCES)
-                               mbox_set_syscall_error(index, "fcntl()");
-                       return FALSE;
-               }
-
-               now = time(NULL);
-               if (max_wait_time != 0 && now >= max_wait_time) {
-                       index->mailbox_lock_timeout = TRUE;
-                       index_set_error(index, "Timeout while waiting for "
-                                       "release of fcntl() lock for mbox file "
-                                       "%s", index->mailbox_path);
-                       return FALSE;
-               }
-
-               if (index->lock_notify_cb != NULL) {
-                       index->lock_notify_cb(MAIL_LOCK_NOTIFY_MAILBOX_ABORT,
-                                             max_wait_time - now,
-                                             index->lock_notify_context);
-               }
-       }
-       return TRUE;
-}
-
-static int mbox_file_locks(struct mail_index *index,
-                          enum mail_lock_type lock_type, time_t max_wait_time)
-{
-       struct stat st;
-
-       /* now we need to have the file itself locked. open it if needed. */
-       if (stat(index->mailbox_path, &st) < 0)
-               return mbox_set_syscall_error(index, "stat()");
-
-       if (st.st_dev != index->mbox_dev || st.st_ino != index->mbox_ino)
-               mbox_file_close_fd(index);
-
-       if (index->mbox_fd == -1) {
-               if (!mbox_file_open(index)) {
-                       (void)mbox_unlock(index);
-                       return FALSE;
-               }
-       }
-
-       if (use_fcntl_lock && fcntl_before_flock) {
-               if (!mbox_lock_fcntl(index, lock_type, max_wait_time))
-                       return FALSE;
-       }
-#ifdef HAVE_FLOCK
-       if (use_flock) {
-               if (!mbox_lock_flock(index, lock_type, max_wait_time))
-                       return FALSE;
-       }
-#endif
-       if (use_fcntl_lock && !fcntl_before_flock) {
-               if (!mbox_lock_fcntl(index, lock_type, max_wait_time))
-                       return FALSE;
-       }
-       return TRUE;
-}
-
-static int mbox_file_unlock(struct mail_index *index)
-{
-       int failed = FALSE;
-
-#ifdef HAVE_FLOCK
-       if (use_flock && !mbox_lock_flock(index, MAIL_LOCK_UNLOCK, 0))
-               failed = TRUE;
-#endif
-       if (use_fcntl_lock &&
-           !mbox_lock_fcntl(index, MAIL_LOCK_UNLOCK, 0))
-               failed = TRUE;
-
-       return !failed;
-}
-
-static int dotlock_callback(unsigned int secs_left, int stale, void *context)
-{
-       struct dotlock_context *ctx = context;
-
-       if (stale && !ctx->last_stale) {
-               if (!mbox_file_locks(ctx->index, ctx->lock_type, 0)) {
-                       /* we couldn't get fcntl/flock - it's really locked */
-                       ctx->last_stale = TRUE;
-                       return FALSE;
-               }
-               (void)mbox_file_unlock(ctx->index);
-       }
-       ctx->last_stale = stale;
-
-       if (ctx->index->lock_notify_cb != NULL) {
-               ctx->index->lock_notify_cb(stale ?
-                                          MAIL_LOCK_NOTIFY_MAILBOX_OVERRIDE :
-                                          MAIL_LOCK_NOTIFY_MAILBOX_ABORT,
-                                          secs_left,
-                                          ctx->index->lock_notify_context);
-       }
-       return TRUE;
-}
-
-int mbox_lock(struct mail_index *index, enum mail_lock_type lock_type)
-{
-       time_t max_wait_time;
-       int ret;
-
-       /* index must be locked before mbox file, to avoid deadlocks */
-       i_assert(index->lock_type != MAIL_LOCK_UNLOCK);
-
-       /* allow only unlock -> shared/exclusive or exclusive -> shared */
-       i_assert(lock_type == MAIL_LOCK_SHARED ||
-                lock_type == MAIL_LOCK_EXCLUSIVE);
-       i_assert(lock_type != MAIL_LOCK_EXCLUSIVE ||
-                index->mbox_lock_type != MAIL_LOCK_SHARED);
-
-       if (index->mbox_lock_type == lock_type)
-               return TRUE;
-
-       if (!lock_settings_initialized)
-                mbox_init_lock_settings();
-
-       max_wait_time = time(NULL) + lock_timeout;
-
-       /* make .lock file first to protect overwriting the file */
-       if (use_dotlock && index->mbox_dotlock.ino == 0) {
-               struct dotlock_context ctx;
-
-               ctx.index = index;
-               ctx.lock_type = lock_type;
-               ctx.last_stale = -1;
-
-               ret = file_lock_dotlock(index->mailbox_path, NULL,
-                                       lock_type == MAIL_LOCK_SHARED &&
-                                       !use_read_dotlock, lock_timeout,
-                                       dotlock_change_timeout, 0,
-                                       dotlock_callback, &ctx,
-                                       &index->mbox_dotlock);
-
-               if (ret < 0) {
-                       mbox_set_syscall_error(index, "file_lock_dotlock()");
-                       return FALSE;
-               }
-               if (ret == 0) {
-                       index_set_error(index, "Timeout while waiting for "
-                                       "release of dotlock for mbox %s",
-                                       index->mailbox_path);
-                       index->mailbox_lock_timeout = TRUE;
-                       return FALSE;
-               }
-       }
-
-       index->mbox_lock_type = lock_type;
-       if (!mbox_file_locks(index, index->mbox_lock_type, max_wait_time)) {
-               (void)mbox_unlock(index);
-               return FALSE;
-       }
-
-       return TRUE;
-}
-
-int mbox_unlock(struct mail_index *index)
-{
-       int failed;
-
-       index->mbox_lock_counter++;
-
-       if (index->mbox_lock_type == MAIL_LOCK_UNLOCK)
-               return TRUE;
-
-       failed = FALSE;
-       if (index->mbox_fd != -1) {
-               if (!mbox_file_unlock(index))
-                       failed = TRUE;
-       }
-
-       if (index->mbox_dotlock.ino != 0) {
-               if (file_unlock_dotlock(index->mailbox_path,
-                                       &index->mbox_dotlock) <= 0) {
-                        mbox_set_syscall_error(index, "file_unlock_dotlock()");
-                       failed = TRUE;
-               }
-                index->mbox_dotlock.ino = 0;
-       }
-
-       /* make sure we don't keep mmap() between locks - there could have
-          been changes to file size which would break things. or actually
-          it'd break only if file was shrinked+grown back to exact size,
-          but still possible :) */
-       mbox_file_close_stream(index);
-
-       index->mbox_lock_type = MAIL_LOCK_UNLOCK;
-       return !failed;
-}
diff --git a/src/lib-index/mbox/mbox-lock.h b/src/lib-index/mbox/mbox-lock.h
deleted file mode 100644 (file)
index d09ed6a..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-#ifndef __MBOX_LOCK_H
-#define __MBOX_LOCK_H
-
-/* NOTE: if mbox file is not open, it's opened. if it is open but file has
-   been overwritten (ie. inode has changed), it's reopened. */
-int mbox_lock(struct mail_index *index, enum mail_lock_type lock_type);
-int mbox_unlock(struct mail_index *index);
-
-#endif
diff --git a/src/lib-index/mbox/mbox-open.c b/src/lib-index/mbox/mbox-open.c
deleted file mode 100644 (file)
index be56814..0000000
+++ /dev/null
@@ -1,39 +0,0 @@
-/* Copyright (C) 2002 Timo Sirainen */
-
-#include "lib.h"
-#include "istream.h"
-#include "mbox-index.h"
-#include "mail-index-util.h"
-
-#include <stdlib.h>
-#include <unistd.h>
-#include <fcntl.h>
-
-struct istream *mbox_open_mail(struct mail_index *index,
-                              struct mail_index_record *rec,
-                              time_t *received_date, int *deleted)
-{
-       struct istream *input;
-       uoff_t offset, body_size;
-
-       i_assert(index->lock_type != MAIL_LOCK_UNLOCK);
-
-       *deleted = FALSE;
-
-       /* check for inconsistency here, to avoid extra error messages */
-       if (index->inconsistent)
-               return NULL;
-
-       if (!mbox_mail_get_location(index, rec, &offset, &body_size))
-               return NULL;
-
-       input = mbox_get_stream(index, MAIL_LOCK_SHARED);
-       if (input == NULL)
-               return NULL;
-
-       if (received_date != NULL)
-               *received_date = index->get_received_date(index, rec);
-
-       i_assert(index->mbox_sync_counter == index->mbox_lock_counter);
-       return i_stream_create_mbox(default_pool, input, offset, body_size);
-}
diff --git a/src/lib-index/mbox/mbox-rewrite.c b/src/lib-index/mbox/mbox-rewrite.c
deleted file mode 100644 (file)
index e2da691..0000000
+++ /dev/null
@@ -1,791 +0,0 @@
-/* Copyright (C) 2002 Timo Sirainen */
-
-#include "lib.h"
-#include "ioloop.h"
-#include "istream.h"
-#include "ostream.h"
-#include "file-set-size.h"
-#include "str.h"
-#include "write-full.h"
-#include "mbox-index.h"
-#include "mbox-lock.h"
-#include "mail-index-util.h"
-#include "mail-custom-flags.h"
-#include "mail-cache.h"
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <sys/stat.h>
-
-struct mbox_rewrite_context {
-       struct ostream *output;
-
-       uoff_t content_length;
-       unsigned int seq, uid;
-       unsigned int msg_flags;
-       const char **custom_flags;
-
-       unsigned int uid_validity;
-       unsigned int uid_last;
-       char *x_keywords;
-
-       unsigned int ximapbase_found:1;
-       unsigned int xuid_found:1;
-       unsigned int status_found:1;
-       unsigned int xstatus_found:1;
-       unsigned int content_length_found:1;
-};
-
-/* Remove dirty flag from all messages */
-static int reset_dirty_flags(struct mail_index *index)
-{
-       struct mail_index_record *rec;
-       enum mail_index_record_flag index_flags;
-
-       if (mail_cache_lock(index->cache, FALSE) <= 0)
-               return FALSE;
-       mail_cache_unlock_later(index->cache);
-
-       rec = index->lookup(index, 1);
-       while (rec != NULL) {
-               index_flags = mail_cache_get_index_flags(index->cache, rec);
-               if ((index_flags & MAIL_INDEX_FLAG_DIRTY) != 0) {
-                       index_flags &= ~MAIL_INDEX_FLAG_DIRTY;
-                       if (!mail_cache_update_index_flags(index->cache,
-                                                          rec, index_flags))
-                               return FALSE;
-               }
-
-               rec = index->next(index, rec);
-       }
-
-       index->header->flags &= ~(MAIL_INDEX_HDR_FLAG_DIRTY_MESSAGES |
-                                 MAIL_INDEX_HDR_FLAG_DIRTY_CUSTOMFLAGS);
-       return TRUE;
-}
-
-static int mbox_write(struct mail_index *index, struct istream *input,
-                     struct ostream *output, uoff_t end_offset)
-{
-       int failed;
-
-       i_assert(input->v_offset <= end_offset);
-
-       input = i_stream_create_limit(default_pool, input, 0, end_offset);
-       if (o_stream_send_istream(output, input) < 0) {
-               index_set_error(index, "Error rewriting mbox file %s: %s",
-                               index->mailbox_path,
-                               strerror(output->stream_errno));
-               failed = TRUE;
-       } else if (input->v_offset < end_offset) {
-               /* sync should have noticed it.. */
-               index_set_error(index, "Error rewriting mbox file %s: "
-                               "Unexpected end of file", index->mailbox_path);
-               failed = TRUE;
-       } else {
-               failed = FALSE;
-       }
-
-       i_stream_unref(input);
-       return !failed;
-}
-
-static int mbox_write_ximapbase(struct mbox_rewrite_context *ctx)
-{
-       const char *str;
-       int i;
-
-       str = t_strdup_printf("X-IMAPbase: %u %u",
-                             ctx->uid_validity, ctx->uid_last);
-       if (o_stream_send_str(ctx->output, str) < 0)
-               return FALSE;
-
-       for (i = 0; i < MAIL_CUSTOM_FLAGS_COUNT; i++) {
-               if (ctx->custom_flags[i] != NULL) {
-                       if (o_stream_send(ctx->output, " ", 1) < 0)
-                               return FALSE;
-
-                       if (o_stream_send_str(ctx->output,
-                                             ctx->custom_flags[i]) < 0)
-                               return FALSE;
-               }
-       }
-
-       if (o_stream_send(ctx->output, "\n", 1) < 0)
-               return FALSE;
-
-       return TRUE;
-}
-
-static int mbox_write_xuid(struct mbox_rewrite_context *ctx)
-{
-       const char *str;
-
-       str = t_strdup_printf("X-UID: %u\n", ctx->uid);
-
-       if (o_stream_send_str(ctx->output, str) < 0)
-               return FALSE;
-
-       return TRUE;
-}
-
-static int mbox_write_xkeywords(struct mbox_rewrite_context *ctx,
-                               const char *x_keywords, uoff_t wanted_offset,
-                               int force_filler)
-{
-       unsigned int field;
-       int i;
-
-       if ((ctx->msg_flags & MAIL_CUSTOM_FLAGS_MASK) == 0 &&
-           x_keywords == NULL && !force_filler &&
-           ctx->output->offset + sizeof("X-Keywords:")+1 >= wanted_offset) {
-               /* nothing to do, and not enough extra space to write the
-                  filler. Do it only if there's space for "X-Keywords: \n" */
-               return TRUE;
-       }
-
-       if (o_stream_send_str(ctx->output, "X-Keywords:") < 0)
-               return FALSE;
-
-       field = 1 << MAIL_CUSTOM_FLAG_1_BIT;
-       for (i = 0; i < MAIL_CUSTOM_FLAGS_COUNT; i++, field <<= 1) {
-               if ((ctx->msg_flags & field) && ctx->custom_flags[i] != NULL) {
-                       if (o_stream_send(ctx->output, " ", 1) < 0)
-                               return FALSE;
-
-                       if (o_stream_send_str(ctx->output,
-                                             ctx->custom_flags[i]) < 0)
-                               return FALSE;
-               }
-       }
-
-       if (x_keywords != NULL) {
-               /* X-Keywords that aren't custom flags */
-               if (o_stream_send(ctx->output, " ", 1) < 0)
-                       return FALSE;
-
-               if (o_stream_send_str(ctx->output, x_keywords) < 0)
-                       return FALSE;
-       }
-
-       /* fill the rest with spaces. -1 for \n */
-       if (ctx->output->offset < wanted_offset-1 || force_filler) {
-               char buf[1024];
-               uoff_t fill_left;
-
-               fill_left = force_filler ? MBOX_HEADER_EXTRA_SPACE :
-                       wanted_offset-1 - ctx->output->offset;
-               memset(buf, ' ', sizeof(buf));
-               while (fill_left > sizeof(buf)) {
-                       if (o_stream_send(ctx->output, buf, sizeof(buf)) < 0)
-                               return FALSE;
-                       fill_left -= sizeof(buf);
-               }
-               if (o_stream_send(ctx->output, buf, fill_left) < 0)
-                       return FALSE;
-       }
-
-       if (o_stream_send(ctx->output, "\n", 1) < 0)
-               return FALSE;
-
-       return TRUE;
-}
-
-static int mbox_write_status(struct mbox_rewrite_context *ctx,
-                            const char *status)
-{
-       const char *str;
-
-       str = (ctx->msg_flags & MAIL_SEEN) ? "Status: RO" : "Status: O";
-       if (status != NULL)
-               str = t_strconcat(str, status, NULL);
-
-       if (o_stream_send_str(ctx->output, str) < 0)
-               return FALSE;
-       if (o_stream_send(ctx->output, "\n", 1) < 0)
-               return FALSE;
-
-       return TRUE;
-}
-
-static int mbox_write_xstatus(struct mbox_rewrite_context *ctx,
-                             const char *x_status)
-{
-       const char *str;
-
-       /* X-Status field */
-       if ((ctx->msg_flags & (MAIL_SYSTEM_FLAGS_MASK^MAIL_SEEN)) == 0 &&
-           x_status == NULL)
-               return TRUE;
-
-       str = t_strconcat("X-Status: ",
-                         (ctx->msg_flags & MAIL_ANSWERED) ? "A" : "",
-                         (ctx->msg_flags & MAIL_DELETED) ? "D" : "",
-                         (ctx->msg_flags & MAIL_FLAGGED) ? "F" : "",
-                         (ctx->msg_flags & MAIL_DRAFT) ? "T" : "",
-                         x_status, NULL);
-
-       if (o_stream_send_str(ctx->output, str) < 0)
-               return FALSE;
-       if (o_stream_send(ctx->output, "\n", 1) < 0)
-               return FALSE;
-
-       return TRUE;
-}
-
-static int mbox_write_content_length(struct mbox_rewrite_context *ctx)
-{
-       char str[MAX_INT_STRLEN+30];
-
-       i_snprintf(str, sizeof(str), "Content-Length: %"PRIuUOFF_T"\n",
-                  ctx->content_length);
-
-       if (o_stream_send_str(ctx->output, str) < 0)
-               return FALSE;
-       return TRUE;
-}
-
-static const char *strip_chars(const unsigned char *value, size_t value_len,
-                              const char *list)
-{
-       /* @UNSAFE: leave only unknown flags, very likely none */
-       char *ret, *p;
-       size_t i;
-
-       ret = p = t_buffer_get(value_len+1);
-       for (i = 0; i < value_len; i++) {
-               if (strchr(list, value[i]) == NULL)
-                       *p++ = value[i];
-       }
-
-       if (ret == p)
-               return NULL;
-       *p = '\0';
-        t_buffer_alloc((size_t) (p-ret)+1);
-       return ret;
-}
-
-static void update_stripped_custom_flags(const unsigned char *value, size_t len,
-                                        int index, void *context)
-{
-       string_t *str = context;
-
-       if (index < 0) {
-               /* not found, keep it */
-               if (str_len(str) != 0)
-                       str_append_c(str, ' ');
-               str_append_n(str, value, len);
-       }
-}
-
-static const char *strip_custom_flags(const unsigned char *value, size_t len,
-                                     struct mbox_rewrite_context *ctx)
-{
-       string_t *str;
-
-       str = t_str_new(len+1);
-       mbox_keywords_parse(value, len, ctx->custom_flags,
-                           update_stripped_custom_flags, str);
-       return str_len(str) == 0 ? NULL : str_c(str);
-}
-
-static int write_header(struct mbox_rewrite_context *ctx,
-                       struct message_header_line *hdr)
-{
-       const char *str;
-
-       switch (hdr->name_len) {
-       case 5:
-               if (strcasecmp(hdr->name, "X-UID") == 0) {
-                       if (ctx->xuid_found)
-                               return TRUE;
-
-                       ctx->xuid_found = TRUE;
-                       return mbox_write_xuid(ctx);
-               }
-               break;
-       case 6:
-               if (strcasecmp(hdr->name, "Status") == 0) {
-                       if (ctx->status_found)
-                               return TRUE;
-                       if (hdr->continues) {
-                               hdr->use_full_value = TRUE;
-                               return TRUE;
-                       }
-
-                       ctx->status_found = TRUE;
-                       str = strip_chars(hdr->full_value,
-                                         hdr->full_value_len, "RO");
-                       return mbox_write_status(ctx, str);
-               }
-               break;
-       case 8:
-               if (strcasecmp(hdr->name, "X-Status") == 0) {
-                       if (ctx->xstatus_found)
-                               return TRUE;
-                       if (hdr->continues) {
-                               hdr->use_full_value = TRUE;
-                               return TRUE;
-                       }
-
-                       ctx->xstatus_found = TRUE;
-                       str = strip_chars(hdr->full_value,
-                                         hdr->full_value_len, "ADFT");
-                       return mbox_write_xstatus(ctx, str);
-               }
-               break;
-       case 10:
-               if (strcasecmp(hdr->name, "X-Keywords") == 0) {
-                       if (ctx->x_keywords != NULL)
-                               return TRUE;
-                       if (hdr->continues) {
-                               hdr->use_full_value = TRUE;
-                               return TRUE;
-                       }
-
-                       str = strip_custom_flags(hdr->full_value,
-                                                hdr->full_value_len, ctx);
-                       ctx->x_keywords = i_strdup(str);
-                       return TRUE;
-               } else if (strcasecmp(hdr->name, "X-IMAPbase") == 0) {
-                       if (ctx->seq != 1 || ctx->ximapbase_found)
-                               return TRUE;
-
-                       ctx->ximapbase_found = TRUE;
-                       return mbox_write_ximapbase(ctx);
-               }
-               break;
-       case 14:
-               if (strcasecmp(hdr->name, "Content-Length") == 0) {
-                       if (ctx->content_length_found)
-                               return TRUE;
-
-                       ctx->content_length_found = TRUE;
-                       return mbox_write_content_length(ctx);
-               }
-               break;
-       }
-
-       if (!hdr->eoh) {
-               /* save this header */
-               if (!hdr->continued) {
-                       (void)o_stream_send(ctx->output, hdr->name,
-                                           hdr->name_len);
-                       (void)o_stream_send(ctx->output, ": ", 2);
-               }
-               (void)o_stream_send(ctx->output, hdr->value, hdr->value_len);
-               if (!hdr->no_newline)
-                       (void)o_stream_send(ctx->output, "\n", 1);
-       }
-
-       return !ctx->output->closed;
-}
-
-static int mbox_write_header(struct mail_index *index,
-                            struct mail_index_record *rec, unsigned int seq,
-                            struct istream *input, struct ostream *output,
-                            uoff_t dirty_offset,
-                            uoff_t *hdr_input_size, uoff_t body_size)
-{
-       /* We need to update fields that define message flags. Standard fields
-          are stored in Status and X-Status. For custom flags we use
-          uw-imapd compatible format, by first listing them in first message's
-          X-IMAPbase field and actually defining them in X-Keywords field.
-
-          Format of X-IMAPbase is: <UID validity> <last used UID> <flag names>
-
-          We don't want to sync our UIDs with the mbox file, so the UID
-          validity is always kept different from our internal UID validity.
-          Last used UID is also not updated, and set to 0 initially.
-       */
-       struct mbox_rewrite_context ctx;
-       struct message_header_parser_ctx *hdr_ctx;
-       struct message_header_line *hdr;
-       struct message_size hdr_size;
-       struct istream *hdr_input;
-       uoff_t offset;
-       int force_filler;
-
-       t_push();
-
-       /* parse the header, write the fields we don't want to change */
-       memset(&ctx, 0, sizeof(ctx));
-       ctx.output = output;
-       ctx.content_length = body_size;
-       ctx.seq = seq;
-       ctx.uid = rec->uid;
-       ctx.msg_flags = rec->msg_flags;
-       ctx.uid_validity = index->header->uid_validity;
-       ctx.uid_last = index->header->next_uid-1;
-       ctx.custom_flags = mail_custom_flags_list_get(index->custom_flags);
-
-       if (body_size != 0) {
-               hdr_input = input;
-               i_stream_ref(hdr_input);
-       } else {
-               /* possibly broken message, find the next From-line
-                  and make sure header parser won't pass it. */
-               offset = input->v_offset;
-               mbox_skip_header(input);
-               i_stream_seek(input, offset);
-               hdr_input = i_stream_create_limit(default_pool, input, 0,
-                                                 input->v_offset);
-       } 
-
-       hdr_ctx = message_parse_header_init(hdr_input, &hdr_size);
-       while ((hdr = message_parse_header_next(hdr_ctx)) != NULL) {
-               t_push();
-               write_header(&ctx, hdr);
-               t_pop();
-       }
-       message_parse_header_deinit(hdr_ctx);
-       *hdr_input_size = hdr_size.physical_size;
-
-       i_stream_unref(hdr_input);
-
-       /* append the flag fields */
-       if (seq == 1 && !ctx.ximapbase_found) {
-               /* write X-IMAPbase header to first message */
-               (void)mbox_write_ximapbase(&ctx);
-       }
-
-       force_filler = !ctx.xuid_found;
-       if (!ctx.status_found)
-               (void)mbox_write_status(&ctx, NULL);
-       if (!ctx.xstatus_found)
-               (void)mbox_write_xstatus(&ctx, NULL);
-       if (!ctx.xuid_found)
-               (void)mbox_write_xuid(&ctx);
-       if (!ctx.content_length_found)
-               (void)mbox_write_content_length(&ctx);
-
-       /* write the x-keywords header last so it can fill the extra space
-          with spaces. -1 is for ending \n. */
-       (void)mbox_write_xkeywords(&ctx, ctx.x_keywords,
-                                  input->v_offset - dirty_offset - 1,
-                                  force_filler);
-       i_free(ctx.x_keywords);
-
-       t_pop();
-
-       /* empty line ends headers */
-       (void)o_stream_send(output, "\n", 1);
-
-       return TRUE;
-}
-
-static int fd_copy(struct mail_index *index, int in_fd, int out_fd,
-                  uoff_t out_offset, uoff_t size)
-{
-       struct istream *input, *input2;
-       struct ostream *output;
-       struct stat st;
-       int ret;
-
-       i_assert(out_offset <= OFF_T_MAX);
-
-       /* first grow the file to wanted size, to make sure we don't run out
-          of disk space */
-       if (fstat(out_fd, &st) < 0) {
-               mbox_set_syscall_error(index, "fstat()");
-               return -1;
-       }
-
-       if ((uoff_t)st.st_size < out_offset + size) {
-               if (file_set_size(out_fd, (off_t)(out_offset + size)) < 0) {
-                       mbox_set_syscall_error(index, "file_set_size()");
-                       (void)ftruncate(out_fd, st.st_size);
-                       return -1;
-               }
-       }
-
-       if (lseek(out_fd, (off_t)out_offset, SEEK_SET) < 0) {
-               mbox_set_syscall_error(index, "lseek()");
-               (void)ftruncate(out_fd, st.st_size);
-               return -1;
-       }
-
-       t_push();
-
-       input = i_stream_create_file(in_fd, pool_datastack_create(),
-                                    1024*256, FALSE);
-       input2 = i_stream_create_limit(pool_datastack_create(), input, 0, size);
-
-       output = o_stream_create_file(out_fd, pool_datastack_create(),
-                                     1024, FALSE);
-       o_stream_set_blocking(output, 60000, NULL, NULL);
-
-       ret = o_stream_send_istream(output, input2);
-       if (ret < 0) {
-               errno = output->stream_errno;
-               mbox_set_syscall_error(index, "o_stream_send_istream()");
-       }
-
-       o_stream_unref(output);
-       i_stream_unref(input2);
-       i_stream_unref(input);
-       t_pop();
-
-       return ret;
-}
-
-static int dirty_flush(struct mail_index *index, uoff_t dirty_offset,
-                      struct ostream *output, int output_fd)
-{
-       if (output->offset == 0)
-               return TRUE;
-
-       if (o_stream_flush(output) < 0) {
-               mbox_set_syscall_error(index, "o_stream_flush()");
-               return FALSE;
-       }
-
-       /* POSSIBLE DATA LOSS HERE. We're writing to the mbox file,
-          so if we get killed here before finished, we'll lose some
-          bytes. I can't really think of any way to fix this,
-          rename() is problematic too especially because of file
-          locking issues (new mail could be lost).
-
-          Usually we're moving the data by just a few bytes, so
-          the data loss should never be more than those few bytes..
-          If we moved more, we could have written the file from end
-          to beginning in blocks (it'd be a bit slow to do it in
-          blocks of ~1-10 bytes which is the usual case, so we don't
-          bother).
-
-          Also, we might as well be shrinking the file, in which
-          case we can't lose data. */
-       if (fd_copy(index, output_fd, index->mbox_fd,
-                   dirty_offset, output->offset) < 0)
-               return FALSE;
-
-       /* All ok. Just make sure the timestamps of index and
-          mbox differ, so index will be updated at next sync */
-       index->sync_stamp = 0;
-
-       if (o_stream_seek(output, 0) < 0) {
-               mbox_set_syscall_error(index, "o_stream_seek()");
-               return FALSE;
-       }
-       return TRUE;
-}
-
-#define INDEX_DIRTY_FLAGS \
-       (MAIL_INDEX_HDR_FLAG_DIRTY_MESSAGES | \
-        MAIL_INDEX_HDR_FLAG_DIRTY_CUSTOMFLAGS)
-
-int mbox_index_rewrite(struct mail_index *index)
-{
-       /* Write messages beginning from the first dirty one to temp file,
-          then copy it over the mbox file. This may create data loss if
-          interrupted (see below). This rewriting relies quite a lot on
-          valid header/body sizes which fsck() should have ensured. */
-       struct mail_index_record *rec;
-       struct istream *input;
-       struct ostream *output;
-       uoff_t offset, hdr_size, body_size, dirty_offset;
-       const char *path;
-       unsigned int seq;
-       int tmp_fd, failed, dirty, dirty_found, rewrite, no_locking;
-
-       i_assert(!index->mailbox_readonly);
-       i_assert(index->lock_type == MAIL_LOCK_UNLOCK ||
-                (index->lock_type == MAIL_LOCK_EXCLUSIVE &&
-                 index->mbox_lock_type == MAIL_LOCK_EXCLUSIVE));
-
-       no_locking = index->mbox_lock_type == MAIL_LOCK_EXCLUSIVE;
-       if (!no_locking) {
-               if (!index->set_lock(index, MAIL_LOCK_SHARED))
-                       return FALSE;
-       }
-
-       rewrite = (index->header->flags & INDEX_DIRTY_FLAGS) &&
-               index->header->messages_count > 0;
-
-       if (!no_locking) {
-               if (!index->set_lock(index, MAIL_LOCK_UNLOCK))
-                       return FALSE;
-       }
-
-       if (!rewrite) {
-               /* no need to rewrite */
-               return TRUE;
-       }
-
-       /* kludgy .. but we need to force resyncing */
-       index->mbox_rewritten = TRUE;
-
-       tmp_fd = -1; input = NULL;
-       failed = TRUE; rewrite = FALSE;
-       do {
-               if (!no_locking) {
-                       if (!index->set_lock(index, MAIL_LOCK_EXCLUSIVE))
-                               break;
-
-                       if (!index->sync_and_lock(index, FALSE,
-                                                 MAIL_LOCK_EXCLUSIVE, NULL))
-                               break;
-               }
-
-               input = mbox_get_stream(index, MAIL_LOCK_EXCLUSIVE);
-               if (input == NULL)
-                       break;
-
-               if ((index->header->flags & INDEX_DIRTY_FLAGS) == 0) {
-                       /* fsck() figured out there's no dirty messages
-                          after all */
-                       failed = FALSE; rewrite = FALSE;
-                       break;
-               }
-
-               tmp_fd = mail_index_create_temp_file(index, &path);
-               if (tmp_fd == -1)
-                       break;
-
-               failed = FALSE; rewrite = TRUE;
-       } while (0);
-
-       if (!rewrite) {
-               if (!no_locking) {
-                       if (!index->set_lock(index, MAIL_LOCK_UNLOCK))
-                               failed = TRUE;
-               }
-               if (input != NULL)
-                       i_stream_unref(input);
-               return !failed;
-       }
-
-       if (index->header->flags & MAIL_INDEX_HDR_FLAG_DIRTY_CUSTOMFLAGS) {
-               /* need to update X-IMAPbase in first message */
-               dirty_found = TRUE;
-       } else {
-               dirty_found = FALSE;
-       }
-       dirty_offset = 0;
-
-       /* note: we can't use data_stack_pool with output stream because it's
-          being written to inside t_push() .. t_pop() calls */
-       output = o_stream_create_file(tmp_fd, system_pool, 8192, FALSE);
-       o_stream_set_blocking(output, 60000, NULL, NULL);
-
-       failed = FALSE; seq = 1;
-       rec = index->lookup(index, 1);
-       while (rec != NULL) {
-               if (dirty_found)
-                       dirty = FALSE;
-               else {
-                       dirty = (mail_cache_get_index_flags(index->cache, rec) &
-                                MAIL_INDEX_FLAG_DIRTY) != 0;
-               }
-
-               if (dirty_found || dirty) {
-                       /* get offset to beginning of mail headers */
-                       if (!mbox_mail_get_location(index, rec, &offset,
-                                                   &body_size)) {
-                               /* fsck should have fixed it */
-                               failed = TRUE;
-                               break;
-                       }
-
-                       if (offset < input->v_offset) {
-                               mail_cache_set_corrupted(index->cache,
-                                       "Invalid message offset");
-                               failed = TRUE;
-                               break;
-                       }
-
-                       if (!dirty_found) {
-                               /* first dirty message */
-                               dirty_found = TRUE;
-                               dirty_offset = offset;
-
-                               i_stream_seek(input, dirty_offset);
-                       }
-
-                       /* write the From-line */
-                       if (!mbox_write(index, input, output, offset)) {
-                               failed = TRUE;
-                               break;
-                       }
-
-                       /* write header, updating flag fields */
-                       if (!mbox_write_header(index, rec, seq, input, output,
-                                              dirty_offset,
-                                              &hdr_size, body_size)) {
-                               failed = TRUE;
-                               break;
-                       }
-                       offset += hdr_size;
-                       i_assert(input->v_offset == offset);
-
-                       if (dirty_found &&
-                           offset - dirty_offset == output->offset) {
-                               /* no need to write more, flush */
-                               if (!dirty_flush(index, dirty_offset,
-                                                output, tmp_fd)) {
-                                       failed = TRUE;
-                                       break;
-                               }
-                               dirty_found = FALSE;
-                       } else {
-                               /* write body */
-                               offset += body_size;
-                               if (!mbox_write(index, input, output, offset)) {
-                                       failed = TRUE;
-                                       break;
-                               }
-                       }
-               }
-
-               seq++;
-               rec = index->next(index, rec);
-       }
-
-       if (!failed && dirty_found) {
-               /* end with \n */
-               (void)o_stream_send(output, "\n", 1);
-       }
-
-       if (output->closed) {
-               errno = output->stream_errno;
-               mbox_set_syscall_error(index, "write()");
-               failed = TRUE;
-       }
-
-       if (!failed && dirty_found) {
-               uoff_t dirty_size = output->offset;
-
-               if (!dirty_flush(index, dirty_offset, output, tmp_fd))
-                       failed = TRUE;
-               else {
-                       /* we may have shrinked the file */
-                       i_assert(dirty_offset + dirty_size <= OFF_T_MAX);
-                       if (ftruncate(index->mbox_fd,
-                                     (off_t)(dirty_offset + dirty_size)) < 0) {
-                               mbox_set_syscall_error(index, "ftruncate()");
-                               failed = TRUE;
-                       }
-               }
-       }
-
-       if (!failed) {
-               if (!reset_dirty_flags(index))
-                       failed = TRUE;
-       }
-
-       i_stream_unref(input);
-       o_stream_unref(output);
-
-       if (!no_locking) {
-               if (!index->set_lock(index, MAIL_LOCK_UNLOCK))
-                       failed = TRUE;
-       }
-
-       (void)unlink(path);
-
-       if (close(tmp_fd) < 0)
-               index_file_set_syscall_error(index, path, "close()");
-       return !failed;
-}
diff --git a/src/lib-index/mbox/mbox-sync-full.c b/src/lib-index/mbox/mbox-sync-full.c
deleted file mode 100644 (file)
index fecde5f..0000000
+++ /dev/null
@@ -1,349 +0,0 @@
-/* Copyright (C) 2002 Timo Sirainen */
-
-#include "lib.h"
-#include "istream.h"
-#include "hex-binary.h"
-#include "message-parser.h"
-#include "message-part-serialize.h"
-#include "mbox-index.h"
-#include "mbox-lock.h"
-#include "mail-index-util.h"
-#include "mail-cache.h"
-
-#include <unistd.h>
-#include <fcntl.h>
-#include <sys/stat.h>
-
-static void skip_line(struct istream *input)
-{
-       const unsigned char *msg;
-       size_t i, size;
-       int ret;
-
-       while ((ret = i_stream_read_data(input, &msg, &size, 0)) > 0) {
-               for (i = 0; i < size; i++) {
-                       if (msg[i] == '\n') {
-                               i_stream_skip(input, i+1);
-                               return;
-                       }
-               }
-
-               i_stream_skip(input, i);
-       }
-}
-
-static int verify_header(struct mail_index *index,
-                        struct mail_index_record *rec,
-                        unsigned int uid, unsigned char current_digest[16])
-{
-       const void *old_digest;
-       size_t size;
-
-       if (uid != 0) {
-               /* X-UID header - no need to check more */
-               return uid == rec->uid;
-       }
-
-       /* check if MD5 sums match */
-       if (!mail_cache_lookup_field(index->cache, rec, MAIL_CACHE_MD5,
-                                    &old_digest, &size))
-               return FALSE;
-
-       return memcmp(old_digest, current_digest, 16) == 0;
-}
-
-static int mbox_check_uidvalidity(struct mail_index *index,
-                                 unsigned int uid_validity)
-{
-       if (uid_validity == index->header->uid_validity)
-               return TRUE;
-
-       index->header->flags |= MAIL_INDEX_HDR_FLAG_DIRTY_MESSAGES |
-               MAIL_INDEX_HDR_FLAG_DIRTY_CUSTOMFLAGS;
-
-       if (uid_validity == 0) {
-               /* X-IMAPbase header isn't written yet */
-       } else {
-               /* UID validity has changed - rebuild whole index */
-               index->set_flags |= MAIL_INDEX_HDR_FLAG_REBUILD;
-               index->inconsistent = TRUE;
-               return FALSE;
-       }
-
-       return TRUE;
-}
-
-static int match_next_record(struct mail_index *index,
-                            struct mail_index_record *rec,
-                            unsigned int *seq, struct istream *input,
-                            struct mail_index_record **next_rec, int *dirty)
-{
-       struct mbox_header_context ctx;
-       struct mail_index_record *first_rec, *last_rec;
-       struct istream *hdr_input;
-        enum mail_index_record_flag index_flags;
-       uoff_t header_offset, body_offset, offset, body_size, eoh_offset;
-       unsigned char current_digest[16];
-       unsigned int first_seq, last_seq;
-       int ret, hdr_parsed;
-
-       *next_rec = NULL;
-
-       /* skip the From-line */
-       skip_line(input);
-       header_offset = input->v_offset;
-
-       first_rec = last_rec = NULL;
-       first_seq = last_seq = 0;
-       ret = 0; body_offset = 0; eoh_offset = (uoff_t)-1; hdr_parsed = FALSE;
-       do {
-               if (!mbox_mail_get_location(index, rec, &offset, &body_size))
-                       return -1;
-
-               if (body_size == 0 && eoh_offset == (uoff_t)-1) {
-                       /* possibly broken message, find the next From-line
-                          and make sure header parser won't pass it. */
-                       i_stream_seek(input, header_offset);
-                       mbox_skip_header(input);
-                       eoh_offset = input->v_offset;
-                       hdr_parsed = FALSE;
-               }
-
-               if (!hdr_parsed) {
-                       /* get the MD5 sum of fixed headers and the current
-                          message flags in Status and X-Status fields */
-                       if (eoh_offset == (uoff_t)-1)
-                               hdr_input = input;
-                       else {
-                               hdr_input = i_stream_create_limit(default_pool,
-                                               input, 0, eoh_offset);
-                       }
-                       i_stream_seek(hdr_input, header_offset);
-
-                       mbox_header_init_context(&ctx, index, hdr_input);
-                       message_parse_header(NULL, hdr_input, NULL,
-                                            mbox_header_cb, &ctx);
-
-                       hdr_parsed = TRUE;
-                       body_offset = hdr_input->v_offset;
-
-                       if (eoh_offset != (uoff_t)-1)
-                               i_stream_unref(hdr_input);
-                       hdr_input = NULL;
-                       md5_final(&ctx.md5, current_digest);
-
-                       if (*seq == 1) {
-                               if (!mbox_check_uidvalidity(index,
-                                                           ctx.uid_validity)) {
-                                       /* uidvalidity changed, abort */
-                                       return -1;
-                               }
-
-                               if (ctx.uid_last >= index->header->next_uid) {
-                                       /* last_uid larger than ours */
-                                       index->header->next_uid =
-                                               ctx.uid_last+1;
-                               }
-                       }
-               }
-
-               if (verify_header(index, rec, ctx.uid, current_digest) &&
-                   mbox_verify_end_of_body(input, body_offset + body_size)) {
-                       /* valid message */
-
-                       /* update flags, unless we've changed them */
-                       index_flags =
-                               mail_cache_get_index_flags(index->cache, rec);
-                       if ((index_flags & MAIL_INDEX_FLAG_DIRTY) == 0) {
-                               if (!index->update_flags(index, rec, *seq,
-                                                        MODIFY_REPLACE,
-                                                        ctx.flags, TRUE))
-                                       return -1;
-                       } else if (rec->msg_flags == ctx.flags) {
-                               /* flags are same, it's not dirty anymore */
-                               index_flags &= ~MAIL_INDEX_FLAG_DIRTY;
-                               mail_cache_update_index_flags(index->cache,
-                                                             rec, index_flags);
-                       } else {
-                               *dirty = TRUE;
-                       }
-
-                       /* update location */
-                       if (offset != header_offset) {
-                               if (!mail_cache_update_location_offset(
-                                       index->cache, rec, header_offset))
-                                       return -1;
-                       }
-                       ret = 1;
-                       break;
-               }
-
-               /* try next message */
-               if (first_rec == NULL) {
-                       first_rec = rec;
-                       first_seq = *seq;
-               }
-               last_rec = rec;
-               last_seq = *seq;
-
-               rec = index->next(index, rec); *seq += 1;
-       } while (rec != NULL);
-
-       if (first_rec == NULL) {
-               *seq += 1;
-               *next_rec = rec == NULL ? NULL : index->next(index, rec);
-       } else {
-               if (!index->expunge(index, first_rec, last_rec,
-                                   first_seq, last_seq, TRUE))
-                       return -1;
-
-               *seq = first_seq + 1;
-               *next_rec = index->lookup(index, *seq);
-       }
-
-       return ret;
-}
-
-static int mbox_sync_from_stream(struct mail_index *index,
-                                struct istream *input)
-{
-       struct mail_index_record *rec;
-       uoff_t from_offset;
-       const unsigned char *data;
-       size_t size;
-       unsigned int seq;
-       int dirty, ret;
-
-       if (mail_cache_lock(index->cache, FALSE) <= 0)
-               return -1;
-       mail_cache_unlock_later(index->cache);
-
-       mbox_skip_empty_lines(input);
-
-       /* first make sure we start with a "From " line. If file is too
-          small, we'll just treat it as empty mbox file. */
-       if (i_stream_read_data(input, &data, &size, 5) > 0 &&
-           memcmp(data, "From ", 5) != 0) {
-               index_set_error(index, "File isn't in mbox format: %s",
-                               index->mailbox_path);
-               return -1;
-       }
-
-       /* we'll go through the mailbox and index in order matching the
-          messages by their size and Message-ID. old mails aren't remembered,
-          so we handle well only the cases when mail has been deleted. if
-          mails have been reordered (eg. sorted by someone) most of the mails
-          will show up as being new. if we really wanted to support that well,
-          we could save the message-ids into hash but I don't know if it's
-          worth the trouble. */
-
-       seq = 1;
-       rec = index->lookup(index, 1);
-
-       dirty = FALSE;
-       while (rec != NULL) {
-               from_offset = input->v_offset;
-               if (input->v_offset != 0) {
-                       /* we're at the [\r]\n before the From-line,
-                          skip it */
-                       if (!mbox_skip_crlf(input)) {
-                               /* they just went and broke it, even while
-                                  we had it locked. */
-                               index_set_error(index,
-                                               "Error syncing mbox file %s: "
-                                               "LF not found where expected",
-                                               index->mailbox_path);
-                               return -1;
-                       }
-               }
-
-               ret = match_next_record(index, rec, &seq, input, &rec, &dirty);
-               if (ret < 0)
-                       return -1;
-
-               if (ret == 0) {
-                       /* Get back to line before From */
-                       i_stream_seek(input, from_offset);
-               }
-       }
-
-       /* delete the rest of the records */
-       if (rec != NULL) {
-               if (!index->expunge(index, rec, INDEX_END_RECORD(index)-1,
-                                   seq, index->header->messages_count, TRUE))
-                       return -1;
-       }
-
-       if (!dirty &&
-           (index->header->flags & MAIL_INDEX_HDR_FLAG_DIRTY_MESSAGES)) {
-               /* no flags are dirty anymore, no need to rewrite */
-               index->header->flags &= ~MAIL_INDEX_HDR_FLAG_DIRTY_MESSAGES;
-       }
-
-       if ((index->set_flags & MAIL_INDEX_HDR_FLAG_REBUILD))
-               return 1;
-       else
-               return mbox_index_append_stream(index, input);
-}
-
-int mbox_sync_full(struct mail_index *index)
-{
-       struct istream *input;
-       struct stat orig_st, st;
-       uoff_t continue_offset;
-       int ret, failed;
-
-       i_assert(index->lock_type == MAIL_LOCK_EXCLUSIVE);
-
-       input = mbox_get_stream(index, MAIL_LOCK_SHARED);
-       if (input == NULL)
-               return FALSE;
-
-       if (fstat(index->mbox_fd, &orig_st) < 0) {
-               mbox_set_syscall_error(index, "fstat()");
-               continue_offset = (uoff_t)-1;
-               failed = TRUE;
-       } else {
-               ret = mbox_sync_from_stream(index, input);
-               failed = ret < 0;
-               continue_offset = ret != 0 ||
-                       (index->set_flags & MAIL_INDEX_HDR_FLAG_REBUILD) ?
-                       (uoff_t)-1 : input->v_offset;
-               i_stream_unref(input);
-       }
-
-       if (continue_offset != (uoff_t)-1) {
-               /* mbox_index_append() stopped, which means that it wants
-                  write access to mbox. if mbox hasn't changed after
-                  unlock+lock, we should be able to safely continue where we
-                  were left off last time. otherwise do full resync. */
-               if (!mbox_unlock(index))
-                       return FALSE;
-
-               input = mbox_get_stream(index, MAIL_LOCK_EXCLUSIVE);
-               if (input == NULL)
-                       return FALSE;
-
-               if (fstat(index->mbox_fd, &st) < 0) {
-                       mbox_set_syscall_error(index, "fstat()");
-                       failed = TRUE;
-               } else if (st.st_mtime == orig_st.st_mtime &&
-                          st.st_size == orig_st.st_size) {
-                       i_stream_seek(input, continue_offset);
-                       failed = mbox_index_append_stream(index, input) <= 0;
-               } else {
-                       failed = mbox_sync_from_stream(index, input) <= 0;
-               }
-
-               if (index->mbox_rewritten) {
-                       /* rewritten, sync again */
-                        index->mbox_rewritten = FALSE;
-                       i_stream_seek(input, 0);
-                       failed = mbox_sync_from_stream(index, input) <= 0;
-               }
-
-               i_stream_unref(input);
-       }
-
-       return !failed;
-}
diff --git a/src/lib-index/mbox/mbox-sync.c b/src/lib-index/mbox/mbox-sync.c
deleted file mode 100644 (file)
index 2b9362d..0000000
+++ /dev/null
@@ -1,126 +0,0 @@
-/* Copyright (C) 2002 Timo Sirainen */
-
-#include "lib.h"
-#include "mbox-index.h"
-#include "mbox-lock.h"
-#include "mail-index-util.h"
-
-#include <stdlib.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <sys/stat.h>
-
-static int mbox_lock_and_sync_full(struct mail_index *index,
-                                  enum mail_lock_type data_lock_type)
-{
-        enum mail_lock_type lock_type;
-
-       /* syncing needs exclusive index lock and shared
-          mbox lock, but if we'd want exclusive mbox lock
-          we need to set it here already */
-       if (index->lock_type == MAIL_LOCK_SHARED)
-               (void)mail_index_set_lock(index, MAIL_LOCK_UNLOCK);
-
-       if (!index->set_lock(index, MAIL_LOCK_EXCLUSIVE))
-               return FALSE;
-
-       if (index->mbox_lock_type == MAIL_LOCK_UNLOCK) {
-               lock_type = data_lock_type == MAIL_LOCK_EXCLUSIVE ?
-                       MAIL_LOCK_EXCLUSIVE : MAIL_LOCK_SHARED;
-               if (!mbox_lock(index, lock_type))
-                       return FALSE;
-       }
-
-       return mbox_sync_full(index);
-}
-
-int mbox_index_sync(struct mail_index *index, int minimal_sync __attr_unused__,
-                   enum mail_lock_type data_lock_type, int *changes)
-{
-       struct stat st;
-       int count, fd;
-
-       if (index->mailbox_readonly && data_lock_type == MAIL_LOCK_EXCLUSIVE) {
-               index_set_error(index, "sync: %s is read-only, "
-                               "can't get exclusive lock",
-                               index->mailbox_path);
-               return FALSE;
-       }
-
-       if (changes != NULL)
-               *changes = FALSE;
-
-       if (index->mbox_sync_counter == index->mbox_lock_counter) {
-               /* we've already synced in this locking session */
-               return TRUE;
-       }
-
-       i_assert(index->lock_type != MAIL_LOCK_SHARED);
-
-       count = 0;
-       while (stat(index->mailbox_path, &st) < 0) {
-               if (errno != ENOENT || ++count == 3)
-                       return mbox_set_syscall_error(index, "stat()");
-
-               /* mbox was deleted by someone - happens with some MUAs
-                  when all mail is expunged. easiest way to deal with this
-                  is to recreate the file. */
-               fd = open(index->mailbox_path, O_RDWR | O_CREAT | O_EXCL, 0660);
-               if (fd != -1)
-                       (void)close(fd);
-               else if (errno != EEXIST)
-                       return mbox_set_syscall_error(index, "open()");
-       }
-
-       if (index->mbox_fd != -1 &&
-           (index->mbox_ino != st.st_ino ||
-            !CMP_DEV_T(index->mbox_dev, st.st_dev))) {
-               /* mbox file was overwritten, close it if it was open */
-               index->mbox_dev = st.st_dev;
-               index->mbox_ino = st.st_ino;
-               index->sync_size = (uoff_t)-1;
-               index->sync_stamp = (time_t)-1;
-
-                mbox_file_close_fd(index);
-       }
-
-       if (index->sync_stamp != st.st_mtime ||
-           index->sync_size != (uoff_t)st.st_size) {
-               mbox_file_close_stream(index);
-
-               if (changes != NULL)
-                       *changes = TRUE;
-
-               if (!mbox_lock_and_sync_full(index, data_lock_type))
-                       return FALSE;
-
-               if ((index->set_flags & MAIL_INDEX_HDR_FLAG_REBUILD) != 0) {
-                       /* uidvalidity probably changed, rebuild */
-                       if (!index->rebuild(index))
-                               return FALSE;
-               }
-
-               if (fstat(index->mbox_fd, &st) < 0)
-                       return mbox_set_syscall_error(index, "fstat()");
-
-               index->sync_stamp = st.st_mtime;
-               index->sync_size = st.st_size;
-       }
-
-       /* we need some index lock to be able to lock mbox */
-       if (index->lock_type == MAIL_LOCK_UNLOCK) {
-               if (!index->set_lock(index, MAIL_LOCK_SHARED))
-                       return FALSE;
-       }
-
-       if (data_lock_type == MAIL_LOCK_UNLOCK) {
-               if (!mbox_unlock(index))
-                       return FALSE;
-       } else {
-               if (!mbox_lock(index, data_lock_type))
-                       return FALSE;
-       }
-
-       index->mbox_sync_counter = index->mbox_lock_counter;
-       return TRUE;
-}