changeset 6277:5f66277bbe40 HEAD

mail_index_lookup*() can't fail anymore. Changed several APIs not to return failure anymore.
author Timo Sirainen <tss@iki.fi>
date Sun, 12 Aug 2007 18:02:29 +0300
parents b5a23c868935
children ce83635191d4
files src/deliver/deliver.c src/imap/cmd-store.c src/imap/imap-expunge.c src/imap/imap-fetch.c src/imap/imap-sync.c src/imap/imap-thread.c src/lib-index/mail-cache-lookup.c src/lib-index/mail-index-sync.c src/lib-index/mail-index-transaction-view.c src/lib-index/mail-index-transaction.c src/lib-index/mail-index-view-private.h src/lib-index/mail-index-view.c src/lib-index/mail-index.h src/lib-storage/index/cydir/cydir-save.c src/lib-storage/index/dbox/dbox-file.c src/lib-storage/index/dbox/dbox-save.c src/lib-storage/index/index-mail.c src/lib-storage/index/index-mail.h src/lib-storage/index/index-search.c src/lib-storage/index/index-sort.c src/lib-storage/index/index-sort.h src/lib-storage/index/maildir/maildir-save.c src/lib-storage/index/maildir/maildir-sync-index.c src/lib-storage/index/mbox/mbox-file.c src/lib-storage/index/mbox/mbox-save.c src/lib-storage/index/mbox/mbox-sync-parse.c src/lib-storage/index/mbox/mbox-sync-private.h src/lib-storage/index/mbox/mbox-sync.c src/lib-storage/list/index-mailbox-list-sync.c src/lib-storage/list/index-mailbox-list.c src/lib-storage/mail-storage-private.h src/lib-storage/mail-storage.h src/lib-storage/mail.c src/plugins/acl/acl-mailbox.c src/plugins/expire/expire-plugin.c src/plugins/expire/expire-tool.c src/plugins/fts/fts-storage.c src/plugins/lazy-expunge/lazy-expunge-plugin.c src/plugins/mail-log/mail-log-plugin.c src/plugins/quota/quota-storage.c src/plugins/trash/trash-plugin.c src/pop3/commands.c
diffstat 42 files changed, 411 insertions(+), 522 deletions(-) [+]
line wrap: on
line diff
--- a/src/deliver/deliver.c	Sun Aug 12 16:50:47 2007 +0300
+++ b/src/deliver/deliver.c	Sun Aug 12 18:02:29 2007 +0300
@@ -749,8 +749,7 @@
 
 	t = mailbox_transaction_begin(box, 0);
 	mail = mail_alloc(t, 0, NULL);
-	if (mail_set_seq(mail, 1) < 0)
-		i_fatal("mail_set_seq() failed");
+	mail_set_seq(mail, 1);
 
 	storage = NULL;
 	default_mailbox_name = mailbox;
--- a/src/imap/cmd-store.c	Sun Aug 12 16:50:47 2007 +0300
+++ b/src/imap/cmd-store.c	Sun Aug 12 18:02:29 2007 +0300
@@ -92,36 +92,23 @@
 		mailbox_keywords_create(t, keywords_list) : NULL;
 	search_ctx = mailbox_search_init(t, NULL, search_arg, NULL);
 
-	failed = FALSE;
 	mail = mail_alloc(t, MAIL_FETCH_FLAGS, NULL);
 	while (mailbox_search_next(search_ctx, mail) > 0) {
-		if (modify_type == MODIFY_REPLACE || flags != 0) {
-			if (mail_update_flags(mail, modify_type, flags) < 0) {
-				failed = TRUE;
-				break;
-			}
-		}
-		if (modify_type == MODIFY_REPLACE || keywords != NULL) {
-			if (mail_update_keywords(mail, modify_type,
-						 keywords) < 0) {
-				failed = TRUE;
-				break;
-			}
-		}
+		if (modify_type == MODIFY_REPLACE || flags != 0)
+			mail_update_flags(mail, modify_type, flags);
+		if (modify_type == MODIFY_REPLACE || keywords != NULL)
+			mail_update_keywords(mail, modify_type, keywords);
 	}
 	mail_free(&mail);
 
 	if (keywords != NULL)
 		mailbox_keywords_free(t, &keywords);
 
