# HG changeset patch # User Timo Sirainen # Date 1030419190 -10800 # Node ID 306c20092a96fa099f163bb31da16b424889d7d1 # Parent b2bc8d2e56ff6e756cea89342ad85fac9d364094 Errors in user-specified messagesets are now properly reported back to user. diff -r b2bc8d2e56ff -r 306c20092a96 src/lib-index/mail-messageset.c --- 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) diff -r b2bc8d2e56ff -r 306c20092a96 src/lib-index/mail-messageset.h --- 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 diff -r b2bc8d2e56ff -r 306c20092a96 src/lib-storage/index/index-copy.c --- 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; } - diff -r b2bc8d2e56ff -r 306c20092a96 src/lib-storage/index/index-fetch.c --- 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; } diff -r b2bc8d2e56ff -r 306c20092a96 src/lib-storage/index/index-storage.c --- 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; diff -r b2bc8d2e56ff -r 306c20092a96 src/lib-storage/index/index-storage.h --- 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[]); diff -r b2bc8d2e56ff -r 306c20092a96 src/lib-storage/index/index-update-flags.c --- 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; } diff -r b2bc8d2e56ff -r 306c20092a96 src/lib-storage/index/maildir/maildir-copy.c --- 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;