dovecot-2.0: lib-storage: Mailbox deletion API changed.

dovecot at dovecot.org dovecot at dovecot.org
Tue Feb 9 04:12:03 EET 2010


details:   http://hg.dovecot.org/dovecot-2.0/rev/1fd7833c16ca
changeset: 10676:1fd7833c16ca
user:      Timo Sirainen <tss at iki.fi>
date:      Tue Feb 09 04:11:53 2010 +0200
description:
lib-storage: Mailbox deletion API changed.
Mailbox deletion should now be free of race conditions. The actual file
deletion code is now responsibility of mailbox_list backend.

diffstat:

45 files changed, 837 insertions(+), 1158 deletions(-)
src/dsync/dsync-worker-local.c                    |   10 
src/imap/cmd-delete.c                             |   15 -
src/lib-storage/index/cydir/cydir-storage.c       |  117 --------
src/lib-storage/index/dbox-common/dbox-mail.h     |    2 
src/lib-storage/index/dbox-common/dbox-storage.c  |  123 ---------
src/lib-storage/index/dbox-common/dbox-storage.h  |    5 
src/lib-storage/index/dbox-multi/mdbox-map.c      |    5 
src/lib-storage/index/dbox-multi/mdbox-map.h      |    1 
src/lib-storage/index/dbox-multi/mdbox-storage.c  |   87 +-----
src/lib-storage/index/dbox-single/sdbox-storage.c |   31 --
src/lib-storage/index/index-storage.c             |   71 ++++-
src/lib-storage/index/index-storage.h             |    2 
src/lib-storage/index/index-transaction.c         |    6 
src/lib-storage/index/maildir/maildir-storage.c   |  274 +-------------------
src/lib-storage/index/maildir/maildir-storage.h   |    1 
src/lib-storage/index/mbox/mbox-storage.c         |   87 ------
src/lib-storage/index/raw/raw-storage.c           |   11 
src/lib-storage/index/shared/shared-list.c        |    3 
src/lib-storage/list/Makefile.am                  |    2 
src/lib-storage/list/mailbox-list-delete.c        |  284 +++++++++++++++++++++
src/lib-storage/list/mailbox-list-delete.h        |   14 +
src/lib-storage/list/mailbox-list-fs.c            |   52 +++
src/lib-storage/list/mailbox-list-fs.h            |    4 
src/lib-storage/list/mailbox-list-maildir.c       |   42 ++-
src/lib-storage/list/mailbox-list-maildir.h       |    4 
src/lib-storage/mail-copy.h                       |    3 
src/lib-storage/mail-storage-private.h            |    3 
src/lib-storage/mail-storage.c                    |   67 ++++
src/lib-storage/mail-storage.h                    |    6 
src/lib-storage/mailbox-list-private.h            |    4 
src/lib-storage/mailbox-list.c                    |   69 -----
src/lib-storage/mailbox-list.h                    |    2 
src/lib-storage/test-mailbox.c                    |    8 
src/plugins/acl/acl-mailbox-list.c                |   26 -
src/plugins/acl/acl-mailbox.c                     |   69 +++--
src/plugins/lazy-expunge/lazy-expunge-plugin.c    |  164 ++++++------
src/plugins/listescape/listescape-plugin.c        |   15 -
src/plugins/mail-log/mail-log-plugin.c            |    7 
src/plugins/notify/notify-noop.c                  |    6 
src/plugins/notify/notify-plugin-private.h        |    6 
src/plugins/notify/notify-plugin.c                |   33 +-
src/plugins/notify/notify-plugin.h                |   13 
src/plugins/notify/notify-storage.c               |   30 +-
src/plugins/quota/quota-storage.c                 |  116 +++-----
src/plugins/virtual/virtual-storage.c             |   95 -------

diffs (truncated from 3059 to 300 lines):