-	if (mailbox_search_deinit(&search_ctx) < 0)
+	if (mailbox_search_deinit(&search_ctx) < 0) {
 		failed = TRUE;
-
-	if (failed)
 		mailbox_transaction_rollback(&t);
-	else {
-		if (mailbox_transaction_commit(&t, 0) < 0)
-			failed = TRUE;
+	} else {
+		failed = mailbox_transaction_commit(&t, 0) < 0;
 	}
 
 	if (!failed) {
--- a/src/imap/imap-expunge.c	Sun Aug 12 16:50:47 2007 +0300
+++ b/src/imap/imap-expunge.c	Sun Aug 12 18:02:29 2007 +0300
@@ -12,7 +12,7 @@
 	struct mail *mail;
 	struct mail_search_arg search_arg;
         enum mailbox_sync_flags flags;
-	bool failed = FALSE;
+	bool failed;
 
 	if (mailbox_is_readonly(box)) {
 		/* silently ignore */
@@ -27,24 +27,17 @@
 	ctx = mailbox_search_init(t, NULL, &search_arg, NULL);
 
 	mail = mail_alloc(t, 0, NULL);
-	while (mailbox_search_next(ctx, mail) > 0) {
-		if (mail_expunge(mail) < 0) {
-			failed = TRUE;
-			break;
-		}
-	}
+	while (mailbox_search_next(ctx, mail) > 0)
+		mail_expunge(mail);
 	mail_free(&mail);
 
-	if (mailbox_search_deinit(&ctx) < 0)
+	if (mailbox_search_deinit(&ctx) < 0) {
 		failed = TRUE;
-
-	if (failed)
 		mailbox_transaction_rollback(&t);
-	else {
+	} else {
 		flags = MAILBOX_SYNC_FLAG_FULL_READ |
 			MAILBOX_SYNC_FLAG_FULL_WRITE;
-		if (mailbox_transaction_commit(&t, flags) < 0)
-			failed = TRUE;
+		failed = mailbox_transaction_commit(&t, flags) < 0;
 	}
 
 	return !failed;
--- a/src/imap/imap-fetch.c	Sun Aug 12 16:50:47 2007 +0300
+++ b/src/imap/imap-fetch.c	Sun Aug 12 18:02:29 2007 +0300
@@ -514,8 +514,7 @@
 	if (ctx->flags_update_seen && (flags & MAIL_SEEN) == 0) {
 		/* Add \Seen flag */
 		flags |= MAIL_SEEN;
-		if (mail_update_flags(mail, MODIFY_ADD, MAIL_SEEN) < 0)
-			return -1;
+		mail_update_flags(mail, MODIFY_ADD, MAIL_SEEN);
 	} else if (ctx->flags_show_only_seen_changes) {
 		return 1;
 	}
--- a/src/imap/imap-sync.c	Sun Aug 12 16:50:47 2007 +0300
+++ b/src/imap/imap-sync.c	Sun Aug 12 18:02:29 2007 +0300
@@ -143,11 +143,7 @@
 				if (ret <= 0)
 					break;
 
-				if (mail_set_seq(ctx->mail, ctx->seq) < 0) {
-					t_pop();
-					return -1;
-				}
-
+				mail_set_seq(ctx->mail, ctx->seq);
 				flags = mail_get_flags(ctx->mail);
 				keywords = mail_get_keywords(ctx->mail);
 
--- a/src/imap/imap-thread.c	Sun Aug 12 16:50:47 2007 +0300
+++ b/src/imap/imap-thread.c	Sun Aug 12 18:02:29 2007 +0300
@@ -691,7 +691,8 @@
 		else
 			mailbox_get_uids(ctx->box, id, id, &seq, &seq);
 
-		if (seq != 0 && mail_set_seq(ctx->mail, seq) == 0) {
+		if (seq != 0) {
+			mail_set_seq(ctx->mail, seq);
 			t_push();
                         subject = mail_get_first_header(ctx->mail, "subject");
 			add_base_subject(ctx, subject, node);
--- a/src/lib-index/mail-cache-lookup.c	Sun Aug 12 16:50:47 2007 +0300
+++ b/src/lib-index/mail-cache-lookup.c	Sun Aug 12 18:02:29 2007 +0300
@@ -57,9 +57,8 @@
 	uint32_t reset_id;
 	int i, ret;
 
-	if (mail_index_lookup_ext_full(view, seq, cache->ext_id,
-				       &map, &data) < 0)
-		return -1;
+	mail_index_lookup_ext_full(view, seq, cache->ext_id,
+				   &map, &data, NULL);
 	if (data == NULL || *((const uint32_t *)data) == 0) {
 		/* nothing in cache (for this record) */
 		return 0;
--- a/src/lib-index/mail-index-sync.c	Sun Aug 12 16:50:47 2007 +0300
+++ b/src/lib-index/mail-index-sync.c	Sun Aug 12 18:02:29 2007 +0300
@@ -149,7 +149,7 @@
 	return TRUE;
 }
 
-static int mail_index_sync_add_dirty_updates(struct mail_index_sync_ctx *ctx)
+static void mail_index_sync_add_dirty_updates(struct mail_index_sync_ctx *ctx)
 {
 	struct mail_transaction_flag_update update;
 	const struct mail_index_record *rec;
@@ -159,16 +159,13 @@
 
 	messages_count = mail_index_view_get_messages_count(ctx->view);
 	for (seq = 1; seq <= messages_count; seq++) {
-		if (mail_index_lookup(ctx->view, seq, &rec) < 0)
-			return -1;
-
+		rec = mail_index_lookup(ctx->view, seq);
 		if ((rec->flags & MAIL_INDEX_MAIL_FLAG_DIRTY) == 0)
 			continue;
 
 		mail_index_update_flags(ctx->sync_trans, rec->uid,
 					MODIFY_REPLACE, rec->flags);
 	}
-	return 0;
 }
 
 static void
@@ -196,8 +193,7 @@
 	if ((ctx->view->map->hdr.flags & MAIL_INDEX_HDR_FLAG_HAVE_DIRTY) &&
 	    (ctx->flags & MAIL_INDEX_SYNC_FLAG_FLUSH_DIRTY) != 0) {
 		/* show dirty flags as flag updates */
-		if (mail_index_sync_add_dirty_updates(ctx) < 0)
-			return -1;
+		mail_index_sync_add_dirty_updates(ctx);
 	}
 
 	/* read all transactions from log into a transaction in memory.
--- a/src/lib-index/mail-index-transaction-view.c	Sun Aug 12 16:50:47 2007 +0300
+++ b/src/lib-index/mail-index-transaction-view.c	Sun Aug 12 18:02:29 2007 +0300
@@ -60,30 +60,29 @@
 	return hdr;
 }
 
-static int _tview_lookup_full(struct mail_index_view *view, uint32_t seq,
-			      struct mail_index_map **map_r,
-			      const struct mail_index_record **rec_r)
+static const struct mail_index_record *
+_tview_lookup_full(struct mail_index_view *view, uint32_t seq,
+		   struct mail_index_map **map_r, bool *expunged_r)
 {
 	struct mail_index_view_transaction *tview =
                 (struct mail_index_view_transaction *)view;
-	int ret;
+	const struct mail_index_record *rec;
 
 	if (seq >= tview->t->first_new_seq) {
 		/* FIXME: is this right to return index map..?
 		   it's not there yet. */
 		*map_r = view->index->map;
-		*rec_r = mail_index_transaction_lookup(tview->t, seq);
-		return 1;
+		*expunged_r = FALSE;
+		return mail_index_transaction_lookup(tview->t, seq);
 	}
 
-	ret = tview->super->lookup_full(view, seq, map_r, rec_r);
-	if (ret <= 0)
-		return ret;
+	rec = tview->super->lookup_full(view, seq, map_r, expunged_r);
 
 	/* if we're expunged within this transaction, return 0 */
-	return array_is_created(&tview->t->expunges) &&
-		seq_range_exists(&tview->t->expunges, seq) ? 0 : 1;
-
+	if (array_is_created(&tview->t->expunges) &&
+	    seq_range_exists(&tview->t->expunges, seq))
+		*expunged_r = TRUE;
+	return rec;
 }
 
 static void _tview_lookup_uid(struct mail_index_view *view, uint32_t seq,
@@ -176,10 +175,10 @@
 	return tview->lookup_map;
 }
 
-static int
+static void
 _tview_lookup_ext_full(struct mail_index_view *view, uint32_t seq,
 		       uint32_t ext_id, struct mail_index_map **map_r,
-		       const void **data_r)
+		       const void **data_r, bool *expunged_r)
 {
 	struct mail_index_view_transaction *tview =
 		(struct mail_index_view_transaction *)view;
@@ -189,6 +188,8 @@
 
 	i_assert(ext_id < array_count(&view->index->extensions));
 
+	*expunged_r = FALSE;
+
 	if (array_is_created(&tview->t->ext_rec_updates) &&
 	    ext_id < array_count(&tview->t->ext_rec_updates)) {
 		/* there are some ext updates in transaction.
@@ -199,19 +200,18 @@
 			data = array_idx(ext_buf, idx);
 			*map_r = tview_get_lookup_map(tview);
 			*data_r = CONST_PTR_OFFSET(data, sizeof(uint32_t));
-			return 1;
+			return;
 		}
 	}
 
 	/* not updated, return the existing value */
 	if (seq < tview->t->first_new_seq) {
-		return tview->super->lookup_ext_full(view, seq, ext_id,
-						     map_r, data_r);
+		tview->super->lookup_ext_full(view, seq, ext_id,
+					      map_r, data_r, expunged_r);
+	} else {
+		*map_r = view->index->map;
+		*data_r = NULL;
 	}
-
-	*map_r = view->index->map;
-	*data_r = NULL;
-	return 1;
 }
 
 static void _tview_get_header_ext(struct mail_index_view *view,
--- a/src/lib-index/mail-index-transaction.c	Sun Aug 12 16:50:47 2007 +0300
+++ b/src/lib-index/mail-index-transaction.c	Sun Aug 12 18:02:29 2007 +0300
@@ -592,9 +592,7 @@
 		return TRUE;
 
 	for (seq = u->uid1; seq <= u->uid2; seq++) {
-		if (mail_index_lookup(t->view, seq, &rec) < 0)
-			return TRUE;
-
+		rec = mail_index_lookup(t->view, seq);
 		if ((rec->flags & u->add_flags) != u->add_flags ||
 		    (rec->flags & u->remove_flags) != 0)
 			return TRUE;
--- a/src/lib-index/mail-index-view-private.h	Sun Aug 12 16:50:47 2007 +0300
+++ b/src/lib-index/mail-index-view-private.h	Sun Aug 12 18:02:29 2007 +0300
@@ -15,9 +15,9 @@
 	uint32_t (*get_messages_count)(struct mail_index_view *view);
 	const struct mail_index_header *
 		(*get_header)(struct mail_index_view *view);
-	int (*lookup_full)(struct mail_index_view *view, uint32_t seq,
-			   struct mail_index_map **map_r,
-			   const struct mail_index_record **rec_r);
+	const struct mail_index_record *
+		(*lookup_full)(struct mail_index_view *view, uint32_t seq,
+			       struct mail_index_map **map_r, bool *expunged_r);
 	void (*lookup_uid)(struct mail_index_view *view, uint32_t seq,
 			   uint32_t *uid_r);
 	void (*lookup_uid_range)(struct mail_index_view *view,
@@ -26,9 +26,9 @@
 	void (*lookup_first)(struct mail_index_view *view,
 			     enum mail_flags flags, uint8_t flags_mask,
 			     uint32_t *seq_r);
-	int (*lookup_ext_full)(struct mail_index_view *view, uint32_t seq,
-			       uint32_t ext_id, struct mail_index_map **map_r,
-			       const void **data_r);
+	void (*lookup_ext_full)(struct mail_index_view *view, uint32_t seq,
+				uint32_t ext_id, struct mail_index_map **map_r,
+				const void **data_r, bool *expunged_r);
 	void (*get_header_ext)(struct mail_index_view *view,
 			       struct mail_index_map *map, uint32_t ext_id,
 			       const void **data_r, size_t *data_size_r);
--- a/src/lib-index/mail-index-view.c	Sun Aug 12 16:50:47 2007 +0300
+++ b/src/lib-index/mail-index-view.c	Sun Aug 12 18:02:29 2007 +0300
@@ -141,9 +141,9 @@
 	return &view->map->hdr;
 }
 
-static int _view_lookup_full(struct mail_index_view *view, uint32_t seq,
-			     struct mail_index_map **map_r,
-			     const struct mail_index_record **rec_r)
+static const struct mail_index_record *
+_view_lookup_full(struct mail_index_view *view, uint32_t seq,
+		  struct mail_index_map **map_r, bool *expunged_r)
 {
 	struct mail_index_map *map;
 	const struct mail_index_record *rec, *head_rec;
@@ -156,13 +156,16 @@
 		mail_index_set_error(view->index, "Corrupted Index file %s: "
 			"Record [%u].uid=0", view->index->filepath, seq);
 		mail_index_mark_corrupted(view->index);
-		return -1;
+
+		*map_r = view->map;
+		*expunged_r = TRUE;
+		return rec;
 	}
 	if (view->map == view->index->map) {
 		/* view's mapping is latest. we can use it directly. */
 		*map_r = view->map;
-		*rec_r = rec;
-		return 1;
+		*expunged_r = FALSE;
+		return rec;
 	}
 
 	/* look up the record from head mapping. it may contain some changes.
@@ -179,8 +182,8 @@
 	if (seq == 0) {
 		/* everything is expunged from head. use the old record. */
 		*map_r = view->map;
-		*rec_r = rec;
-		return 0;
+		*expunged_r = TRUE;
+		return rec;
 	}
 
 	map = view->index->map;
@@ -196,13 +199,13 @@
 		   returned record doesn't get invalidated after next sync. */
 		mail_index_view_ref_map(view, view->index->map);
 		*map_r = view->index->map;
-		*rec_r = head_rec;
-		return 1;
+		*expunged_r = FALSE;
+		return head_rec;
 	} else {
 		/* expuned from head. use the old record. */
 		*map_r = view->map;
-		*rec_r = rec;
-		return 0;
+		*expunged_r = TRUE;
+		return rec;
 	}
 }
 
@@ -340,28 +343,25 @@
 	}
 }
 
-static int _view_lookup_ext_full(struct mail_index_view *view, uint32_t seq,
-				 uint32_t ext_id, struct mail_index_map **map_r,
-				 const void **data_r)
+static void
+_view_lookup_ext_full(struct mail_index_view *view, uint32_t seq,
+		      uint32_t ext_id, struct mail_index_map **map_r,
+		      const void **data_r, bool *expunged_r)
 {
 	const struct mail_index_ext *ext;
 	const struct mail_index_record *rec;
 	uint32_t idx, offset;
-	int ret;
 
-	if ((ret = mail_index_lookup_full(view, seq, map_r, &rec)) < 0)
-		return -1;
-
-	if (rec == NULL || !mail_index_map_get_ext_idx(*map_r, ext_id, &idx)) {
+	rec = view->v.lookup_full(view, seq, map_r, expunged_r);
+	if (!mail_index_map_get_ext_idx(*map_r, ext_id, &idx)) {
 		*data_r = NULL;
-		return ret;
+		return;
 	}
 
 	ext = array_idx(&(*map_r)->extensions, idx);
 	offset = ext->record_offset;
 
 	*data_r = offset == 0 ? NULL : CONST_PTR_OFFSET(rec, offset);
-	return ret;
 }
 
 static void _view_get_header_ext(struct mail_index_view *view,
@@ -427,23 +427,34 @@
 	return view->v.get_header(view);
 }
 
-int mail_index_lookup(struct mail_index_view *view, uint32_t seq,
-		      const struct mail_index_record **rec_r)
+const struct mail_index_record *
+mail_index_lookup(struct mail_index_view *view, uint32_t seq)
 {
 	struct mail_index_map *map;
 
-	return mail_index_lookup_full(view, seq, &map, rec_r);
+	return mail_index_lookup_full(view, seq, &map);
+}
+
+const struct mail_index_record *
+mail_index_lookup_full(struct mail_index_view *view, uint32_t seq,
+		       struct mail_index_map **map_r)
+{
+	bool expunged;
+
+	return view->v.lookup_full(view, seq, map_r, &expunged);
 }
 
-int mail_index_lookup_full(struct mail_index_view *view, uint32_t seq,
-			   struct mail_index_map **map_r,
-			   const struct mail_index_record **rec_r)
+bool mail_index_is_expunged(struct mail_index_view *view, uint32_t seq)
 {
-	return view->v.lookup_full(view, seq, map_r, rec_r);
+	struct mail_index_map *map;
+	bool expunged;
+
+	(void)view->v.lookup_full(view, seq, &map, &expunged);
+	return expunged;
 }
 
-int mail_index_lookup_keywords(struct mail_index_view *view, uint32_t seq,
-			       ARRAY_TYPE(keyword_indexes) *keyword_idx)
+void mail_index_lookup_keywords(struct mail_index_view *view, uint32_t seq,
+				ARRAY_TYPE(keyword_indexes) *keyword_idx)
 {
 	struct mail_index_map *map;
 	const void *data;
@@ -452,19 +463,15 @@
 	unsigned int i, j, keyword_count, index_idx;
 	uint32_t ext_id, idx;
 	uint16_t record_size;
-	int ret;
 
 	array_clear(keyword_idx);
 
 	/* get the keywords data. */
 	ext_id = view->index->keywords_ext_id;
-	ret = mail_index_lookup_ext_full(view, seq, ext_id, &map, &data);
-	if (ret < 0)
-		return -1;
-
+	mail_index_lookup_ext_full(view, seq, ext_id, &map, &data, NULL);
 	if (data == NULL) {
 		/* no keywords at all in index */
-		return ret;
+		return;
 	}
 
 	(void)mail_index_ext_get_size(view, ext_id, map, NULL,
@@ -494,10 +501,10 @@
 				/* keyword header was updated, parse it again
 				   it so we know what this keyword is called */
 				if (mail_index_map_parse_keywords(map) < 0)
-					return -1;
+					return;
 
 				if (!array_is_created(&map->keyword_idx_map))
-					return ret;
+					return;
 
 				/* pointer may have changed. update it. */
 				keyword_idx_map =
@@ -515,7 +522,6 @@
 			array_append(keyword_idx, &index_idx, 1);
 		}
 	}
-	return ret;
 }
 
 void mail_index_lookup_uid(struct mail_index_view *view, uint32_t seq,
@@ -539,19 +545,25 @@
 	view->v.lookup_first(view, flags, flags_mask, seq_r);
 }
 
-int mail_index_lookup_ext(struct mail_index_view *view, uint32_t seq,
-			  uint32_t ext_id, const void **data_r)
+void mail_index_lookup_ext(struct mail_index_view *view, uint32_t seq,
+			   uint32_t ext_id, const void **data_r,
+			   bool *expunged_r)
 {
 	struct mail_index_map *map;
 
-	return view->v.lookup_ext_full(view, seq, ext_id, &map, data_r);
+	mail_index_lookup_ext_full(view, seq, ext_id, &map, data_r, expunged_r);
 }
 
-int mail_index_lookup_ext_full(struct mail_index_view *view, uint32_t seq,
-			       uint32_t ext_id, struct mail_index_map **map_r,
-			       const void **data_r)
+void mail_index_lookup_ext_full(struct mail_index_view *view, uint32_t seq,
+				uint32_t ext_id, struct mail_index_map **map_r,
+				const void **data_r, bool *expunged_r)
 {
-	return view->v.lookup_ext_full(view, seq, ext_id, map_r, data_r);
+	bool expunged;
+
+	if (expunged_r == NULL)
+		expunged_r = &expunged;
+
+	view->v.lookup_ext_full(view, seq, ext_id, map_r, data_r, expunged_r);
 }
 
 void mail_index_get_header_ext(struct mail_index_view *view, uint32_t ext_id,
@@ -574,10 +586,10 @@
 	return view->v.ext_get_reset_id(view, map, ext_id, reset_id_r);
 }
 
-int mail_index_ext_get_size(struct mail_index_view *view __attr_unused__,
-			    uint32_t ext_id, struct mail_index_map *map,
-			    uint32_t *hdr_size_r, uint16_t *record_size_r,
-			    uint16_t *record_align_r)
+void mail_index_ext_get_size(struct mail_index_view *view __attr_unused__,
+			     uint32_t ext_id, struct mail_index_map *map,
+			     uint32_t *hdr_size_r, uint16_t *record_size_r,
+			     uint16_t *record_align_r)
 {
 	const struct mail_index_ext *ext;
 	uint32_t idx;
@@ -592,7 +604,7 @@
 			*record_size_r = 0;
 		if (record_align_r != NULL)
 			*record_align_r = 0;
-		return 0;
+		return;
 	}
 
 	ext = array_idx(&map->extensions, idx);
@@ -602,7 +614,6 @@
 		*record_size_r = ext->record_size;
 	if (record_align_r != NULL)
 		*record_align_r = ext->record_align;
-	return 0;
 }
 
 static struct mail_index_view_vfuncs view_vfuncs = {
--- a/src/lib-index/mail-index.h	Sun Aug 12 16:50:47 2007 +0300
+++ b/src/lib-index/mail-index.h	Sun Aug 12 18:02:29 2007 +0300
@@ -295,16 +295,17 @@
 /* Returns the index header. */
 const struct mail_index_header *
 mail_index_get_header(struct mail_index_view *view);
-/* Returns the given message. Returns -1 if error, 1 if ok, 0 if mail was
-   expunged but data was returned from some older index.  */
-int mail_index_lookup(struct mail_index_view *view, uint32_t seq,
-		      const struct mail_index_record **rec_r);
-int mail_index_lookup_full(struct mail_index_view *view, uint32_t seq,
-			   struct mail_index_map **map_r,
-			   const struct mail_index_record **rec_r);
+/* Returns the wanted message record. */
+const struct mail_index_record *
+mail_index_lookup(struct mail_index_view *view, uint32_t seq);
+const struct mail_index_record *
+mail_index_lookup_full(struct mail_index_view *view, uint32_t seq,
+		       struct mail_index_map **map_r);
+/* Returns TRUE if the given message has already been expunged from index. */
+bool mail_index_is_expunged(struct mail_index_view *view, uint32_t seq);
 /* Note that returned keyword indexes aren't sorted. */
-int mail_index_lookup_keywords(struct mail_index_view *view, uint32_t seq,
-			       ARRAY_TYPE(keyword_indexes) *keyword_idx);
+void mail_index_lookup_keywords(struct mail_index_view *view, uint32_t seq,
+				ARRAY_TYPE(keyword_indexes) *keyword_idx);
 /* Returns the UID for given message. May be slightly faster than
    mail_index_lookup()->uid. */
 void mail_index_lookup_uid(struct mail_index_view *view, uint32_t seq,
@@ -424,18 +425,20 @@
 				   struct mail_index_map *map, uint32_t ext_id,
 				   const void **data_r, size_t *data_size_r);
 /* Returns the wanted extension record for given message. If it doesn't exist,
-   *data_r is set to NULL. Return values are same as for mail_index_lookup(). */
-int mail_index_lookup_ext(struct mail_index_view *view, uint32_t seq,
-			  uint32_t ext_id, const void **data_r);
-int mail_index_lookup_ext_full(struct mail_index_view *view, uint32_t seq,
-			       uint32_t ext_id, struct mail_index_map **map_r,
-			       const void **data_r);
+   *data_r is set to NULL. expunged_r is TRUE if the message has already been
+   expunged from the index. */
+void mail_index_lookup_ext(struct mail_index_view *view, uint32_t seq,
+			   uint32_t ext_id, const void **data_r,
+			   bool *expunged_r);
+void mail_index_lookup_ext_full(struct mail_index_view *view, uint32_t seq,
+				uint32_t ext_id, struct mail_index_map **map_r,
+				const void **data_r, bool *expunged_r);
 /* Get current extension sizes. Returns 1 if ok, 0 if extension doesn't exist
    in view. Any of the _r parameters may be NULL. */
-int mail_index_ext_get_size(struct mail_index_view *view,
-			    uint32_t ext_id, struct mail_index_map *map,
-			    uint32_t *hdr_size_r, uint16_t *record_size_r,
-			    uint16_t *record_align_r);
+void mail_index_ext_get_size(struct mail_index_view *view,
+			     uint32_t ext_id, struct mail_index_map *map,
+			     uint32_t *hdr_size_r, uint16_t *record_size_r,
+			     uint16_t *record_align_r);
 /* Update extension header field. */
 void mail_index_update_header_ext(struct mail_index_transaction *t,
 				  uint32_t ext_id, size_t offset,
--- a/src/lib-storage/index/cydir/cydir-save.c	Sun Aug 12 16:50:47 2007 +0300
+++ b/src/lib-storage/index/cydir/cydir-save.c	Sun Aug 12 18:02:29 2007 +0300
@@ -114,8 +114,7 @@
 			ctx->mail = index_mail_alloc(_t, 0, NULL);
 		dest_mail = ctx->mail;
 	}
-	if (mail_set_seq(dest_mail, ctx->seq) < 0)
-		i_unreached();
+	mail_set_seq(dest_mail, ctx->seq);
 
 	ctx->cur_dest_mail = dest_mail;
 	ctx->input = index_mail_cache_parse_init(dest_mail, input);
--- a/src/lib-storage/index/dbox/dbox-file.c	Sun Aug 12 16:50:47 2007 +0300
+++ b/src/lib-storage/index/dbox/dbox-file.c	Sun Aug 12 18:02:29 2007 +0300
@@ -15,17 +15,16 @@
 			    uint32_t *file_seq_r, uoff_t *offset_r)
 {
 	const void *data1, *data2;
-	int ret;
+	bool expunged;
 
-	ret = mail_index_lookup_ext(view, seq, mbox->dbox_file_ext_idx, &data1);
-	ret = ret <= 0 ? ret :
-		mail_index_lookup_ext(view, seq, mbox->dbox_offset_ext_idx,
-				      &data2);
-	if (ret <= 0) {
-		if (ret < 0)
-			mail_storage_set_index_error(&mbox->ibox);
-		return ret;
-	}
+	mail_index_lookup_ext(view, seq, mbox->dbox_file_ext_idx,
+			      &data1, &expunged);
+	if (expunged)
+		return 0;
+	mail_index_lookup_ext(view, seq, mbox->dbox_offset_ext_idx,
+			      &data2, &expunged);
+	if (expunged)
+		return 0;
 
 	if (data1 == NULL || data2 == NULL) {
 		*file_seq_r = 0;
--- a/src/lib-storage/index/dbox/dbox-save.c	Sun Aug 12 16:50:47 2007 +0300
+++ b/src/lib-storage/index/dbox/dbox-save.c	Sun Aug 12 18:02:29 2007 +0300
@@ -238,8 +238,7 @@
 			ctx->mail = index_mail_alloc(_t, 0, NULL);
 		dest_mail = ctx->mail;
 	}
-	if (mail_set_seq(dest_mail, ctx->seq) < 0)
-		i_unreached();
+	mail_set_seq(dest_mail, ctx->seq);
 
 	if (t->first_saved_mail_seq == 0)
 		t->first_saved_mail_seq = ctx->seq;
--- a/src/lib-storage/index/index-mail.c	Sun Aug 12 16:50:47 2007 +0300
+++ b/src/lib-storage/index/index-mail.c	Sun Aug 12 18:02:29 2007 +0300
@@ -137,12 +137,8 @@
 
 	t_push();
 	t_array_init(&keyword_indexes_arr, 128);
-	if (mail_index_lookup_keywords(mail->ibox->view, mail->data.seq,
-				       &keyword_indexes_arr) < 0) {
-		mail_storage_set_index_error(mail->ibox);
-		t_pop();
-		return NULL;
-	}
+	mail_index_lookup_keywords(mail->ibox->view, mail->data.seq,
+				   &keyword_indexes_arr);
 
 	keyword_indexes = array_get(&keyword_indexes_arr, &count);
 	if (count == 0) {
@@ -825,12 +821,9 @@
 	case MAIL_FETCH_UIDL_FILE_NAME:
 		return NULL;
 	case MAIL_FETCH_HEADER_MD5:
-		if (mail_index_lookup_ext(mail->trans->trans_view, data->seq,
-					  mail->ibox->md5hdr_ext_idx,
-					  &ext_data) < 0) {
-			mail_storage_set_index_error(mail->ibox);
-			return NULL;
-		}
+		mail_index_lookup_ext(mail->trans->trans_view, data->seq,
+				      mail->ibox->md5hdr_ext_idx,
+				      &ext_data, NULL);
 		if (ext_data == NULL)
 			return NULL;
 		return binary_to_hex(ext_data, 16);
@@ -930,7 +923,7 @@
 	mail->data.save_envelope = TRUE;
 }
 
-int index_mail_set_seq(struct mail *_mail, uint32_t seq)
+void index_mail_set_seq(struct mail *_mail, uint32_t seq)
 {
 	struct index_mail *mail = (struct index_mail *)_mail;
 	struct index_mail_data *data = &mail->data;
@@ -939,15 +932,11 @@
 	const struct mail_index_record *rec;
 
 	if (data->seq == seq)
-		return 0;
-
-	if (mail_index_lookup(mail->trans->trans_view, seq, &rec) < 0) {
-		mail_storage_set_index_error(mail->ibox);
-		return -1;
-	}
+		return;
 
 	index_mail_reset(mail);
 
+	rec = mail_index_lookup(mail->trans->trans_view, seq);
 	data->seq = seq;
 	data->flags = rec->flags & MAIL_FLAGS_NONRECENT;
 
@@ -1044,26 +1033,23 @@
 
 		(void)mail_get_stream(_mail, NULL, NULL);
 	}
-
-	return 0;
 }
 
