From: Timo Sirainen Date: Tue, 28 Sep 2010 16:15:52 +0000 (+0100) Subject: maildir: If we see unwanted non-empty directories in new/ or cur/, move them to ... X-Git-Tag: 2.0.5~36 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=f6f021c133f680cf3d559187524fd9abcbaae9b9;p=thirdparty%2Fdovecot%2Fcore.git maildir: If we see unwanted non-empty directories in new/ or cur/, move them to ../extra-* --- diff --git a/src/lib-storage/index/maildir/maildir-mail.c b/src/lib-storage/index/maildir/maildir-mail.c index 8742cc3102..7bebdaf8a7 100644 --- a/src/lib-storage/index/maildir/maildir-mail.c +++ b/src/lib-storage/index/maildir/maildir-mail.c @@ -58,22 +58,6 @@ do_stat(struct maildir_mailbox *mbox, const char *path, struct stat *st) return -1; } -static int -maildir_rmdir_unexpected_dir(struct mail_storage *storage, const char *path) -{ - if (rmdir(path) == 0) { - mail_storage_set_critical(storage, - "Maildir: rmdir()ed unwanted empty directory: %s", - path); - return 0; - } else { - mail_storage_set_critical(storage, - "Maildir: Found unwanted directory %s, " - "but rmdir() failed: %m", path); - return -1; - } -} - static struct istream * maildir_open_mail(struct maildir_mailbox *mbox, struct mail *mail, bool *deleted_r) @@ -105,14 +89,9 @@ maildir_open_mail(struct maildir_mailbox *mbox, struct mail *mail, input = i_stream_create_fd(ctx.fd, 0, TRUE); if (input->stream_errno == EISDIR) { - /* there's a directory in maildir. many installations seem to - have messed up something and causing "cur", "new" and "tmp" - directories to be created under the "cur" directory. - if the directory is empty, just get rid of it and log an - error */ i_stream_destroy(&input); - if (maildir_rmdir_unexpected_dir(&mbox->storage->storage, - ctx.path) == 0) + if (maildir_lose_unexpected_dir(&mbox->storage->storage, + ctx.path) >= 0) *deleted_r = TRUE; } else { i_stream_set_name(input, ctx.path); diff --git a/src/lib-storage/index/maildir/maildir-storage.h b/src/lib-storage/index/maildir/maildir-storage.h index 2f532d5f6f..c76bbe59c7 100644 --- a/src/lib-storage/index/maildir/maildir-storage.h +++ b/src/lib-storage/index/maildir/maildir-storage.h @@ -109,6 +109,7 @@ int maildir_file_do(struct maildir_mailbox *mbox, uint32_t uid, bool maildir_set_deleted(struct mailbox *box); uint32_t maildir_get_uidvalidity_next(struct mailbox_list *list); +int maildir_lose_unexpected_dir(struct mail_storage *storage, const char *path); struct mail_save_context * maildir_save_alloc(struct mailbox_transaction_context *_t); diff --git a/src/lib-storage/index/maildir/maildir-sync-index.c b/src/lib-storage/index/maildir/maildir-sync-index.c index bd62d1be5b..7e710619ec 100644 --- a/src/lib-storage/index/maildir/maildir-sync-index.c +++ b/src/lib-storage/index/maildir/maildir-sync-index.c @@ -98,6 +98,8 @@ static int maildir_expunge(struct maildir_mailbox *mbox, const char *path, } if (errno == ENOENT) return 0; + if (errno == EISDIR) + return maildir_lose_unexpected_dir(box->storage, path); mail_storage_set_critical(&mbox->storage->storage, "unlink(%s) failed: %m", path); diff --git a/src/lib-storage/index/maildir/maildir-util.c b/src/lib-storage/index/maildir/maildir-util.c index b4be61d437..47bd119171 100644 --- a/src/lib-storage/index/maildir/maildir-util.c +++ b/src/lib-storage/index/maildir/maildir-util.c @@ -12,6 +12,7 @@ #include "maildir-filename.h" #include "maildir-sync.h" +#include #include #include #include @@ -224,3 +225,54 @@ bool maildir_set_deleted(struct mailbox *box) } T_END; return ret < 0 ? FALSE : TRUE; } + +int maildir_lose_unexpected_dir(struct mail_storage *storage, const char *path) +{ + const char *dest, *fname, *p; + + /* There's a directory in maildir, get rid of it. + + In some installations this was caused by a messed up configuration + where e.g. mails was initially delivered to new/new/ directory. + Also Dovecot v2.0.0 - v2.0.4 sometimes may have renamed tmp/ + directory under new/ or cur/. */ + if (rmdir(path) == 0) { + mail_storage_set_critical(storage, + "Maildir: rmdir()ed unwanted empty directory: %s", + path); + return 1; + } else if (errno == ENOENT) { + /* someone else rmdired or renamed it */ + return 0; + } else if (errno != ENOTEMPTY) { + mail_storage_set_critical(storage, + "Maildir: Found unwanted directory %s, " + "but rmdir() failed: %m", path); + return -1; + } + + /* It's not safe to delete this directory since it has some files in it, + but it's also not helpful to log this message over and over again. + Get rid of this error by renaming the directory elsewhere */ + p = strrchr(path, '/'); + i_assert(p != NULL); + fname = p + 1; + while (p != path && p[-1] != '/') p--; + i_assert(p != NULL); + + dest = t_strconcat(t_strdup_until(path, p), "extra-", fname, NULL); + if (rename(path, dest) == 0) { + mail_storage_set_critical(storage, + "Maildir: renamed unwanted directory %s to %s", + path, dest); + return 1; + } else if (errno == ENOENT) { + /* someone else renamed it (could have been flag change) */ + return 0; + } else { + mail_storage_set_critical(storage, + "Maildir: Found unwanted directory, " + "but rename(%s, %s) failed: %m", path, dest); + return -1; + } +}