changeset 47:306c20092a96 HEAD

Errors in user-specified messagesets are now properly reported back to user.
author Timo Sirainen <tss@iki.fi>
date Tue, 27 Aug 2002 06:33:10 +0300
parents b2bc8d2e56ff
children 5e9cf9565353
files src/lib-index/mail-messageset.c src/lib-index/mail-messageset.h src/lib-storage/index/index-copy.c src/lib-storage/index/index-fetch.c src/lib-storage/index/index-storage.c src/lib-storage/index/index-storage.h src/lib-storage/index/index-update-flags.c src/lib-storage/index/maildir/maildir-copy.c
diffstat 8 files changed, 112 insertions(+), 87 deletions(-) [+]
line wrap: on
line diff
--- a/src/lib-index/mail-messageset.c	Tue Aug 27 06:28:07 2002 +0300
+++ b/src/lib-index/mail-messageset.c	Tue Aug 27 06:33:10 2002 +0300
@@ -25,7 +25,8 @@
 
 static int mail_index_foreach(MailIndex *index,
 			      unsigned int seq, unsigned int seq2,
-			      MsgsetForeachFunc func, void *context)
+			      MsgsetForeachFunc func, void *context,
+			      const char **error)
 {
 	MailIndexRecord *rec;
 	const unsigned int *expunges;
@@ -37,9 +38,9 @@
 		   them but I think it's a bug in client if it does this,
 		   and better complain about it immediately than later let
 		   them wonder why it doesn't work with other imapds.. */
-		index_set_error(index, "Invalid messageset range: %u > %u",
-				seq, seq2);
-		return -1;
+		*error = t_strdup_printf("Invalid messageset range: %u > %u",
+					 seq, seq2);
+		return -2;
 	}
 
 	/* get list of expunged messages in our range. the expunges_before
@@ -84,7 +85,8 @@
 
 int mail_index_messageset_foreach(MailIndex *index, const char *messageset,
 				  unsigned int messages_count,
-				  MsgsetForeachFunc func, void *context)
+				  MsgsetForeachFunc func, void *context,
+				  const char **error)
 {
 	const char *input;
 	unsigned int seq, seq2;
@@ -92,6 +94,7 @@
 
 	i_assert(index->lock_type != MAIL_LOCK_UNLOCK);
 
+	*error = NULL;
 	if (messages_count == 0) {
 		/* no messages in mailbox */
 		return 1;
@@ -107,9 +110,9 @@
 		} else {
 			seq = get_next_number(&input);
 			if (seq == 0) {
-				index_set_error(index, "Invalid messageset: "
-						"%s", messageset);
-				return -1;
+				*error = t_strconcat("Invalid messageset: ",
+						     messageset, NULL);
+				return -2;
 			}
 		}
 