-int index_mail_set_uid(struct mail *_mail, uint32_t uid)
+bool index_mail_set_uid(struct mail *_mail, uint32_t uid)
 {
 	struct index_mail *mail = (struct index_mail *)_mail;
 	uint32_t seq;
 
 	mail_index_lookup_uid_range(mail->ibox->view, uid, uid, &seq, &seq);
-	if (seq == 0) {
+	if (seq != 0) {
+		index_mail_set_seq(_mail, seq);
+		return TRUE;
+	} else {
 		index_mail_reset(mail);
 		mail->mail.mail.uid = uid;
 		mail_set_expunged(&mail->mail.mail);
-		return 0;
+		return FALSE;
 	}
-
-	if (index_mail_set_seq(_mail, seq) < 0)
-		return -1;
-	return 1;
 }
 
 void index_mail_free(struct mail *_mail)
@@ -1157,30 +1143,27 @@
 	index_mail_cache_dates(mail);
 }
 
-int index_mail_update_flags(struct mail *mail, enum modify_type modify_type,
-			    enum mail_flags flags)
+void index_mail_update_flags(struct mail *mail, enum modify_type modify_type,
+			     enum mail_flags flags)
 {
 	struct index_mail *imail = (struct index_mail *)mail;
 
 	mail_index_update_flags(imail->trans->trans, mail->seq, modify_type,
 				flags & MAIL_FLAGS_NONRECENT);
-	return 0;
 }
 
