dovecot-2.0: maildir: If we see unwanted non-empty directories i...

dovecot at dovecot.org dovecot at dovecot.org
Tue Sep 28 19:15:55 EEST 2010


details:   http://hg.dovecot.org/dovecot-2.0/rev/cf1e5238f747
changeset: 12195:cf1e5238f747
user:      Timo Sirainen <tss at iki.fi>
date:      Tue Sep 28 17:15:52 2010 +0100
description:
maildir: If we see unwanted non-empty directories in new/ or cur/, move them to ../extra-*

diffstat:

 src/lib-storage/index/maildir/maildir-mail.c       |  25 +-----------
 src/lib-storage/index/maildir/maildir-storage.h    |   1 +
 src/lib-storage/index/maildir/maildir-sync-index.c |   2 +
 src/lib-storage/index/maildir/maildir-util.c       |  52 ++++++++++++++++++++++++++
 4 files changed, 57 insertions(+), 23 deletions(-)

diffs (132 lines):

diff -r 2bfe672e7c8a -r cf1e5238f747 src/lib-storage/index/maildir/maildir-mail.c
--- 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);
diff -r 2bfe672e7c8a -r cf1e5238f747 src/lib-storage/index/maildir/maildir-storage.h
--- 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);
diff -r 2bfe672e7c8a -r cf1e5238f747 src/lib-storage/index/maildir/maildir-sync-index.c
--- 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);
diff -r 2bfe672e7c8a -r cf1e5238f747 src/lib-storage/index/maildir/maildir-util.c
--- 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;
+	}
+}


More information about the dovecot-cvs mailing list