Mercurial > dovecot > core-2.2
changeset 12195:cf1e5238f747
maildir: If we see unwanted non-empty directories in new/ or cur/, move them to ../extra-*
author | Timo Sirainen <tss@iki.fi> |
---|---|
date | Tue, 28 Sep 2010 17:15:52 +0100 |
parents | 2bfe672e7c8a |
children | 9939f0565916 |
files | src/lib-storage/index/maildir/maildir-mail.c src/lib-storage/index/maildir/maildir-storage.h src/lib-storage/index/maildir/maildir-sync-index.c src/lib-storage/index/maildir/maildir-util.c |
diffstat | 4 files changed, 57 insertions(+), 23 deletions(-) [+] |
line wrap: on
line diff
--- a/src/lib-storage/index/maildir/maildir-mail.c Tue Sep 28 17:09:50 2010 +0100 +++ b/src/lib-storage/index/maildir/maildir-mail.c Tue Sep 28 17:15:52 2010 +0100 @@ -58,22 +58,6 @@ 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 @@ 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);
--- a/src/lib-storage/index/maildir/maildir-storage.h Tue Sep 28 17:09:50 2010 +0100 +++ b/src/lib-storage/index/maildir/maildir-storage.h Tue Sep 28 17:15:52 2010 +0100 @@ -109,6 +109,7 @@ 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);
--- a/src/lib-storage/index/maildir/maildir-sync-index.c Tue Sep 28 17:09:50 2010 +0100 +++ b/src/lib-storage/index/maildir/maildir-sync-index.c Tue Sep 28 17:15:52 2010 +0100 @@ -98,6 +98,8 @@ } 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);
--- a/src/lib-storage/index/maildir/maildir-util.c Tue Sep 28 17:09:50 2010 +0100 +++ b/src/lib-storage/index/maildir/maildir-util.c Tue Sep 28 17:15:52 2010 +0100 @@ -12,6 +12,7 @@ #include "maildir-filename.h" #include "maildir-sync.h" +#include <stdio.h> #include <unistd.h> #include <dirent.h> #include <fcntl.h> @@ -224,3 +225,54 @@ } 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; + } +}