@@ -122,10 +125,10 @@
 			if (*input != '*') {
 				seq2 = get_next_number(&input);
 				if (seq2 == 0) {
-					index_set_error(index, "Invalid "
-							"messageset: %s",
-							messageset);
-					return -1;
+					*error = t_strconcat("Invalid "
+							     "messageset: ",
+							     messageset, NULL);
+					return -2;
 				}
 
 				if (seq2 > messages_count) {
@@ -141,17 +144,17 @@
 		if (*input == ',')
 			input++;
 		else if (*input != '\0') {
-			index_set_error(index, "Unexpected char '%c' "
-					"with messageset: %s",
-					*input, messageset);
-			return -1;
+			*error = t_strdup_printf("Unexpected char '%c' "
+						 "with messageset: %s",
+						 *input, messageset);
+			return -2;
 		}
 
 		if (seq > messages_count) {
 			/* too large .. ignore silently */
 		} else {
 			ret = mail_index_foreach(index, seq, seq2,
-						 func, context);
+						 func, context, error);
 			if (ret <= 0)
 				return ret;
 			if (ret == 2)
@@ -165,7 +168,8 @@
 static int mail_index_uid_foreach(MailIndex *index,
 				  unsigned int uid, unsigned int uid2,
 				  unsigned int max_sequence,
-				  MsgsetForeachFunc func, void *context)
+				  MsgsetForeachFunc func, void *context,
+				  const char **error)
 {
 	MailIndexRecord *rec;
 	off_t pos;
@@ -175,9 +179,9 @@
 
 	if (uid > uid2) {
 		/* not allowed - see mail_index_foreach() */
-		index_set_error(index, "Invalid uidset range: %u > %u",
-				uid, uid2);
-		return -1;
+		*error = t_strdup_printf("Invalid uidset range: %u > %u",
+					 uid, uid2);
+		return -2;
 	}
 
 	/* get list of expunged messages in our range. */
@@ -199,6 +203,21 @@
 	   _should_ work.. */
 	pos = mail_hash_lookup_uid(index->hash, uid);
 	if (pos != 0) {
+		if (pos + sizeof(MailIndexRecord) > index->mmap_length) {
+			/* hash is corrupted */
+			index_set_error(index, "Corrupted hash for index %s: "
+					"lookup returned offset outside range",
+					index->filepath);
+
+			if (!mail_hash_rebuild(index->hash))
+				return -1;
+
+			/* lets try again */
+			pos = mail_hash_lookup_uid(index->hash, uid);
+			if (pos + sizeof(MailIndexRecord) > index->mmap_length)
+				return -1;
+		}
+
 		rec = (MailIndexRecord *) ((char *) index->mmap_base + pos);
 	} else {
 		/* ..however if for any reason it doesn't,
@@ -237,7 +256,8 @@
 
 int mail_index_uidset_foreach(MailIndex *index, const char *uidset,
 			      unsigned int messages_count,
-			      MsgsetForeachFunc func, void *context)
+			      MsgsetForeachFunc func, void *context,
+			      const char **error)
 {
 	MailIndexRecord *rec;
 	const char *input;
@@ -246,6 +266,7 @@
 
 	i_assert(index->lock_type != MAIL_LOCK_UNLOCK);
 
+	*error = NULL;
 	if (messages_count == 0) {
 		/* no messages in mailbox */
 		return 1;
@@ -262,9 +283,9 @@
 		} else {
 			uid = get_next_number(&input);
 			if (uid == 0) {
-				index_set_error(index, "Invalid uidset: %s",
-						uidset);
-				return -1;
+				*error = t_strconcat("Invalid uidset: ",
+						     uidset, NULL);
+				return -2;
 			}
 		}
 
@@ -277,10 +298,9 @@
 			if (*input != '*') {
 				uid2 = get_next_number(&input);
 				if (uid2 == 0) {
-					index_set_error(index,
-							"Invalid uidset: %s",
-							uidset);
-					return -1;
+					*error = t_strconcat("Invalid uidset: ",
+							     uidset, NULL);
+					return -2;
 				}
 			} else {
 				uid2 = index->header->next_uid-1;
@@ -291,10 +311,9 @@
 		if (*input == ',')
 			input++;
 		else if (*input != '\0') {
-			index_set_error(index,
-					"Unexpected char '%c' with uidset: %s",
-					*input, uidset);
-			return -1;
+			*error = t_strdup_printf("Unexpected char '%c' with "
+						 "uidset: %s", *input, uidset);
+			return -2;
 		}
 
 		if (uid >= index->header->next_uid) {
@@ -302,7 +321,7 @@
 		} else {
 			ret = mail_index_uid_foreach(index, uid, uid2,
 						     messages_count,
-						     func, context);
+						     func, context, error);
 			if (ret <= 0)
 				return ret;
 			if (ret == 2)
--- a/src/lib-index/mail-messageset.h	Tue Aug 27 06:28:07 2002 +0300
+++ b/src/lib-index/mail-messageset.h	Tue Aug 27 06:33:10 2002 +0300
@@ -7,15 +7,18 @@
 typedef int (*MsgsetForeachFunc)(MailIndex *index, MailIndexRecord *rec,
 				 unsigned int seq, void *context);
 
-/* Returns -1 if error occured, 0 if foreach-func returned FALSE,
-   1 if everything was ok or 2 if some of the given sequences were expunged */
+/* Returns -1 if internal error occured, -2 if messageset was invalid
+   (sets error), 0 if foreach-func returned FALSE, 1 if everything was ok
+   or 2 if some of the given sequences were expunged */
 int mail_index_messageset_foreach(MailIndex *index, const char *messageset,
 				  unsigned int messages_count,
-				  MsgsetForeachFunc func, void *context);
+				  MsgsetForeachFunc func, void *context,
+				  const char **error);
 
 /* Like messageset_foreach() but for UIDs. */
 int mail_index_uidset_foreach(MailIndex *index, const char *uidset,
 			      unsigned int messages_count,
-			      MsgsetForeachFunc func, void *context);
+			      MsgsetForeachFunc func, void *context,
+			      const char **error);
 
 #endif
--- a/src/lib-storage/index/index-copy.c	Tue Aug 27 06:28:07 2002 +0300
+++ b/src/lib-storage/index/index-copy.c	Tue Aug 27 06:33:10 2002 +0300
@@ -51,20 +51,13 @@
 	cd.custom_flags = flags_file_list_get(ibox->flagsfile);
 	cd.dest = destbox;
 
-	if (uidset) {
-		failed = mail_index_uidset_foreach(ibox->index, messageset,
-						   ibox->synced_messages_count,
-						   copy_func, destbox) <= 0;
-	} else {
-		failed = mail_index_messageset_foreach(ibox->index, messageset,
-			ibox->synced_messages_count, copy_func, destbox) <= 0;
-	}
+	failed = index_messageset_foreach(ibox, messageset, uidset,
+					  copy_func, destbox) <= 0;
 
 	flags_file_list_unref(ibox->flagsfile);
 
-	if (!ibox->index->set_lock(ibox->index, MAIL_LOCK_UNLOCK) || failed)
+	if (!ibox->index->set_lock(ibox->index, MAIL_LOCK_UNLOCK))
 		return mail_storage_set_index_error(ibox);
 
-	return TRUE;
+	return !failed;
 }
