# HG changeset patch # User Timo Sirainen # Date 1224416289 -10800 # Node ID d3b37327936e70d2570414199a62b2fc8b1d4ff3 # Parent 0db37acdc59fa56965ff5f53999623044e24ed0c Maildir: Re-read uidlist from the beginning before deciding it's corrupted. diff -r 0db37acdc59f -r d3b37327936e src/lib-storage/index/maildir/maildir-uidlist.c --- a/src/lib-storage/index/maildir/maildir-uidlist.c Sun Oct 19 14:00:57 2008 +0300 +++ b/src/lib-storage/index/maildir/maildir-uidlist.c Sun Oct 19 14:38:09 2008 +0300 @@ -90,6 +90,7 @@ unsigned int initial_read:1; unsigned int initial_hdr_read:1; unsigned int initial_sync:1; + unsigned int retry_rewind:1; }; struct maildir_uidlist_sync_ctx { @@ -305,9 +306,17 @@ va_list args; va_start(args, fmt); - mail_storage_set_critical(storage, "Broken file %s line %u: %s", - uidlist->path, uidlist->read_line_count, - t_strdup_vprintf(fmt, args)); + if (uidlist->retry_rewind) { + mail_storage_set_critical(storage, + "Broken or unexpectedly changed file %s " + "line %u: %s - re-reading from beginning", + uidlist->path, uidlist->read_line_count, + t_strdup_vprintf(fmt, args)); + } else { + mail_storage_set_critical(storage, "Broken file %s line %u: %s", + uidlist->path, uidlist->read_line_count, + t_strdup_vprintf(fmt, args)); + } va_end(args); } @@ -405,7 +414,7 @@ } if (uid <= uidlist->prev_read_uid) { maildir_uidlist_set_corrupted(uidlist, - "UIDs not ordered (%u > %u)", + "UIDs not ordered (%u >= %u)", uid, uidlist->prev_read_uid); return FALSE; } @@ -627,16 +636,23 @@ uidlist->prev_read_uid = 0; uidlist->change_counter++; uidlist->read_records_count = 0; + uidlist->retry_rewind = last_read_offset != 0 && try_retry; ret = 1; while ((line = i_stream_read_next_line(input)) != NULL) { uidlist->read_records_count++; uidlist->read_line_count++; if (!maildir_uidlist_next(uidlist, line)) { - ret = 0; + if (!uidlist->retry_rewind) + ret = 0; + else { + ret = -1; + *retry_r = TRUE; + } break; } } + uidlist->retry_rewind = FALSE; if (input->stream_errno != 0) ret = -1; @@ -663,7 +679,7 @@ uidlist->fd_size = st.st_size; uidlist->last_read_offset = input->v_offset; maildir_uidlist_update_hdr(uidlist, &st); - } else { + } else if (!*retry_r) { /* I/O error */ if (input->stream_errno == ESTALE && try_retry) *retry_r = TRUE;