-int index_mail_update_keywords(struct mail *mail, enum modify_type modify_type,
-			       struct mail_keywords *keywords)
+void index_mail_update_keywords(struct mail *mail, enum modify_type modify_type,
+				struct mail_keywords *keywords)
 {
 	struct index_mail *imail = (struct index_mail *)mail;
 
 	mail_index_update_keywords(imail->trans->trans, mail->seq, modify_type,
 				   keywords);
-	return 0;
 }
 
-int index_mail_expunge(struct mail *mail)
+void index_mail_expunge(struct mail *mail)
 {
 	struct index_mail *imail = (struct index_mail *)mail;
 
 	mail_index_expunge(imail->trans->trans, mail->seq);
-	return 0;
 }
--- a/src/lib-storage/index/index-mail.h	Sun Aug 12 16:50:47 2007 +0300
+++ b/src/lib-storage/index/index-mail.h	Sun Aug 12 18:02:29 2007 +0300
@@ -131,8 +131,8 @@
 index_mail_alloc(struct mailbox_transaction_context *t,
 		 enum mail_fetch_field wanted_fields,
 		 struct mailbox_header_lookup_ctx *wanted_headers);
-int index_mail_set_seq(struct mail *mail, uint32_t seq);
-int index_mail_set_uid(struct mail *mail, uint32_t uid);
+void index_mail_set_seq(struct mail *mail, uint32_t seq);
+bool index_mail_set_uid(struct mail *mail, uint32_t uid);
 void index_mail_free(struct mail *mail);
 
 bool index_mail_want_parse_headers(struct index_mail *mail);
@@ -168,11 +168,11 @@
 const char *index_mail_get_special(struct mail *_mail,
 				   enum mail_fetch_field field);
 
-int index_mail_update_flags(struct mail *mail, enum modify_type modify_type,
-			    enum mail_flags flags);
-int index_mail_update_keywords(struct mail *mail, enum modify_type modify_type,
-			       struct mail_keywords *keywords);
-int index_mail_expunge(struct mail *mail);
+void index_mail_update_flags(struct mail *mail, enum modify_type modify_type,
+			     enum mail_flags flags);
+void index_mail_update_keywords(struct mail *mail, enum modify_type modify_type,
+				struct mail_keywords *keywords);
+void index_mail_expunge(struct mail *mail);
 
 uoff_t index_mail_get_cached_uoff_t(struct index_mail *mail,
 				    enum index_cache_field field);
--- a/src/lib-storage/index/index-search.c	Sun Aug 12 16:50:47 2007 +0300
+++ b/src/lib-storage/index/index-search.c	Sun Aug 12 18:02:29 2007 +0300
@@ -118,12 +118,10 @@
 		return mail_get_flags(&imail->mail.mail) & MAIL_RECENT;
 	case SEARCH_KEYWORD:
 		keywords = mail_get_keywords(&imail->mail.mail);
-		if (keywords != NULL) {
-			while (*keywords != NULL) {
-				if (strcasecmp(*keywords, value) == 0)
-					return 1;
-				keywords++;
-			}
+		while (*keywords != NULL) {
+			if (strcasecmp(*keywords, value) == 0)
+				return 1;
+			keywords++;
 		}
 		return 0;
 
@@ -961,7 +959,9 @@
 	if (ctx->sorted) {
 		/* everything searched at this point already. just returning
 		   matches from sort list */
-		return index_sort_list_next(ctx->mail_ctx.sort_program, mail);
+		if (!index_sort_list_next(ctx->mail_ctx.sort_program, mail))
+			return 0;
+		return 1;
 	}
 
 	ctx->mail = mail;
@@ -972,10 +972,7 @@
 		index_storage_search_notify(box, ctx);
 
 	while ((ret = box->v.search_next_update_seq(_ctx)) > 0) {
-		if (mail_set_seq(mail, _ctx->seq) < 0) {
-			ret = -1;
-			break;
-		}
+		mail_set_seq(mail, _ctx->seq);
 
 		t_push();
 		ret = search_match_next(ctx) ? 1 : 0;
@@ -989,11 +986,7 @@
 			if (ctx->mail_ctx.sort_program == NULL)
 				break;
 
-			if (index_sort_list_add(ctx->mail_ctx.sort_program,
-						mail) < 0) {
-				ret = -1;
-				break;
-			}
+			index_sort_list_add(ctx->mail_ctx.sort_program, mail);
 		}
 
 		if (++count == SEARCH_NONBLOCK_COUNT) {
@@ -1010,8 +1003,7 @@
 		/* finished searching the messages. now sort them and start
 		   returning the messages. */
 		ctx->sorted = TRUE;
-		if (index_sort_list_finish(ctx->mail_ctx.sort_program) < 0)
-			return -1;
+		index_sort_list_finish(ctx->mail_ctx.sort_program);
 		return index_storage_search_next_nonblock(_ctx, mail,
 							  tryagain_r);
 	}
--- a/src/lib-storage/index/index-sort.c	Sun Aug 12 16:50:47 2007 +0300
+++ b/src/lib-storage/index/index-sort.c	Sun Aug 12 18:02:29 2007 +0300
@@ -596,8 +596,8 @@
 	index_sort_add_ids(program, static_node_cmp_context.mail);
 }
 
-static int index_sort_build(struct mail_search_sort_program *program,
-			    uint32_t last_seq)
+static void index_sort_build(struct mail_search_sort_program *program,
+			     uint32_t last_seq)
 {
 	struct index_mailbox *ibox = (struct index_mailbox *)program->t->box;
 	struct mail_sort_node node;
@@ -612,9 +612,8 @@
 		for (; i < last_seq; i++) {
 			node.seq = i+1;
 
-			if (mail_index_lookup_ext(ibox->view, i+1,
-						  program->ext_id, &data) < 0)
-				return -1;
+			mail_index_lookup_ext(ibox->view, i+1, program->ext_id,
+					      &data, NULL);
 
 			node.sort_id = data == NULL ? 0 :
 				*(const uint32_t *)data;
@@ -638,7 +637,6 @@
 		break;
 	}
 	index_sort_save_ids(program, first_missing_sort_id_seq);
-	return 0;
 }
 
 static void index_sort_add_node(struct mail_search_sort_program *program,
@@ -661,15 +659,14 @@
 	program->prev_seq = node->seq;
 }
 