-
--- a/src/lib-storage/index/index-fetch.c	Tue Aug 27 06:28:07 2002 +0300
+++ b/src/lib-storage/index/index-fetch.c	Tue Aug 27 06:33:10 2002 +0300
@@ -341,17 +341,9 @@
 		}
 	}
 
-	if (fetch_data->uidset) {
-		ret = mail_index_uidset_foreach(ibox->index,
-						fetch_data->messageset,
-						ibox->synced_messages_count,
-						index_fetch_mail, &ctx);
-	} else {
-		ret = mail_index_messageset_foreach(ibox->index,
-						    fetch_data->messageset,
-						    ibox->synced_messages_count,
-						    index_fetch_mail, &ctx);
-	}
+	ret = index_messageset_foreach(ibox, fetch_data->messageset,
+				       fetch_data->uidset,
+				       index_fetch_mail, &ctx);
 
 	/* close open message files in cache, they're reopened at next fetch
 	   anyway, and especially with mbox the old data may not be valid
@@ -360,7 +352,7 @@
 
         flags_file_list_unref(ibox->flagsfile);
 
-	if (!ibox->index->set_lock(ibox->index, MAIL_LOCK_UNLOCK) || ret == -1)
+	if (!ibox->index->set_lock(ibox->index, MAIL_LOCK_UNLOCK))
 		return mail_storage_set_index_error(ibox);
 
 	if (all_found != NULL)
@@ -377,5 +369,5 @@
 			return FALSE;
 	}
 
-	return TRUE;
+	return ret >= 0;
 }
--- a/src/lib-storage/index/index-storage.c	Tue Aug 27 06:28:07 2002 +0300
+++ b/src/lib-storage/index/index-storage.c	Tue Aug 27 06:33:10 2002 +0300
@@ -62,6 +62,36 @@
 	return FALSE;
 }
 
+int index_messageset_foreach(IndexMailbox *ibox,
+			     const char *messageset, int uidset,
+			     MsgsetForeachFunc func, void *context)
+{
+	const char *error;
+	int ret;
+
+	if (uidset) {
+		ret = mail_index_uidset_foreach(ibox->index, messageset,
+						ibox->synced_messages_count,
+						func, context, &error);
+	} else {
+		ret = mail_index_messageset_foreach(ibox->index, messageset,
+						    ibox->synced_messages_count,
+						    func, context, &error);
+	}
+
+	if (ret < 0) {
+		if (ret == -2) {
+			/* user error */
+			mail_storage_set_error(ibox->box.storage, "%s", error);
+		} else {
+			mail_storage_set_index_error(ibox);
+		}
+	}
+
+	return ret;
+}
+
+
 static MailFlags get_used_flags(void *context)
 {
         IndexMailbox *ibox = context;
--- a/src/lib-storage/index/index-storage.h	Tue Aug 27 06:28:07 2002 +0300
+++ b/src/lib-storage/index/index-storage.h	Tue Aug 27 06:33:10 2002 +0300
@@ -2,6 +2,7 @@
 #define __INDEX_STORAGE_H
 
 #include "mail-storage.h"
+#include "mail-messageset.h"
 #include "mail-index.h"
 #include "imap-message-cache.h"
 #include "flags-file/flags-file.h"
@@ -29,6 +30,10 @@
 
 int mail_storage_set_index_error(IndexMailbox *ibox);
 
+int index_messageset_foreach(IndexMailbox *ibox,
+			     const char *messageset, int uidset,
+			     MsgsetForeachFunc func, void *context);
+
 int index_mailbox_fix_custom_flags(IndexMailbox *ibox, MailFlags *flags,
 				   const char *custom_flags[]);
 
--- a/src/lib-storage/index/index-update-flags.c	Tue Aug 27 06:28:07 2002 +0300
+++ b/src/lib-storage/index/index-update-flags.c	Tue Aug 27 06:33:10 2002 +0300
@@ -77,21 +77,13 @@
 	ctx.func = func;
 	ctx.context = context;
 
-	if (uidset) {
-		ret = mail_index_uidset_foreach(ibox->index, messageset,
-						ibox->synced_messages_count,
-						update_func, &ctx);
-	} else {
-		ret = mail_index_messageset_foreach(ibox->index,
-						    messageset,
-						    ibox->synced_messages_count,
-						    update_func, &ctx);
-	}
+	ret = index_messageset_foreach(ibox, messageset, uidset,
+				       update_func, &ctx);
 
-	if (!ibox->index->set_lock(ibox->index, MAIL_LOCK_UNLOCK) || ret == -1)
+	if (!ibox->index->set_lock(ibox->index, MAIL_LOCK_UNLOCK))
 		return mail_storage_set_index_error(ibox);
 
 	if (all_found != NULL)
 		*all_found = ret == 1;
-	return TRUE;
+	return ret >= 0;
 }
