]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
dsync: Add escape_char to dsync-mailbox-tree
authorTimo Sirainen <timo.sirainen@open-xchange.com>
Tue, 1 Mar 2022 13:06:14 +0000 (08:06 -0500)
committerMarkus Valentin <markus.valentin@open-xchange.com>
Mon, 21 Mar 2022 09:06:53 +0000 (10:06 +0100)
This will be used by the following changes.

src/doveadm/dsync/dsync-brain-mailbox-tree.c
src/doveadm/dsync/dsync-brain-private.h
src/doveadm/dsync/dsync-ibc-pipe.c
src/doveadm/dsync/dsync-ibc-private.h
src/doveadm/dsync/dsync-ibc-stream.c
src/doveadm/dsync/dsync-ibc.c
src/doveadm/dsync/dsync-ibc.h
src/doveadm/dsync/dsync-mailbox-tree-private.h
src/doveadm/dsync/dsync-mailbox-tree.c
src/doveadm/dsync/dsync-mailbox-tree.h
src/doveadm/dsync/test-dsync-mailbox-tree-sync.c

index 0539571295dfc743ecbd1110ef4585b6da4d5d4b..007082cef8123f7f52593400fb5585ce8cbc6d21 100644 (file)
 static void dsync_brain_check_namespaces(struct dsync_brain *brain)
 {
        struct mail_namespace *ns, *first_ns = NULL;
-       char sep;
+       char sep, escape_char;
 
        i_assert(brain->hierarchy_sep == '\0');
+       i_assert(brain->escape_char == '\0');
 
        for (ns = brain->user->namespaces; ns != NULL; ns = ns->next) {
                if (!dsync_brain_want_namespace(brain, ns))
                        continue;
 
                sep = mail_namespace_get_sep(ns);
+               escape_char = mailbox_list_get_settings(ns->list)->vname_escape_char;
                if (first_ns == NULL) {
                        brain->hierarchy_sep = sep;
+                       brain->escape_char = escape_char;
                        first_ns = ns;
                } else if (brain->hierarchy_sep != sep) {
                        i_fatal("Synced namespaces have conflicting separators "
                                "('%c' for prefix=\"%s\", '%c' for prefix=\"%s\")",
                                brain->hierarchy_sep, first_ns->prefix,
                                sep, ns->prefix);
+               } else if (brain->escape_char != escape_char) {
+                       i_fatal("Synced namespaces have conflicting escape chars "
+                               "('%c' for prefix=\"%s\", '%c' for prefix=\"%s\")",
+                               brain->escape_char, first_ns->prefix,
+                               escape_char, ns->prefix);
                }
        }
        if (brain->hierarchy_sep != '\0')
@@ -47,10 +55,12 @@ void dsync_brain_mailbox_trees_init(struct dsync_brain *brain)
        dsync_brain_check_namespaces(brain);
 
        brain->local_mailbox_tree =
-               dsync_mailbox_tree_init(brain->hierarchy_sep, brain->alt_char);
+               dsync_mailbox_tree_init(brain->hierarchy_sep,
+                                       brain->escape_char, brain->alt_char);
        /* we'll convert remote mailbox names to use our own separator */
        brain->remote_mailbox_tree =
-               dsync_mailbox_tree_init(brain->hierarchy_sep, brain->alt_char);
+               dsync_mailbox_tree_init(brain->hierarchy_sep,
+                                       brain->escape_char, brain->alt_char);
 
        /* fill the local mailbox tree */
        for (ns = brain->user->namespaces; ns != NULL; ns = ns->next) {
@@ -138,7 +148,8 @@ void dsync_brain_send_mailbox_tree_deletes(struct dsync_brain *brain)
        deletes = dsync_mailbox_tree_get_deletes(brain->local_mailbox_tree,
                                                 &count);
        dsync_ibc_send_mailbox_deletes(brain->ibc, deletes, count,
-                                      brain->hierarchy_sep);
+                                      brain->hierarchy_sep,
+                                      brain->escape_char);
 
        brain->state = DSYNC_STATE_RECV_MAILBOX_TREE;
 }
@@ -500,14 +511,15 @@ bool dsync_brain_recv_mailbox_tree_deletes(struct dsync_brain *brain)
        const char *status;
        const struct dsync_mailbox_delete *deletes;
        unsigned int i, count;
