changeset 3627:c0e35566dd14 HEAD

Unlocking cache file can also corrupt it since it modifies it. Added a return value for it and checks to handle the failure. Fixes a crash in some error situations.
author Timo Sirainen <tss@iki.fi>
date Fri, 30 Sep 2005 21:46:30 +0300
parents 68ab7800d735
children 571336db01f4
files src/lib-index/mail-cache-compress.c src/lib-index/mail-cache-fields.c src/lib-index/mail-cache-private.h src/lib-index/mail-cache-sync-update.c src/lib-index/mail-cache-transaction.c src/lib-index/mail-cache.c
diffstat 6 files changed, 40 insertions(+), 24 deletions(-) [+]
line wrap: on
line diff
--- a/src/lib-index/mail-cache-compress.c	Fri Sep 30 21:25:30 2005 +0300
+++ b/src/lib-index/mail-cache-compress.c	Fri Sep 30 21:46:30 2005 +0300
@@ -319,7 +319,8 @@
 	default:
 		/* locking succeeded. */
 		ret = mail_cache_compress_locked(cache, view);
-		mail_cache_unlock(cache);
+		if (mail_cache_unlock(cache) < 0)
+			ret = -1;
 		return ret;
 	}
 }
--- a/src/lib-index/mail-cache-fields.c	Fri Sep 30 21:25:30 2005 +0300
+++ b/src/lib-index/mail-cache-fields.c	Fri Sep 30 21:46:30 2005 +0300
@@ -349,7 +349,8 @@
 		return -1;
 
 	ret = mail_cache_header_fields_update_locked(cache);
-	mail_cache_unlock(cache);
+	if (mail_cache_unlock(cache) < 0)
+		ret = -1;
 	return ret;
 }
 
--- a/src/lib-index/mail-cache-private.h	Fri Sep 30 21:25:30 2005 +0300
+++ b/src/lib-index/mail-cache-private.h	Fri Sep 30 21:46:30 2005 +0300
@@ -175,7 +175,8 @@
 /* Explicitly lock the cache file. Returns -1 if error, 1 if ok, 0 if we
    couldn't lock */
 int mail_cache_lock(struct mail_cache *cache);
-void mail_cache_unlock(struct mail_cache *cache);
+/* Returns -1 if cache is / just got corrupted, 0 if ok. */
+int mail_cache_unlock(struct mail_cache *cache);
 
 int mail_cache_write(struct mail_cache *cache, const void *data, size_t size,
 		     uoff_t offset);
--- a/src/lib-index/mail-cache-sync-update.c	Fri Sep 30 21:25:30 2005 +0300
+++ b/src/lib-index/mail-cache-sync-update.c	Fri Sep 30 21:46:30 2005 +0300
@@ -18,7 +18,7 @@
 		return;
 
 	if (ctx->locked)
-		mail_cache_unlock(sync_ctx->view->index->cache);
+		(void)mail_cache_unlock(sync_ctx->view->index->cache);
 	i_free(ctx);
 }
 
--- a/src/lib-index/mail-cache-transaction.c	Fri Sep 30 21:25:30 2005 +0300
+++ b/src/lib-index/mail-cache-transaction.c	Fri Sep 30 21:46:30 2005 +0300
@@ -294,17 +294,17 @@
 	}
 }
 
-static void
+static int
 mail_cache_transaction_free_space(struct mail_cache_transaction_ctx *ctx)
 {
 	int locked = ctx->cache->locked;
 
 	if (ctx->reserved_space == 0)
-		return;
+		return 0;
 
 	if (!locked) {
 		if (mail_cache_transaction_lock(ctx) <= 0)
-			return;
+			return 0;
 	}
 
 	/* check again - locking might have reopened the cache file */
@@ -316,8 +316,11 @@
                 ctx->reserved_space = 0;
 	}
 
-	if (!locked)
-		mail_cache_unlock(ctx->cache);
+	if (!locked) {
+		if (mail_cache_unlock(ctx->cache) < 0)
+			return -1;
+	}
+	return 0;
 }
 
 static int
