dovecot-2.1: maildir: If maildir filename has broken W/S size, r...
dovecot at dovecot.org
dovecot at dovecot.org
Tue Oct 18 16:44:49 EEST 2011
details: http://hg.dovecot.org/dovecot-2.1/rev/e3d2262e995a
changeset: 13637:e3d2262e995a
user: Timo Sirainen <tss at iki.fi>
date: Tue Oct 18 16:53:06 2011 +0300
description:
maildir: If maildir filename has broken W/S size, rename the file to drop them.
diffstat:
src/lib-storage/index/maildir/maildir-mail.c | 92 ++++++++++++++++++++-------
1 files changed, 66 insertions(+), 26 deletions(-)
diffs (112 lines):
diff -r fb22546542a5 -r e3d2262e995a src/lib-storage/index/maildir/maildir-mail.c
--- a/src/lib-storage/index/maildir/maildir-mail.c Tue Oct 18 16:52:23 2011 +0300
+++ b/src/lib-storage/index/maildir/maildir-mail.c Tue Oct 18 16:53:06 2011 +0300
@@ -9,6 +9,7 @@
#include "maildir-uidlist.h"
#include "maildir-sync.h"
+#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
@@ -595,35 +596,74 @@
MAILDIR_UIDLIST_REC_EXT_POP3_UIDL, uidl);
}
+static void maildir_mail_remove_sizes_from_uidlist(struct mail *mail)
+{
+ struct maildir_mailbox *mbox = (struct maildir_mailbox *)mail->box;
+
+ if (maildir_uidlist_lookup_ext(mbox->uidlist, mail->uid,
+ MAILDIR_UIDLIST_REC_EXT_VSIZE) != NULL) {
+ maildir_uidlist_set_ext(mbox->uidlist, mail->uid,
+ MAILDIR_UIDLIST_REC_EXT_VSIZE, NULL);
+ }
+ if (maildir_uidlist_lookup_ext(mbox->uidlist, mail->uid,
+ MAILDIR_UIDLIST_REC_EXT_PSIZE) != NULL) {
+ maildir_uidlist_set_ext(mbox->uidlist, mail->uid,
+ MAILDIR_UIDLIST_REC_EXT_PSIZE, NULL);
+ }
+}
+
+static void
+maildir_mail_remove_sizes_from_filename(struct mail *mail,
+ enum mail_fetch_field field)
+{
+ struct maildir_mailbox *mbox = (struct maildir_mailbox *)mail->box;
+ enum maildir_uidlist_rec_flag flags;
+ const char *subdir, *fname, *path, *newpath, *p;
+ uoff_t size;
+
+ if (maildir_sync_lookup(mbox, mail->uid, &flags, &fname) <= 0)
+ return;
+
+ p = strchr(fname, MAILDIR_EXTRA_SEP);
+ if (p == NULL)
+ return;
+
+ subdir = (flags & MAILDIR_UIDLIST_REC_FLAG_NEW_DIR) != 0 ?
+ "new" : "cur";
+ path = t_strdup_printf("%s/%s/%s", mailbox_get_path(&mbox->box),
+ subdir, fname);
+
+ if (maildir_filename_get_size(fname, MAILDIR_EXTRA_VIRTUAL_SIZE,
+ &size) &&
+ field == MAIL_FETCH_VIRTUAL_SIZE) {
+ mail_storage_set_critical(mail->box->storage,
+ "Maildir filename has wrong W value: %s", path);
+ }
+ if (maildir_filename_get_size(fname, MAILDIR_EXTRA_FILE_SIZE,
+ &size) &&
+ field == MAIL_FETCH_PHYSICAL_SIZE) {
+ mail_storage_set_critical(mail->box->storage,
+ "Maildir filename has wrong S value: %s", path);
+ }
+
+ newpath = t_strdup_printf("%s/%s/%s", mailbox_get_path(&mbox->box),
+ subdir, t_strdup_until(fname, p));
+ if (rename(path, newpath) == 0) {
+ i_warning("Renamed broken maildir filename %s to %s",
+ path, newpath);
+ } else {
+ mail_storage_set_critical(mail->box->storage,
+ "rename(%s, %s) failed: %m", path, newpath);
+ }
+}
+
static void maildir_mail_set_cache_corrupted(struct mail *_mail,
enum mail_fetch_field field)
{
- struct maildir_mailbox *mbox = (struct maildir_mailbox *)_mail->box;
- enum maildir_uidlist_rec_flag flags;
- const char *fname;
- uoff_t size;
- int ret;
-
- if (field == MAIL_FETCH_VIRTUAL_SIZE) {
- /* make sure it gets removed from uidlist.
- if it's in file name, we can't really do more than log it. */
- ret = maildir_sync_lookup(mbox, _mail->uid, &flags, &fname);
- if (ret <= 0)
- return;
- if (maildir_filename_get_size(fname, MAILDIR_EXTRA_VIRTUAL_SIZE,
- &size)) {
- const char *subdir =
- (flags & MAILDIR_UIDLIST_REC_FLAG_NEW_DIR) != 0 ?
- "new" : "cur";
- mail_storage_set_critical(_mail->box->storage,
- "Maildir filename has wrong W value: %s/%s/%s",
- mailbox_get_path(&mbox->box), subdir, fname);
- } else if (maildir_uidlist_lookup_ext(mbox->uidlist, _mail->uid,
- MAILDIR_UIDLIST_REC_EXT_VSIZE) != NULL) {
- maildir_uidlist_set_ext(mbox->uidlist, _mail->uid,
- MAILDIR_UIDLIST_REC_EXT_VSIZE,
- NULL);
- }
+ if (field == MAIL_FETCH_PHYSICAL_SIZE ||
+ field == MAIL_FETCH_VIRTUAL_SIZE) {
+ maildir_mail_remove_sizes_from_uidlist(_mail);
+ maildir_mail_remove_sizes_from_filename(_mail, field);
}
index_mail_set_cache_corrupted(_mail, field);
}
More information about the dovecot-cvs
mailing list