-       char sep;
+       char sep, escape_char;
 
        if (dsync_ibc_recv_mailbox_deletes(brain->ibc, &deletes, &count,
-                                          &sep) == 0)
+                                          &sep, &escape_char) == 0)
                return FALSE;
 
        /* apply remote's mailbox deletions based on our local tree */
-       dsync_mailbox_tree_set_remote_sep(brain->local_mailbox_tree, sep);
+       dsync_mailbox_tree_set_remote_chars(brain->local_mailbox_tree, sep,
+                                           escape_char);
        for (i = 0; i < count; i++) {
                dsync_brain_mailbox_tree_add_delete(brain->local_mailbox_tree,
                                                    brain->remote_mailbox_tree,
@@ -526,8 +538,9 @@ bool dsync_brain_recv_mailbox_tree_deletes(struct dsync_brain *brain)
        /* apply local mailbox deletions based on remote tree */
        deletes = dsync_mailbox_tree_get_deletes(brain->local_mailbox_tree,
                                                 &count);
-       dsync_mailbox_tree_set_remote_sep(brain->remote_mailbox_tree,
-                                         brain->hierarchy_sep);
+       dsync_mailbox_tree_set_remote_chars(brain->remote_mailbox_tree,
+                                           brain->hierarchy_sep,
+                                           brain->escape_char);
        for (i = 0; i < count; i++) {
                dsync_brain_mailbox_tree_add_delete(brain->remote_mailbox_tree,
                                                    brain->local_mailbox_tree,
index 8dc8f609c12059f7dfc7e42913ede80d44f973e8..984970349b5fbb4bd2747c842aafb260314ffa1a 100644 (file)
@@ -72,7 +72,7 @@ struct dsync_brain {
        const char *lock_path;
        struct file_lock *lock;
 
-       char hierarchy_sep;
+       char hierarchy_sep, escape_char;
        struct dsync_mailbox_tree *local_mailbox_tree;
        struct dsync_mailbox_tree *remote_mailbox_tree;
        struct dsync_mailbox_tree_iter *local_tree_iter;
index d9c33c93d020f97e98ece8fa123929fe8a033c83..1b8886e9c1ab7d015afa4de24b22c1692201c5da 100644 (file)
@@ -41,6 +41,7 @@ struct item {
                        const struct dsync_mailbox_delete *deletes;
                        unsigned int count;
                        char hierarchy_sep;
+                       char escape_char;
                } mailbox_delete;
                struct {
                        const char *error;
@@ -289,7 +290,8 @@ dsync_ibc_pipe_recv_mailbox_tree_node(struct dsync_ibc *ibc,
 static void
 dsync_ibc_pipe_send_mailbox_deletes(struct dsync_ibc *ibc,
                                    const struct dsync_mailbox_delete *deletes,
-                                   unsigned int count, char hierarchy_sep)
+                                   unsigned int count, char hierarchy_sep,
+                                   char escape_char)
 {
        struct dsync_ibc_pipe *pipe = (struct dsync_ibc_pipe *)ibc;
        struct item *item;
@@ -301,13 +303,15 @@ dsync_ibc_pipe_send_mailbox_deletes(struct dsync_ibc *ibc,
        item->u.mailbox_delete.deletes = deletes;
        item->u.mailbox_delete.count = count;
        item->u.mailbox_delete.hierarchy_sep = hierarchy_sep;
+       item->u.mailbox_delete.escape_char = escape_char;
 }
 
 static enum dsync_ibc_recv_ret
 dsync_ibc_pipe_recv_mailbox_deletes(struct dsync_ibc *ibc,
                                    const struct dsync_mailbox_delete **deletes_r,
                                    unsigned int *count_r,
-                                   char *hierarchy_sep_r)
+                                   char *hierarchy_sep_r,
+                                   char *escape_char_r)
 {
        struct dsync_ibc_pipe *pipe = (struct dsync_ibc_pipe *)ibc;
        struct item *item;
@@ -322,6 +326,7 @@ dsync_ibc_pipe_recv_mailbox_deletes(struct dsync_ibc *ibc,
        *deletes_r = item->u.mailbox_delete.deletes;
        *count_r = item->u.mailbox_delete.count;
        *hierarchy_sep_r = item->u.mailbox_delete.hierarchy_sep;
+       *escape_char_r = item->u.mailbox_delete.escape_char;
        return DSYNC_IBC_RECV_RET_OK;
 }
 
index 0fcc0e588a59ff0bb855eafe5c32f7d6f66ea50b..c055aca2c43e21af7dcb8ffad4f12ddf4b35fd80 100644 (file)
@@ -31,12 +31,14 @@ struct dsync_ibc_vfuncs {
 
        void (*send_mailbox_deletes)(struct dsync_ibc *ibc,
                                     const struct dsync_mailbox_delete *deletes,
-                                    unsigned int count, char hierarchy_sep);
+                                    unsigned int count, char hierarchy_sep,
+                                    char escape_char);
        enum dsync_ibc_recv_ret
                (*recv_mailbox_deletes)(struct dsync_ibc *ibc,
                                        const struct dsync_mailbox_delete **deletes_r,
                                        unsigned int *count_r,
-                                       char *hierarchy_sep_r);
+                                       char *hierarchy_sep_r,
+                                       char *escape_char_r);
 
        void (*send_mailbox)(struct dsync_ibc *ibc,
                             const struct dsync_mailbox *dsync_box);
index f440b0654393698b562663ac15131774c35d371b..17115b0833fcc2ce27abe259c28cb98d578bd8df 100644 (file)
@@ -96,7 +96,7 @@ static const struct {
        { .name = "mailbox_delete",
          .chr = 'D',
          .required_keys = "hierarchy_sep",
-         .optional_keys = "mailboxes dirs unsubscribes"
+         .optional_keys = "escape_char mailboxes dirs unsubscribes"
        },
        { .name = "mailbox",
          .chr = 'B',
@@ -1160,7 +1160,8 @@ dsync_ibc_stream_encode_delete(string_t *str,
 static void
 dsync_ibc_stream_send_mailbox_deletes(struct dsync_ibc *_ibc,
                                      const struct dsync_mailbox_delete *deletes,
-                                     unsigned int count, char hierarchy_sep)
+                                     unsigned int count, char hierarchy_sep,
+                                     char escape_char)
 {
        struct dsync_ibc_stream *ibc = (struct dsync_ibc_stream *)_ibc;
        struct dsync_serializer_encoder *encoder;
@@ -1173,6 +1174,8 @@ dsync_ibc_stream_send_mailbox_deletes(struct dsync_ibc *_ibc,
        encoder = dsync_ibc_send_encode_begin(ibc, ITEM_MAILBOX_DELETE);
        sep[0] = hierarchy_sep; sep[1] = '\0';
        dsync_serializer_encode_add(encoder, "hierarchy_sep", sep);
+       sep[0] = escape_char; sep[1] = '\0';
+       dsync_serializer_encode_add(encoder, "escape_char", sep);
 
        substr = t_str_new(128);
        dsync_ibc_stream_encode_delete(substr, encoder, deletes, count,
@@ -1213,7 +1216,8 @@ decode_mailbox_deletes(ARRAY_TYPE(dsync_mailbox_delete) *deletes,
 static enum dsync_ibc_recv_ret
 dsync_ibc_stream_recv_mailbox_deletes(struct dsync_ibc *_ibc,
                                      const struct dsync_mailbox_delete **deletes_r,
-                                     unsigned int *count_r, char *hierarchy_sep_r)
+                                     unsigned int *count_r, char *hierarchy_sep_r,
+                                     char *escape_char_r)
 {
        struct dsync_ibc_stream *ibc = (struct dsync_ibc_stream *)_ibc;
        struct dsync_deserializer_decoder *decoder;
@@ -1235,6 +1239,16 @@ dsync_ibc_stream_recv_mailbox_deletes(struct dsync_ibc *_ibc,
        }
        *hierarchy_sep_r = value[0];
 
+       if (!dsync_deserializer_decode_try(decoder, "escape_char", &value))
+               *escape_char_r = '\0';
+       else {
+               if (strlen(value) > 1) {
+                       dsync_ibc_input_error(ibc, decoder, "Invalid escape_char '%s'", value);
+                       return DSYNC_IBC_RECV_RET_TRYAGAIN;
+               }
+               *escape_char_r = value[0];
+       }
+
        if (dsync_deserializer_decode_try(decoder, "mailboxes", &value) &&
            decode_mailbox_deletes(&deletes, value,
                                   DSYNC_MAILBOX_DELETE_TYPE_MAILBOX) < 0) {
index dea7a23d97ab1e203f5ef8f016c459ed5a7c07df..ede7b837eb460557ba111969c32e2d3e70f9a4e4 100644 (file)
@@ -88,11 +88,12 @@ dsync_ibc_recv_mailbox_tree_node(struct dsync_ibc *ibc,
 enum dsync_ibc_send_ret
 dsync_ibc_send_mailbox_deletes(struct dsync_ibc *ibc,
                               const struct dsync_mailbox_delete *deletes,
-                              unsigned int count, char hierarchy_sep)
+                              unsigned int count, char hierarchy_sep,
+                              char escape_char)
 {
        T_BEGIN {
                ibc->v.send_mailbox_deletes(ibc, deletes, count,
-                                             hierarchy_sep);
+                                           hierarchy_sep, escape_char);
        } T_END;
        return dsync_ibc_send_ret(ibc);
 }
@@ -100,10 +101,11 @@ dsync_ibc_send_mailbox_deletes(struct dsync_ibc *ibc,
 enum dsync_ibc_recv_ret
 dsync_ibc_recv_mailbox_deletes(struct dsync_ibc *ibc,
                               const struct dsync_mailbox_delete **deletes_r,
-                              unsigned int *count_r, char *hierarchy_sep_r)
+                              unsigned int *count_r, char *hierarchy_sep_r,
+                              char *escape_char_r)
 {
        return ibc->v.recv_mailbox_deletes(ibc, deletes_r, count_r,
-                                            hierarchy_sep_r);
+                                          hierarchy_sep_r, escape_char_r);
 }
 
 enum dsync_ibc_send_ret
index 5b07e2a3f1b12fd8b275944cc125ae3bd35f12ef..dc85560ce3f094a6d483594771849d4059ed7f78 100644 (file)
@@ -117,11 +117,13 @@ dsync_ibc_recv_mailbox_tree_node(struct dsync_ibc *ibc,
 enum dsync_ibc_send_ret ATTR_NOWARN_UNUSED_RESULT
 dsync_ibc_send_mailbox_deletes(struct dsync_ibc *ibc,
                               const struct dsync_mailbox_delete *deletes,
-                              unsigned int count, char hierarchy_sep);
+                              unsigned int count, char hierarchy_sep,
+                              char escape_char);
 enum dsync_ibc_recv_ret
 dsync_ibc_recv_mailbox_deletes(struct dsync_ibc *ibc,
                               const struct dsync_mailbox_delete **deletes_r,
-                              unsigned int *count_r, char *hierarchy_sep_r);
+                              unsigned int *count_r, char *hierarchy_sep_r,
+                              char *escape_char_r);
 
 enum dsync_ibc_send_ret ATTR_NOWARN_UNUSED_RESULT
 dsync_ibc_send_mailbox(struct dsync_ibc *ibc,
index b4d1b8503b639fb1f1358c95731fd50e0bd07713..06141514fe19d6e37dbff63cd4afed99ad8baf02 100644 (file)
@@ -6,6 +6,7 @@
 struct dsync_mailbox_tree {
        pool_t pool;
        char sep, sep_str[2], remote_sep, alt_char;
+       char escape_char, remote_escape_char;
        /* root node isn't part of the real mailbox tree. its name is "" and
           it has no siblings */
        struct dsync_mailbox_node root;
index e9ecaf477ec1873dbda74c9783e3f86f0da4e8a4..e932378c96c5b33f8489179a5aa7914fdaf408fa 100644 (file)
@@ -16,7 +16,8 @@ struct dsync_mailbox_tree_iter {
        string_t *name;
 };
 
-struct dsync_mailbox_tree *dsync_mailbox_tree_init(char sep, char alt_char)
+struct dsync_mailbox_tree *
+dsync_mailbox_tree_init(char sep, char escape_char, char alt_char)
 {
        struct dsync_mailbox_tree *tree;
        pool_t pool;
@@ -28,6 +29,7 @@ struct dsync_mailbox_tree *dsync_mailbox_tree_init(char sep, char alt_char)
        tree = p_new(pool, struct dsync_mailbox_tree, 1);
        tree->pool = pool;
        tree->sep = tree->sep_str[0] = sep;
+       tree->escape_char = escape_char;
        tree->alt_char = alt_char;
        tree->root.name = "";
        i_array_init(&tree->deletes, 32);
@@ -381,12 +383,14 @@ dsync_mailbox_tree_find_delete(struct dsync_mailbox_tree *tree,
        }
 }
 
-void dsync_mailbox_tree_set_remote_sep(struct dsync_mailbox_tree *tree,
-                                      char remote_sep)
+void dsync_mailbox_tree_set_remote_chars(struct dsync_mailbox_tree *tree,
+                                        char remote_sep, char escape_char)
 {
        i_assert(tree->remote_sep == '\0');
+       i_assert(tree->remote_escape_char == '\0');
 
        tree->remote_sep = remote_sep;
+       tree->remote_escape_char = escape_char;
 }
 
 static void
@@ -429,7 +433,8 @@ dsync_mailbox_tree_dup(const struct dsync_mailbox_tree *src)
        struct dsync_mailbox_tree *dest;
        string_t *str = t_str_new(128);
 
-       dest = dsync_mailbox_tree_init(src->sep, src->alt_char);
+       dest = dsync_mailbox_tree_init(src->sep, src->escape_char,
+                                      src->alt_char);
        dsync_mailbox_tree_dup_nodes(dest, &src->root, str);
        return dest;
 }
index 454790c63676e12c7211f64dad411580bbb7d784..69698132ab9630286bc2bee75cdda126749b16b7 100644 (file)
@@ -116,7 +116,8 @@ struct dsync_mailbox_tree_sync_change {
        const char *rename_dest_name;
 };
 
-struct dsync_mailbox_tree *dsync_mailbox_tree_init(char sep, char alt_char);
+struct dsync_mailbox_tree *
+dsync_mailbox_tree_init(char sep, char escape_char, char alt_char);
 void dsync_mailbox_tree_deinit(struct dsync_mailbox_tree **tree);
 
 /* Lookup a mailbox node by name. Returns NULL if not known. */
@@ -174,8 +175,9 @@ int dsync_mailbox_tree_guid_hash_add(struct dsync_mailbox_tree *tree,
                                     struct dsync_mailbox_node **old_node_r);
 /* Set remote separator used for directory deletions in
    dsync_mailbox_tree_find_delete() */
-void dsync_mailbox_tree_set_remote_sep(struct dsync_mailbox_tree *tree,
-                                      char remote_sep);
+void dsync_mailbox_tree_set_remote_chars(struct dsync_mailbox_tree *tree,
+                                        char remote_sep,
+                                        char remote_escape_char);
 
 /* Iterate through all nodes in a tree (depth-first) */
 struct dsync_mailbox_tree_iter *
index b81ca9c5ff3197c355fbe3bd50b453fd5587288e..b7e88da61f4ebdcae87071dff235e1afc82ca316 100644 (file)
@@ -101,7 +101,7 @@ static struct dsync_mailbox_tree *create_random_tree(void)
        struct dsync_mailbox_tree *tree;
        unsigned int counter = 0;
 
-       tree = dsync_mailbox_tree_init('/', '_');
+       tree = dsync_mailbox_tree_init('/', '\0', '_');
        create_random_nodes(tree, "", 0, &counter);
        return tree;
 }
@@ -273,7 +273,7 @@ static void test_dsync_mailbox_tree_sync_creates(void)
        unsigned int counter = 0;
 
        test_begin("dsync mailbox tree sync creates");
-       tree1 = dsync_mailbox_tree_init('/', '_');
+       tree1 = dsync_mailbox_tree_init('/', '\0', '_');
        nodes_create(tree1, &counter, common_nodes);
        tree2 = dsync_mailbox_tree_dup(tree1);
        nodes_create(tree1, &counter, create1_nodes);
@@ -292,7 +292,7 @@ static void test_dsync_mailbox_tree_sync_deletes(void)
        unsigned int counter = 0;
 
        test_begin("dsync mailbox tree sync deletes");
-       tree1 = dsync_mailbox_tree_init('/', '_');
+       tree1 = dsync_mailbox_tree_init('/', '\0', '_');
        nodes_create(tree1, &counter, common_nodes);
        tree2 = dsync_mailbox_tree_dup(tree1);
        nodes_delete(tree1, &counter, delete1_nodes);
@@ -310,7 +310,7 @@ static void test_dsync_mailbox_tree_sync_renames1(void)
        unsigned int counter = 0;
 
        test_begin("dsync mailbox tree sync renames 1");
-       tree1 = dsync_mailbox_tree_init('/', '_');
+       tree1 = dsync_mailbox_tree_init('/', '\0', '_');
        nodes_create(tree1, &counter, common_nodes);
        tree2 = dsync_mailbox_tree_dup(tree1);
 
@@ -336,8 +336,8 @@ static void test_dsync_mailbox_tree_sync_renames2(void)
        struct dsync_mailbox_tree *tree1, *tree2;
 
        test_begin("dsync mailbox tree sync renames 2");
-       tree1 = dsync_mailbox_tree_init('/', '_');
-       tree2 = dsync_mailbox_tree_init('/', '_');
+       tree1 = dsync_mailbox_tree_init('/', '\0', '_');
+       tree2 = dsync_mailbox_tree_init('/', '\0', '_');
 
        node_create(tree1, 1, "0/1", 1);
        node_create(tree1, 2, "0/1/2", 3);
@@ -354,8 +354,8 @@ static void test_dsync_mailbox_tree_sync_renames3(void)
        struct dsync_mailbox_tree *tree1, *tree2;
 
        test_begin("dsync mailbox tree sync renames 3");
-       tree1 = dsync_mailbox_tree_init('/', '_');
-       tree2 = dsync_mailbox_tree_init('/', '_');
+       tree1 = dsync_mailbox_tree_init('/', '\0', '_');
+       tree2 = dsync_mailbox_tree_init('/', '\0', '_');
 
        node_create(tree1, 1, "0/2", 1);
        node_create(tree1, 2, "0/3", 1);
@@ -372,8 +372,8 @@ static void test_dsync_mailbox_tree_sync_renames4(void)
        struct dsync_mailbox_tree *tree1, *tree2;
 
        test_begin("dsync mailbox tree sync renames 4");
-       tree1 = dsync_mailbox_tree_init('/', '_');
-       tree2 = dsync_mailbox_tree_init('/', '_');
+       tree1 = dsync_mailbox_tree_init('/', '\0', '_');
+       tree2 = dsync_mailbox_tree_init('/', '\0', '_');
 
        node_create(tree1, 1, "0/b", 0);
        node_create(tree1, 2, "c", 2);
@@ -389,8 +389,8 @@ static void test_dsync_mailbox_tree_sync_renames5(void)
        struct dsync_mailbox_tree *tree1, *tree2;
 
        test_begin("dsync mailbox tree sync renames 5");
-       tree1 = dsync_mailbox_tree_init('/', '_');
-       tree2 = dsync_mailbox_tree_init('/', '_');
+       tree1 = dsync_mailbox_tree_init('/', '\0', '_');
+       tree2 = dsync_mailbox_tree_init('/', '\0', '_');
 
        node_create(tree1, 1, "b", 0);
        node_create(tree1, 2, "c", 2);
@@ -406,8 +406,8 @@ static void test_dsync_mailbox_tree_sync_renames6(void)
        struct dsync_mailbox_tree *tree1, *tree2;
 
        test_begin("dsync mailbox tree sync renames 6");
-       tree1 = dsync_mailbox_tree_init('/', '_');
-       tree2 = dsync_mailbox_tree_init('/', '_');
+       tree1 = dsync_mailbox_tree_init('/', '\0', '_');
+       tree2 = dsync_mailbox_tree_init('/', '\0', '_');
 
        node_create(tree1, 1, "0/1", 0);
        node_create(tree1, 2, "0/2", 1);
@@ -424,8 +424,8 @@ static void test_dsync_mailbox_tree_sync_renames7(void)
        struct dsync_mailbox_tree *tree1, *tree2;
 
        test_begin("dsync mailbox tree sync renames 7");
-       tree1 = dsync_mailbox_tree_init('/', '_');
-       tree2 = dsync_mailbox_tree_init('/', '_');
+       tree1 = dsync_mailbox_tree_init('/', '\0', '_');
+       tree2 = dsync_mailbox_tree_init('/', '\0', '_');
 
        node_create(tree1, 1, "0/2", 0);
        node_create(tree2, 1, "1/2", 0);
@@ -439,8 +439,8 @@ static void test_dsync_mailbox_tree_sync_renames8(void)
        struct dsync_mailbox_tree *tree1, *tree2;
 
        test_begin("dsync mailbox tree sync renames 8");
-       tree1 = dsync_mailbox_tree_init('/', '_');
-       tree2 = dsync_mailbox_tree_init('/', '_');
+       tree1 = dsync_mailbox_tree_init('/', '\0', '_');
+       tree2 = dsync_mailbox_tree_init('/', '\0', '_');
 
        node_create(tree1, 1, "0/1", 0);
        node_create(tree1, 2, "0/2", 1);
@@ -456,8 +456,8 @@ static void test_dsync_mailbox_tree_sync_renames9(void)
        struct dsync_mailbox_tree *tree1, *tree2;
 
        test_begin("dsync mailbox tree sync renames 9");
-       tree1 = dsync_mailbox_tree_init('/', '_');
-       tree2 = dsync_mailbox_tree_init('/', '_');
+       tree1 = dsync_mailbox_tree_init('/', '\0', '_');
+       tree2 = dsync_mailbox_tree_init('/', '\0', '_');
 
        node_create(tree1, 1, "0/1/2", 0);
        node_create(tree1, 2, "0/3", 1);
@@ -473,8 +473,8 @@ static void test_dsync_mailbox_tree_sync_renames10(void)
        struct dsync_mailbox_tree *tree1, *tree2;
 
        test_begin("dsync mailbox tree sync renames 10");
-       tree1 = dsync_mailbox_tree_init('/', '_');
-       tree2 = dsync_mailbox_tree_init('/', '_');
+       tree1 = dsync_mailbox_tree_init('/', '\0', '_');
+       tree2 = dsync_mailbox_tree_init('/', '\0', '_');
 
        node_create(tree1, 1, "0/1", 0);
        node_create(tree1, 3, "0/2/3", 0);
@@ -490,8 +490,8 @@ static void test_dsync_mailbox_tree_sync_renames11(void)
        struct dsync_mailbox_tree *tree1, *tree2;
 
        test_begin("dsync mailbox tree sync renames 11");
-       tree1 = dsync_mailbox_tree_init('/', '_');
-       tree2 = dsync_mailbox_tree_init('/', '_');
+       tree1 = dsync_mailbox_tree_init('/', '\0', '_');
+       tree2 = dsync_mailbox_tree_init('/', '\0', '_');
 
        node_create(tree1, 1, "0/1", 2);
        node_create(tree1, 0, "0/1/2", 0);
@@ -508,8 +508,8 @@ static void test_dsync_mailbox_tree_sync_renames12(void)
        struct dsync_mailbox_tree *tree1, *tree2;
 
        test_begin("dsync mailbox tree sync renames 12");
-       tree1 = dsync_mailbox_tree_init('/', '_');
-       tree2 = dsync_mailbox_tree_init('/', '_');
+       tree1 = dsync_mailbox_tree_init('/', '\0', '_');
+       tree2 = dsync_mailbox_tree_init('/', '\0', '_');
 
        node_create(tree1, 1, "0/2", 0);
        node_create(tree1, 2, "1", 0);
@@ -530,8 +530,8 @@ static void test_dsync_mailbox_tree_sync_renames13(void)
        struct dsync_mailbox_tree *tree1, *tree2;
 
        test_begin("dsync mailbox tree sync renames 13");
-       tree1 = dsync_mailbox_tree_init('/', '_');
-       tree2 = dsync_mailbox_tree_init('/', '_');
+       tree1 = dsync_mailbox_tree_init('/', '\0', '_');
+       tree2 = dsync_mailbox_tree_init('/', '\0', '_');
 
        node_create(tree1, 4, "0.0/1.0/2.1", 0);
        node_create(tree1, 5, "0.1", 2);
@@ -551,8 +551,8 @@ static void test_dsync_mailbox_tree_sync_renames14(void)
        struct dsync_mailbox_tree *tree1, *tree2;
 
        test_begin("dsync mailbox tree sync renames 14");
-       tree1 = dsync_mailbox_tree_init('/', '_');
-       tree2 = dsync_mailbox_tree_init('/', '_');
+       tree1 = dsync_mailbox_tree_init('/', '\0', '_');
+       tree2 = dsync_mailbox_tree_init('/', '\0', '_');
 
        node_create(tree1, 1, "1", 0);
        node_create(tree1, 2, "1/2", 0);
@@ -571,8 +571,8 @@ static void test_dsync_mailbox_tree_sync_renames15(void)
        struct dsync_mailbox_tree *tree1, *tree2;
 
        test_begin("dsync mailbox tree sync renames 15");
-       tree1 = dsync_mailbox_tree_init('/', '_');
-       tree2 = dsync_mailbox_tree_init('/', '_');
+       tree1 = dsync_mailbox_tree_init('/', '\0', '_');
+       tree2 = dsync_mailbox_tree_init('/', '\0', '_');
 
        node_create(tree1, 1, "1", 0);
        node_create(tree2, 2, "1", 1);
@@ -586,8 +586,8 @@ static void test_dsync_mailbox_tree_sync_renames16(void)
        struct dsync_mailbox_tree *tree1, *tree2;
 
        test_begin("dsync mailbox tree sync renames 16");
-       tree1 = dsync_mailbox_tree_init('/', '_');
-       tree2 = dsync_mailbox_tree_init('/', '_');
+       tree1 = dsync_mailbox_tree_init('/', '\0', '_');
+       tree2 = dsync_mailbox_tree_init('/', '\0', '_');
 
        node_create(tree1, 1, "1/2", 4);
        node_create(tree1, 2, "1", 2);
@@ -605,8 +605,8 @@ static void test_dsync_mailbox_tree_sync_renames17(void)
        struct dsync_mailbox_tree *tree1, *tree2;
 
        test_begin("dsync mailbox tree sync renames 17");
-       tree1 = dsync_mailbox_tree_init('/', '_');
-       tree2 = dsync_mailbox_tree_init('/', '_');
+       tree1 = dsync_mailbox_tree_init('/', '\0', '_');
+       tree2 = dsync_mailbox_tree_init('/', '\0', '_');
 
        node_create(tree1, 1, "1", 1);
 
@@ -622,8 +622,8 @@ static void test_dsync_mailbox_tree_sync_renames18(void)
        struct dsync_mailbox_tree *tree1, *tree2;
 
        test_begin("dsync mailbox tree sync renames 18");
-       tree1 = dsync_mailbox_tree_init('/', '_');
-       tree2 = dsync_mailbox_tree_init('/', '_');
+       tree1 = dsync_mailbox_tree_init('/', '\0', '_');
+       tree2 = dsync_mailbox_tree_init('/', '\0', '_');
 
        node_create(tree1, 2, "a", 5);
        node_create(tree1, 4, "a/c", 2);
@@ -643,8 +643,8 @@ static void test_dsync_mailbox_tree_sync_renames19(void)
        struct dsync_mailbox_tree *tree1, *tree2;
 
        test_begin("dsync mailbox tree sync renames 19");
-       tree1 = dsync_mailbox_tree_init('/', '_');
-       tree2 = dsync_mailbox_tree_init('/', '_');
+       tree1 = dsync_mailbox_tree_init('/', '\0', '_');
+       tree2 = dsync_mailbox_tree_init('/', '\0', '_');
 
        node_create(tree1, 1, "0/2/1", 1);
        node_create(tree1, 2, "0/4", 3);
@@ -662,8 +662,8 @@ static void test_dsync_mailbox_tree_sync_renames20(void)
        struct dsync_mailbox_tree *tree1, *tree2;
 
        test_begin("dsync mailbox tree sync renames 20");
-       tree1 = dsync_mailbox_tree_init('/', '_');
-       tree2 = dsync_mailbox_tree_init('/', '_');
+       tree1 = dsync_mailbox_tree_init('/', '\0', '_');
+       tree2 = dsync_mailbox_tree_init('/', '\0', '_');
 
        node_create(tree1, 1, "1", 0);
        node_create(tree1, 2, "0", 0);
@@ -687,8 +687,8 @@ static void test_dsync_mailbox_tree_sync_renames21(void)
        struct dsync_mailbox_tree *tree1, *tree2;
 
        test_begin("dsync mailbox tree sync renames 21");
-       tree1 = dsync_mailbox_tree_init('/', '_');
-       tree2 = dsync_mailbox_tree_init('/', '_');
+       tree1 = dsync_mailbox_tree_init('/', '\0', '_');
+       tree2 = dsync_mailbox_tree_init('/', '\0', '_');
 
        node_create(tree1, 1, "INBOX", 0);
        node_create(tree1, 2, "foo", 0);
@@ -707,8 +707,8 @@ static void test_dsync_mailbox_tree_sync_renames22(void)
        struct dsync_mailbox_tree *tree1, *tree2;
 
        test_begin("dsync mailbox tree sync renames 22");
-       tree1 = dsync_mailbox_tree_init('/', '_');
-       tree2 = dsync_mailbox_tree_init('/', '_');
+       tree1 = dsync_mailbox_tree_init('/', '\0', '_');
+       tree2 = dsync_mailbox_tree_init('/', '\0', '_');
 
        node_create(tree1, 3, "p/a", 0);
        node_create(tree1, 0, "p/2", 0);