changeset 4116:9d95aad9e9a7 HEAD

When deleting a maildir, rename it to ..DOVECOT-TRASHED, and assume only that directory to be safe to be deleted, instead of all ..dirs. When deleting maildir with absolute path, don't do renaming at all but delete it directly.
author Timo Sirainen <tss@iki.fi>
date Sat, 01 Apr 2006 12:31:15 +0300
parents d358e0f0fd18
children 273ae8a1a58a
files src/lib-storage/index/maildir/maildir-list.c src/lib-storage/index/maildir/maildir-storage.c src/lib-storage/index/maildir/maildir-storage.h
diffstat 3 files changed, 34 insertions(+), 29 deletions(-) [+]
line wrap: on
line diff
--- a/src/lib-storage/index/maildir/maildir-list.c	Sat Apr 01 12:15:45 2006 +0300
+++ b/src/lib-storage/index/maildir/maildir-list.c	Sat Apr 01 12:31:15 2006 +0300
@@ -104,13 +104,12 @@
 				continue;
 		}
 
-		if (fname[1] == MAILDIR_FS_SEP) {
-			/* this mailbox is in the middle of being deleted,
+		if (fname[1] == MAILDIR_FS_SEP &&
+		    strcmp(fname+1, MAILDIR_UNLINK_DIRNAME) == 0) {
+			/* this directory is in the middle of being deleted,
 			   or the process trying to delete it had died.
-
 			   delete it ourself if it's been there longer than
-			   one hour. don't touch it if it's outside our
-			   mail root dir. */
+			   one hour. */
 			t_push();
 			path = t_strdup_printf("%s/%s", ctx->dir, fname);
 			if (stat(path, &st) == 0 &&
--- a/src/lib-storage/index/maildir/maildir-storage.c	Sat Apr 01 12:15:45 2006 +0300
+++ b/src/lib-storage/index/maildir/maildir-storage.c	Sat Apr 01 12:31:15 2006 +0300
@@ -219,7 +219,7 @@
 	return TRUE;
 }
 
-static const char *maildir_get_absolute_path(const char *name, bool unlink)
+static const char *maildir_get_absolute_path(const char *name)
 {
 	const char *p;
 
@@ -229,7 +229,6 @@
 	if (p == NULL)
 		return name;
 	return t_strconcat(t_strdup_until(name, p+1),
-			   unlink ? MAILDIR_FS_SEP_S MAILDIR_FS_SEP_S :
 			   MAILDIR_FS_SEP_S, p+1, NULL);
 }
 
@@ -237,7 +236,7 @@
 {
 	if ((storage->storage.flags & MAIL_STORAGE_FLAG_FULL_FS_ACCESS) != 0 &&
 	    (*name == '/' || *name == '~'))
-		return maildir_get_absolute_path(name, FALSE);
+		return maildir_get_absolute_path(name);
 
 	if (strcmp(name, "INBOX") == 0) {
 		return storage->inbox_path != NULL ?
@@ -248,14 +247,13 @@
 }
 
 static const char *
-maildir_get_unlink_path(struct index_storage *storage, const char *name)
+maildir_get_unlink_dest(struct index_storage *storage, const char *name)
 {
 	if ((storage->storage.flags & MAIL_STORAGE_FLAG_FULL_FS_ACCESS) != 0 &&
 	    (*name == '/' || *name == '~'))
-		return maildir_get_absolute_path(name, TRUE);
+		return NULL;
 
-	return maildir_get_path(storage,
-				t_strconcat(MAILDIR_FS_SEP_S, name, NULL));
+	return maildir_get_path(storage, MAILDIR_UNLINK_DIRNAME);
 }
 
 static const char *maildir_get_index_path(struct index_storage *storage,
@@ -270,7 +268,7 @@
 
 	if ((storage->storage.flags & MAIL_STORAGE_FLAG_FULL_FS_ACCESS) != 0 &&
 	    (*name == '/' || *name == '~'))
-		return maildir_get_absolute_path(name, FALSE);
+		return maildir_get_absolute_path(name);
 
 	return t_strconcat(storage->index_dir, "/"MAILDIR_FS_SEP_S, name, NULL);
 }
@@ -283,7 +281,7 @@
 
 	if ((STORAGE(storage)->flags & MAIL_STORAGE_FLAG_FULL_FS_ACCESS) != 0 &&
 	    (*name == '/' || *name == '~'))
-		return maildir_get_absolute_path(name, FALSE);
+		return maildir_get_absolute_path(name);
 
 	return t_strconcat(storage->control_dir, "/"MAILDIR_FS_SEP_S,
 			   name, NULL);
@@ -624,11 +622,11 @@
 		return -1;
 	}
 
-	/* rename the .maildir into ..maildir which marks it as being
+	/* rename the .maildir into ..DOVECOT-TRASH which marks it as being
 	   deleted. delete indexes before the actual maildir. this way we
 	   never see partially deleted mailboxes. */
 	src = maildir_get_path(storage, name);
-	dest = maildir_get_unlink_path(storage, name);
+	dest = maildir_get_unlink_dest(storage, name);
 	if (stat(src, &st) != 0 && errno == ENOENT) {
 		mail_storage_set_error(_storage,
 			MAIL_STORAGE_ERR_MAILBOX_NOT_FOUND, name);
@@ -651,21 +649,28 @@
 		}
 	}
 
-	count = 0;
-	while (rename(src, dest) < 0 && count < 2) {
-		if (errno != EEXIST && errno != ENOTEMPTY) {
-			mail_storage_set_critical(_storage,
-				"rename(%s, %s) failed: %m", src, dest);
-			return -1;
-		}
+	if (dest == NULL) {
+		/* absolute maildir path, delete the directory directly
+		   without any renaming */
+		dest = src;
+	} else {
+		count = 0;
+		while (rename(src, dest) < 0 && count < 2) {
+			if (errno != EEXIST && errno != ENOTEMPTY) {
+				mail_storage_set_critical(_storage,
+					"rename(%s, %s) failed: %m", src, dest);
+				return -1;
+			}
 
-		/* ..dir already existed? delete it and try again */
-		if (unlink_directory(dest, TRUE) < 0) {
-			mail_storage_set_critical(_storage,
-				"unlink_directory(%s) failed: %m", dest);
-			return -1;
+			/* already existed, delete it and try again */
+			if (unlink_directory(dest, TRUE) < 0) {
+				mail_storage_set_critical(_storage,
+					"unlink_directory(%s) failed: %m",
+					dest);
+				return -1;
+			}
+			count++;
 		}
-		count++;
 	}
 
 	if (unlink_directory(dest, TRUE) < 0 && errno != ENOTEMPTY) {
--- a/src/lib-storage/index/maildir/maildir-storage.h	Sat Apr 01 12:15:45 2006 +0300
+++ b/src/lib-storage/index/maildir/maildir-storage.h	Sat Apr 01 12:31:15 2006 +0300
@@ -7,6 +7,7 @@
 
 #define SUBSCRIPTION_FILE_NAME "subscriptions"
 #define MAILDIR_INDEX_PREFIX "dovecot.index"
+#define MAILDIR_UNLINK_DIRNAME MAILDIR_FS_SEP_S"DOVECOT-TRASHED"
 
 /* "base,S=123:2," means:
    <base> [<extra sep> <extra data> [..]] <info sep> 2 <flags sep> */