void mailbox_list_subscriptions_fill(struct mailbox_list_iterate_context *ctx,
				     struct mailbox_tree_context *tree,
				     bool default_nonexistent)
{
	struct mailbox_list_iter_update_context update_ctx;
	struct mailbox_tree_iterate_context *iter;
	const char *name;

	memset(&update_ctx, 0, sizeof(update_ctx));
	update_ctx.iter_ctx = ctx;
	update_ctx.tree_ctx = tree;
	update_ctx.glob = ctx->glob;
	update_ctx.leaf_flags = MAILBOX_SUBSCRIBED;
	if (default_nonexistent)
		update_ctx.leaf_flags |= MAILBOX_NONEXISTENT;
	update_ctx.parent_flags = MAILBOX_CHILD_SUBSCRIBED;
	update_ctx.match_parents =
		(ctx->flags & MAILBOX_LIST_ITER_SELECT_RECURSIVEMATCH) != 0;

	iter = mailbox_tree_iterate_init(ctx->list->subscriptions, NULL,
					 MAILBOX_SUBSCRIBED);
	while (mailbox_tree_iterate_next(iter, &name) != NULL)
		mailbox_list_iter_update(&update_ctx, name);
	mailbox_tree_iterate_deinit(&iter);
}
struct mailbox_list_iterate_context *
mailbox_list_subscriptions_iter_init(struct mailbox_list *list,
				     const char *const *patterns,
				     enum mailbox_list_iter_flags flags)
{
	struct subscriptions_mailbox_list_iterate_context *ctx;
	pool_t pool;
	char sep = mail_namespace_get_sep(list->ns);

	pool = pool_alloconly_create("mailbox list subscriptions iter", 1024);
	ctx = p_new(pool, struct subscriptions_mailbox_list_iterate_context, 1);
	ctx->ctx.pool = pool;
	ctx->ctx.list = list;
	ctx->ctx.flags = flags;
	ctx->ctx.glob = imap_match_init_multiple(pool, patterns, TRUE, sep);
	array_create(&ctx->ctx.module_contexts, pool, sizeof(void *), 5);

	ctx->tree = mailbox_tree_init(sep);
	mailbox_list_subscriptions_fill(&ctx->ctx, ctx->tree, FALSE);

	ctx->info.ns = list->ns;
	/* the tree usually has only those entries we want to iterate through,
	   but there are also non-matching root entries (e.g. "LSUB foo/%" will
	   include the "foo"), which we'll drop with MAILBOX_MATCHED. */
	ctx->iter = mailbox_tree_iterate_init(ctx->tree, NULL, MAILBOX_MATCHED);
	return &ctx->ctx;
}
	    (flags & MAILBOX_LIST_ITER_RETURN_NO_FLAGS) == 0) {
		/* Add/update mailbox list with flags */
		bool update_only =
			(flags & MAILBOX_LIST_ITER_SELECT_SUBSCRIBED) != 0;

		T_BEGIN {
			ret = maildir_fill_readdir(ctx, ctx->ctx.glob,
						   update_only);
		} T_END;
		if (ret < 0) {
			ctx->ctx.failed = TRUE;
			return &ctx->ctx;
		}
	}

	ctx->tree_iter = mailbox_tree_iterate_init(ctx->tree_ctx, NULL,
						   MAILBOX_MATCHED);
	return &ctx->ctx;
}

int maildir_list_iter_deinit(struct mailbox_list_iterate_context *_ctx)
{
	struct maildir_list_iterate_context *ctx =
		(struct maildir_list_iterate_context *)_ctx;
	int ret = _ctx->failed ? -1 : 0;

	if (ctx->tree_iter != NULL)
		mailbox_tree_iterate_deinit(&ctx->tree_iter);
	mailbox_tree_deinit(&ctx->tree_ctx);
	pool_unref(&ctx->ctx.pool);
	return ret;
}