changeset 101:edc37d046b08 HEAD

Added overwrite_incompatible_index setting. Also we now try to use only .imap.index-<hostname> and .imap.index index files instead of scanning the dir for any compatible index. This also fixes (partly) LIST giving \Marked flag when there's no new mails.
author Timo Sirainen <tss@iki.fi>
date Sat, 31 Aug 2002 18:24:00 +0300
parents 867ec80dbf42
children fc3383ac21a9
files dovecot-example.conf src/lib-index/mail-index.c src/lib-storage/index/maildir/maildir-list.c src/master/imap-process.c src/master/settings.c src/master/settings.h
diffstat 6 files changed, 116 insertions(+), 59 deletions(-) [+]
line wrap: on
line diff
--- a/dovecot-example.conf	Thu Aug 29 22:21:51 2002 +0300
+++ b/dovecot-example.conf	Sat Aug 31 18:24:00 2002 +0300
@@ -98,6 +98,12 @@
 # down things as extra stat() needs to be called for each file.
 #maildir_check_content_changes = no
 
+# If main index file is incompatible with us, should we overwrite it or
+# create a new index with another name. Unless you are running Dovecot in
+# multiple computers with different architectures accessing the same
+# mailboxes (eg. via NFS), it's safe to set this "yes".
+#overwrite_incompatible_index = no
+
 # umask to use for mail files and directories
 #umask = 0077
 
--- a/src/lib-index/mail-index.c	Thu Aug 29 22:21:51 2002 +0300
+++ b/src/lib-index/mail-index.c	Sat Aug 31 18:24:00 2002 +0300
@@ -16,9 +16,10 @@
 #include <stdlib.h>
 #include <unistd.h>
 #include <fcntl.h>
-#include <dirent.h>
 #include <utime.h>
 
+static const char *index_file_prefixes[] = { "data", "hash", "log", NULL };
+
 static int mmap_update(MailIndex *index)
 {
 	unsigned int extra;
@@ -363,7 +364,28 @@
 	return TRUE;
 }
 
-static int read_and_verify_header(int fd, MailIndexHeader *hdr)
+static int delete_index(const char *path)
+{
+	char tmp[1024];
+	int i;
+
+	/* main index */
+	if (unlink(path) < 0)
+		return FALSE;
+
+	for (i = 0; index_file_prefixes[i] != NULL; i++) {
+		i_snprintf(tmp, sizeof(tmp), "%s.%s",
+			   path, index_file_prefixes[i]);
+		if (unlink(tmp) < 0)
+			return FALSE;
+		i++;
+	}
+
+	return TRUE;
+}
+
+static int read_and_verify_header(int fd, MailIndexHeader *hdr,
+				  int check_version)
 {
 	/* read the header */
 	if (lseek(fd, 0, SEEK_SET) != 0)
@@ -373,25 +395,37 @@
 		return FALSE;
 
 	/* check the compatibility */
-	return hdr->compat_data[0] == MAIL_INDEX_VERSION &&
-		hdr->compat_data[1] == MAIL_INDEX_COMPAT_FLAGS &&
+	return hdr->compat_data[1] == MAIL_INDEX_COMPAT_FLAGS &&
 		hdr->compat_data[2] == sizeof(unsigned int) &&
 		hdr->compat_data[3] == sizeof(time_t) &&
 		hdr->compat_data[4] == sizeof(uoff_t) &&
-		hdr->compat_data[5] == MEM_ALIGN_SIZE;
+		hdr->compat_data[5] == MEM_ALIGN_SIZE &&
+		(!check_version || hdr->compat_data[0] == MAIL_INDEX_VERSION);
 }
 
