changeset 5017:987397c331d7 HEAD

Fixes to error handling paths.
author Timo Sirainen <tss@iki.fi>
date Wed, 17 Jan 2007 18:17:42 +0200
parents 874dede81cc1
children 9b8c3efa85ec
files src/lib-index/mail-index-lock.c src/lib-index/mail-index-view.c src/lib-index/mail-index.c src/lib-index/mail-transaction-log-view.c src/lib-index/mail-transaction-log.c
diffstat 5 files changed, 49 insertions(+), 26 deletions(-) [+]
line wrap: on
line diff
--- a/src/lib-index/mail-index-lock.c	Wed Jan 17 16:57:11 2007 +0200
+++ b/src/lib-index/mail-index-lock.c	Wed Jan 17 18:17:42 2007 +0200
@@ -270,24 +270,29 @@
 
 static int mail_index_copy_lock_finish(struct mail_index *index)
 {
+	int ret = 0;
+
 	if (!index->fsync_disable) {
 		if (fsync(index->fd) < 0) {
 			mail_index_file_set_syscall_error(index,
 							  index->copy_lock_path,
 							  "fsync()");
-			return -1;
+			ret = -1;
 		}
 	}
 
-	if (rename(index->copy_lock_path, index->filepath) < 0) {
-		mail_index_set_error(index, "rename(%s, %s) failed: %m",
-				     index->copy_lock_path, index->filepath);
-		return -1;
+	if (ret == 0) {
+		if (rename(index->copy_lock_path, index->filepath) < 0) {
+			mail_index_set_error(index, "rename(%s, %s) failed: %m",
+					     index->copy_lock_path,
+					     index->filepath);
+			ret = -1;
+		}
 	}
 
 	i_free(index->copy_lock_path);
 	index->copy_lock_path = NULL;
-	return 0;
+	return ret;
 }
 
 static int mail_index_write_map_over(struct mail_index *index)
--- a/src/lib-index/mail-index-view.c	Wed Jan 17 16:57:11 2007 +0200
+++ b/src/lib-index/mail-index-view.c	Wed Jan 17 18:17:42 2007 +0200
@@ -73,6 +73,8 @@
 #ifdef DEBUG
 	mail_index_view_check_nextuid(view);
 #endif
+	if (mail_index_view_is_inconsistent(view))
+		return -1;
 	if (MAIL_INDEX_MAP_IS_IN_MEMORY(view->index->map))
 		return 0;
 
@@ -106,11 +108,11 @@
 
 int mail_index_view_lock(struct mail_index_view *view)
 {
-	if (mail_index_view_is_inconsistent(view))
-		return -1;
-
 	if (view->map != view->index->map) {
 		/* not head mapping, no need to lock */
+		if (mail_index_view_is_inconsistent(view))
+			return -1;
+
 #ifdef DEBUG
 		mail_index_view_check_nextuid(view);
 #endif
--- a/src/lib-index/mail-index.c	Wed Jan 17 16:57:11 2007 +0200
+++ b/src/lib-index/mail-index.c	Wed Jan 17 18:17:42 2007 +0200
@@ -1518,21 +1518,25 @@
 	index->indexid = hdr.indexid;
 
 	index->log = mail_transaction_log_open_or_create(index);
-	if (index->log == NULL)
+	if (index->log == NULL) {
+		if (ret == 0)
+			index->hdr = NULL;
 		return -1;
+	}
 
 	if (index->fd == -1) {
-		if (index->indexid != hdr.indexid) {
-			/* looks like someone else created the transaction log
-			   before we had the chance. use its indexid so we
-			   don't try to create conflicting ones. */
-			hdr.indexid = index->indexid;
-		}
+		mail_index_header_init(&hdr);
+		index->hdr = &hdr;
+
+		/* index->indexid may be updated by transaction log opening,
+		   in case someone else had already created a new log file */
+		hdr.indexid = index->indexid;
 
 		if (lock_id != 0) {
 			mail_index_unlock(index, lock_id);
 			lock_id = 0;
 		}
+
 		if (!MAIL_INDEX_IS_IN_MEMORY(index)) {
 			if (mail_index_create(index, &hdr) < 0) {
 				/* fallback to in-memory index */
@@ -1544,6 +1548,7 @@
 		}
 		created = TRUE;
 	}
+	i_assert(index->hdr != &hdr);
 
 	if (lock_id == 0) {
 		if (mail_index_lock_shared(index, FALSE, &lock_id) < 0)
--- a/src/lib-index/mail-transaction-log-view.c	Wed Jan 17 16:57:11 2007 +0200
+++ b/src/lib-index/mail-transaction-log-view.c	Wed Jan 17 18:17:42 2007 +0200
@@ -147,14 +147,16 @@
 		if (max_file_offset == 0 && min_file_seq == max_file_seq)
 			max_file_offset = min_file_offset;
 	}
+	i_assert(min_file_offset >= file->hdr.hdr_size);
 
-	/* check these later than others as index file may have corrupted
-	   log_file_offset. we should have recreated the log file and
-	   skipped min_file_seq file above.. max_file_offset can be broken
-	   only if min_file_seq = max_file_seq. */
-	i_assert(min_file_offset >= file->hdr.hdr_size);
-	i_assert(min_file_seq != max_file_seq ||
-		 min_file_offset <= max_file_offset);
+	if (min_file_seq == max_file_seq && min_file_offset > max_file_offset) {
+		/* log file offset is probably corrupted in the index file. */
+		mail_transaction_log_view_set_corrupted(view,
+			"file_seq=%u, min_file_offset (%"PRIuUOFF_T
+			") > max_file_offset (%"PRIuUOFF_T")",
+			min_file_seq, min_file_offset, max_file_offset);
+		return -1;
+	}
 
 	end_offset = min_file_seq == max_file_seq ?
 		max_file_offset : (uoff_t)-1;
--- a/src/lib-index/mail-transaction-log.c	Wed Jan 17 16:57:11 2007 +0200
+++ b/src/lib-index/mail-transaction-log.c	Wed Jan 17 18:17:42 2007 +0200
@@ -979,6 +979,9 @@
 		}
 	}
 
+	if (MAIL_INDEX_IS_IN_MEMORY(log->index))
+		return 0;
+
 	/* see if we have it in log.2 file */
 	path = t_strconcat(log->index->filepath,
 			   MAIL_TRANSACTION_LOG_SUFFIX".2", NULL);
@@ -1186,9 +1189,6 @@
 		return 0;
 	}
 
-	if (MAIL_TRANSACTION_LOG_FILE_IN_MEMORY(file))
-		return 1;
-
 	if (start_offset < file->hdr.hdr_size) {
 		mail_transaction_log_file_set_corrupted(file,
 			"offset (%"PRIuUOFF_T") < header size (%u)",
@@ -1196,6 +1196,9 @@
 		return -1;
 	}
 
+	if (MAIL_TRANSACTION_LOG_FILE_IN_MEMORY(file))
+		return 1;
+
 	/* with mmap_no_write we could alternatively just write to log with
 	   msync() rather than pwrite(). but since there aren't many such OSes
 	   left, it's easier to just use mmap_disable behavior with it */
@@ -1285,6 +1288,12 @@
 			return -1;
 	}
 
+	if (start_offset > file->sync_offset) {
+		mail_transaction_log_file_set_corrupted(file,
+			"start_offset (%"PRIuUOFF_T") > current sync_offset "
+			"(%"PRIuUOFF_T")", start_offset, file->sync_offset);
+		return -1;
+	}
 	if (end_offset != (uoff_t)-1 && end_offset > file->sync_offset) {
 		mail_transaction_log_file_set_corrupted(file,
 			"end_offset (%"PRIuUOFF_T") > current sync_offset "