changeset 1370:5f521a721671 HEAD

Use mtime to check changes in dovecot-uidlist file rather than inode changes which aren't reliable.
author Timo Sirainen <tss@iki.fi>
date Mon, 21 Apr 2003 16:42:00 +0300
parents 945f857cb514
children b73c2bdd12d0
files src/lib-index/mail-index.h src/lib-index/maildir/maildir-sync.c src/lib-index/maildir/maildir-uidlist.c src/lib-index/maildir/maildir-uidlist.h
diffstat 4 files changed, 67 insertions(+), 38 deletions(-) [+]
line wrap: on
line diff
--- a/src/lib-index/mail-index.h	Thu Apr 17 17:20:47 2003 +0300
+++ b/src/lib-index/mail-index.h	Mon Apr 21 16:42:00 2003 +0300
@@ -394,9 +394,7 @@
 	ino_t mbox_ino;
 
 	/* last maildir sync: */
-	dev_t uidlist_dev;
-	ino_t uidlist_ino;
-
+	time_t uidlist_mtime;
 	int maildir_lock_fd;
 
 	int fd; /* opened index file */
@@ -445,7 +443,7 @@
 	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_. */
--- a/src/lib-index/maildir/maildir-sync.c	Thu Apr 17 17:20:47 2003 +0300
+++ b/src/lib-index/maildir/maildir-sync.c	Mon Apr 21 16:42:00 2003 +0300
@@ -197,6 +197,16 @@
 			return FALSE;
 		}
 
+		if (uid_rec.uid > uid &&
+		    (hash_rec->action == MAILDIR_FILE_ACTION_UPDATE_FLAGS ||
+		     hash_rec->action == MAILDIR_FILE_ACTION_NONE)) {
+			/* it's UID has changed */
+			hash_rec->action = MAILDIR_FILE_ACTION_UPDATE_CONTENT;
+
+			/* make sure filename is not invalidated by expunge */
+			hash_insert(files, p_strdup(pool, fname), hash_rec);
+		}
+
 		switch (hash_rec->action) {
 		case MAILDIR_FILE_ACTION_EXPUNGE:
 			if (!index->expunge(index, rec, seq, TRUE))
@@ -247,7 +257,14 @@
 			i_assert(hash_rec->action == MAILDIR_FILE_ACTION_NEW);
 
 			/* make sure we set the same UID for it. */
-			i_assert(index->header->next_uid <= uid_rec.uid);
+			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;
 
                         hash_rec->action = MAILDIR_FILE_ACTION_NONE;
@@ -428,7 +445,7 @@
 	struct utimbuf ut;
 	struct maildir_uidlist *uidlist;
 	const char *uidlist_path, *cur_dir, *new_dir;
-	time_t index_mtime;
+	time_t index_mtime, uidlist_mtime;
 	int cur_changed;
 
 	*uidlist_r = uidlist = NULL;
@@ -456,12 +473,13 @@
 
 		memset(&st, 0, sizeof(st));
 		cur_changed = TRUE;
+                uidlist_mtime = 0;
 	} else {
-		/* FIXME: save device and inode into index header, so we don't
+		/* FIXME: save mtime into index header, so we don't
 		   have to read it every time mailbox is opened */
+                uidlist_mtime = st.st_mtime;
 		cur_changed = index_mtime != std.st_mtime ||
-			st.st_ino != index->uidlist_ino ||
-			!CMP_DEV_T(st.st_dev, index->uidlist_dev);
+			index->uidlist_mtime != uidlist_mtime;
 	}
 
 	if (new_dirp != NULL || cur_changed) {
@@ -556,18 +574,12 @@
 			return TRUE;
 		}
 
-		if (fstat(index->maildir_lock_fd, &st) < 0) {
-			return index_file_set_syscall_error(index, uidlist_path,
-							    "fstat()");
-		}
-
-		if (!maildir_uidlist_rewrite(index))
+		if (!maildir_uidlist_rewrite(index, &uidlist_mtime))
 			return FALSE;
 	}
 
 	/* uidlist file synced */
-	index->uidlist_ino = st.st_ino;
-	index->uidlist_dev = st.st_dev;
+	index->uidlist_mtime = uidlist_mtime;
 
 	/* update sync stamp */
 	index->file_sync_stamp = std.st_mtime;
--- a/src/lib-index/maildir/maildir-uidlist.c	Thu Apr 17 17:20:47 2003 +0300
+++ b/src/lib-index/maildir/maildir-uidlist.c	Mon Apr 21 16:42:00 2003 +0300
@@ -12,6 +12,7 @@
 
 #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)
@@ -168,23 +169,14 @@
 	i_free(uidlist);
 }
 
-int maildir_uidlist_rewrite(struct mail_index *index)
+static int maildir_uidlist_rewrite_fd(struct mail_index *index,
+				      const char *temp_path, time_t *mtime)
 {
 	struct mail_index_record *rec;
-	const char *temp_path, *db_path, *p, *fname;
+	struct utimbuf ut;
+	const char *p, *fname;
 	string_t *str;
 	size_t len;
-	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->mailbox_path,
-				"/" MAILDIR_UIDLIST_NAME ".lock", NULL);
 
 	str = t_str_new(4096);
 	str_printfa(str, "1 %u %u\n",
@@ -194,7 +186,7 @@
 	while (rec != NULL) {
 		fname = maildir_get_location(index, rec);
 		if (fname == NULL)
-			break;
+			return FALSE;
 
 		p = strchr(fname, ':');
 		len = p == NULL ? strlen(fname) : (size_t)(p-fname);
@@ -205,7 +197,7 @@
 				       str_data(str), str_len(str)) < 0) {
 				index_file_set_syscall_error(index, temp_path,
 							     "write_full()");
-				break;
+				return FALSE;
 			}
 			str_truncate(str, 0);
 		}
@@ -220,20 +212,47 @@
 	if (write_full(index->maildir_lock_fd,
 		       str_data(str), str_len(str)) < 0) {
 		index_file_set_syscall_error(index, temp_path, "write_full()");
-		failed = TRUE;
+		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;
 	}
 
-	if (fdatasync(index->maildir_lock_fd) < 0) {
-		index_file_set_syscall_error(index, temp_path, "fdatasync()");
-		failed = TRUE;
+	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->mailbox_path,
+				"/" MAILDIR_UIDLIST_NAME ".lock", NULL);
+
+	failed = !maildir_uidlist_rewrite_fd(index, temp_path, mtime);
 	if (close(index->maildir_lock_fd) < 0) {
 		index_file_set_syscall_error(index, temp_path, "close()");
 		failed = TRUE;
 	}
         index->maildir_lock_fd = -1;
 
-	if (rec == NULL) {
+	if (!failed) {
 		db_path = t_strconcat(index->mailbox_path,
 				      "/" MAILDIR_UIDLIST_NAME, NULL);
 
--- a/src/lib-index/maildir/maildir-uidlist.h	Thu Apr 17 17:20:47 2003 +0300
+++ b/src/lib-index/maildir/maildir-uidlist.h	Mon Apr 21 16:42:00 2003 +0300
@@ -22,7 +22,7 @@
 
 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);
+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);