dovecot: Fixes to returning mailboxes

dovecot at dovecot.org dovecot at dovecot.org
Sun Jul 15 06:46:05 EEST 2007


details:   http://hg.dovecot.org/dovecot/rev/ed6c07975ccb
changeset: 6010:ed6c07975ccb
user:      Timo Sirainen <tss at iki.fi>
date:      Sun Jul 15 06:46:00 2007 +0300
description:
Fixes to returning mailboxes

diffstat:

2 files changed, 167 insertions(+), 158 deletions(-)
src/lib-storage/list/mailbox-list-maildir-iter.c  |  195 +++++++++++----------
src/lib-storage/list/mailbox-list-subscriptions.c |  130 ++++++--------

diffs (truncated from 385 to 300 lines):

diff -r 62f92a68fc72 -r ed6c07975ccb src/lib-storage/list/mailbox-list-maildir-iter.c
--- a/src/lib-storage/list/mailbox-list-maildir-iter.c	Sun Jul 15 06:45:36 2007 +0300
+++ b/src/lib-storage/list/mailbox-list-maildir-iter.c	Sun Jul 15 06:46:00 2007 +0300
@@ -22,81 +22,37 @@ struct maildir_list_iterate_context {
 	struct mailbox_info info;
 };
 
-static int
-maildir_fill_readdir(struct maildir_list_iterate_context *ctx,
-		     struct imap_match_glob *glob, bool update_only)
-{
-	DIR *dirp;
-	struct dirent *d;
-	const char *p, *mailbox_c;
-	string_t *mailbox;
-	enum mailbox_info_flags flags;
-	enum imap_match_result match;
-	struct mailbox_node *node;
+static void node_fix_parents(struct mailbox_node *node)
+{
+	/* Fix parent nodes' children states. also if we happened to create any
+	   of the parents, we need to mark them nonexistent. */
+	node = node->parent;
+	for (; node != NULL; node = node->parent) {
+		if ((node->flags & MAILBOX_MATCHED) == 0)
+			node->flags |= MAILBOX_NONEXISTENT;
+
+		node->flags |= MAILBOX_CHILDREN;
+		node->flags &= ~MAILBOX_NOCHILDREN;
+	}
+}
+
+static void maildir_fill_parents(struct maildir_list_iterate_context *ctx,
+				 struct imap_match_glob *glob, bool update_only,
+				 string_t *mailbox, const char *mailbox_c,
+				 enum mailbox_info_flags flags)
+{
+	struct mailbox_node *node;
+	const char *p;
+	char hierarchy_sep;
 	bool created;
-	char hierarchy_sep;
-	int ret;
-
-	dirp = opendir(ctx->dir);
-	if (dirp == NULL) {
-		if (errno != ENOENT) {
-			mailbox_list_set_critical(ctx->ctx.list,
-				"opendir(%s) failed: %m", ctx->dir);
-			return -1;
-		}
-		return 0;
-	}
 
 	hierarchy_sep = ctx->ctx.list->hierarchy_sep;
 
 	t_push();
-	mailbox = t_str_new(PATH_MAX);
-	while ((d = readdir(dirp)) != NULL) {
-		const char *fname = d->d_name;
-
-		if (fname[0] != hierarchy_sep)
-			continue;
-
-		/* skip . and .. */
-		if (fname[0] == '.' &&
-		    (fname[1] == '\0' || (fname[1] == '.' && fname[2] == '\0')))
-			continue;
-
-		/* make sure the pattern matches */
-		str_truncate(mailbox, 0);
-		str_append(mailbox, ctx->prefix);
-		str_append(mailbox, fname + 1);
-                mailbox_c = str_c(mailbox);
-
-		match = imap_match(glob, mailbox_c);
-		if ((match & (IMAP_MATCH_YES | IMAP_MATCH_PARENT)) == 0)
-			continue;
-
-		/* check if this is an actual mailbox */
-		flags = 0;
-		ret = ctx->ctx.list->v.
-			iter_is_mailbox(&ctx->ctx, ctx->dir, fname,
-					mailbox_list_get_file_type(d), &flags);
-		if (ret < 0) {
-			t_pop();
-			return -1;
-		}
-		if (ret == 0)
-			continue;
-
-		if ((match & IMAP_MATCH_PARENT) != 0) {
-			/* get the name of the parent mailbox that matches */
-			t_push();
-			while ((p = strrchr(mailbox_c,
-					    hierarchy_sep)) != NULL) {
-				str_truncate(mailbox, (size_t) (p-mailbox_c));
-				mailbox_c = str_c(mailbox);
-				if (imap_match(glob, mailbox_c) ==
-				    IMAP_MATCH_YES)
-					break;
-			}
-			i_assert(p != NULL);
-
+	while ((p = strrchr(mailbox_c, hierarchy_sep)) != NULL) {
+		str_truncate(mailbox, (size_t) (p-mailbox_c));
+		mailbox_c = str_c(mailbox);
+		if (imap_match(glob, mailbox_c) == IMAP_MATCH_YES) {
 			created = FALSE;
 			node = update_only ?
 				mailbox_tree_lookup(ctx->tree_ctx, mailbox_c) :
@@ -110,11 +66,85 @@ maildir_fill_readdir(struct maildir_list
 				}
 				if (!update_only)
 					node->flags |= MAILBOX_MATCHED;
-				node->flags |= MAILBOX_CHILDREN;
+				node->flags |= MAILBOX_CHILDREN | flags;
 				node->flags &= ~MAILBOX_NOCHILDREN;
+				node_fix_parents(node);
 			}
-
+		}
+	}
+	t_pop();
+}
+
+static int
+maildir_fill_readdir(struct maildir_list_iterate_context *ctx,
+		     struct imap_match_glob *glob, bool update_only)
+{
+	DIR *dirp;
+	struct dirent *d;
+	const char *mailbox_c;
+	string_t *mailbox;
+	enum mailbox_info_flags flags;
+	enum imap_match_result match;
+	struct mailbox_node *node;
+	bool created;
+	char hierarchy_sep;
+	int ret;
+
+	dirp = opendir(ctx->dir);
+	if (dirp == NULL) {
+		if (errno != ENOENT) {
+			mailbox_list_set_critical(ctx->ctx.list,
+				"opendir(%s) failed: %m", ctx->dir);
+			return -1;
+		}
+		return 0;
+	}
+
+	hierarchy_sep = ctx->ctx.list->hierarchy_sep;
+
+	t_push();
+	mailbox = t_str_new(PATH_MAX);
+	while ((d = readdir(dirp)) != NULL) {
+		const char *fname = d->d_name;
+
+		if (fname[0] != hierarchy_sep)
+			continue;
+
+		/* skip . and .. */
+		if (fname[0] == '.' &&
+		    (fname[1] == '\0' || (fname[1] == '.' && fname[2] == '\0')))
+			continue;
+
+		/* make sure the pattern matches */
+		str_truncate(mailbox, 0);
+		str_append(mailbox, ctx->prefix);
+		str_append(mailbox, fname + 1);
+                mailbox_c = str_c(mailbox);
+
+		match = imap_match(glob, mailbox_c);
+		if ((match & (IMAP_MATCH_YES | IMAP_MATCH_PARENT)) == 0)
+			continue;
+
+		/* check if this is an actual mailbox */
+		flags = 0;
+		ret = ctx->ctx.list->v.
+			iter_is_mailbox(&ctx->ctx, ctx->dir, fname,
+					mailbox_list_get_file_type(d), &flags);
+		if (ret < 0) {
 			t_pop();
+			return -1;
+		}
+		if (ret == 0)
+			continue;
+
+		/* we know the children flags ourself, so ignore if any of
+		   them were set. */
+		flags &= ~(MAILBOX_NOINFERIORS |
+			   MAILBOX_CHILDREN | MAILBOX_NOCHILDREN);
+
+		if ((match & IMAP_MATCH_PARENT) != 0) {
+			maildir_fill_parents(ctx, glob, update_only,
+					     mailbox, mailbox_c, flags);
 		} else {
 			created = FALSE;
 			node = update_only ?
@@ -129,25 +159,8 @@ maildir_fill_readdir(struct maildir_list
 					node->flags &= ~MAILBOX_NONEXISTENT;
 				if (!update_only)
 					node->flags |= MAILBOX_MATCHED;
-			}
-		}
-		if (node != NULL) {
-			/* apply flags given by storage. we know the children
-			   flags ourself, so ignore if any of them were set. */
-			node->flags |= flags & ~(MAILBOX_NOINFERIORS |
-						 MAILBOX_CHILDREN |
-						 MAILBOX_NOCHILDREN);
-
-			/* Fix parent nodes' children states. also if we
-			   happened to create any of the parents, we need to
-			   mark them nonexistent. */
-			node = node->parent;
-			for (; node != NULL; node = node->parent) {
-				if ((node->flags & MAILBOX_MATCHED) == 0)
-					node->flags |= MAILBOX_NONEXISTENT;
-
-				node->flags |= MAILBOX_CHILDREN;
-				node->flags &= ~MAILBOX_NOCHILDREN;
+				node->flags |= flags;
+				node_fix_parents(node);
 			}
 		}
 	}
diff -r 62f92a68fc72 -r ed6c07975ccb src/lib-storage/list/mailbox-list-subscriptions.c
--- a/src/lib-storage/list/mailbox-list-subscriptions.c	Sun Jul 15 06:45:36 2007 +0300
+++ b/src/lib-storage/list/mailbox-list-subscriptions.c	Sun Jul 15 06:46:00 2007 +0300
@@ -7,15 +7,68 @@
 #include "mailbox-list-private.h"
 #include "mailbox-list-subscriptions.h"
 
-static void nodes_add_child_subscribed(struct mailbox_node *node)
+static void node_fix_parents(struct mailbox_node *node)
 {
-	while (node != NULL) {
-		if (node->children != NULL) {
-			node->flags |= MAILBOX_MATCHED |
-				MAILBOX_CHILD_SUBSCRIBED;
-		}
-		node = node->next;
+	/* If we happened to create any of the parents, we need to mark them
+	   nonexistent. */
+	node = node->parent;
+	for (; node != NULL; node = node->parent) {
+		if ((node->flags & MAILBOX_MATCHED) == 0)
+			node->flags |= MAILBOX_NONEXISTENT;
 	}
+}
+
+static void
+mailbox_list_subscription_add(struct mailbox_list_iterate_context *ctx,
+			      struct mailbox_tree_context *tree_ctx,
+			      struct imap_match_glob *glob,
+			      bool update_only, const char *name)
+{
+	struct mailbox_node *node;
+	enum mailbox_info_flags create_flags, always_flags;
+	enum imap_match_result match;
+	const char *p;
+	bool created;
+
+	create_flags = (update_only ||
+			(ctx->flags & MAILBOX_LIST_ITER_RETURN_NO_FLAGS) == 0) ?
+		(MAILBOX_NONEXISTENT | MAILBOX_NOCHILDREN) : 0;
+	always_flags = MAILBOX_SUBSCRIBED;
+
+	t_push();
+	for (;;) {
+		created = FALSE;
+		match = imap_match(glob, name);
+		if (match == IMAP_MATCH_YES) {
+			node = update_only ?
+				mailbox_tree_lookup(tree_ctx, name) :
+				mailbox_tree_get(tree_ctx, name, &created);
+			if (created) {
+				node->flags = create_flags;
+				if (create_flags != 0)
+					node_fix_parents(node);
+			}
+			if (node != NULL) {
+				if (!update_only)
+					node->flags |= MAILBOX_MATCHED;
+				node->flags |= always_flags;
+			}
+		} else if ((match & IMAP_MATCH_PARENT) == 0)
+			break;
+
+		if ((ctx->flags & MAILBOX_LIST_ITER_SELECT_RECURSIVEMATCH) == 0)
+			break;
+
+		/* see if parent matches */
+		p = strrchr(name, ctx->list->hierarchy_sep);
+		if (p == NULL)
+			break;
+
+		name = t_strdup_until(name, p);
+		create_flags &= ~MAILBOX_NOCHILDREN;


More information about the dovecot-cvs mailing list