diff -r 9cefc944d82a -r 1fd7833c16ca src/dsync/dsync-worker-local.c
--- a/src/dsync/dsync-worker-local.c	Tue Feb 09 04:09:28 2010 +0200
+++ b/src/dsync/dsync-worker-local.c	Tue Feb 09 04:11:53 2010 +0200
@@ -1105,6 +1105,7 @@ local_worker_delete_mailbox(struct dsync
 		(struct local_dsync_worker *)_worker;
 	struct local_dsync_mailbox *lbox;
 	const mailbox_guid_t *mailbox = &dsync_box->mailbox_guid;
+	struct mailbox *box;
 
 	lbox = hash_table_lookup(worker->mailbox_hash, mailbox);
 	if (lbox == NULL) {
@@ -1116,12 +1117,15 @@ local_worker_delete_mailbox(struct dsync
 
 	mailbox_list_set_changelog_timestamp(lbox->ns->list,
 					     dsync_box->last_change);
-	if (mailbox_list_delete_mailbox(lbox->ns->list,
-					lbox->storage_name) < 0) {
+	box = mailbox_alloc(lbox->ns->list, lbox->storage_name, NULL, 0);
+	if (mailbox_delete(box) < 0) {
+		struct mail_storage *storage = mailbox_get_storage(box);
+
 		i_error("Can't delete mailbox %s: %s", lbox->storage_name,
-			mailbox_list_get_last_error(lbox->ns->list, NULL));
+			mail_storage_get_last_error(storage, NULL));
 		dsync_worker_set_failure(_worker);
 	}
+	mailbox_free(&box);
 	mailbox_list_set_changelog_timestamp(lbox->ns->list, (time_t)-1);
 }
 
diff -r 9cefc944d82a -r 1fd7833c16ca src/imap/cmd-delete.c
--- a/src/imap/cmd-delete.c	Tue Feb 09 04:09:28 2010 +0200
+++ b/src/imap/cmd-delete.c	Tue Feb 09 04:11:53 2010 +0200
@@ -7,7 +7,7 @@ bool cmd_delete(struct client_command_co
 {
 	struct client *client = cmd->client;
 	struct mail_namespace *ns;
-	struct mailbox *mailbox;
+	struct mailbox *box;
 	const char *name;
 
 	/* <mailbox> */
@@ -25,19 +25,18 @@ bool cmd_delete(struct client_command_co
 	if (ns == NULL)
 		return TRUE;
 
-	mailbox = mailbox_alloc(ns->list, name, NULL, 0);
+	box = mailbox_alloc(ns->list, name, NULL, 0);
 	if (client->mailbox != NULL &&
-	    mailbox_backends_equal(mailbox, client->mailbox)) {
+	    mailbox_backends_equal(box, client->mailbox)) {
 		/* deleting selected mailbox. close it first */
 		client_search_updates_free(client);
 		mailbox_free(&client->mailbox);
 	}
-	mailbox_free(&mailbox);
 
-	if (mailbox_list_delete_mailbox(ns->list, name) < 0)
-		client_send_list_error(cmd, ns->list);
-	else {
+	if (mailbox_delete(box) < 0)
+		client_send_storage_error(cmd, mailbox_get_storage(box));
+	else
 		client_send_tagline(cmd, "OK Delete completed.");
-	}
+	mailbox_free(&box);
 	return TRUE;
 }
diff -r 9cefc944d82a -r 1fd7833c16ca src/lib-storage/index/cydir/cydir-storage.c
--- a/src/lib-storage/index/cydir/cydir-storage.c	Tue Feb 09 04:09:28 2010 +0200
+++ b/src/lib-storage/index/cydir/cydir-storage.c	Tue Feb 09 04:11:53 2010 +0200
@@ -1,30 +1,15 @@
 /* Copyright (c) 2007-2010 Dovecot authors, see the included COPYING file */
 
 #include "lib.h"
-#include "array.h"
-#include "str.h"
-#include "mkdir-parents.h"
+#include "mail-copy.h"
 #include "index-mail.h"
-#include "mail-copy.h"
 #include "cydir-sync.h"
 #include "cydir-storage.h"
 
-#include <unistd.h>
-#include <dirent.h>
 #include <sys/stat.h>
-
-#define CYDIR_LIST_CONTEXT(obj) \
-	MODULE_CONTEXT(obj, cydir_mailbox_list_module)
-
-struct cydir_mailbox_list {
-	union mailbox_list_module_context module_ctx;
-};
 
 extern struct mail_storage cydir_storage;
 extern struct mailbox cydir_mailbox;
-
-static MODULE_CONTEXT_DEFINE_INIT(cydir_mailbox_list_module,
-				  &mailbox_list_module_register);
 
 static struct mail_storage *cydir_storage_alloc(void)
 {
@@ -126,97 +111,6 @@ cydir_mailbox_create(struct mailbox *box
 
 	return update == NULL ? 0 :
 		index_storage_mailbox_update(box, update);
-}
-
-static int
-cydir_delete_nonrecursive(struct mailbox_list *list, const char *path,
-			  const char *name)
-{
-	DIR *dir;
-	struct dirent *d;
-	string_t *full_path;
-	unsigned int dir_len;
-	bool unlinked_something = FALSE;
-
-	dir = opendir(path);
-	if (dir == NULL) {
-		if (!mailbox_list_set_error_from_errno(list)) {
-			mailbox_list_set_critical(list,
-				"opendir(%s) failed: %m", path);
-		}
-		return -1;
-	}
-
-	full_path = t_str_new(256);
-	str_append(full_path, path);
-	str_append_c(full_path, '/');
-	dir_len = str_len(full_path);
-
-	errno = 0;
-	while ((d = readdir(dir)) != NULL) {
-		if (d->d_name[0] == '.') {
-			/* skip . and .. */
-			if (d->d_name[1] == '\0')
-				continue;
-			if (d->d_name[1] == '.' && d->d_name[2] == '\0')
-				continue;
-		}
-
-		str_truncate(full_path, dir_len);
-		str_append(full_path, d->d_name);
-
-		/* trying to unlink() a directory gives either EPERM or EISDIR
-		   (non-POSIX). it doesn't really work anywhere in practise,
-		   so don't bother stat()ing the file first */
-		if (unlink(str_c(full_path)) == 0)
-			unlinked_something = TRUE;
-		else if (errno != ENOENT && errno != EISDIR && errno != EPERM) {
-			mailbox_list_set_critical(list, "unlink(%s) failed: %m",
-						  str_c(full_path));
-		}
-	}
-
-	if (closedir(dir) < 0) {
-		mailbox_list_set_critical(list, "closedir(%s) failed: %m",
-					  path);
-	}
-
-	if (rmdir(path) == 0)
-		unlinked_something = TRUE;
-	else if (errno != ENOENT && errno != ENOTEMPTY) {
-		mailbox_list_set_critical(list, "rmdir(%s) failed: %m", path);
-		return -1;
-	}
-
-	if (!unlinked_something) {
-		mailbox_list_set_error(list, MAIL_ERROR_NOTFOUND,
-			t_strdup_printf("Directory %s isn't empty, "
-					"can't delete it.", name));
-		return -1;
-	}
-	return 0;
-}
-
-static int
-cydir_list_delete_mailbox(struct mailbox_list *list, const char *name)
-{
-	struct cydir_mailbox_list *mlist = CYDIR_LIST_CONTEXT(list);
-	struct stat st;
-	const char *src;
-
-	/* delete the index and control directories */
-	if (mlist->module_ctx.super.delete_mailbox(list, name) < 0)
-		return -1;
-
-	/* check if the mailbox actually exists */
-	src = mailbox_list_get_path(list, name, MAILBOX_LIST_PATH_TYPE_MAILBOX);
-	if (stat(src, &st) != 0 && errno == ENOENT) {
-		mailbox_list_set_error(list, MAIL_ERROR_NOTFOUND,
-			T_MAIL_ERR_MAILBOX_NOT_FOUND(name));
-		return -1;
-	}
-
-	return cydir_delete_nonrecursive(list, src, name);
 }
 
 static void cydir_notify_changes(struct mailbox *box)
@@ -286,15 +180,7 @@ static void cydir_storage_add_list(struc
 static void cydir_storage_add_list(struct mail_storage *storage ATTR_UNUSED,
 				   struct mailbox_list *list)
 {
-	struct cydir_mailbox_list *mlist;
-
-	mlist = p_new(list->pool, struct cydir_mailbox_list, 1);
-	mlist->module_ctx.super = list->v;
-
 	list->v.iter_is_mailbox = cydir_list_iter_is_mailbox;
-	list->v.delete_mailbox = cydir_list_delete_mailbox;
-
-	MODULE_CONTEXT_SET(list, cydir_mailbox_list_module, mlist);
 }
 
 struct mail_storage cydir_storage = {
@@ -323,6 +209,7 @@ struct mailbox cydir_mailbox = {
 		index_storage_mailbox_close,
 		cydir_mailbox_create,
 		index_storage_mailbox_update,
+		index_storage_mailbox_delete,
 		index_storage_get_status,
 		NULL,
 		NULL,
diff -r 9cefc944d82a -r 1fd7833c16ca src/lib-storage/index/dbox-common/dbox-mail.h
--- a/src/lib-storage/index/dbox-common/dbox-mail.h	Tue Feb 09 04:09:28 2010 +0200
+++ b/src/lib-storage/index/dbox-common/dbox-mail.h	Tue Feb 09 04:11:53 2010 +0200
@@ -1,5 +1,7 @@
 #ifndef DBOX_MAIL_H
 #define DBOX_MAIL_H
+
+#include "index-mail.h"
 
 struct dbox_mail {
 	struct index_mail imail;
diff -r 9cefc944d82a -r 1fd7833c16ca src/lib-storage/index/dbox-common/dbox-storage.c
--- a/src/lib-storage/index/dbox-common/dbox-storage.c	Tue Feb 09 04:09:28 2010 +0200
+++ b/src/lib-storage/index/dbox-common/dbox-storage.c	Tue Feb 09 04:11:53 2010 +0200
@@ -2,10 +2,7 @@
 
 #include "lib.h"
 #include "ioloop.h"
-#include "randgen.h"
-#include "hex-binary.h"
 #include "mkdir-parents.h"
-#include "unlink-directory.h"
 #include "unlink-old-files.h"
 #include "mailbox-uidvalidity.h"
 #include "mailbox-list-private.h"
@@ -326,123 +323,3 @@ int dbox_list_rename_mailbox(struct mail
 	}
 	return 0;
 }
-
-static const char *dbox_get_trash_dest(const char *trash_dir)
-{
-	const char *path;
-	unsigned char randbuf[16];
-	struct stat st;
-
-	do {
-		random_fill_weak(randbuf, sizeof(randbuf));
-		path = t_strconcat(trash_dir, "/",
-			binary_to_hex(randbuf, sizeof(randbuf)), NULL);
-	} while (lstat(path, &st) == 0);
-	return path;
-}
-
-int dbox_list_delete_mailbox1(struct mailbox_list *list, const char *name,
-			      const char **trash_dest_r)
-{
-	struct stat st;
-	const char *path, *trash_dir, *trash_dest;
-	int ret;
-
-	path = mailbox_list_get_path(list, name,
-				     MAILBOX_LIST_PATH_TYPE_MAILBOX);
-	trash_dir = mailbox_list_get_path(list, NULL,
-					  MAILBOX_LIST_PATH_TYPE_DIR);
-	trash_dir = t_strconcat(trash_dir, "/"DBOX_TRASH_DIR_NAME, NULL);
-	trash_dest = *trash_dest_r = dbox_get_trash_dest(trash_dir);
-
-	/* first try renaming the actual mailbox to trash directory */
-	ret = rename(path, trash_dest);
-	if (ret < 0 && errno == ENOENT) {
-		/* either source mailbox doesn't exist or trash directory
-		   doesn't exist. try creating the trash and retrying. */
-		const char *origin;
-		mode_t mode;
-		gid_t gid;
-
-		mailbox_list_get_dir_permissions(list, NULL, &mode,
-						 &gid, &origin);
-		if (mkdir_parents_chgrp(trash_dir, mode, gid, origin) < 0 &&
-		    errno != EEXIST) {
-			mailbox_list_set_critical(list,
-				"mkdir(%s) failed: %m", trash_dir);
-			return -1;
-		}


More information about the dovecot-cvs mailing list