changeset 8802:f93d9e08f89c HEAD

lazy_expunge: When deleting mailboxes, if the destination parent dir didn't exist, delete failed.
author Timo Sirainen <tss@iki.fi>
date Wed, 04 Mar 2009 18:30:42 -0500
parents 60e778555558
children fe4782341037
files src/plugins/lazy-expunge/lazy-expunge-plugin.c
diffstat 1 files changed, 30 insertions(+), 3 deletions(-) [+]
line wrap: on
line diff
--- a/src/plugins/lazy-expunge/lazy-expunge-plugin.c	Wed Mar 04 18:03:23 2009 -0500
+++ b/src/plugins/lazy-expunge/lazy-expunge-plugin.c	Wed Mar 04 18:30:42 2009 -0500
@@ -5,6 +5,7 @@
 #include "array.h"
 #include "str.h"
 #include "seq-range-array.h"
+#include "mkdir-parents.h"
 #include "maildir-storage.h"
 #include "mail-namespace.h"
 #include "lazy-expunge-plugin.h"
@@ -379,15 +380,41 @@
 	     struct mailbox_list *dest_list, const char **_dest_name)
 {
 	const char *dest_name = *_dest_name;
-	const char *srcdir, *src2dir, *src3dir, *destdir;
+	const char *srcdir, *src2dir, *src3dir, *destdir, *p, *destparent;
+	struct stat st;
+	mode_t mode;
+	gid_t gid;
 
 	srcdir = mailbox_list_get_path(src_list, src_name,
 				       MAILBOX_LIST_PATH_TYPE_MAILBOX);
 	destdir = mailbox_list_get_path(dest_list, dest_name,
 					MAILBOX_LIST_PATH_TYPE_MAILBOX);
 	while (rename(srcdir, destdir) < 0) {
-		if (errno == ENOENT)
-			return 0;
+		if (errno == ENOENT) {
+			/* if this is because the destination parent directory
+			   didn't exist, create it. */
+			p = strrchr(destdir, '/');
+			if (p == NULL)
+				return 0;
+			destparent = t_strdup_until(destdir, p);
+			if (stat(destparent, &st) == 0)
+				return 0;
+
+			mailbox_list_get_dir_permissions(dest_list, NULL,
+							 &mode, &gid);
+			if (mkdir_parents_chown(destparent, mode,
+						(uid_t)-1, gid) < 0) {
+				if (errno == EEXIST) {
+					/* race condition */
+					continue;
+				}
+				mailbox_list_set_critical(src_list,
+					"mkdir(%s) failed: %m", destparent);
+				return -1;
+			}
+			/* created, try again. */
+			continue;
+		}
 
 		if (!EDESTDIREXISTS(errno)) {
 			mailbox_list_set_critical(src_list,