-/* Returns TRUE if we're compatible with given index file */
-static int mail_is_compatible_index(const char *path)
+/* Returns TRUE if we're compatible with given index file. May delete the
+   file if it's from older version. */
+static int mail_check_compatible_index(MailIndex *index, const char *path)
 {
         MailIndexHeader hdr;
 	int fd, compatible;
 
 	fd = open(path, O_RDONLY);
-	if (fd == -1)
+	if (fd == -1) {
+		if (errno != ENOENT)
+			index_set_error(index, "Can't open index %s: %m", path);
 		return FALSE;
+	}
 
-	compatible = read_and_verify_header(fd, &hdr);
+	compatible = read_and_verify_header(fd, &hdr, FALSE);
+	if (hdr.compat_data[0] != MAIL_INDEX_VERSION) {
+		/* version mismatch */
+		compatible = FALSE;
+		if (hdr.compat_data[0] < MAIL_INDEX_VERSION) {
+			/* of older version, we don't need it anymore */
+			(void)delete_index(path);
+		}
+	}
 
 	(void)close(fd);
 	return compatible;
@@ -400,41 +434,24 @@
 /* Returns a file name of compatible index */
 static const char *mail_find_index(MailIndex *index)
 {
-	DIR *dir;
-	struct dirent *d;
 	const char *name;
 	char path[1024];
-	unsigned int len;
 
-	/* first try the primary name */
-	i_snprintf(path, sizeof(path), "%s/" INDEX_FILE_PREFIX, index->dir);
-	if (mail_is_compatible_index(path))
-		return INDEX_FILE_PREFIX;
-
-	dir = opendir(index->dir);
-	if (dir == NULL) {
-		/* path doesn't exist */
-		index_set_error(index, "Can't open dir %s: %m",
-				index->dir);
-		return NULL;
-	}
+	hostpid_init();
 
-	len = strlen(INDEX_FILE_PREFIX);
-	name = NULL;
-	while ((d = readdir(dir)) != NULL) {
-		if (strncmp(d->d_name, INDEX_FILE_PREFIX, len) == 0) {
-			/* index found, check if we're compatible */
-			i_snprintf(path, sizeof(path), "%s/%s",
-				   index->dir, d->d_name);
-			if (mail_is_compatible_index(path)) {
-				name = t_strdup(d->d_name);
-				break;
-			}
-		}
-	}
+	/* first try .imap.index-<hostname> */
+	name = t_strconcat(INDEX_FILE_PREFIX "-", my_hostname, NULL);
+	i_snprintf(path, sizeof(path), "%s/%s", index->dir, name);
+	if (mail_check_compatible_index(index, path))
+		return name;
 
-	(void)closedir(dir);
-	return name;
+	/* then try the generic .imap.index */
+	name = INDEX_FILE_PREFIX;
+	i_snprintf(path, sizeof(path), "%s/%s", index->dir, name);
+	if (mail_check_compatible_index(index, path))
+		return name;
+
+	return NULL;
 }
 
 static int mail_index_open_init(MailIndex *index, int update_recent,
@@ -491,7 +508,7 @@
 	}
 
 	/* check the compatibility anyway just to be sure */
-	if (!read_and_verify_header(fd, &hdr)) {
+	if (!read_and_verify_header(fd, &hdr, TRUE)) {
 		index_set_error(index, "Non-compatible index file %s", path);
 		return FALSE;
 	}
@@ -647,12 +664,17 @@
 			return FALSE;
 		}
 
-		/* fallback to index.hostname - we require each system to
-		   have a different hostname so it's safe to override
-		   previous index as well */
-		hostpid_init();
-		i_snprintf(index_path + len, sizeof(index_path)-len,
-			   "-%s", my_hostname);
+		if (getenv("OVERWRITE_INCOMPATIBLE_INDEX") != NULL) {
+			/* don't try to support different architectures,
+			   just overwrite the index if it's already there. */
+		} else {
+			/* fallback to .imap.index-hostname - we require each
+			   system to have a different hostname so it's safe to
+			   override previous index as well */
+			hostpid_init();
+			i_snprintf(index_path + len, sizeof(index_path)-len,
+				   "-%s", my_hostname);
+		}
 
 		if (rename(path, index_path) == -1) {
 			index_set_error(index, "rename(%s, %s) failed: %m",
--- a/src/lib-storage/index/maildir/maildir-list.c	Thu Aug 29 22:21:51 2002 +0300
+++ b/src/lib-storage/index/maildir/maildir-list.c	Sat Aug 31 18:24:00 2002 +0300
@@ -1,6 +1,7 @@
 /* Copyright (C) 2002 Timo Sirainen */
 
 #include "lib.h"
+#include "hostpid.h"
 #include "unlink-directory.h"
 #include "imap-match.h"
 #include "subscription-file/subscription-file.h"
@@ -15,20 +16,12 @@
 	void *context;
 } FindSubscribedContext;
 
-static MailboxFlags maildir_get_marked_flags(const char *dir)
+static MailboxFlags
+maildir_get_marked_flags_from(const char *dir, time_t index_stamp)
 {
 	struct stat st;
 	char path[1024];
-	time_t index_stamp, cur_stamp;
-
-	i_snprintf(path, sizeof(path), "%s/" INDEX_FILE_PREFIX, dir);
-	if (stat(path, &st) == -1) {
-		/* index file wasn't found. it might be with another name,
-		   but finding it would be too slow. */
-		return 0;
-	}
-
-	index_stamp = st.st_mtime;
+	time_t cur_stamp;
 
 	i_snprintf(path, sizeof(path), "%s/cur", dir);
 	if (stat(path, &st) == -1) {
@@ -51,6 +44,33 @@
 	return st.st_mtime <= cur_stamp ? MAILBOX_UNMARKED : MAILBOX_MARKED;
 }
 
+static MailboxFlags
+maildir_get_marked_flags(MailStorage *storage, const char *dir)
+{
+	const char *path;
+	struct stat st;
+
+	hostpid_init();
+
+	/* first try to use .imap.index-hostname */
+	path = t_strconcat(dir, "/" INDEX_FILE_PREFIX "-", my_hostname, NULL);
+	if (stat(path, &st) == -1 && errno == ENOENT) {
+		/* fallback to .imap.index */
+		path = t_strconcat(dir, "/" INDEX_FILE_PREFIX, NULL);
+	}
+
+	if (stat(path, &st) == -1) {
+		/* error, or index simply isn't created yet */
+		if (errno != ENOENT) {
+			mail_storage_set_critical(storage,
+						  "stat(%s) failed: %m", path);
+		}
+		return 0;
+	}
+
+	return maildir_get_marked_flags_from(dir, st.st_mtime);
+}
+
 int maildir_find_mailboxes(MailStorage *storage, const char *mask,
 			   MailboxFunc func, void *context)
 {
@@ -115,7 +135,10 @@
 			continue;
 		}
 
-                flags = maildir_get_marked_flags(path);
+		if (strcasecmp(fname+1, "INBOX") == 0)
+			found_inbox = TRUE;
+
+                flags = maildir_get_marked_flags(storage, path);
 		func(storage, fname+1, flags, context);
 	}
 
@@ -140,7 +163,7 @@
 	i_snprintf(path, sizeof(path), "%s/.%s", storage->dir, name);
 
 	if (stat(path, &st) == 0 && S_ISDIR(st.st_mode))
-		flags = maildir_get_marked_flags(path);
+		flags = maildir_get_marked_flags(storage, path);
 	else
 		flags = MAILBOX_NOSELECT;
 
--- a/src/master/imap-process.c	Thu Aug 29 22:21:51 2002 +0300
+++ b/src/master/imap-process.c	Sat Aug 31 18:24:00 2002 +0300
@@ -119,6 +119,8 @@
 		putenv("COPY_WITH_HARDLINKS=1");
 	if (set_maildir_check_content_changes)
 		putenv("CHECK_CONTENT_CHANGES=1");
+	if (set_overwrite_incompatible_index)
+		putenv("OVERWRITE_INCOMPATIBLE_INDEX=1");
 	if (umask(set_umask) != set_umask)
 		i_fatal("Invalid umask: %o", set_umask);
 
--- a/src/master/settings.c	Thu Aug 29 22:21:51 2002 +0300
+++ b/src/master/settings.c	Sat Aug 31 18:24:00 2002 +0300
@@ -52,6 +52,8 @@
 				SET_BOOL,&set_maildir_copy_with_hardlinks },
 	{ "maildir_check_content_changes",
 				SET_BOOL,&set_maildir_check_content_changes },
+	{ "overwrite_incompatible_index",
+				SET_BOOL,&set_overwrite_incompatible_index },
 	{ "umask",		SET_INT, &set_umask },
 
 	{ NULL, 0, NULL }
@@ -92,6 +94,7 @@
 
 int set_maildir_copy_with_hardlinks = FALSE;
 int set_maildir_check_content_changes = FALSE;
+int set_overwrite_incompatible_index = FALSE;
 unsigned int set_umask = 0077;
 
 /* auth */
--- a/src/master/settings.h	Thu Aug 29 22:21:51 2002 +0300
+++ b/src/master/settings.h	Sat Aug 31 18:24:00 2002 +0300
@@ -35,6 +35,7 @@
 
 extern int set_maildir_copy_with_hardlinks;
 extern int set_maildir_check_content_changes;
+extern int set_overwrite_incompatible_index;
 extern unsigned int set_umask;
 
 /* auth */