# HG changeset patch # User Timo Sirainen # Date 1128105990 -10800 # Node ID c0e35566dd14ba11db960dd02a5626bc007ab191 # Parent 68ab7800d73509bdc0daae2f25deb7f63389006e 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. diff -r 68ab7800d735 -r c0e35566dd14 src/lib-index/mail-cache-compress.c --- 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; } } diff -r 68ab7800d735 -r c0e35566dd14 src/lib-index/mail-cache-fields.c --- 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; } diff -r 68ab7800d735 -r c0e35566dd14 src/lib-index/mail-cache-private.h --- 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); diff -r 68ab7800d735 -r c0e35566dd14 src/lib-index/mail-cache-sync-update.c --- 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); } diff -r 68ab7800d735 -r c0e35566dd14 src/lib-index/mail-cache-transaction.c --- 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; } diff -r 68ab7800d735 -r c0e35566dd14 src/lib-index/mail-cache.c --- 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,