dovecot-2.1: lib-storage: MAILBOX_LIST_ITER_SKIP_ALIASES now ski...

dovecot at dovecot.org dovecot at dovecot.org
Tue Sep 18 18:45:16 EEST 2012


details:   http://hg.dovecot.org/dovecot-2.1/rev/eff1d11ce14b
changeset: 14706:eff1d11ce14b
user:      Timo Sirainen <tss at iki.fi>
date:      Tue Sep 18 18:40:17 2012 +0300
description:
lib-storage: MAILBOX_LIST_ITER_SKIP_ALIASES now skips also "alias symlinks"
An "alias symlink" is a symlink that points to the same directory. These can
safely be skipped when iterating through all mails in all mailboxes (unlike
other symlinks that may point to external storages).

diffstat:

 src/lib-storage/list/mailbox-list-fs-iter.c      |   6 ++++
 src/lib-storage/list/mailbox-list-maildir-iter.c |   5 +++
 src/lib-storage/mailbox-guid-cache.c             |   1 +
 src/lib-storage/mailbox-list-private.h           |   3 ++
 src/lib-storage/mailbox-list.c                   |  33 ++++++++++++++++++++++++
 src/lib-storage/mailbox-list.h                   |   4 ++-
 6 files changed, 51 insertions(+), 1 deletions(-)

diffs (112 lines):

diff -r 8cec3b4c43ca -r eff1d11ce14b src/lib-storage/list/mailbox-list-fs-iter.c
--- a/src/lib-storage/list/mailbox-list-fs-iter.c	Fri Sep 14 20:51:02 2012 +0300
+++ b/src/lib-storage/list/mailbox-list-fs-iter.c	Tue Sep 18 18:40:17 2012 +0300
@@ -183,6 +183,12 @@
 		/* mailbox doesn't match any patterns, we don't care about it */
 		return 0;
 	}
+	if ((ctx->ctx.flags & MAILBOX_LIST_ITER_SKIP_ALIASES) != 0) {
+		ret = mailbox_list_dirent_is_alias_symlink(ctx->ctx.list,
+							   dir_path, d);
+		if (ret != 0)
+			return ret < 0 ? -1 : 0;
+	}
 	ret = ctx->ctx.list->v.
 		get_mailbox_flags(ctx->ctx.list, dir_path, d->d_name,
 				  mailbox_list_get_file_type(d), &info_flags);
diff -r 8cec3b4c43ca -r eff1d11ce14b src/lib-storage/list/mailbox-list-maildir-iter.c
--- a/src/lib-storage/list/mailbox-list-maildir-iter.c	Fri Sep 14 20:51:02 2012 +0300
+++ b/src/lib-storage/list/mailbox-list-maildir-iter.c	Tue Sep 18 18:40:17 2012 +0300
@@ -323,6 +323,11 @@
 	if (maildir_delete_trash_dir(ctx, fname))
 		return 0;
 
+	if ((ctx->ctx.flags & MAILBOX_LIST_ITER_SKIP_ALIASES) != 0) {
+		ret = mailbox_list_dirent_is_alias_symlink(list, ctx->dir, d);
+		if (ret != 0)
+			return ret < 0 ? -1 : 0;
+	}
 	T_BEGIN {
 		ret = list->v.get_mailbox_flags(list, ctx->dir, fname,
 				mailbox_list_get_file_type(d), &flags);
diff -r 8cec3b4c43ca -r eff1d11ce14b src/lib-storage/mailbox-guid-cache.c
--- a/src/lib-storage/mailbox-guid-cache.c	Fri Sep 14 20:51:02 2012 +0300
+++ b/src/lib-storage/mailbox-guid-cache.c	Tue Sep 18 18:40:17 2012 +0300
@@ -56,6 +56,7 @@
 	list->guid_cache_errors = FALSE;
 
 	ctx = mailbox_list_iter_init(list, "*",
+				     MAILBOX_LIST_ITER_SKIP_ALIASES |
 				     MAILBOX_LIST_ITER_NO_AUTO_BOXES);
 	while ((info = mailbox_list_iter_next(ctx)) != NULL) {
 		if ((info->flags &
diff -r 8cec3b4c43ca -r eff1d11ce14b src/lib-storage/mailbox-list-private.h
--- a/src/lib-storage/mailbox-list-private.h	Fri Sep 14 20:51:02 2012 +0300
+++ b/src/lib-storage/mailbox-list-private.h	Tue Sep 18 18:40:17 2012 +0300
@@ -192,6 +192,9 @@
 
 bool mailbox_list_name_is_too_large(const char *name, char sep);
 enum mailbox_list_file_type mailbox_list_get_file_type(const struct dirent *d);
+int mailbox_list_dirent_is_alias_symlink(struct mailbox_list *list,
+					 const char *dir_path,
+					 const struct dirent *d);
 bool mailbox_list_try_get_absolute_path(struct mailbox_list *list,
 					const char **name);
 int mailbox_list_create_missing_index_dir(struct mailbox_list *list,
diff -r 8cec3b4c43ca -r eff1d11ce14b src/lib-storage/mailbox-list.c
--- a/src/lib-storage/mailbox-list.c	Fri Sep 14 20:51:02 2012 +0300
+++ b/src/lib-storage/mailbox-list.c	Tue Sep 18 18:40:17 2012 +0300
@@ -1282,6 +1282,39 @@
 	return type;
 }
 
+int mailbox_list_dirent_is_alias_symlink(struct mailbox_list *list,
+					 const char *dir_path,
+					 const struct dirent *d)
+{
+	struct stat st;
+	int ret;
+
+	if (mailbox_list_get_file_type(d) == MAILBOX_LIST_FILE_TYPE_SYMLINK)
+		return 1;
+
+	T_BEGIN {
+		const char *path, *readlink;
+
+		path = t_strconcat(dir_path, "/", d->d_name, NULL);
+		if (lstat(path, &st) < 0) {
+			mailbox_list_set_critical(list,
+						  "lstat(%s) failed: %m", path);
+			ret = -1;
+		} else if (!S_ISLNK(st.st_mode)) {
+			ret = 0;
+		} else if (t_readlink(path, &linkpath) < 0) {
+			i_error("readlink(%s) failed: %m", path);
+			ret = -1;
+		} else {
+			/* it's an alias only if it points to the same
+			   directory */
+			ret = strchr(linkpath, '/') == NULL ? 1 : 0;
+		}
+	} T_END;
+	return ret;
+}
+
+
 static bool
 mailbox_list_try_get_home_path(struct mailbox_list *list, const char **name)
 {
diff -r 8cec3b4c43ca -r eff1d11ce14b src/lib-storage/mailbox-list.h
--- a/src/lib-storage/mailbox-list.h	Fri Sep 14 20:51:02 2012 +0300
+++ b/src/lib-storage/mailbox-list.h	Tue Sep 18 18:40:17 2012 +0300
@@ -64,7 +64,9 @@
 	   physically exist */
 	MAILBOX_LIST_ITER_NO_AUTO_BOXES		= 0x000004,
 
-	/* For mailbox_list_iter_init_namespaces(): Skip namespaces that
+	/* Skip all kinds of mailbox aliases. This typically includes symlinks
+	   that point to the same directory. Also when iterating with
+	   mailbox_list_iter_init_namespaces() skip namespaces that
 	   have alias_for set. */
 	MAILBOX_LIST_ITER_SKIP_ALIASES		= 0x000008,
 	/* For mailbox_list_iter_init_namespaces(): '*' in a pattern doesn't


More information about the dovecot-cvs mailing list