-int index_sort_list_add(struct mail_search_sort_program *program,
-			struct mail *mail)
+void index_sort_list_add(struct mail_search_sort_program *program,
+			 struct mail *mail)
 {
 	struct index_transaction_context *t =
 		(struct index_transaction_context *)program->t;
 	const struct mail_index_header *hdr;
 	const void *data;
 	struct mail_sort_node node;
-	int ret;
 
 	i_assert(mail->transaction == program->t);
 
@@ -680,14 +677,12 @@
 	if (program->last_sorted_seq == program->prev_seq) {
 		/* we're still on the fast path using sort_ids from the
 		   index file */
-		if (mail_index_lookup_ext(t->trans_view, mail->seq,
-					  program->ext_id, &data) < 0)
-			return -1;
-
+		mail_index_lookup_ext(t->trans_view, mail->seq,
+				      program->ext_id, &data, NULL);
 		node.sort_id = data == NULL ? 0 : *(const uint32_t *)data;
 		if (node.sort_id != 0) {
 			index_sort_add_node(program, &node);
-			return 0;
+			return;
 		}
 		i_assert(!program->sort_ids_added);
 	} else {
@@ -701,24 +696,21 @@
 		   node array. so here we just keep counting the sequences
 		   until either we skip a sequence or we reach list_finish() */
 		program->prev_seq = mail->seq;
-		return 0;
+		return;
 	}
 
 	/* we're not returning all the mails. have to create a temporary array
 	   for all the nodes so we can set all the missing sort_ids. */
 	hdr = mail_index_get_header(t->ibox->view);
 	i_array_init(&program->all_nodes, hdr->messages_count);
-	ret = index_sort_build(program, hdr->messages_count);
+	index_sort_build(program, hdr->messages_count);
 	array_free(&program->all_nodes);
-	if (ret < 0)
-		return -1;
 
 	/* add the nodes in the middle */
 	node.seq = program->last_sorted_seq + 1;
 	for (; node.seq <= program->prev_seq; node.seq++) {
-		if (mail_index_lookup_ext(t->trans_view, mail->seq,
-					  program->ext_id, &data) < 0)
-			return -1;
+		mail_index_lookup_ext(t->trans_view, mail->seq, program->ext_id,
+				      &data, NULL);
 
 		node.sort_id = *(const uint32_t *)data;
 		i_assert(node.sort_id != 0);
@@ -728,10 +720,10 @@
 
 	/* and add this last node */
 	program->sort_ids_added = TRUE;
-	return index_sort_list_add(program, mail);
+	index_sort_list_add(program, mail);
 }
 
-int index_sort_list_finish(struct mail_search_sort_program *program)
+void index_sort_list_finish(struct mail_search_sort_program *program)
 {
 	if (program->last_sorted_seq != program->prev_seq) {
 		/* nodes array contains a contiguous range of sequences from
@@ -740,8 +732,7 @@
 		i_assert(!program->sort_ids_added);
 
 		program->all_nodes = program->nodes;
-		if (index_sort_build(program, program->prev_seq) < 0)
-			return -1;
+		index_sort_build(program, program->prev_seq);
 	}
 
 	program->nodes_ptr =
@@ -749,25 +740,24 @@
 
 	if (program->reverse)
 		program->iter_idx = program->nodes_count;
-	return 0;
 }
 
-int index_sort_list_next(struct mail_search_sort_program *program,
-			 struct mail *mail)
+bool index_sort_list_next(struct mail_search_sort_program *program,
+			  struct mail *mail)
 {
 	const struct mail_sort_node *node;
 
 	if (!program->reverse) {
 		if (program->iter_idx == program->nodes_count)
-			return 0;
+			return FALSE;
 
 		node = &program->nodes_ptr[program->iter_idx++];
 	} else {
 		if (program->iter_idx == 0)
-			return 0;
+			return FALSE;
 
 		node = &program->nodes_ptr[--program->iter_idx];
 	}
 	mail_set_seq(mail, node->seq);
-	return 1;
+	return TRUE;
 }
--- a/src/lib-storage/index/index-sort.h	Sun Aug 12 16:50:47 2007 +0300
+++ b/src/lib-storage/index/index-sort.h	Sun Aug 12 18:02:29 2007 +0300
@@ -8,11 +8,11 @@
 			const enum mail_sort_type *sort_program);
 void index_sort_program_deinit(struct mail_search_sort_program **program);
 
-int index_sort_list_add(struct mail_search_sort_program *program,
-			struct mail *mail);
-int index_sort_list_finish(struct mail_search_sort_program *program);
+void index_sort_list_add(struct mail_search_sort_program *program,
+			 struct mail *mail);
+void index_sort_list_finish(struct mail_search_sort_program *program);
 
-int index_sort_list_next(struct mail_search_sort_program *program,
-			 struct mail *mail);
+bool index_sort_list_next(struct mail_search_sort_program *program,
+			  struct mail *mail);
 
 #endif
--- a/src/lib-storage/index/maildir/maildir-save.c	Sun Aug 12 16:50:47 2007 +0300
+++ b/src/lib-storage/index/maildir/maildir-save.c	Sun Aug 12 18:02:29 2007 +0300
@@ -194,8 +194,7 @@
 		}
 		dest_mail = ctx->mail;
 	}
-	if (mail_set_seq(dest_mail, ctx->seq) < 0)
-		i_unreached();
+	mail_set_seq(dest_mail, ctx->seq);
 
 	if (ctx->input == NULL) {
 		/* FIXME: copying with hardlinking. we could copy the
--- a/src/lib-storage/index/maildir/maildir-sync-index.c	Sun Aug 12 16:50:47 2007 +0300
+++ b/src/lib-storage/index/maildir/maildir-sync-index.c	Sun Aug 12 18:02:29 2007 +0300
@@ -348,12 +348,7 @@
 			continue;
 		}
 
-		if (mail_index_lookup(view, seq, &rec) < 0) {
-			mail_storage_set_index_error(&mbox->ibox);
-			ret = -1;
-			break;
-		}
-
+		rec = mail_index_lookup(view, seq);
 		if (uid > rec->uid) {
 			/* expunged */
 			mail_index_expunge(trans, seq);
@@ -422,11 +417,7 @@
 		}
 
 		/* update keywords if they have changed */
-		if (mail_index_lookup_keywords(view, seq, &idx_keywords) < 0) {
-			mail_storage_set_index_error(&mbox->ibox);
-			ret = -1;
-			break;
-		}
+		mail_index_lookup_keywords(view, seq, &idx_keywords);
 		if (!index_keyword_array_cmp(&ctx->keywords, &idx_keywords)) {
 			struct mail_keywords *kw;
 
@@ -512,13 +503,14 @@
 	const char *root_dir, *new_dir, *cur_dir;
 	struct stat st;
 	uint32_t ext_id;
+	bool expunged;
 
 	ext_id = maildir_list_get_ext_id(mbox->storage, list_view);
-	if (mail_index_lookup_ext(list_view, seq, ext_id, &data) <= 0)
-		return -1;
+	mail_index_lookup_ext(list_view, seq, ext_id, &data, &expunged);
 	rec = data;
 
-	if (rec == NULL || rec->new_mtime == 0 || rec->cur_mtime == 0) {
+	if (rec == NULL || expunged ||
+	    rec->new_mtime == 0 || rec->cur_mtime == 0) {
 		/* doesn't exist, not synced or dirty-synced */
 		return 1;
 	}
@@ -560,12 +552,14 @@
 	struct maildir_list_index_record new_rec;
 	const void *data;
 	uint32_t ext_id;
+	bool expunged;
 
 	/* get the current record */
 	list_view = mail_index_transaction_get_view(trans);
 	ext_id = maildir_list_get_ext_id(mbox->storage, list_view);
-	if (mail_index_lookup_ext(list_view, seq, ext_id, &data) <= 0)
-		return -1;
+	mail_index_lookup_ext(list_view, seq, ext_id, &data, &expunged);
+	if (expunged)
+		return 0;
 	old_rec = data;
 
 	memset(&new_rec, 0, sizeof(new_rec));
--- a/src/lib-storage/index/mbox/mbox-file.c	Sun Aug 12 16:50:47 2007 +0300
+++ b/src/lib-storage/index/mbox/mbox-file.c	Sun Aug 12 18:02:29 2007 +0300
@@ -147,14 +147,9 @@
 
 	*deleted_r = FALSE;
 
-	ret = mail_index_lookup_ext(view, seq, mbox->mbox_ext_idx, &data);
-	if (ret <= 0) {
-		if (ret < 0)
-			mail_storage_set_index_error(&mbox->ibox);
-		else
-			*deleted_r = TRUE;
+	mail_index_lookup_ext(view, seq, mbox->mbox_ext_idx, &data, deleted_r);
+	if (*deleted_r)
 		return -1;
-	}
 
 	if (data == NULL) {
 		mail_storage_set_critical(&mbox->storage->storage,
@@ -185,9 +180,8 @@
 
 	if (mbox->mbox_sync_dirty) {
 		/* we're dirty - make sure this is the correct mail */
-		ret = mbox_sync_parse_match_mail(mbox, view, seq);
-		if (ret <= 0)
-			return ret;
+		if (!mbox_sync_parse_match_mail(mbox, view, seq))
+			return 0;
 
 		ret = istream_raw_mbox_seek(mbox->mbox_stream, offset);
 		i_assert(ret == 0);
--- a/src/lib-storage/index/mbox/mbox-save.c	Sun Aug 12 16:50:47 2007 +0300
+++ b/src/lib-storage/index/mbox/mbox-save.c	Sun Aug 12 18:02:29 2007 +0300
@@ -453,8 +453,7 @@
 				ctx->mail = index_mail_alloc(_t, 0, NULL);
 			dest_mail = ctx->mail;
 		}
-		if (mail_set_seq(dest_mail, ctx->seq) < 0)
-			i_unreached();
+		mail_set_seq(dest_mail, ctx->seq);
 	}
 	mbox_save_append_flag_headers(ctx->headers, save_flags);
 	mbox_save_append_keyword_headers(ctx, keywords);
--- a/src/lib-storage/index/mbox/mbox-sync-parse.c	Sun Aug 12 16:50:47 2007 +0300
+++ b/src/lib-storage/index/mbox/mbox-sync-parse.c	Sun Aug 12 18:02:29 2007 +0300
@@ -544,8 +544,8 @@
 	ctx->body_offset = input->v_offset;
 }
 
-int mbox_sync_parse_match_mail(struct mbox_mailbox *mbox,
-			       struct mail_index_view *view, uint32_t seq)
+bool mbox_sync_parse_match_mail(struct mbox_mailbox *mbox,
+				struct mail_index_view *view, uint32_t seq)
 {
         struct mbox_sync_mail_context ctx;
 	struct message_header_parser_ctx *hdr_ctx;
@@ -600,11 +600,8 @@
 	/* match by MD5 sum */
 	mbox->mbox_save_md5 = TRUE;
 
-	if (mail_index_lookup_ext(view, seq, mbox->ibox.md5hdr_ext_idx,
-				  &data) < 0) {
-		mail_storage_set_index_error(&mbox->ibox);
-		return -1;
-	}
+	mail_index_lookup_ext(view, seq, mbox->ibox.md5hdr_ext_idx,
+			      &data, NULL);
 	return data == NULL ? 0 :
 		memcmp(data, ctx.hdr_md5_sum, 16) == 0;
 }
--- a/src/lib-storage/index/mbox/mbox-sync-private.h	Sun Aug 12 16:50:47 2007 +0300
+++ b/src/lib-storage/index/mbox/mbox-sync-private.h	Sun Aug 12 18:02:29 2007 +0300
@@ -152,8 +152,8 @@
 
 void mbox_sync_parse_next_mail(struct istream *input,
 			       struct mbox_sync_mail_context *ctx);
-int mbox_sync_parse_match_mail(struct mbox_mailbox *mbox,
-			       struct mail_index_view *view, uint32_t seq);
+bool mbox_sync_parse_match_mail(struct mbox_mailbox *mbox,
+				struct mail_index_view *view, uint32_t seq);
 
 void mbox_sync_update_header(struct mbox_sync_mail_context *ctx);
 void mbox_sync_update_header_from(struct mbox_sync_mail_context *ctx,
--- a/src/lib-storage/index/mbox/mbox-sync.c	Sun Aug 12 16:50:47 2007 +0300
+++ b/src/lib-storage/index/mbox/mbox-sync.c	Sun Aug 12 18:02:29 2007 +0300
@@ -182,30 +182,23 @@
 	return 0;
 }
 
-static int
+static bool
 mbox_sync_read_index_rec(struct mbox_sync_context *sync_ctx,
 			 uint32_t uid, const struct mail_index_record **rec_r)
 {
         const struct mail_index_record *rec = NULL;
 	uint32_t messages_count;
-	int ret = 0;
+	bool ret = FALSE;
 
 	if (sync_ctx->index_reset) {
 		*rec_r = NULL;
-		return 1;
+		return TRUE;
 	}
 
 	messages_count =
 		mail_index_view_get_messages_count(sync_ctx->sync_view);
 	while (sync_ctx->idx_seq <= messages_count) {
-		ret = mail_index_lookup(sync_ctx->sync_view,
-					sync_ctx->idx_seq, &rec);
-		if (ret < 0) {
-			mail_storage_set_index_error(&sync_ctx->mbox->ibox);
-			return -1;
-		}
-		i_assert(ret != 0); /* we should be looking at head index */
-
+		rec = mail_index_lookup(sync_ctx->sync_view, sync_ctx->idx_seq);
 		if (uid <= rec->uid)
 			break;
 
@@ -222,54 +215,43 @@
 			"(UID %u < %u, seq=%u, idx_msgs=%u)",
 			sync_ctx->mbox->path, uid, sync_ctx->idx_next_uid,
 			sync_ctx->seq, messages_count);
-		ret = 0; rec = NULL;
+		ret = FALSE; rec = NULL;
 	} else if (rec != NULL && rec->uid != uid) {
 		/* new UID in the middle of the mailbox - shouldn't happen */
 		mbox_sync_set_critical(sync_ctx,
 			"mbox sync: UID inserted in the middle of mailbox %s "
 			"(%u > %u, seq=%u, idx_msgs=%u)", sync_ctx->mbox->path,
 			rec->uid, uid, sync_ctx->seq, messages_count);
-		ret = 0; rec = NULL;
+		ret = FALSE; rec = NULL;
 	} else {
-		ret = 1;
+		ret = TRUE;
 	}
 
 	*rec_r = rec;
 	return ret;
 }
 
-static int mbox_sync_find_index_md5(struct mbox_sync_context *sync_ctx,
-				    unsigned char hdr_md5_sum[],
-				    const struct mail_index_record **rec_r)
+static void mbox_sync_find_index_md5(struct mbox_sync_context *sync_ctx,
+				     unsigned char hdr_md5_sum[],
+				     const struct mail_index_record **rec_r)
 {
         const struct mail_index_record *rec = NULL;
 	uint32_t messages_count;
 	const void *data;
-	int ret;
 
 	if (sync_ctx->index_reset) {
 		*rec_r = NULL;
-		return 0;
+		return;
 	}
 
 	messages_count =
 		mail_index_view_get_messages_count(sync_ctx->sync_view);
 	while (sync_ctx->idx_seq <= messages_count) {
-		ret = mail_index_lookup(sync_ctx->sync_view,
-					sync_ctx->idx_seq, &rec);
-		if (ret < 0) {
-			mail_storage_set_index_error(&sync_ctx->mbox->ibox);
-			return -1;
-		}
-
-		if (mail_index_lookup_ext(sync_ctx->sync_view,
-					  sync_ctx->idx_seq,
-					  sync_ctx->mbox->ibox.md5hdr_ext_idx,
-					  &data) < 0) {
-			mail_storage_set_index_error(&sync_ctx->mbox->ibox);
-			return -1;
-		}
-
+		rec = mail_index_lookup(sync_ctx->sync_view, sync_ctx->idx_seq);
+		mail_index_lookup_ext(sync_ctx->sync_view,
+				      sync_ctx->idx_seq,
+				      sync_ctx->mbox->ibox.md5hdr_ext_idx,
+				      &data, NULL);
 		if (data != NULL && memcmp(data, hdr_md5_sum, 16) == 0)
 			break;
 
@@ -280,10 +262,9 @@
 	}
 
 	*rec_r = rec;
-	return 0;
 }
 
-static int
+static void
 mbox_sync_update_from_offset(struct mbox_sync_context *sync_ctx,
                              struct mbox_sync_mail *mail,
 			     bool nocheck)
@@ -293,23 +274,17 @@
 
 	if (!nocheck) {
 		/* see if from_offset needs updating */
-		if (mail_index_lookup_ext(sync_ctx->sync_view,
-					  sync_ctx->idx_seq,
-					  sync_ctx->mbox->mbox_ext_idx,
-					  &data) < 0) {
-			mail_storage_set_index_error(&sync_ctx->mbox->ibox);
-			return -1;
-		}
-
+		mail_index_lookup_ext(sync_ctx->sync_view, sync_ctx->idx_seq,
+				      sync_ctx->mbox->mbox_ext_idx,
+				      &data, NULL);
 		if (data != NULL &&
 		    *((const uint64_t *)data) == mail->from_offset)
-			return 0;
+			return;
 	}
 
 	offset = mail->from_offset;
 	mail_index_update_ext(sync_ctx->t, sync_ctx->idx_seq,
 			      sync_ctx->mbox->mbox_ext_idx, &offset, NULL);
-	return 0;
 }
 
 static void
@@ -327,30 +302,25 @@
 	mail_index_keywords_free(&keywords);
 }
 
-static int
+static void
 mbox_sync_update_md5_if_changed(struct mbox_sync_mail_context *mail_ctx)
 {
         struct mbox_sync_context *sync_ctx = mail_ctx->sync_ctx;
 	const void *ext_data;
 
-	if (mail_index_lookup_ext(sync_ctx->sync_view, sync_ctx->idx_seq,
-				  sync_ctx->mbox->ibox.md5hdr_ext_idx,
-				  &ext_data) < 0) {
-		mail_storage_set_index_error(&sync_ctx->mbox->ibox);
-		return -1;
-	}
-
+	mail_index_lookup_ext(sync_ctx->sync_view, sync_ctx->idx_seq,
+			      sync_ctx->mbox->ibox.md5hdr_ext_idx,
+			      &ext_data, NULL);
 	if (ext_data == NULL ||
 	    memcmp(mail_ctx->hdr_md5_sum, ext_data, 16) != 0) {
 		mail_index_update_ext(sync_ctx->t, sync_ctx->idx_seq,
 				      sync_ctx->mbox->ibox.md5hdr_ext_idx,
 				      mail_ctx->hdr_md5_sum, NULL);
 	}
-	return 0;
 }
 
-static int mbox_sync_update_index(struct mbox_sync_mail_context *mail_ctx,
-				  const struct mail_index_record *rec)
+static void mbox_sync_update_index(struct mbox_sync_mail_context *mail_ctx,
+				   const struct mail_index_record *rec)
 {
 	struct mbox_sync_context *sync_ctx = mail_ctx->sync_ctx;
 	struct mbox_sync_mail *mail = &mail_ctx->mail;
@@ -389,14 +359,9 @@
 		/* get old keywords */
 		t_push();
 		t_array_init(&idx_mail.keywords, 32);
-		if (mail_index_lookup_keywords(sync_ctx->sync_view,
-					       sync_ctx->idx_seq,
-					       &idx_mail.keywords) < 0) {
-			mail_storage_set_index_error(&sync_ctx->mbox->ibox);
-			t_pop();
-			return -1;
-		}
-
+		mail_index_lookup_keywords(sync_ctx->sync_view,
+					   sync_ctx->idx_seq,
+					   &idx_mail.keywords);
 		index_sync_changes_apply(sync_ctx->sync_changes,
 					 sync_ctx->mail_keyword_pool,
 					 &idx_mail.flags, &idx_mail.keywords,
@@ -440,10 +405,8 @@
 		t_pop();
 
 		/* see if we need to update md5 sum. */
-		if (sync_ctx->mbox->mbox_save_md5 != 0) {
-			if (mbox_sync_update_md5_if_changed(mail_ctx) < 0)
-				return -1;
-		}
+		if (sync_ctx->mbox->mbox_save_md5 != 0)
+			mbox_sync_update_md5_if_changed(mail_ctx);
 	}
 
 	/* mail_ctx->recent is TRUE always if Status: O doesn't exist in the
@@ -458,10 +421,8 @@
 	   rewriting would just move it anyway. */
 	if (sync_ctx->need_space_seq == 0) {
 		bool nocheck = rec == NULL || sync_ctx->expunged_space > 0;
-		if (mbox_sync_update_from_offset(sync_ctx, mail, nocheck) < 0)
-			return -1;
+		mbox_sync_update_from_offset(sync_ctx, mail, nocheck);
 	}
-	return 0;
 }
 
 static int mbox_read_from_line(struct mbox_sync_mail_context *ctx)
@@ -1031,9 +992,8 @@
 
 		rec = NULL; ret = 1;
 		if (uid != 0) {
-			ret = mbox_sync_read_index_rec(sync_ctx, uid, &rec);
-			if (ret < 0)
-				return -1;
+			if (!mbox_sync_read_index_rec(sync_ctx, uid, &rec))
+				ret = 0;
 		}
 
 		if (ret == 0) {
@@ -1048,11 +1008,8 @@
 			   able to write X-UIDs. */
 			sync_ctx->mbox->mbox_save_md5 = TRUE;
 
-			if (mbox_sync_find_index_md5(sync_ctx,
-						     mail_ctx->hdr_md5_sum,
-						     &rec) < 0)
-				return -1;
-
+			mbox_sync_find_index_md5(sync_ctx,
+						 mail_ctx->hdr_md5_sum, &rec);
 			if (rec != NULL)
 				uid = mail_ctx->mail.uid = rec->uid;
 		}
@@ -1113,10 +1070,8 @@
 		}
 
 		if (!mail_ctx->mail.pseudo) {
-			if (!expunged) {
-				if (mbox_sync_update_index(mail_ctx, rec) < 0)
-					return -1;
-			}
+			if (!expunged)
+				mbox_sync_update_index(mail_ctx, rec);
 			sync_ctx->idx_seq++;
 		}
 
