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 {
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);
}
}
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;
}
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;
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;