@@ -343,8 +346,10 @@
 		}
 		ret = mail_cache_transaction_reserve_more(ctx, max_size,
 							  commit);
-		if (!locked)
-			mail_cache_unlock(ctx->cache);
+		if (!locked) {
+			if (mail_cache_unlock(ctx->cache) < 0)
+				return -1;
+		}
 
 		if (ret < 0)
 			return -1;
@@ -369,7 +374,8 @@
 	if (size == max_size && commit) {
 		/* final commit - see if we can free the rest of the
 		   reserved space */
-		mail_cache_transaction_free_space(ctx);
+		if (mail_cache_transaction_free_space(ctx) < 0)
+			return -1;
 	}
 
 	i_assert(size >= min_size);
@@ -568,7 +574,8 @@
 		ret = -1;
 	}
 
-	mail_cache_unlock(cache);
+	if (mail_cache_unlock(cache) < 0)
+		ret = -1;
 	mail_cache_transaction_free(ctx);
 	return ret;
 }
@@ -598,7 +605,7 @@
 							      buf[size+1]);
 				} while (size > 0);
 			}
-			mail_cache_unlock(cache);
+			(void)mail_cache_unlock(cache);
 		}
 	}
 
@@ -620,13 +627,14 @@
 
 	/* re-read header to make sure we don't lose any fields. */
 	if (mail_cache_header_fields_read(cache) < 0) {
-		mail_cache_unlock(cache);
+		(void)mail_cache_unlock(cache);
 		return -1;
 	}
 
 	if (ctx->cache->field_file_map[field] != (uint32_t)-1) {
 		/* it was already added */
-		mail_cache_unlock(cache);
+		if (mail_cache_unlock(cache) < 0)
+			return -1;
 		return 0;
 	}
 
@@ -660,7 +668,8 @@
 	}
 	t_pop();
 
-	mail_cache_unlock(cache);
+	if (mail_cache_unlock(cache) < 0)
+		ret = -1;
 	return ret;
 }
 
--- a/src/lib-index/mail-cache.c	Fri Sep 30 21:25:30 2005 +0300
+++ b/src/lib-index/mail-cache.c	Fri Sep 30 21:46:30 2005 +0300
@@ -391,7 +391,7 @@
 		}
 
 		/* okay, so it was just compressed. try again. */
-		mail_cache_unlock(cache);
+		(void)mail_cache_unlock(cache);
 		if ((ret = mail_cache_reopen(cache)) <= 0)
 			break;
 		ret = 0;
@@ -406,7 +406,7 @@
 		if (mail_cache_map(cache, 0, 0) == 0)
 			cache->hdr_copy = *cache->hdr;
 		else {
-			mail_cache_unlock(cache);
+			(void)mail_cache_unlock(cache);
 			ret = -1;
 		}
 	}
@@ -438,29 +438,33 @@
 		cache->need_compress = TRUE;
 }
 
-void mail_cache_unlock(struct mail_cache *cache)
+int mail_cache_unlock(struct mail_cache *cache)
 {
+	int ret = 0;
+
 	i_assert(cache->locked);
 
 	if (cache->field_header_write_pending)
-                (void)mail_cache_header_fields_update(cache);
+                ret = mail_cache_header_fields_update(cache);
 
 	cache->locked = FALSE;
 
 	if (MAIL_CACHE_IS_UNUSABLE(cache)) {
 		/* we found it to be broken during the lock. just clean up. */
 		cache->hdr_modified = FALSE;
-		return;
+		return -1;
 	}
 
 	if (cache->hdr_modified) {
 		cache->hdr_modified = FALSE;
-		(void)mail_cache_write(cache, &cache->hdr_copy,
-				       sizeof(cache->hdr_copy), 0);
+		if (mail_cache_write(cache, &cache->hdr_copy,
+				     sizeof(cache->hdr_copy), 0) < 0)
+			ret = -1;
 		mail_cache_update_need_compress(cache);
 	}
 
 	(void)mail_cache_lock_file(cache, F_UNLCK);
+	return ret;
 }
 
 int mail_cache_write(struct mail_cache *cache, const void *data, size_t size,