--- a/src/lib-storage/list/index-mailbox-list-sync.c	Sun Aug 12 16:50:47 2007 +0300
+++ b/src/lib-storage/list/index-mailbox-list-sync.c	Sun Aug 12 18:02:29 2007 +0300
@@ -139,6 +139,7 @@
 	const void *data;
 	uint32_t seq, *ext_id_p, *counter_p;
 	unsigned int i;
+	bool expunged;
 	int ret;
 
 	memset(status, 0, sizeof(*status));
@@ -151,16 +152,18 @@
 	ilist = INDEX_LIST_CONTEXT(list);
 	for (i = 0; index_list_map[i].name != NULL; i++) {
 		ext_id_p = PTR_OFFSET(ilist, index_list_map[i].eid_offset);
-		ret = mail_index_lookup_ext(view, seq, *ext_id_p, &data);
-		if (ret <= 0 || data == NULL)
+		mail_index_lookup_ext(view, seq, *ext_id_p, &data, &expunged);
+		if (expunged || data == NULL) {
+			ret = 0;
 			break;
+		}
 
 		counter_p = PTR_OFFSET(status, index_list_map[i].status_offset);
 		*counter_p = *(const uint32_t *)data;
 	}
 
 	mail_index_view_close(&view);
-	return 1;
+	return ret;
 }
 
 static void
@@ -225,7 +228,8 @@
 	const uint32_t *counter_p;
 	uint32_t *ext_id_p;
 	unsigned int i;
-	int ret = 1;
+	bool expunged;
+	int ret = 0;
 
 	trans = mail_index_transaction_begin(view,
 					MAIL_INDEX_TRANSACTION_FLAG_EXTERNAL);
@@ -233,9 +237,11 @@
 	/* update counters */
 	for (i = 0; index_list_map[i].name != NULL; i++) {
 		ext_id_p = PTR_OFFSET(ilist, index_list_map[i].eid_offset);
-		ret = mail_index_lookup_ext(view, seq, *ext_id_p, &data);
-		if (ret <= 0)
+		mail_index_lookup_ext(view, seq, *ext_id_p, &data, &expunged);
+		if (expunged) {
+			ret = -1;
 			break;
+		}
 
 		counter_p = CONST_PTR_OFFSET(status,
 					     index_list_map[i].status_offset);
@@ -248,7 +254,7 @@
 
 	if (box->v.list_index_update_sync(box, trans, seq) < 0)
 		ret = -1;
-	if (ret <= 0) {
+	if (ret < 0) {
 		mail_index_transaction_rollback(&trans);
 		return -1;
 	}
--- a/src/lib-storage/list/index-mailbox-list.c	Sun Aug 12 16:50:47 2007 +0300
+++ b/src/lib-storage/list/index-mailbox-list.c	Sun Aug 12 18:02:29 2007 +0300
@@ -304,9 +304,7 @@
 		return -1;
 	}
 
-	if (mail_index_lookup(ctx->mail_view, seq, &rec) < 0)
-		return -1;
-
+	rec = mail_index_lookup(ctx->mail_view, seq);
 	*flags_r = index_mailbox_list_index_flags_translate(rec->flags);
 	return 0;
 }
--- a/src/lib-storage/mail-storage-private.h	Sun Aug 12 16:50:47 2007 +0300
+++ b/src/lib-storage/mail-storage-private.h	Sun Aug 12 18:02:29 2007 +0300
@@ -196,8 +196,8 @@
 
 struct mail_vfuncs {
 	void (*free)(struct mail *mail);
-	int (*set_seq)(struct mail *mail, uint32_t seq);
-	int (*set_uid)(struct mail *mail, uint32_t uid);
+	void (*set_seq)(struct mail *mail, uint32_t seq);
+	bool (*set_uid)(struct mail *mail, uint32_t uid);
 
 	enum mail_flags (*get_flags)(struct mail *mail);
 	const char *const *(*get_keywords)(struct mail *mail);
@@ -223,12 +223,11 @@
 	const char *(*get_special)(struct mail *mail,
 				   enum mail_fetch_field field);
 
-	int (*update_flags)(struct mail *mail, enum modify_type modify_type,
-			    enum mail_flags flags);
-	int (*update_keywords)(struct mail *mail, enum modify_type modify_type,
-			       struct mail_keywords *keywords);
-
-	int (*expunge)(struct mail *mail);
+	void (*update_flags)(struct mail *mail, enum modify_type modify_type,
+			     enum mail_flags flags);
+	void (*update_keywords)(struct mail *mail, enum modify_type modify_type,
+				struct mail_keywords *keywords);
+	void (*expunge)(struct mail *mail);
 };
 
 union mail_module_context {
--- a/src/lib-storage/mail-storage.h	Sun Aug 12 16:50:47 2007 +0300
+++ b/src/lib-storage/mail-storage.h	Sun Aug 12 18:02:29 2007 +0300
@@ -401,9 +401,10 @@
 			enum mail_fetch_field wanted_fields,
 			struct mailbox_header_lookup_ctx *wanted_headers);
 void mail_free(struct mail **mail);