--- a/src/lib-storage/index/maildir/maildir-copy.c	Tue Aug 27 06:28:07 2002 +0300
+++ b/src/lib-storage/index/maildir/maildir-copy.c	Tue Aug 27 06:33:10 2002 +0300
@@ -41,7 +41,7 @@
 				       IndexMailbox *dest,
 				       const char *messageset, int uidset)
 {
-        CopyHardContext ctx;
+	CopyHardContext ctx;
 	int ret;
 
 	if (!src->index->set_lock(src->index, MAIL_LOCK_SHARED))
@@ -55,18 +55,8 @@
 	ctx.dest_maildir = dest->index->dir;
 	ctx.error = FALSE;
 
-	if (uidset) {
-		ret = mail_index_uidset_foreach(src->index, messageset,
-						src->synced_messages_count,
-						copy_hard_func, &ctx);
-	} else {
-		ret = mail_index_messageset_foreach(src->index, messageset,
-						    src->synced_messages_count,
-						    copy_hard_func, &ctx);
-	}
-
-	if (ret == -1)
-		mail_storage_set_index_error(src);
+	ret = index_messageset_foreach(src, messageset, uidset,
+				       copy_hard_func, &ctx) <= 0;
 
 	if (!dest->index->set_lock(dest->index, MAIL_LOCK_UNLOCK)) {
 		mail_storage_set_index_error(dest);
@@ -99,6 +89,7 @@
 		switch (maildir_copy_with_hardlinks(ibox,
 			(IndexMailbox *) destbox, messageset, uidset)) {
 		case -1:
+		case -2:
 			return FALSE;
 		case 1:
 			return TRUE;