changeset 15134:eff1d11ce14b

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).
author Timo Sirainen <tss@iki.fi>
date Tue, 18 Sep 2012 18:40:17 +0300
parents 8cec3b4c43ca
children 1937b38f50f0
files src/lib-storage/list/mailbox-list-fs-iter.c src/lib-storage/list/mailbox-list-maildir-iter.c src/lib-storage/mailbox-guid-cache.c src/lib-storage/mailbox-list-private.h src/lib-storage/mailbox-list.c src/lib-storage/mailbox-list.h
diffstat 6 files changed, 51 insertions(+), 1 deletions(-) [+]
line wrap: on
line diff
--- 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);
--- 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);
--- 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 &
--- 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,
--- 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)
 {
--- 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