-int mail_set_seq(struct mail *mail, uint32_t seq);
-/* Returns -1 if error, 0 if UID has already been expunged, 1 if ok */
-int mail_set_uid(struct mail *mail, uint32_t uid);
+void mail_set_seq(struct mail *mail, uint32_t seq);
+/* Returns TRUE if successful, FALSE if message doesn't exist.
+   mail_*() functions shouldn't be called if FALSE is returned. */
+bool mail_set_uid(struct mail *mail, uint32_t uid);
 
 /* Get the Date-header of the mail. Timezone is in minutes.
    Returns (time_t)-1 if error occurred, 0 if field wasn't found or
@@ -445,13 +446,13 @@
 const char *mail_get_special(struct mail *mail, enum mail_fetch_field field);
 
 /* Update message flags. */
-int mail_update_flags(struct mail *mail, enum modify_type modify_type,
-		      enum mail_flags flags);
+void mail_update_flags(struct mail *mail, enum modify_type modify_type,
+		       enum mail_flags flags);
 /* Update message keywords. */
-int mail_update_keywords(struct mail *mail, enum modify_type modify_type,
-			 struct mail_keywords *keywords);
+void mail_update_keywords(struct mail *mail, enum modify_type modify_type,
+			  struct mail_keywords *keywords);
 
 /* Expunge this message. Sequence numbers don't change until commit. */
-int mail_expunge(struct mail *mail);
+void mail_expunge(struct mail *mail);
 
 #endif
--- a/src/lib-storage/mail.c	Sun Aug 12 16:50:47 2007 +0300
+++ b/src/lib-storage/mail.c	Sun Aug 12 18:02:29 2007 +0300
@@ -19,14 +19,14 @@
 	*mail = NULL;
 }
 
-int mail_set_seq(struct mail *mail, uint32_t seq)
+void mail_set_seq(struct mail *mail, uint32_t seq)
 {
 	struct mail_private *p = (struct mail_private *)mail;
 
-	return p->v.set_seq(mail, seq);
+	p->v.set_seq(mail, seq);
 }
 
-int mail_set_uid(struct mail *mail, uint32_t uid)
+bool mail_set_uid(struct mail *mail, uint32_t uid)
 {
 	struct mail_private *p = (struct mail_private *)mail;
 
@@ -142,27 +142,27 @@
 	return p->v.get_special(mail, field);
 }
 
-int mail_update_flags(struct mail *mail, enum modify_type modify_type,
-		      enum mail_flags flags)
+void mail_update_flags(struct mail *mail, enum modify_type modify_type,
+		       enum mail_flags flags)
 {
 	struct mail_private *p = (struct mail_private *)mail;
 
 	return p->v.update_flags(mail, modify_type, flags);
 }
 
-int mail_update_keywords(struct mail *mail, enum modify_type modify_type,
-			 struct mail_keywords *keywords)
+void mail_update_keywords(struct mail *mail, enum modify_type modify_type,
+			  struct mail_keywords *keywords)
 {
 	struct mail_private *p = (struct mail_private *)mail;
 
-	return p->v.update_keywords(mail, modify_type, keywords);
+	p->v.update_keywords(mail, modify_type, keywords);
 }
 
-int mail_expunge(struct mail *mail)
+void mail_expunge(struct mail *mail)
 {
 	struct mail_private *p = (struct mail_private *)mail;
 
-	return p->v.expunge(mail);
+	p->v.expunge(mail);
 }
 
 void mail_set_expunged(struct mail *mail)
--- a/src/plugins/acl/acl-mailbox.c	Sun Aug 12 16:50:47 2007 +0300
+++ b/src/plugins/acl/acl-mailbox.c	Sun Aug 12 18:02:29 2007 +0300
@@ -23,7 +23,12 @@
 	unsigned int save_hack:1;
 };
 
+struct acl_transaction_context {
+	union mailbox_transaction_module_context module_ctx;
+};
+
 static MODULE_CONTEXT_DEFINE_INIT(acl_mail_module, &mail_module_register);
+static struct acl_transaction_context acl_transaction_failure;
 
 static int mailbox_acl_right_lookup(struct mailbox *box, unsigned int right_idx)
 {
@@ -111,7 +116,13 @@
 	return 0;
 }
 
-static int
+static void acl_transaction_set_failure(struct mailbox_transaction_context *t)
+{
+	MODULE_CONTEXT_SET(t, acl_storage_module,
+			   &acl_transaction_failure);
+}
+
+static void
 acl_mail_update_flags(struct mail *_mail, enum modify_type modify_type,
 		      enum mail_flags flags)
 {
@@ -120,8 +131,10 @@
 	bool acl_flags, acl_flag_seen, acl_flag_del;
 
 	if (acl_get_write_rights(_mail->box, &acl_flags, &acl_flag_seen,
-				 &acl_flag_del) < 0)
-		return -1;
+				 &acl_flag_del) < 0) {
+		acl_transaction_set_failure(_mail->transaction);
+		return;
+	}
 
 	if (modify_type != MODIFY_REPLACE) {
 		/* adding/removing flags. just remove the disallowed
@@ -136,21 +149,19 @@
 		/* we don't have permission to replace all the flags. */
 		if (!acl_flags && !acl_flag_seen && !acl_flag_del) {
 			/* no flag changes allowed. ignore silently. */
-			return 0;
+			return;
 		}
 
 		/* handle this by first removing the allowed flags and
 		   then adding the allowed flags */
-		if (acl_mail_update_flags(_mail, MODIFY_REMOVE,
-					  ~flags) < 0)
-			return -1;
-		return acl_mail_update_flags(_mail, MODIFY_ADD, flags);
+		acl_mail_update_flags(_mail, MODIFY_REMOVE, ~flags);
+		acl_mail_update_flags(_mail, MODIFY_ADD, flags);
 	}
 
-	return amail->super.update_flags(_mail, modify_type, flags);
+	amail->super.update_flags(_mail, modify_type, flags);
 }
 
-static int
+static void
 acl_mail_update_keywords(struct mail *_mail, enum modify_type modify_type,
 			 struct mail_keywords *keywords)
 {
@@ -161,13 +172,15 @@
 	ret = mailbox_acl_right_lookup(_mail->box, ACL_STORAGE_RIGHT_WRITE);
 	if (ret <= 0) {
 		/* if we don't have permission, just silently return success. */
-		return ret;
+		if (ret < 0)
+			acl_transaction_set_failure(_mail->transaction);
+		return;
 	}
 
-	return amail->super.update_keywords(_mail, modify_type, keywords);
+	amail->super.update_keywords(_mail, modify_type, keywords);
 }
 
-static int acl_mail_expunge(struct mail *_mail)
+static void acl_mail_expunge(struct mail *_mail)
 {
 	struct mail_private *mail = (struct mail_private *)_mail;
 	union mail_module_context *amail = ACL_MAIL_CONTEXT(mail);
@@ -178,10 +191,12 @@
 		/* if we don't have permission, silently return success so
 		   users won't see annoying error messages in case their
 		   clients try automatic expunging. */
-		return ret;
+		if (ret < 0)
+			acl_transaction_set_failure(_mail->transaction);
+		return;
 	}
 
-	return amail->super.expunge(_mail);
+	amail->super.expunge(_mail);
 }
 
 static struct mail *
@@ -263,6 +278,23 @@
 	return abox->module_ctx.super.copy(t, mail, flags, keywords, dest_mail);
 }
 
+static int
+acl_transaction_commit(struct mailbox_transaction_context *ctx,
+		       enum mailbox_sync_flags flags, uint32_t *uid_validity_r,
+		       uint32_t *first_saved_uid_r, uint32_t *last_saved_uid_r)
+{
+	struct acl_mailbox *abox = ACL_CONTEXT(ctx->box);
+	void *at = ACL_CONTEXT(ctx);
+
+	if (at != NULL) {
+		abox->module_ctx.super.transaction_rollback(ctx);
+		return -1;
+	}
+
+	return abox->module_ctx.super.
+		transaction_commit(ctx, flags, uid_validity_r,
+				   first_saved_uid_r, last_saved_uid_r);
+}
 struct mailbox *acl_mailbox_open_box(struct mailbox *box)
 {
 	struct acl_mail_storage *astorage = ACL_CONTEXT(box->storage);
@@ -280,6 +312,7 @@
 	box->v.mail_alloc = acl_mail_alloc;
 	box->v.save_init = acl_save_init;
 	box->v.copy = acl_copy;
+	box->v.transaction_commit = acl_transaction_commit;
 	MODULE_CONTEXT_SET(box, acl_storage_module, abox);
 	return box;
 }
--- a/src/plugins/expire/expire-plugin.c	Sun Aug 12 16:50:47 2007 +0300
+++ b/src/plugins/expire/expire-plugin.c	Sun Aug 12 18:02:29 2007 +0300
@@ -62,41 +62,30 @@
 	return t;
 }
 
-static int first_nonexpunged_timestamp(struct mailbox_transaction_context *_t,
-				       time_t *stamp_r)
+static void first_nonexpunged_timestamp(struct mailbox_transaction_context *_t,
+					time_t *stamp_r)
 {
 	struct index_transaction_context *t =
 		(struct index_transaction_context *)_t;
 	struct expire_transaction_context *xt = EXPIRE_CONTEXT(_t);
 	struct mail_index_view *view = t->trans_view;
 	const struct mail_index_header *hdr;
-	const struct mail_index_record *rec;
 	uint32_t seq;
-	int ret = 0;
 
 	/* find the first non-expunged mail. we're here because the first
 	   mail was expunged, so don't bother checking it. */
 	hdr = mail_index_get_header(view);
 	for (seq = 2; seq <= hdr->messages_count; seq++) {
-		ret = mail_index_lookup(view, seq, &rec);
-		if (ret != 0)
-			break;
-	}
-	if (ret < 0) {
-		*stamp_r = 0;
-		return -1;
+		if (!mail_index_is_expunged(view, seq)) {
+			mail_set_seq(xt->mail, seq);
+			*stamp_r = mail_get_save_date(xt->mail);
+			if (*stamp_r != (time_t)-1)
+				return;
+		}
 	}
 
-	if (ret > 0) {
-		mail_set_seq(xt->mail, seq);
-		*stamp_r = mail_get_save_date(xt->mail);
-		if (*stamp_r == (time_t)-1)
-			return -1;
-	} else {
-		/* everything expunged */
-		*stamp_r = 0;
-	}
-	return 0;
+	/* everything expunged */
+	*stamp_r = 0;
 }
 
 static int
@@ -119,7 +108,8 @@
 
 	if (xt->first_expunged) {
 		/* first mail expunged. dict needs updating. */
-		update_dict = first_nonexpunged_timestamp(t, &new_stamp) == 0;
+		first_nonexpunged_timestamp(t, &new_stamp);
+		update_dict = TRUE;
 	} else {
 		/* saved new mails. dict needs to be updated only if this is
 		   the first mail in the database */
@@ -164,21 +154,18 @@
 	i_free(xt);
 }
 
-static int expire_mail_expunge(struct mail *_mail)
+static void expire_mail_expunge(struct mail *_mail)
 {
 	struct mail_private *mail = (struct mail_private *)_mail;
 	union mail_module_context *xpr_mail = EXPIRE_MAIL_CONTEXT(mail);
 	struct expire_transaction_context *xt =
 		EXPIRE_CONTEXT(_mail->transaction);
 
-	if (xpr_mail->super.expunge(_mail) < 0)
-		return -1;
-
 	if (_mail->seq == 1) {
 		/* first mail expunged, database needs to be updated */
 		xt->first_expunged = TRUE;
 	}
-	return 0;
+	xpr_mail->super.expunge(_mail);
 }
 
 static struct mail *
--- a/src/plugins/expire/expire-tool.c	Sun Aug 12 16:50:47 2007 +0300
+++ b/src/plugins/expire/expire-tool.c	Sun Aug 12 18:02:29 2007 +0300
@@ -64,7 +64,7 @@
 	struct mail_search_arg search_arg;
 	struct mail *mail;
 	time_t now, save_time;
-	int ret = 0;
+	int ret;
 
 	*oldest_r = 0;
 
@@ -90,7 +90,7 @@
 	mail = mail_alloc(t, 0, NULL);
 
 	now = time(NULL);
-	while (mailbox_search_next(search_ctx, mail) > 0) {
+	while ((ret = mailbox_search_next(search_ctx, mail)) > 0) {
 		save_time = mail_get_save_date(mail);
 		if (save_time == (time_t)-1) {
 			/* maybe just got expunged. anyway try again later. */
@@ -98,12 +98,9 @@
 			break;
 		}
 
-		if (save_time + expire_secs <= now) {
-			if (mail_expunge(mail) < 0) {
-				ret = -1;
-				break;
-			}
-		} else {
+		if (save_time + expire_secs <= now)
+			mail_expunge(mail);
+		else {
 			/* first non-expunged one. */
 			*oldest_r = save_time;
 			break;
--- a/src/plugins/fts/fts-storage.c	Sun Aug 12 16:50:47 2007 +0300
+++ b/src/plugins/fts/fts-storage.c	Sun Aug 12 18:02:29 2007 +0300
@@ -679,22 +679,20 @@
 	return fbox->module_ctx.super.search_deinit(ctx);
 }
 
-static int fts_mail_expunge(struct mail *_mail)
+static void fts_mail_expunge(struct mail *_mail)
 {
 	struct mail_private *mail = (struct mail_private *)_mail;
 	union mail_module_context *fmail = FTS_MAIL_CONTEXT(mail);
 	struct fts_mailbox *fbox = FTS_CONTEXT(_mail->box);
 	struct fts_transaction_context *ft = FTS_CONTEXT(_mail->transaction);
 
-	if (fmail->super.expunge(_mail) < 0)
-		return -1;
-
 	ft->expunges = TRUE;
 	if (fbox->backend_exact != NULL)
 		fts_backend_expunge(fbox->backend_exact, _mail);
 	if (fbox->backend_fast != NULL)
 		fts_backend_expunge(fbox->backend_fast, _mail);
-	return 0;
+
+	fmail->super.expunge(_mail);
 }
 
 static struct mail *
--- a/src/plugins/lazy-expunge/lazy-expunge-plugin.c	Sun Aug 12 16:50:47 2007 +0300
+++ b/src/plugins/lazy-expunge/lazy-expunge-plugin.c	Sun Aug 12 18:02:29 2007 +0300
@@ -45,6 +45,8 @@
 
 	ARRAY_TYPE(seq_range) expunge_seqs;
 	struct mailbox *expunge_box;
+
+	bool failed;
 };
 
 const char *lazy_expunge_plugin_version = PACKAGE_VERSION;
@@ -91,7 +93,7 @@
 	return box;
 }
 
-static int lazy_expunge_mail_expunge(struct mail *_mail)
+static void lazy_expunge_mail_expunge(struct mail *_mail)
 {
 	struct lazy_expunge_transaction *lt =
 		LAZY_EXPUNGE_CONTEXT(_mail->transaction);
@@ -104,12 +106,12 @@
 		if (lt->expunge_box == NULL) {
 			mail_storage_set_critical(_mail->box->storage,
 				"lazy_expunge: Couldn't open expunge mailbox");
-			return -1;
+			lt->failed = TRUE;
+			return;
 		}
 	}
 
 	seq_range_array_add(&lt->expunge_seqs, 32, _mail->uid);
-	return 0;
 }
 
 static struct mailbox_transaction_context *
@@ -206,19 +208,24 @@
 
 static int
 lazy_expunge_transaction_commit(struct mailbox_transaction_context *ctx,
-				  enum mailbox_sync_flags flags,
-				  uint32_t *uid_validity_r,
-				  uint32_t *first_saved_uid_r,
-				  uint32_t *last_saved_uid_r)
+				enum mailbox_sync_flags flags,
+				uint32_t *uid_validity_r,
+				uint32_t *first_saved_uid_r,
+				uint32_t *last_saved_uid_r)
 {
 	union mailbox_module_context *mbox = LAZY_EXPUNGE_CONTEXT(ctx->box);
 	struct lazy_expunge_transaction *lt = LAZY_EXPUNGE_CONTEXT(ctx);
 	struct mailbox *srcbox = ctx->box;
 	int ret;
 
-	ret = mbox->super.transaction_commit(ctx, flags, uid_validity_r,
-					     first_saved_uid_r,
-					     last_saved_uid_r);
+	if (lt->failed) {
+		mbox->super.transaction_rollback(ctx);
+		ret = -1;
+	} else {
+		ret = mbox->super.transaction_commit(ctx, flags, uid_validity_r,
+						     first_saved_uid_r,
+						     last_saved_uid_r);
+	}
 
 	if (ret == 0 && array_is_created(&lt->expunge_seqs))
 		ret = lazy_expunge_move_expunges(srcbox, lt);
--- a/src/plugins/mail-log/mail-log-plugin.c	Sun Aug 12 16:50:47 2007 +0300
+++ b/src/plugins/mail-log/mail-log-plugin.c	Sun Aug 12 18:02:29 2007 +0300
@@ -320,19 +320,16 @@
 	t_pop();
 }
 
-static int mail_log_mail_expunge(struct mail *_mail)
+static void mail_log_mail_expunge(struct mail *_mail)
 {
 	struct mail_private *mail = (struct mail_private *)_mail;
 	union mail_module_context *lmail = MAIL_LOG_MAIL_CONTEXT(mail);
 
-	if (lmail->super.expunge(_mail) < 0)
-		return -1;
-
 	mail_log_action(_mail, MAIL_LOG_EVENT_EXPUNGE, NULL);
-	return 0;
+	lmail->super.expunge(_mail);
 }
 
-static int
+static void
 mail_log_mail_update_flags(struct mail *_mail, enum modify_type modify_type,
 			   enum mail_flags flags)
 {
@@ -341,8 +338,7 @@
 	enum mail_flags old_flags, new_flags;
 
 	old_flags = mail_get_flags(_mail);
-	if (lmail->super.update_flags(_mail, modify_type, flags) < 0)
-		return -1;
+	lmail->super.update_flags(_mail, modify_type, flags);
 
 	new_flags = old_flags;
 	switch (modify_type) {
@@ -357,11 +353,10 @@
 		break;
 	}
 	if (((old_flags ^ new_flags) & MAIL_DELETED) == 0)
-		return 0;
+		return;
 
 	mail_log_action(_mail, (new_flags & MAIL_DELETED) != 0 ?
 			MAIL_LOG_EVENT_DELETE : MAIL_LOG_EVENT_UNDELETE, NULL);
-	return 0;
 }
 
 static struct mail *
--- a/src/plugins/quota/quota-storage.c	Sun Aug 12 16:50:47 2007 +0300
+++ b/src/plugins/quota/quota-storage.c	Sun Aug 12 18:02:29 2007 +0300
@@ -42,16 +42,13 @@
 static MODULE_CONTEXT_DEFINE_INIT(quota_mailbox_list_module,
 				  &mailbox_list_module_register);
 
-static int quota_mail_expunge(struct mail *_mail)
+static void quota_mail_expunge(struct mail *_mail)
 {
 	struct mail_private *mail = (struct mail_private *)_mail;
 	struct quota_mailbox *qbox = QUOTA_CONTEXT(_mail->box);
 	union mail_module_context *qmail = QUOTA_MAIL_CONTEXT(mail);
 	uoff_t size;
 
-	if (qmail->super.expunge(_mail) < 0)
-		return -1;
-
 	/* We need to handle the situation where multiple transactions expunged
 	   the mail at the same time. In here we'll just save the message's
 	   physical size and do the quota freeing later when the message was
@@ -66,7 +63,7 @@
 		array_append(&qbox->expunge_sizes, &size, 1);
 	}
 
-	return 0;
+	qmail->super.expunge(_mail);
 }
 
 static struct mailbox_transaction_context *
@@ -321,7 +318,7 @@
 			mail_alloc(qbox->expunge_trans,
 				   MAIL_FETCH_PHYSICAL_SIZE, NULL);
 	}
-	if (mail_set_uid(qbox->expunge_qt->tmp_mail, uid) <= 0)
+	if (!mail_set_uid(qbox->expunge_qt->tmp_mail, uid))
 		size = (uoff_t)-1;
 	else
 		size = mail_get_physical_size(qbox->expunge_qt->tmp_mail);
--- a/src/plugins/trash/trash-plugin.c	Sun Aug 12 16:50:47 2007 +0300
+++ b/src/plugins/trash/trash-plugin.c	Sun Aug 12 18:02:29 2007 +0300
@@ -152,9 +152,7 @@
 				continue;
 			}
 
-			if (mail_expunge(trashes[oldest_idx].mail) < 0)
-				break;
-
+			mail_expunge(trashes[oldest_idx].mail);
 			expunged_count++;
 			size_expunged += size;
 			if (size_expunged >= size_needed)
--- a/src/pop3/commands.c	Sun Aug 12 16:50:47 2007 +0300
+++ b/src/pop3/commands.c	Sun Aug 12 18:02:29 2007 +0300
@@ -189,7 +189,6 @@
 	struct mail_search_context *ctx;
 	struct mail *mail;
 	uint32_t idx;
-	bool ret = TRUE;
 
 	if (client->deleted_bitmask == NULL)
 		return TRUE;
@@ -212,18 +211,13 @@
 		idx = mail->seq - 1;
 		if ((client->deleted_bitmask[idx / CHAR_BIT] &
 		     1 << (idx % CHAR_BIT)) != 0) {
-			if (mail_expunge(mail) < 0) {
-				ret = FALSE;
-				break;
-			}
+			mail_expunge(mail);
 			client->expunged_count++;
 		}
 	}
 	mail_free(&mail);
 
-	if (mailbox_search_deinit(&ctx) < 0)
-		ret = FALSE;
-	return ret;
+	return mailbox_search_deinit(&ctx) == 0;
 }
 
 static int cmd_quit(struct client *client, const char *args __attr_unused__)
@@ -464,11 +458,8 @@
 		search_ctx = mailbox_search_init(client->trans, NULL,
 						 &search_arg, NULL);
 		mail = mail_alloc(client->trans, 0, NULL);
-		while (mailbox_search_next(search_ctx, mail) > 0) {
-			if (mail_update_flags(mail, MODIFY_REMOVE,
-					      MAIL_SEEN) < 0)
-				break;
-		}
+		while (mailbox_search_next(search_ctx, mail) > 0)
+			mail_update_flags(mail, MODIFY_REMOVE, MAIL_SEEN);
 		mail_free(&mail);
 		(void)mailbox_search_deinit(&search_ctx);
 	} else {