diff --git a/src/include/66/tree.h b/src/include/66/tree.h
index dec81d882c353b1b939ad981128c5aa59b391262..6961b55156d1150227c335be46c314a6db1aef72 100644
--- a/src/include/66/tree.h
+++ b/src/include/66/tree.h
@@ -43,13 +43,13 @@ struct resolve_tree_s
     uint32_t requiredby ;
     uint32_t allow ;
     uint32_t groups ;
-    uint32_t contents ;
+    uint32_t contents ;//not used
 
     uint32_t ndepends ;
     uint32_t nrequiredby ;
     uint32_t nallow ;
     uint32_t ngroups ; //not really useful for now, we accept only one group
-    uint32_t ncontents ;
+    uint32_t ncontents ; //not used
 
     uint32_t init ;//not initialized->0, initialized->1
     uint32_t disen ;//disable->0, enable->1
@@ -141,8 +141,9 @@ extern int tree_find_current(stralloc *tree, char const *base) ;
 extern int tree_iscurrent(char const *base, char const *treename) ;
 
 /** @Return 1 on success
- * @Return 0 on fail */
-extern int tree_isinitialized(char const *live, char const *treename, uid_t owner) ;
+ * @Return 0 on fail
+ * @Return -1 on system error */
+extern int tree_isinitialized(char const *base, char const *treename) ;
 
 /** @Return 1 on success
  * @Return 0 if not valid
@@ -178,15 +179,15 @@ extern int tree_switch_current(char const *base, char const *tree) ;
  * */
 
 /** tree */
-extern int tree_read_cdb(cdb *c, resolve_tree_t *tres) ;
-extern int tree_write_cdb(cdbmaker *c, resolve_tree_t *tres) ;
+extern int tree_resolve_read_cdb(cdb *c, resolve_tree_t *tres) ;
+extern int tree_resolve_write_cdb(cdbmaker *c, resolve_tree_t *tres) ;
 extern int tree_resolve_copy(resolve_tree_t *dst, resolve_tree_t *tres) ;
 extern int tree_resolve_modify_field(resolve_tree_t *tres, uint8_t field, char const *data) ;
 extern int tree_resolve_field_tosa(stralloc *sa, resolve_tree_t *tres, resolve_tree_enum_t field) ;
 
 /** Master */
-extern int tree_read_master_cdb(cdb *c, resolve_tree_master_t *mres) ;
-extern int tree_write_master_cdb(cdbmaker *c, resolve_tree_master_t *mres) ;
+extern int tree_resolve_read_master_cdb(cdb *c, resolve_tree_master_t *mres) ;
+extern int tree_resolve_write_master_cdb(cdbmaker *c, resolve_tree_master_t *mres) ;
 extern int tree_resolve_master_create(char const *base, uid_t owner) ;
 extern int tree_resolve_master_copy(resolve_tree_master_t *dst, resolve_tree_master_t *mres) ;
 extern int tree_resolve_master_modify_field(resolve_tree_master_t *mres, uint8_t field, char const *data) ;
@@ -197,9 +198,14 @@ extern int tree_resolve_master_field_tosa(stralloc *sa, resolve_tree_master_t *m
  * Seed API
  *
  * */
-
+extern int tree_seed_file_isvalid(char const *seedpath, char const *treename) ;
 extern void tree_seed_free(tree_seed_t *seed) ;
-extern int tree_seed_setseed(tree_seed_t *seed, char const *treename, uint8_t check_contents) ;
+extern int tree_seed_get_group_permissions(tree_seed_t *seed, uint8_t check_contents) ;
+extern ssize_t tree_seed_get_key(char *table,char const *str) ;
 extern int tree_seed_isvalid(char const *seed) ;
+extern int tree_seed_parse_file(tree_seed_t *seed, char const *seedpath) ;
+extern int tree_seed_resolve_path(stralloc *sa, char const *seed) ;
+extern int tree_seed_setseed(tree_seed_t *seed, char const *treename, uint8_t check_contents) ;
+
 
 #endif
diff --git a/src/lib66/tree/deps-lib/deps b/src/lib66/tree/deps-lib/deps
index 5e545cb44faeb8da83360018e0940db7279e7878..ede8d6e82e2443334ed99210772a4c021f1b49e0 100644
--- a/src/lib66/tree/deps-lib/deps
+++ b/src/lib66/tree/deps-lib/deps
@@ -1,10 +1,32 @@
-tree.o
 tree_cmd_state.o
 tree_copy.o
 tree_copy_tmp.o
+tree_find_current.o
 tree_get_permissions.o
-tree_resolve.o
-tree_seed.o
+tree_iscurrent.o
+tree_isenabled.o
+tree_isinitialized.o
+tree_isvalid.o
+tree_ongroups.o
+tree_resolve_copy.o
+tree_resolve_field_tosa.o
+tree_resolve_master_copy.o
+tree_resolve_master_create.o
+tree_resolve_master_field_tosa.o
+tree_resolve_master_modify_field.o
+tree_resolve_modify_field.o
+tree_resolve_read_cdb.o
+tree_resolve_read_master_cdb.o
+tree_resolve_write_cdb.o
+tree_resolve_write_master_cdb.o
+tree_seed_file_isvalid.o
+tree_seed_free.o
+tree_seed_get_group_permissions.o
+tree_seed_get_key.o
+tree_seed_isvalid.o
+tree_seed_parse_file.o
+tree_seed_resolve_path.o
+tree_seed_setseed.o
 tree_sethome.o
 tree_setname.o
 tree_switch_current.o
diff --git a/src/lib66/tree/tree.c b/src/lib66/tree/tree.c
deleted file mode 100644
index 3465d08e539f0fc3e545fe9ddd71bff81fca7275..0000000000000000000000000000000000000000
--- a/src/lib66/tree/tree.c
+++ /dev/null
@@ -1,203 +0,0 @@
-/*
- * tree.c
- *
- * Copyright (c) 2018-2021 Eric Vidal <eric@obarun.org>
- *
- * All rights reserved.
- *
- * This file is part of Obarun. It is subject to the license terms in
- * the LICENSE file found in the top-level directory of this
- * distribution.
- * This file may not be copied, modified, propagated, or distributed
- * except according to the terms contained in the LICENSE file./
- */
-
-#include <66/tree.h>
-
-#include <string.h>
-#include <sys/types.h>
-#include <sys/unistd.h>//access
-#include <sys/errno.h>
-
-#include <oblibs/types.h>
-#include <oblibs/string.h>
-#include <oblibs/log.h>
-#include <oblibs/files.h>
-#include <oblibs/sastr.h>
-
-#include <skalibs/types.h>
-#include <skalibs/stralloc.h>
-#include <skalibs/djbunix.h>
-
-#include <66/constants.h>
-#include <66/resolve.h>
-
-int tree_isvalid(char const *base, char const *treename)
-{
-    log_flow() ;
-
-    int r ;
-    size_t baselen = strlen(base), treelen = strlen(treename) ;
-    char t[baselen + SS_SYSTEM_LEN + SS_RESOLVE_LEN + 1 + treelen + 1] ;
-    auto_strings(t, base, SS_SYSTEM, SS_RESOLVE, "/", treename) ;
-
-    r = scan_mode(t, S_IFREG) ;
-    if (r < 0)
-        return -1 ;
-    else if (!r)
-        return 0 ;
-
-    return 1 ;
-}
-
-int tree_find_current(stralloc *tree, char const *base)
-{
-    log_flow() ;
-
-    int e = 0 ;
-    size_t baselen = strlen(base) ;
-    resolve_tree_master_t mres = RESOLVE_TREE_MASTER_ZERO ;
-    resolve_wrapper_t_ref wres = resolve_set_struct(DATA_TREE_MASTER, &mres) ;
-    char t[baselen + SS_SYSTEM_LEN + 1] ;
-
-    auto_strings(t, base, SS_SYSTEM) ;
-
-    if (!resolve_read(wres, t, SS_MASTER + 1))
-        goto err ;
-
-    if (!auto_stra(tree, base, SS_SYSTEM, "/", mres.sa.s + mres.current))
-        goto err ;
-
-    e = 1 ;
-    err:
-        resolve_free(wres) ;
-        return e ;
-}
-
-int tree_iscurrent(char const *base, char const *treename)
-{
-    log_flow() ;
-
-    int e = -1 ;
-    size_t baselen = strlen(base) ;
-    resolve_tree_master_t mres = RESOLVE_TREE_MASTER_ZERO ;
-    resolve_wrapper_t_ref wres = resolve_set_struct(DATA_TREE_MASTER, &mres) ;
-    char t[baselen + SS_SYSTEM_LEN + 1] ;
-
-    auto_strings(t, base, SS_SYSTEM) ;
-
-    if (!resolve_read(wres, t, SS_MASTER + 1))
-        goto err ;
-
-    if (!strcmp(mres.sa.s + mres.current, treename))
-        e = 1 ;
-    else
-        e = 0 ;
-
-    err:
-        resolve_free(wres) ;
-        return e ;
-}
-
-int tree_isinitialized(char const *base, char const *treename)
-{
-    log_flow() ;
-
-    int e = -1 ;
-    size_t baselen = strlen(base) ;
-    resolve_tree_t tres = RESOLVE_TREE_ZERO ;
-    resolve_wrapper_t_ref wres = resolve_set_struct(DATA_TREE, &tres) ;
-    char solve[baselen + SS_SYSTEM_LEN + 1] ;
-
-    auto_strings(solve, base, SS_SYSTEM) ;
-
-    if (!resolve_read(wres, solve, treename))
-        goto err ;
-
-    if (tres.init)
-        e = 1 ;
-    else
-        e = 0 ;
-
-    err:
-        resolve_free(wres) ;
-        return e ;
-}
-
-int tree_isenabled(char const *base, char const *treename)
-{
-    log_flow() ;
-
-    int e = -1 ;
-    size_t baselen = strlen(base), pos = 0 ;
-    stralloc sa = STRALLOC_ZERO ;
-    resolve_tree_master_t mres = RESOLVE_TREE_MASTER_ZERO ;
-    resolve_wrapper_t_ref wres = resolve_set_struct(DATA_TREE_MASTER, &mres) ;
-    char solve[baselen + SS_SYSTEM_LEN + 1] ;
-
-    auto_strings(solve, base, SS_SYSTEM) ;
-
-    if (!resolve_read(wres, solve, SS_MASTER + 1))
-        goto err ;
-
-    if (mres.nenabled) {
-
-        if (!sastr_clean_string(&sa, mres.sa.s + mres.enabled))
-            goto err ;
-
-        e = 0 ;
-
-        FOREACH_SASTR(&sa, pos) {
-
-            if (!strcmp(treename, sa.s + pos)) {
-                e = 1 ;
-                break ;
-            }
-        }
-    }
-    else e = 0 ;
-
-    err:
-        resolve_free(wres) ;
-        stralloc_free(&sa) ;
-        return e ;
-}
-
-int tree_ongroups(char const *base, char const *treename, char const *group)
-{
-    log_flow() ;
-
-    int e = -1 ;
-    size_t baselen = strlen(base), pos = 0 ;
-    stralloc sa = STRALLOC_ZERO ;
-    resolve_tree_t tres = RESOLVE_TREE_ZERO ;
-    resolve_wrapper_t_ref wres = resolve_set_struct(DATA_TREE, &tres) ;
-    char solve[baselen + SS_SYSTEM_LEN + 1] ;
-
-    auto_strings(solve, base, SS_SYSTEM) ;
-
-    if (!resolve_read(wres, solve, treename))
-        goto err ;
-
-    if (tres.ngroups) {
-
-        if (!sastr_clean_string(&sa, tres.sa.s + tres.groups))
-            goto err ;
-
-        e = 0 ;
-
-        FOREACH_SASTR(&sa, pos) {
-
-            if (!strcmp(group, sa.s + pos)) {
-                e = 1 ;
-                break ;
-            }
-        }
-    }
-    else e = 0 ;
-
-    err:
-       resolve_free(wres) ;
-       stralloc_free(&sa) ;
-       return e ;
-}
diff --git a/src/lib66/tree/tree_copy.c b/src/lib66/tree/tree_copy.c
index d146527f90b0e31ed5918912a002494da2338681..b10d3c59fcf86d1f934133f37cef5c624474a57d 100644
--- a/src/lib66/tree/tree_copy.c
+++ b/src/lib66/tree/tree_copy.c
@@ -20,7 +20,6 @@
 #include <oblibs/directory.h>
 #include <oblibs/log.h>
 
-#include <skalibs/stralloc.h>
 #include <skalibs/djbunix.h>
 
 #include <66/constants.h>
diff --git a/src/lib66/tree/tree_find_current.c b/src/lib66/tree/tree_find_current.c
new file mode 100644
index 0000000000000000000000000000000000000000..14ec688a9064fc7b20ed891f9dab24da2a6e2514
--- /dev/null
+++ b/src/lib66/tree/tree_find_current.c
@@ -0,0 +1,48 @@
+/*
+ * tree_find_current.c
+ *
+ * Copyright (c) 2018-2021 Eric Vidal <eric@obarun.org>
+ *
+ * All rights reserved.
+ *
+ * This file is part of Obarun. It is subject to the license terms in
+ * the LICENSE file found in the top-level directory of this
+ * distribution.
+ * This file may not be copied, modified, propagated, or distributed
+ * except according to the terms contained in the LICENSE file./
+ */
+
+#include <string.h>
+
+#include <oblibs/log.h>
+#include <oblibs/string.h>
+
+#include <skalibs/stralloc.h>
+
+#include <66/resolve.h>
+#include <66/tree.h>
+#include <66/constants.h>
+
+int tree_find_current(stralloc *tree, char const *base)
+{
+    log_flow() ;
+
+    int e = 0 ;
+    size_t baselen = strlen(base) ;
+    resolve_tree_master_t mres = RESOLVE_TREE_MASTER_ZERO ;
+    resolve_wrapper_t_ref wres = resolve_set_struct(DATA_TREE_MASTER, &mres) ;
+    char t[baselen + SS_SYSTEM_LEN + 1] ;
+
+    auto_strings(t, base, SS_SYSTEM) ;
+
+    if (!resolve_read(wres, t, SS_MASTER + 1))
+        goto err ;
+
+    if (!auto_stra(tree, base, SS_SYSTEM, "/", mres.sa.s + mres.current))
+        goto err ;
+
+    e = 1 ;
+    err:
+        resolve_free(wres) ;
+        return e ;
+}
diff --git a/src/lib66/tree/tree_get_permissions.c b/src/lib66/tree/tree_get_permissions.c
index d9e9fff345b89ff530829fbf0c815229825d8d61..a5cfd23bb3c9333eeb118361f31373284e2ab5f2 100644
--- a/src/lib66/tree/tree_get_permissions.c
+++ b/src/lib66/tree/tree_get_permissions.c
@@ -15,15 +15,13 @@
 #include <66/utils.h>
 
 #include <sys/types.h>
-#include <sys/stat.h>
 
 #include <oblibs/types.h>
+#include <oblibs/string.h>
 
-#include <skalibs/stralloc.h>
 #include <skalibs/types.h>
 
 #include <66/constants.h>
-#include <66/utils.h>
 
 int tree_get_permissions(char const *tree,uid_t owner)
 {
@@ -38,11 +36,7 @@ int tree_get_permissions(char const *tree,uid_t owner)
 
     char tmp[treelen + SS_RULES_LEN + 1 + packlen + 1] ;
 
-    memcpy(tmp,tree,treelen) ;
-    memcpy(tmp + treelen,SS_RULES,SS_RULES_LEN) ;
-    tmp[treelen + SS_RULES_LEN] = '/' ;
-    memcpy(tmp + treelen + SS_RULES_LEN + 1, pack,packlen) ;
-    tmp[treelen + SS_RULES_LEN + 1 + packlen] = 0 ;
+    auto_strings(tmp, tree, SS_RULES, "/", pack) ;
 
     r = scan_mode(tmp,S_IFREG) ;
     if (r != 1) return 0 ;
diff --git a/src/lib66/tree/tree_iscurrent.c b/src/lib66/tree/tree_iscurrent.c
new file mode 100644
index 0000000000000000000000000000000000000000..f46913c04078860bfd2a66188770c689b36e8a75
--- /dev/null
+++ b/src/lib66/tree/tree_iscurrent.c
@@ -0,0 +1,47 @@
+/*
+ * tree_iscurrent.c
+ *
+ * Copyright (c) 2018-2021 Eric Vidal <eric@obarun.org>
+ *
+ * All rights reserved.
+ *
+ * This file is part of Obarun. It is subject to the license terms in
+ * the LICENSE file found in the top-level directory of this
+ * distribution.
+ * This file may not be copied, modified, propagated, or distributed
+ * except according to the terms contained in the LICENSE file./
+ */
+
+#include <string.h>
+
+#include <oblibs/string.h>
+#include <oblibs/log.h>
+
+#include <66/constants.h>
+#include <66/resolve.h>
+#include <66/tree.h>
+
+int tree_iscurrent(char const *base, char const *treename)
+{
+    log_flow() ;
+
+    int e = -1 ;
+    size_t baselen = strlen(base) ;
+    resolve_tree_master_t mres = RESOLVE_TREE_MASTER_ZERO ;
+    resolve_wrapper_t_ref wres = resolve_set_struct(DATA_TREE_MASTER, &mres) ;
+    char t[baselen + SS_SYSTEM_LEN + 1] ;
+
+    auto_strings(t, base, SS_SYSTEM) ;
+
+    if (!resolve_read(wres, t, SS_MASTER + 1))
+        goto err ;
+
+    if (!strcmp(mres.sa.s + mres.current, treename))
+        e = 1 ;
+    else
+        e = 0 ;
+
+    err:
+        resolve_free(wres) ;
+        return e ;
+}
diff --git a/src/lib66/tree/tree_isenabled.c b/src/lib66/tree/tree_isenabled.c
new file mode 100644
index 0000000000000000000000000000000000000000..fc2bcc3a52fcb5e0c3222165ec27f4578729e1b2
--- /dev/null
+++ b/src/lib66/tree/tree_isenabled.c
@@ -0,0 +1,62 @@
+/*
+ * tree_isenabled.c
+ *
+ * Copyright (c) 2018-2021 Eric Vidal <eric@obarun.org>
+ *
+ * All rights reserved.
+ *
+ * This file is part of Obarun. It is subject to the license terms in
+ * the LICENSE file found in the top-level directory of this
+ * distribution.
+ * This file may not be copied, modified, propagated, or distributed
+ * except according to the terms contained in the LICENSE file./
+ */
+
+#include <oblibs/string.h>
+#include <oblibs/log.h>
+#include <oblibs/sastr.h>
+
+#include <skalibs/stralloc.h>
+
+#include <66/constants.h>
+#include <66/resolve.h>
+#include <66/tree.h>
+
+int tree_isenabled(char const *base, char const *treename)
+{
+    log_flow() ;
+
+    int e = -1 ;
+    size_t baselen = strlen(base), pos = 0 ;
+    stralloc sa = STRALLOC_ZERO ;
+    resolve_tree_master_t mres = RESOLVE_TREE_MASTER_ZERO ;
+    resolve_wrapper_t_ref wres = resolve_set_struct(DATA_TREE_MASTER, &mres) ;
+    char solve[baselen + SS_SYSTEM_LEN + 1] ;
+
+    auto_strings(solve, base, SS_SYSTEM) ;
+
+    if (!resolve_read(wres, solve, SS_MASTER + 1))
+        goto err ;
+
+    if (mres.nenabled) {
+
+        if (!sastr_clean_string(&sa, mres.sa.s + mres.enabled))
+            goto err ;
+
+        e = 0 ;
+
+        FOREACH_SASTR(&sa, pos) {
+
+            if (!strcmp(treename, sa.s + pos)) {
+                e = 1 ;
+                break ;
+            }
+        }
+    }
+    else e = 0 ;
+
+    err:
+        resolve_free(wres) ;
+        stralloc_free(&sa) ;
+        return e ;
+}
diff --git a/src/lib66/tree/tree_isinitialized.c b/src/lib66/tree/tree_isinitialized.c
new file mode 100644
index 0000000000000000000000000000000000000000..ee42d77f06cdcdb2499a4a1b39264bc34abddbda
--- /dev/null
+++ b/src/lib66/tree/tree_isinitialized.c
@@ -0,0 +1,47 @@
+/*
+ * tree_isinitialized.c
+ *
+ * Copyright (c) 2018-2021 Eric Vidal <eric@obarun.org>
+ *
+ * All rights reserved.
+ *
+ * This file is part of Obarun. It is subject to the license terms in
+ * the LICENSE file found in the top-level directory of this
+ * distribution.
+ * This file may not be copied, modified, propagated, or distributed
+ * except according to the terms contained in the LICENSE file./
+ */
+
+#include <string.h>
+
+#include <oblibs/string.h>
+#include <oblibs/log.h>
+
+#include <66/constants.h>
+#include <66/resolve.h>
+#include <66/tree.h>
+
+int tree_isinitialized(char const *base, char const *treename)
+{
+    log_flow() ;
+
+    int e = -1 ;
+    size_t baselen = strlen(base) ;
+    resolve_tree_t tres = RESOLVE_TREE_ZERO ;
+    resolve_wrapper_t_ref wres = resolve_set_struct(DATA_TREE, &tres) ;
+    char solve[baselen + SS_SYSTEM_LEN + 1] ;
+
+    auto_strings(solve, base, SS_SYSTEM) ;
+
+    if (!resolve_read(wres, solve, treename))
+        goto err ;
+
+    if (tres.init)
+        e = 1 ;
+    else
+        e = 0 ;
+
+    err:
+        resolve_free(wres) ;
+        return e ;
+}
diff --git a/src/lib66/tree/tree_isvalid.c b/src/lib66/tree/tree_isvalid.c
new file mode 100644
index 0000000000000000000000000000000000000000..6f0de86fec05c5ab1e4109e0a044835e06bb9e56
--- /dev/null
+++ b/src/lib66/tree/tree_isvalid.c
@@ -0,0 +1,38 @@
+/*
+ * tree_isvalid.c
+ *
+ * Copyright (c) 2018-2021 Eric Vidal <eric@obarun.org>
+ *
+ * All rights reserved.
+ *
+ * This file is part of Obarun. It is subject to the license terms in
+ * the LICENSE file found in the top-level directory of this
+ * distribution.
+ * This file may not be copied, modified, propagated, or distributed
+ * except according to the terms contained in the LICENSE file./
+ */
+
+#include <string.h>
+
+#include <oblibs/log.h>
+#include <oblibs/string.h>
+
+#include <66/constants.h>
+
+int tree_isvalid(char const *base, char const *treename)
+{
+    log_flow() ;
+
+    int r ;
+    size_t baselen = strlen(base), treelen = strlen(treename) ;
+    char t[baselen + SS_SYSTEM_LEN + SS_RESOLVE_LEN + 1 + treelen + 1] ;
+    auto_strings(t, base, SS_SYSTEM, SS_RESOLVE, "/", treename) ;
+
+    r = scan_mode(t, S_IFREG) ;
+    if (r < 0)
+        return -1 ;
+    else if (!r)
+        return 0 ;
+
+    return 1 ;
+}
diff --git a/src/lib66/tree/tree_ongroups.c b/src/lib66/tree/tree_ongroups.c
new file mode 100644
index 0000000000000000000000000000000000000000..be449cfd2752b42af231cd025d1f9e82869adc49
--- /dev/null
+++ b/src/lib66/tree/tree_ongroups.c
@@ -0,0 +1,64 @@
+/*
+ * tree_ongroups.c
+ *
+ * Copyright (c) 2018-2021 Eric Vidal <eric@obarun.org>
+ *
+ * All rights reserved.
+ *
+ * This file is part of Obarun. It is subject to the license terms in
+ * the LICENSE file found in the top-level directory of this
+ * distribution.
+ * This file may not be copied, modified, propagated, or distributed
+ * except according to the terms contained in the LICENSE file./
+ */
+
+#include <string.h>
+
+#include <oblibs/string.h>
+#include <oblibs/log.h>
+#include <oblibs/sastr.h>
+
+#include <skalibs/stralloc.h>
+
+#include <66/constants.h>
+#include <66/resolve.h>
+#include <66/tree.h>
+
+int tree_ongroups(char const *base, char const *treename, char const *group)
+{
+    log_flow() ;
+
+    int e = -1 ;
+    size_t baselen = strlen(base), pos = 0 ;
+    stralloc sa = STRALLOC_ZERO ;
+    resolve_tree_t tres = RESOLVE_TREE_ZERO ;
+    resolve_wrapper_t_ref wres = resolve_set_struct(DATA_TREE, &tres) ;
+    char solve[baselen + SS_SYSTEM_LEN + 1] ;
+
+    auto_strings(solve, base, SS_SYSTEM) ;
+
+    if (!resolve_read(wres, solve, treename))
+        goto err ;
+
+    if (tres.ngroups) {
+
+        if (!sastr_clean_string(&sa, tres.sa.s + tres.groups))
+            goto err ;
+
+        e = 0 ;
+
+        FOREACH_SASTR(&sa, pos) {
+
+            if (!strcmp(group, sa.s + pos)) {
+                e = 1 ;
+                break ;
+            }
+        }
+    }
+    else e = 0 ;
+
+    err:
+       resolve_free(wres) ;
+       stralloc_free(&sa) ;
+       return e ;
+}
diff --git a/src/lib66/tree/tree_resolve.c b/src/lib66/tree/tree_resolve.c
deleted file mode 100644
index e65b47b221d572d1932affda6f6e2507f591fa12..0000000000000000000000000000000000000000
--- a/src/lib66/tree/tree_resolve.c
+++ /dev/null
@@ -1,574 +0,0 @@
-/*
- * tree_resolve.c
- *
- * Copyright (c) 2018-2021 Eric Vidal <eric@obarun.org>
- *
- * All rights reserved.
- *
- * This file is part of Obarun. It is subject to the license terms in
- * the LICENSE file found in the top-level directory of this
- * distribution.
- * This file may not be copied, modified, propagated, or distributed
- * except according to the terms contained in the LICENSE file./
- */
-
-#include <stdint.h>
-#include <stddef.h>
-#include <stdlib.h>//free
-#include <pwd.h>
-#include <sys/stat.h>
-
-#include <oblibs/log.h>
-#include <oblibs/string.h>
-
-#include <skalibs/stralloc.h>
-#include <skalibs/cdbmake.h>
-#include <skalibs/cdb.h>
-#include <skalibs/types.h>//UINT_FMT
-
-#include <66/tree.h>
-#include <66/resolve.h>
-#include <66/constants.h>
-#include <66/graph.h>
-
-
-resolve_field_table_t resolve_tree_field_table[] = {
-
-    [TREE_ENUM_NAME] = { .field = "name" },
-    [TREE_ENUM_DEPENDS] = { .field = "depends" },
-    [TREE_ENUM_REQUIREDBY] = { .field = "requiredby" },
-    [TREE_ENUM_ALLOW] = { .field = "allow" },
-    [TREE_ENUM_GROUPS] = { .field = "groups" },
-    [TREE_ENUM_CONTENTS] = { .field = "contents" },
-    [TREE_ENUM_NDEPENDS] = { .field = "ndepends" },
-    [TREE_ENUM_NREQUIREDBY] = { .field = "nrequiredby" },
-    [TREE_ENUM_NALLOW] = { .field = "nallow" },
-    [TREE_ENUM_NGROUPS] = { .field = "ngroups" },
-    [TREE_ENUM_NCONTENTS] = { .field = "ncontents" },
-    [TREE_ENUM_INIT] = { .field = "init" },
-    [TREE_ENUM_DISEN] = { .field = "disen" },
-    [TREE_ENUM_ENDOFKEY] = { .field = 0 }
-} ;
-
-resolve_field_table_t resolve_tree_master_field_table[] = {
-
-    [TREE_ENUM_MASTER_NAME] = { .field = "name" },
-    [TREE_ENUM_MASTER_ALLOW] = { .field = "allow" },
-    [TREE_ENUM_MASTER_ENABLED] = { .field = "enabled" },
-    [TREE_ENUM_MASTER_CURRENT] = { .field = "current" },
-    [TREE_ENUM_MASTER_NENABLED] = { .field = "nenabled" },
-    [TREE_ENUM_MASTER_ENDOFKEY] = { .field = 0 }
-} ;
-
-int tree_read_cdb(cdb *c, resolve_tree_t *tres)
-{
-    log_flow() ;
-
-    stralloc tmp = STRALLOC_ZERO ;
-    resolve_wrapper_t_ref wres ;
-    uint32_t x ;
-
-    wres = resolve_set_struct(DATA_TREE, tres) ;
-
-    resolve_init(wres) ;
-
-    /* name */
-    resolve_find_cdb(&tmp,c,"name") ;
-    tres->name = tmp.len ? resolve_add_string(wres,tmp.s) : 0 ;
-
-    /* depends */
-    resolve_find_cdb(&tmp,c,"depends") ;
-    tres->depends = tmp.len ? resolve_add_string(wres,tmp.s) : 0 ;
-
-    /* requiredby */
-    resolve_find_cdb(&tmp,c,"requiredby") ;
-    tres->requiredby = tmp.len ? resolve_add_string(wres,tmp.s) : 0 ;
-
-    /* allow */
-    resolve_find_cdb(&tmp,c,"allow") ;
-    tres->allow = tmp.len ? resolve_add_string(wres,tmp.s) : 0 ;
-
-    /* groups */
-    resolve_find_cdb(&tmp,c,"groups") ;
-    tres->groups = tmp.len ? resolve_add_string(wres,tmp.s) : 0 ;
-
-    /* contents */
-    resolve_find_cdb(&tmp,c,"contents") ;
-    tres->contents = tmp.len ? resolve_add_string(wres,tmp.s) : 0 ;
-
-    /* ndepends */
-    x = resolve_find_cdb(&tmp,c,"ndepends") ;
-    tres->ndepends = x ;
-
-    /* nrequiredby */
-    x = resolve_find_cdb(&tmp,c,"nrequiredby") ;
-    tres->nrequiredby = x ;
-
-    /* nallow */
-    x = resolve_find_cdb(&tmp,c,"nallow") ;
-    tres->nallow = x ;
-
-    /* ngroups */
-    x = resolve_find_cdb(&tmp,c,"ngroups") ;
-    tres->ngroups = x ;
-
-    /* ncontents */
-    x = resolve_find_cdb(&tmp,c,"ncontents") ;
-    tres->ncontents = x ;
-
-    /* init */
-    x = resolve_find_cdb(&tmp,c,"init") ;
-    tres->init = x ;
-
-    /* disen */
-    x = resolve_find_cdb(&tmp,c,"disen") ;
-    tres->disen = x ;
-
-    free(wres) ;
-    stralloc_free(&tmp) ;
-
-    return 1 ;
-}
-
-int tree_write_cdb(cdbmaker *c, resolve_tree_t *tres)
-{
-    log_flow() ;
-
-    char *str = tres->sa.s ;
-
-    /* name */
-    if (!resolve_add_cdb(c,"name",str + tres->name) ||
-
-    /* depends */
-    !resolve_add_cdb(c,"depends",str + tres->depends) ||
-
-    /* requiredby */
-    !resolve_add_cdb(c,"requiredby",str + tres->requiredby) ||
-
-    /* allow */
-    !resolve_add_cdb(c,"allow",str + tres->allow) ||
-
-    /* groups */
-    !resolve_add_cdb(c,"groups",str + tres->groups) ||
-
-    /* contents */
-    !resolve_add_cdb(c,"contents",str + tres->contents) ||
-
-    /* ndepends */
-    !resolve_add_cdb_uint(c,"ndepends",tres->ndepends) ||
-
-    /* nrequiredby */
-    !resolve_add_cdb_uint(c,"nrequiredby",tres->nrequiredby) ||
-
-    /* nallow */
-    !resolve_add_cdb_uint(c,"nallow",tres->nallow) ||
-
-    /* ngroups */
-    !resolve_add_cdb_uint(c,"ngroups",tres->ngroups) ||
-
-    /* ncontents */
-    !resolve_add_cdb_uint(c,"ncontents",tres->ncontents) ||
-
-    /* init */
-    !resolve_add_cdb_uint(c,"init",tres->init) ||
-
-    /* disen */
-    !resolve_add_cdb_uint(c,"disen",tres->disen)) return 0 ;
-
-    return 1 ;
-}
-
-int tree_resolve_copy(resolve_tree_t *dst, resolve_tree_t *tres)
-{
-    log_flow() ;
-
-    stralloc_free(&dst->sa) ;
-
-    size_t len = tres->sa.len - 1 ;
-    dst->salen = tres->salen ;
-
-    if (!stralloc_catb(&dst->sa,tres->sa.s,len) ||
-        !stralloc_0(&dst->sa))
-            return 0 ;
-
-    dst->name = tres->name ;
-    dst->depends = tres->depends ;
-    dst->requiredby = tres->requiredby ;
-    dst->allow = tres->allow ;
-    dst->groups = tres->groups ;
-    dst->contents = tres->contents ;
-    dst->ndepends = tres->ndepends ;
-    dst->nrequiredby = tres->nrequiredby ;
-    dst->nallow = tres->nallow ;
-    dst->ngroups = tres->ngroups ;
-    dst->ncontents = tres->ncontents ;
-    dst->init = tres->init ;
-    dst->disen = tres->disen ;
-
-    return 1 ;
-
-}
-
-int tree_resolve_modify_field(resolve_tree_t *tres, uint8_t field, char const *data)
-{
-    log_flow() ;
-
-    uint32_t ifield ;
-    int e = 0 ;
-
-    resolve_wrapper_t_ref wres = resolve_set_struct(DATA_TREE, tres) ;
-
-    switch(field) {
-
-        case TREE_ENUM_NAME:
-            tres->name = resolve_add_string(wres,data) ;
-            break ;
-
-        case TREE_ENUM_DEPENDS:
-            tres->depends = resolve_add_string(wres,data) ;
-            break ;
-
-        case TREE_ENUM_REQUIREDBY:
-            tres->requiredby = resolve_add_string(wres,data) ;
-            break ;
-
-        case TREE_ENUM_ALLOW:
-            tres->allow = resolve_add_string(wres,data) ;
-            break ;
-
-        case TREE_ENUM_GROUPS:
-            tres->groups = resolve_add_string(wres,data) ;
-            break ;
-
-        case TREE_ENUM_CONTENTS:
-            tres->contents = resolve_add_string(wres,data) ;
-            break ;
-
-        case TREE_ENUM_NDEPENDS:
-            if (!uint0_scan(data, &ifield)) goto err ;
-            tres->ndepends = ifield ;
-            break ;
-
-        case TREE_ENUM_NREQUIREDBY:
-            if (!uint0_scan(data, &ifield)) goto err ;
-            tres->nrequiredby = ifield ;
-            break ;
-
-        case TREE_ENUM_NALLOW:
-            if (!uint0_scan(data, &ifield)) goto err ;
-            tres->nallow = ifield ;
-            break ;
-
-        case TREE_ENUM_NGROUPS:
-            if (!uint0_scan(data, &ifield)) goto err ;
-            tres->ngroups = ifield ;
-            break ;
-
-        case TREE_ENUM_NCONTENTS:
-            if (!uint0_scan(data, &ifield)) goto err ;
-            tres->ncontents = ifield ;
-            break ;
-
-        case TREE_ENUM_INIT:
-            if (!uint0_scan(data, &ifield)) goto err ;
-            tres->init = ifield ;
-            break ;
-
-        case TREE_ENUM_DISEN:
-            if (!uint0_scan(data, &ifield)) goto err ;
-            tres->disen = ifield ;
-            break ;
-
-        default:
-            break ;
-    }
-
-    e = 1 ;
-
-    err:
-        free(wres) ;
-        return e ;
-
-}
-
-int tree_resolve_field_tosa(stralloc *sa, resolve_tree_t *tres, resolve_tree_enum_t field)
-{
-    log_flow() ;
-
-    char fmt[UINT32_FMT] ;
-    char const *str = 0 ;
-
-    switch(field) {
-
-        case TREE_ENUM_NAME:
-            str = tres->sa.s + tres->name ;
-            break ;
-
-        case TREE_ENUM_DEPENDS:
-            str = tres->sa.s + tres->depends ;
-            break ;
-
-        case TREE_ENUM_REQUIREDBY:
-            str = tres->sa.s + tres->requiredby ;
-            break ;
-
-        case TREE_ENUM_ALLOW:
-            str = tres->sa.s + tres->allow ;
-            break ;
-
-        case TREE_ENUM_GROUPS:
-            str = tres->sa.s + tres->groups ;
-            break ;
-
-        case TREE_ENUM_CONTENTS:
-            str = tres->sa.s + tres->contents ;
-            break ;
-
-        case TREE_ENUM_NDEPENDS:
-            fmt[uint32_fmt(fmt,tres->ndepends)] = 0 ;
-            str = fmt ;
-            break ;
-
-        case TREE_ENUM_NREQUIREDBY:
-            fmt[uint32_fmt(fmt,tres->nrequiredby)] = 0 ;
-            str = fmt ;
-            break ;
-
-        case TREE_ENUM_NALLOW:
-            fmt[uint32_fmt(fmt,tres->nallow)] = 0 ;
-            str = fmt ;
-            break ;
-
-        case TREE_ENUM_NGROUPS:
-            fmt[uint32_fmt(fmt,tres->ngroups)] = 0 ;
-            str = fmt ;
-            break ;
-
-        case TREE_ENUM_NCONTENTS:
-            fmt[uint32_fmt(fmt,tres->ncontents)] = 0 ;
-            str = fmt ;
-            break ;
-
-        case TREE_ENUM_INIT:
-            fmt[uint32_fmt(fmt,tres->init)] = 0 ;
-            str = fmt ;
-            break ;
-
-        case TREE_ENUM_DISEN:
-            fmt[uint32_fmt(fmt,tres->disen)] = 0 ;
-            str = fmt ;
-            break ;
-
-        default:
-            return 0 ;
-    }
-
-    if (!auto_stra(sa,str))
-        return 0 ;
-
-    return 1 ;
-}
-
-/** Master */
-int tree_read_master_cdb(cdb *c, resolve_tree_master_t *mres)
-{
-    log_flow() ;
-
-    stralloc tmp = STRALLOC_ZERO ;
-    resolve_wrapper_t_ref wres ;
-    uint32_t x ;
-
-    wres = resolve_set_struct(DATA_TREE_MASTER, mres) ;
-
-    resolve_init(wres) ;
-
-    /* name */
-    resolve_find_cdb(&tmp,c,"name") ;
-    mres->name = tmp.len ? resolve_add_string(wres,tmp.s) : 0 ;
-
-    /* allow */
-    resolve_find_cdb(&tmp,c,"allow") ;
-    mres->allow = tmp.len ? resolve_add_string(wres,tmp.s) : 0 ;
-
-    /* enabled */
-    resolve_find_cdb(&tmp,c,"enabled") ;
-    mres->enabled = tmp.len ? resolve_add_string(wres,tmp.s) : 0 ;
-
-    /* current */
-    resolve_find_cdb(&tmp,c,"current") ;
-    mres->current = tmp.len ? resolve_add_string(wres,tmp.s) : 0 ;
-
-    /* nenabled */
-    x = resolve_find_cdb(&tmp,c,"nenabled") ;
-    mres->nenabled = x ;
-
-    free(wres) ;
-    stralloc_free(&tmp) ;
-
-    return 1 ;
-}
-
-int tree_write_master_cdb(cdbmaker *c, resolve_tree_master_t *mres)
-{
-    log_flow() ;
-
-    char *str = mres->sa.s ;
-
-    /* name */
-    if (!resolve_add_cdb(c,"name",str + mres->name) ||
-
-    /* allow */
-    !resolve_add_cdb(c,"allow",str + mres->allow) ||
-
-    /* enabled */
-    !resolve_add_cdb(c,"enabled",str + mres->enabled) ||
-
-    /* current */
-    !resolve_add_cdb(c,"current",str + mres->current) ||
-
-    /* nenabled */
-    !resolve_add_cdb_uint(c,"nenabled",mres->nenabled)) return 0 ;
-
-    return 1 ;
-}
-
-int tree_resolve_master_create(char const *base, uid_t owner)
-{
-    int e = 0 ;
-    size_t baselen = strlen(base) ;
-    struct passwd *pw = getpwuid(owner) ;
-    resolve_tree_master_t mres = RESOLVE_TREE_MASTER_ZERO ;
-    resolve_wrapper_t_ref wres = resolve_set_struct(DATA_TREE_MASTER, &mres) ;
-    char dst[baselen + SS_SYSTEM_LEN + 1] ;
-
-    if (!pw) {
-
-        if (!errno)
-            errno = ESRCH ;
-        goto err ;
-    }
-
-    resolve_init(wres) ;
-
-    auto_strings(dst, base, SS_SYSTEM) ;
-
-    mres.name = resolve_add_string(wres, SS_MASTER + 1) ;
-    mres.allow = resolve_add_string(wres, pw->pw_name) ;
-
-    log_trace("write inner resolve file of trees") ;
-    if (!resolve_write(wres, dst, SS_MASTER + 1))
-        goto err ;
-
-    e  = 1 ;
-
-    err:
-        resolve_free(wres) ;
-        return e ;
-}
-
-int tree_resolve_master_copy(resolve_tree_master_t *dst, resolve_tree_master_t *mres)
-{
-    log_flow() ;
-
-    stralloc_free(&dst->sa) ;
-
-    size_t len = mres->sa.len - 1 ;
-    dst->salen = mres->salen ;
-
-    if (!stralloc_catb(&dst->sa,mres->sa.s,len) ||
-        !stralloc_0(&dst->sa))
-            return 0 ;
-
-    dst->name = mres->name ;
-    dst->allow = mres->allow ;
-    dst->enabled = mres->enabled ;
-    dst->current = mres->current ;
-    dst->nenabled = mres->nenabled ;
-
-    return 1 ;
-
-}
-
-int tree_resolve_master_modify_field(resolve_tree_master_t *mres, uint8_t field, char const *data)
-{
-    log_flow() ;
-
-    uint32_t ifield ;
-    int e = 0 ;
-
-    resolve_wrapper_t_ref wres = resolve_set_struct(DATA_TREE_MASTER, mres) ;
-
-    switch(field) {
-
-        case TREE_ENUM_MASTER_NAME:
-            mres->name = resolve_add_string(wres,data) ;
-            break ;
-
-        case TREE_ENUM_MASTER_ALLOW:
-            mres->allow = resolve_add_string(wres,data) ;
-            break ;
-
-        case TREE_ENUM_MASTER_ENABLED:
-            mres->enabled = resolve_add_string(wres,data) ;
-            break ;
-
-        case TREE_ENUM_MASTER_CURRENT:
-            mres->current = resolve_add_string(wres,data) ;
-            break ;
-
-        case TREE_ENUM_MASTER_NENABLED:
-            if (!uint0_scan(data, &ifield)) goto err ;
-            mres->nenabled = ifield ;
-            break ;
-
-        default:
-            break ;
-    }
-
-    e = 1 ;
-
-    err:
-        free(wres) ;
-        return e ;
-
-}
-
-int tree_resolve_master_field_tosa(stralloc *sa, resolve_tree_master_t *mres, resolve_tree_master_enum_t field)
-{
-    log_flow() ;
-
-    char fmt[UINT32_FMT] ;
-    char const *str = 0 ;
-
-    switch(field) {
-
-        case TREE_ENUM_MASTER_NAME:
-            mres->sa.s + mres->name ;
-            break ;
-
-        case TREE_ENUM_MASTER_ALLOW:
-            mres->sa.s + mres->name ;
-            break ;
-
-        case TREE_ENUM_MASTER_ENABLED:
-            mres->sa.s + mres->enabled ;
-            break ;
-
-        case TREE_ENUM_MASTER_CURRENT:
-            mres->sa.s + mres->current ;
-            break ;
-
-        case TREE_ENUM_MASTER_NENABLED:
-            fmt[uint32_fmt(fmt,mres->nenabled)] = 0 ;
-            str = fmt ;
-            break ;
-
-        default:
-            return 0 ;
-    }
-
-    if (!auto_stra(sa,str))
-        return 0 ;
-
-    return 1 ;
-}
diff --git a/src/lib66/tree/tree_resolve_copy.c b/src/lib66/tree/tree_resolve_copy.c
new file mode 100644
index 0000000000000000000000000000000000000000..c0be4d734d60164afc47afdf56d88500ef18fcd5
--- /dev/null
+++ b/src/lib66/tree/tree_resolve_copy.c
@@ -0,0 +1,52 @@
+/*
+ * tree_write_cdb.c
+ *
+ * Copyright (c) 2018-2021 Eric Vidal <eric@obarun.org>
+ *
+ * All rights reserved.
+ *
+ * This file is part of Obarun. It is subject to the license terms in
+ * the LICENSE file found in the top-level directory of this
+ * distribution.
+ * This file may not be copied, modified, propagated, or distributed
+ * except according to the terms contained in the LICENSE file.
+ */
+
+#include <stddef.h>
+
+#include <oblibs/string.h>
+
+#include <skalibs/stralloc.h>
+
+#include <66/tree.h>
+
+int tree_resolve_copy(resolve_tree_t *dst, resolve_tree_t *tres)
+{
+    log_flow() ;
+
+    stralloc_free(&dst->sa) ;
+
+    size_t len = tres->sa.len - 1 ;
+    dst->salen = tres->salen ;
+
+    if (!stralloc_catb(&dst->sa,tres->sa.s,len) ||
+        !stralloc_0(&dst->sa))
+            return 0 ;
+
+    dst->name = tres->name ;
+    dst->depends = tres->depends ;
+    dst->requiredby = tres->requiredby ;
+    dst->allow = tres->allow ;
+    dst->groups = tres->groups ;
+    dst->contents = tres->contents ;
+    dst->ndepends = tres->ndepends ;
+    dst->nrequiredby = tres->nrequiredby ;
+    dst->nallow = tres->nallow ;
+    dst->ngroups = tres->ngroups ;
+    dst->ncontents = tres->ncontents ;
+    dst->init = tres->init ;
+    dst->disen = tres->disen ;
+
+    return 1 ;
+
+}
diff --git a/src/lib66/tree/tree_resolve_field_tosa.c b/src/lib66/tree/tree_resolve_field_tosa.c
new file mode 100644
index 0000000000000000000000000000000000000000..73011993215eff8f2c334ba41c210e67fbbcd61a
--- /dev/null
+++ b/src/lib66/tree/tree_resolve_field_tosa.c
@@ -0,0 +1,99 @@
+/*
+ * tree_resolve_field_tosa.c
+ *
+ * Copyright (c) 2018-2021 Eric Vidal <eric@obarun.org>
+ *
+ * All rights reserved.
+ *
+ * This file is part of Obarun. It is subject to the license terms in
+ * the LICENSE file found in the top-level directory of this
+ * distribution.
+ * This file may not be copied, modified, propagated, or distributed
+ * except according to the terms contained in the LICENSE file.
+ */
+
+#include <oblibs/log.h>
+#include <oblibs/string.h>
+
+#include <skalibs/types.h>//UINT_FMT
+
+#include <66/tree.h>
+#include <66/resolve.h>
+
+int tree_resolve_field_tosa(stralloc *sa, resolve_tree_t *tres, resolve_tree_enum_t field)
+{
+    log_flow() ;
+
+    char fmt[UINT32_FMT] ;
+    char const *str = 0 ;
+
+    switch(field) {
+
+        case TREE_ENUM_NAME:
+            str = tres->sa.s + tres->name ;
+            break ;
+
+        case TREE_ENUM_DEPENDS:
+            str = tres->sa.s + tres->depends ;
+            break ;
+
+        case TREE_ENUM_REQUIREDBY:
+            str = tres->sa.s + tres->requiredby ;
+            break ;
+
+        case TREE_ENUM_ALLOW:
+            str = tres->sa.s + tres->allow ;
+            break ;
+
+        case TREE_ENUM_GROUPS:
+            str = tres->sa.s + tres->groups ;
+            break ;
+
+        case TREE_ENUM_CONTENTS:
+            str = tres->sa.s + tres->contents ;
+            break ;
+
+        case TREE_ENUM_NDEPENDS:
+            fmt[uint32_fmt(fmt,tres->ndepends)] = 0 ;
+            str = fmt ;
+            break ;
+
+        case TREE_ENUM_NREQUIREDBY:
+            fmt[uint32_fmt(fmt,tres->nrequiredby)] = 0 ;
+            str = fmt ;
+            break ;
+
+        case TREE_ENUM_NALLOW:
+            fmt[uint32_fmt(fmt,tres->nallow)] = 0 ;
+            str = fmt ;
+            break ;
+
+        case TREE_ENUM_NGROUPS:
+            fmt[uint32_fmt(fmt,tres->ngroups)] = 0 ;
+            str = fmt ;
+            break ;
+
+        case TREE_ENUM_NCONTENTS:
+            fmt[uint32_fmt(fmt,tres->ncontents)] = 0 ;
+            str = fmt ;
+            break ;
+
+        case TREE_ENUM_INIT:
+            fmt[uint32_fmt(fmt,tres->init)] = 0 ;
+            str = fmt ;
+            break ;
+
+        case TREE_ENUM_DISEN:
+            fmt[uint32_fmt(fmt,tres->disen)] = 0 ;
+            str = fmt ;
+            break ;
+
+        default:
+            return 0 ;
+    }
+
+    if (!auto_stra(sa,str))
+        return 0 ;
+
+    return 1 ;
+}
diff --git a/src/lib66/tree/tree_resolve_master_copy.c b/src/lib66/tree/tree_resolve_master_copy.c
new file mode 100644
index 0000000000000000000000000000000000000000..18d0c5ca8d27b7e941ef3e4130cd141061443748
--- /dev/null
+++ b/src/lib66/tree/tree_resolve_master_copy.c
@@ -0,0 +1,42 @@
+/*
+ * tree_resolve_master_copy.c
+ *
+ * Copyright (c) 2018-2021 Eric Vidal <eric@obarun.org>
+ *
+ * All rights reserved.
+ *
+ * This file is part of Obarun. It is subject to the license terms in
+ * the LICENSE file found in the top-level directory of this
+ * distribution.
+ * This file may not be copied, modified, propagated, or distributed
+ * except according to the terms contained in the LICENSE file.
+ */
+
+#include <stddef.h>
+
+#include <skalibs/stralloc.h>
+
+#include <66/tree.h>
+
+int tree_resolve_master_copy(resolve_tree_master_t *dst, resolve_tree_master_t *mres)
+{
+    log_flow() ;
+
+    stralloc_free(&dst->sa) ;
+
+    size_t len = mres->sa.len - 1 ;
+    dst->salen = mres->salen ;
+
+    if (!stralloc_catb(&dst->sa,mres->sa.s,len) ||
+        !stralloc_0(&dst->sa))
+            return 0 ;
+
+    dst->name = mres->name ;
+    dst->allow = mres->allow ;
+    dst->enabled = mres->enabled ;
+    dst->current = mres->current ;
+    dst->nenabled = mres->nenabled ;
+
+    return 1 ;
+
+}
diff --git a/src/lib66/tree/tree_resolve_master_create.c b/src/lib66/tree/tree_resolve_master_create.c
new file mode 100644
index 0000000000000000000000000000000000000000..3ccb918a4891a5403363de71f200ee75c9ad3fd9
--- /dev/null
+++ b/src/lib66/tree/tree_resolve_master_create.c
@@ -0,0 +1,62 @@
+/*
+ * tree_resolve_master_create.c
+ *
+ * Copyright (c) 2018-2021 Eric Vidal <eric@obarun.org>
+ *
+ * All rights reserved.
+ *
+ * This file is part of Obarun. It is subject to the license terms in
+ * the LICENSE file found in the top-level directory of this
+ * distribution.
+ * This file may not be copied, modified, propagated, or distributed
+ * except according to the terms contained in the LICENSE file.
+ */
+
+#include <stdint.h>
+#include <string.h>
+#include <pwd.h>
+#include <sys/stat.h>
+#include <errno.h>
+
+#include <oblibs/log.h>
+#include <oblibs/string.h>
+
+#include <66/tree.h>
+#include <66/resolve.h>
+#include <66/constants.h>
+
+int tree_resolve_master_create(char const *base, uid_t owner)
+{
+    log_flow() ;
+
+    int e = 0 ;
+    size_t baselen = strlen(base) ;
+    struct passwd *pw = getpwuid(owner) ;
+    resolve_tree_master_t mres = RESOLVE_TREE_MASTER_ZERO ;
+    resolve_wrapper_t_ref wres = resolve_set_struct(DATA_TREE_MASTER, &mres) ;
+    char dst[baselen + SS_SYSTEM_LEN + 1] ;
+
+    if (!pw) {
+
+        if (!errno)
+            errno = ESRCH ;
+        goto err ;
+    }
+
+    resolve_init(wres) ;
+
+    auto_strings(dst, base, SS_SYSTEM) ;
+
+    mres.name = resolve_add_string(wres, SS_MASTER + 1) ;
+    mres.allow = resolve_add_string(wres, pw->pw_name) ;
+
+    log_trace("write inner resolve file of trees") ;
+    if (!resolve_write(wres, dst, SS_MASTER + 1))
+        goto err ;
+
+    e  = 1 ;
+
+    err:
+        resolve_free(wres) ;
+        return e ;
+}
diff --git a/src/lib66/tree/tree_resolve_master_field_tosa.c b/src/lib66/tree/tree_resolve_master_field_tosa.c
new file mode 100644
index 0000000000000000000000000000000000000000..bf05565953c451681a3e66aa3ed7633cc7cb4ffb
--- /dev/null
+++ b/src/lib66/tree/tree_resolve_master_field_tosa.c
@@ -0,0 +1,61 @@
+/*
+ * tree_resolve_master_field_tosa.c
+ *
+ * Copyright (c) 2018-2021 Eric Vidal <eric@obarun.org>
+ *
+ * All rights reserved.
+ *
+ * This file is part of Obarun. It is subject to the license terms in
+ * the LICENSE file found in the top-level directory of this
+ * distribution.
+ * This file may not be copied, modified, propagated, or distributed
+ * except according to the terms contained in the LICENSE file./
+ */
+
+#include <oblibs/log.h>
+#include <oblibs/string.h>
+
+#include <skalibs/stralloc.h>
+#include <skalibs/types.h>//UINT_FMT
+
+#include <66/tree.h>
+
+int tree_resolve_master_field_tosa(stralloc *sa, resolve_tree_master_t *mres, resolve_tree_master_enum_t field)
+{
+    log_flow() ;
+
+    char fmt[UINT32_FMT] ;
+    char const *str = 0 ;
+
+    switch(field) {
+
+        case TREE_ENUM_MASTER_NAME:
+            mres->sa.s + mres->name ;
+            break ;
+
+        case TREE_ENUM_MASTER_ALLOW:
+            mres->sa.s + mres->name ;
+            break ;
+
+        case TREE_ENUM_MASTER_ENABLED:
+            mres->sa.s + mres->enabled ;
+            break ;
+
+        case TREE_ENUM_MASTER_CURRENT:
+            mres->sa.s + mres->current ;
+            break ;
+
+        case TREE_ENUM_MASTER_NENABLED:
+            fmt[uint32_fmt(fmt,mres->nenabled)] = 0 ;
+            str = fmt ;
+            break ;
+
+        default:
+            return 0 ;
+    }
+
+    if (!auto_stra(sa,str))
+        return 0 ;
+
+    return 1 ;
+}
diff --git a/src/lib66/tree/tree_resolve_master_modify_field.c b/src/lib66/tree/tree_resolve_master_modify_field.c
new file mode 100644
index 0000000000000000000000000000000000000000..a99bcb24d0cbb4a4c1e898a003b9d29b471ff9fc
--- /dev/null
+++ b/src/lib66/tree/tree_resolve_master_modify_field.c
@@ -0,0 +1,77 @@
+/*
+ * tree_resolve_master_modify_field.c
+ *
+ * Copyright (c) 2018-2021 Eric Vidal <eric@obarun.org>
+ *
+ * All rights reserved.
+ *
+ * This file is part of Obarun. It is subject to the license terms in
+ * the LICENSE file found in the top-level directory of this
+ * distribution.
+ * This file may not be copied, modified, propagated, or distributed
+ * except according to the terms contained in the LICENSE file.
+ */
+
+#include <stdint.h>
+#include <stdlib.h>
+
+#include <oblibs/log.h>
+
+#include <skalibs/types.h>
+
+#include <66/tree.h>
+#include <66/resolve.h>
+
+resolve_field_table_t resolve_tree_master_field_table[] = {
+
+    [TREE_ENUM_MASTER_NAME] = { .field = "name" },
+    [TREE_ENUM_MASTER_ALLOW] = { .field = "allow" },
+    [TREE_ENUM_MASTER_ENABLED] = { .field = "enabled" },
+    [TREE_ENUM_MASTER_CURRENT] = { .field = "current" },
+    [TREE_ENUM_MASTER_NENABLED] = { .field = "nenabled" },
+    [TREE_ENUM_MASTER_ENDOFKEY] = { .field = 0 }
+} ;
+
+int tree_resolve_master_modify_field(resolve_tree_master_t *mres, uint8_t field, char const *data)
+{
+    log_flow() ;
+
+    uint32_t ifield ;
+    int e = 0 ;
+
+    resolve_wrapper_t_ref wres = resolve_set_struct(DATA_TREE_MASTER, mres) ;
+
+    switch(field) {
+
+        case TREE_ENUM_MASTER_NAME:
+            mres->name = resolve_add_string(wres,data) ;
+            break ;
+
+        case TREE_ENUM_MASTER_ALLOW:
+            mres->allow = resolve_add_string(wres,data) ;
+            break ;
+
+        case TREE_ENUM_MASTER_ENABLED:
+            mres->enabled = resolve_add_string(wres,data) ;
+            break ;
+
+        case TREE_ENUM_MASTER_CURRENT:
+            mres->current = resolve_add_string(wres,data) ;
+            break ;
+
+        case TREE_ENUM_MASTER_NENABLED:
+            if (!uint0_scan(data, &ifield)) goto err ;
+            mres->nenabled = ifield ;
+            break ;
+
+        default:
+            break ;
+    }
+
+    e = 1 ;
+
+    err:
+        free(wres) ;
+        return e ;
+
+}
diff --git a/src/lib66/tree/tree_resolve_modify_field.c b/src/lib66/tree/tree_resolve_modify_field.c
new file mode 100644
index 0000000000000000000000000000000000000000..8e7c1aa26c81c24d7b140145be92c08f026c7605
--- /dev/null
+++ b/src/lib66/tree/tree_resolve_modify_field.c
@@ -0,0 +1,123 @@
+/*
+ * tree_resolve_modify_field.c
+ *
+ * Copyright (c) 2018-2021 Eric Vidal <eric@obarun.org>
+ *
+ * All rights reserved.
+ *
+ * This file is part of Obarun. It is subject to the license terms in
+ * the LICENSE file found in the top-level directory of this
+ * distribution.
+ * This file may not be copied, modified, propagated, or distributed
+ * except according to the terms contained in the LICENSE file.
+ */
+
+#include <stdint.h>
+#include <stdlib.h>//free
+
+#include <oblibs/log.h>
+
+#include <skalibs/types.h>
+
+#include <66/resolve.h>
+#include <66/tree.h>
+
+resolve_field_table_t resolve_tree_field_table[] = {
+
+    [TREE_ENUM_NAME] = { .field = "name" },
+    [TREE_ENUM_DEPENDS] = { .field = "depends" },
+    [TREE_ENUM_REQUIREDBY] = { .field = "requiredby" },
+    [TREE_ENUM_ALLOW] = { .field = "allow" },
+    [TREE_ENUM_GROUPS] = { .field = "groups" },
+    [TREE_ENUM_CONTENTS] = { .field = "contents" },
+    [TREE_ENUM_NDEPENDS] = { .field = "ndepends" },
+    [TREE_ENUM_NREQUIREDBY] = { .field = "nrequiredby" },
+    [TREE_ENUM_NALLOW] = { .field = "nallow" },
+    [TREE_ENUM_NGROUPS] = { .field = "ngroups" },
+    [TREE_ENUM_NCONTENTS] = { .field = "ncontents" },
+    [TREE_ENUM_INIT] = { .field = "init" },
+    [TREE_ENUM_DISEN] = { .field = "disen" },
+    [TREE_ENUM_ENDOFKEY] = { .field = 0 }
+} ;
+
+int tree_resolve_modify_field(resolve_tree_t *tres, uint8_t field, char const *data)
+{
+    log_flow() ;
+
+    uint32_t ifield ;
+    int e = 0 ;
+
+    resolve_wrapper_t_ref wres = resolve_set_struct(DATA_TREE, tres) ;
+
+    switch(field) {
+
+        case TREE_ENUM_NAME:
+            tres->name = resolve_add_string(wres,data) ;
+            break ;
+
+        case TREE_ENUM_DEPENDS:
+            tres->depends = resolve_add_string(wres,data) ;
+            break ;
+
+        case TREE_ENUM_REQUIREDBY:
+            tres->requiredby = resolve_add_string(wres,data) ;
+            break ;
+
+        case TREE_ENUM_ALLOW:
+            tres->allow = resolve_add_string(wres,data) ;
+            break ;
+
+        case TREE_ENUM_GROUPS:
+            tres->groups = resolve_add_string(wres,data) ;
+            break ;
+
+        case TREE_ENUM_CONTENTS:
+            tres->contents = resolve_add_string(wres,data) ;
+            break ;
+
+        case TREE_ENUM_NDEPENDS:
+            if (!uint0_scan(data, &ifield)) goto err ;
+            tres->ndepends = ifield ;
+            break ;
+
+        case TREE_ENUM_NREQUIREDBY:
+            if (!uint0_scan(data, &ifield)) goto err ;
+            tres->nrequiredby = ifield ;
+            break ;
+
+        case TREE_ENUM_NALLOW:
+            if (!uint0_scan(data, &ifield)) goto err ;
+            tres->nallow = ifield ;
+            break ;
+
+        case TREE_ENUM_NGROUPS:
+            if (!uint0_scan(data, &ifield)) goto err ;
+            tres->ngroups = ifield ;
+            break ;
+
+        case TREE_ENUM_NCONTENTS:
+            if (!uint0_scan(data, &ifield)) goto err ;
+            tres->ncontents = ifield ;
+            break ;
+
+        case TREE_ENUM_INIT:
+            if (!uint0_scan(data, &ifield)) goto err ;
+            tres->init = ifield ;
+            break ;
+
+        case TREE_ENUM_DISEN:
+            if (!uint0_scan(data, &ifield)) goto err ;
+            tres->disen = ifield ;
+            break ;
+
+        default:
+            break ;
+    }
+
+    e = 1 ;
+
+    err:
+        free(wres) ;
+        return e ;
+
+}
diff --git a/src/lib66/tree/tree_resolve_read_cdb.c b/src/lib66/tree/tree_resolve_read_cdb.c
new file mode 100644
index 0000000000000000000000000000000000000000..15de1dcc06f01ba593a486e4a30f81e84c0c9cf9
--- /dev/null
+++ b/src/lib66/tree/tree_resolve_read_cdb.c
@@ -0,0 +1,94 @@
+/*
+ * tree_resolve_read_cdb.c
+ *
+ * Copyright (c) 2018-2021 Eric Vidal <eric@obarun.org>
+ *
+ * All rights reserved.
+ *
+ * This file is part of Obarun. It is subject to the license terms in
+ * the LICENSE file found in the top-level directory of this
+ * distribution.
+ * This file may not be copied, modified, propagated, or distributed
+ * except according to the terms contained in the LICENSE file.
+ */
+
+#include <stdint.h>
+#include <stdlib.h>//free
+
+#include <oblibs/log.h>
+
+#include <skalibs/stralloc.h>
+#include <skalibs/cdb.h>
+
+#include <66/resolve.h>
+#include <66/tree.h>
+
+int tree_resolve_read_cdb(cdb *c, resolve_tree_t *tres)
+{
+    log_flow() ;
+
+    stralloc tmp = STRALLOC_ZERO ;
+    resolve_wrapper_t_ref wres ;
+    uint32_t x ;
+
+    wres = resolve_set_struct(DATA_TREE, tres) ;
+
+    resolve_init(wres) ;
+
+    /* name */
+    resolve_find_cdb(&tmp,c,"name") ;
+    tres->name = tmp.len ? resolve_add_string(wres,tmp.s) : 0 ;
+
+    /* depends */
+    resolve_find_cdb(&tmp,c,"depends") ;
+    tres->depends = tmp.len ? resolve_add_string(wres,tmp.s) : 0 ;
+
+    /* requiredby */
+    resolve_find_cdb(&tmp,c,"requiredby") ;
+    tres->requiredby = tmp.len ? resolve_add_string(wres,tmp.s) : 0 ;
+
+    /* allow */
+    resolve_find_cdb(&tmp,c,"allow") ;
+    tres->allow = tmp.len ? resolve_add_string(wres,tmp.s) : 0 ;
+
+    /* groups */
+    resolve_find_cdb(&tmp,c,"groups") ;
+    tres->groups = tmp.len ? resolve_add_string(wres,tmp.s) : 0 ;
+
+    /* contents */
+    resolve_find_cdb(&tmp,c,"contents") ;
+    tres->contents = tmp.len ? resolve_add_string(wres,tmp.s) : 0 ;
+
+    /* ndepends */
+    x = resolve_find_cdb(&tmp,c,"ndepends") ;
+    tres->ndepends = x ;
+
+    /* nrequiredby */
+    x = resolve_find_cdb(&tmp,c,"nrequiredby") ;
+    tres->nrequiredby = x ;
+
+    /* nallow */
+    x = resolve_find_cdb(&tmp,c,"nallow") ;
+    tres->nallow = x ;
+
+    /* ngroups */
+    x = resolve_find_cdb(&tmp,c,"ngroups") ;
+    tres->ngroups = x ;
+
+    /* ncontents */
+    x = resolve_find_cdb(&tmp,c,"ncontents") ;
+    tres->ncontents = x ;
+
+    /* init */
+    x = resolve_find_cdb(&tmp,c,"init") ;
+    tres->init = x ;
+
+    /* disen */
+    x = resolve_find_cdb(&tmp,c,"disen") ;
+    tres->disen = x ;
+
+    free(wres) ;
+    stralloc_free(&tmp) ;
+
+    return 1 ;
+}
diff --git a/src/lib66/tree/tree_resolve_read_master_cdb.c b/src/lib66/tree/tree_resolve_read_master_cdb.c
new file mode 100644
index 0000000000000000000000000000000000000000..a01299431393a4d12cf44fc64b6d00c5d5f9efcb
--- /dev/null
+++ b/src/lib66/tree/tree_resolve_read_master_cdb.c
@@ -0,0 +1,60 @@
+/*
+ * tree_resolve_read_master_cdb.c
+ *
+ * Copyright (c) 2018-2021 Eric Vidal <eric@obarun.org>
+ *
+ * All rights reserved.
+ *
+ * This file is part of Obarun. It is subject to the license terms in
+ * the LICENSE file found in the top-level directory of this
+ * distribution.
+ * This file may not be copied, modified, propagated, or distributed
+ * except according to the terms contained in the LICENSE file.
+ */
+
+#include <stdint.h>
+#include <stdlib.h>//free
+
+#include <skalibs/stralloc.h>
+#include <skalibs/cdb.h>
+
+#include <66/tree.h>
+#include <66/resolve.h>
+
+int tree_resolve_read_master_cdb(cdb *c, resolve_tree_master_t *mres)
+{
+    log_flow() ;
+
+    stralloc tmp = STRALLOC_ZERO ;
+    resolve_wrapper_t_ref wres ;
+    uint32_t x ;
+
+    wres = resolve_set_struct(DATA_TREE_MASTER, mres) ;
+
+    resolve_init(wres) ;
+
+    /* name */
+    resolve_find_cdb(&tmp,c,"name") ;
+    mres->name = tmp.len ? resolve_add_string(wres,tmp.s) : 0 ;
+
+    /* allow */
+    resolve_find_cdb(&tmp,c,"allow") ;
+    mres->allow = tmp.len ? resolve_add_string(wres,tmp.s) : 0 ;
+
+    /* enabled */
+    resolve_find_cdb(&tmp,c,"enabled") ;
+    mres->enabled = tmp.len ? resolve_add_string(wres,tmp.s) : 0 ;
+
+    /* current */
+    resolve_find_cdb(&tmp,c,"current") ;
+    mres->current = tmp.len ? resolve_add_string(wres,tmp.s) : 0 ;
+
+    /* nenabled */
+    x = resolve_find_cdb(&tmp,c,"nenabled") ;
+    mres->nenabled = x ;
+
+    free(wres) ;
+    stralloc_free(&tmp) ;
+
+    return 1 ;
+}
diff --git a/src/lib66/tree/tree_resolve_write_cdb.c b/src/lib66/tree/tree_resolve_write_cdb.c
new file mode 100644
index 0000000000000000000000000000000000000000..b867ffb9bccb26a4599bc1bdc77b2d1d03b9ffc0
--- /dev/null
+++ b/src/lib66/tree/tree_resolve_write_cdb.c
@@ -0,0 +1,68 @@
+/*
+ * tree_resolve_write_cdb.c
+ *
+ * Copyright (c) 2018-2021 Eric Vidal <eric@obarun.org>
+ *
+ * All rights reserved.
+ *
+ * This file is part of Obarun. It is subject to the license terms in
+ * the LICENSE file found in the top-level directory of this
+ * distribution.
+ * This file may not be copied, modified, propagated, or distributed
+ * except according to the terms contained in the LICENSE file.
+ */
+
+#include <oblibs/log.h>
+
+#include <skalibs/cdbmake.h>
+
+#include <66/tree.h>
+#include <66/resolve.h>
+
+int tree_resolve_write_cdb(cdbmaker *c, resolve_tree_t *tres)
+{
+    log_flow() ;
+
+    char *str = tres->sa.s ;
+
+    /* name */
+    if (!resolve_add_cdb(c,"name",str + tres->name) ||
+
+    /* depends */
+    !resolve_add_cdb(c,"depends",str + tres->depends) ||
+
+    /* requiredby */
+    !resolve_add_cdb(c,"requiredby",str + tres->requiredby) ||
+
+    /* allow */
+    !resolve_add_cdb(c,"allow",str + tres->allow) ||
+
+    /* groups */
+    !resolve_add_cdb(c,"groups",str + tres->groups) ||
+
+    /* contents */
+    !resolve_add_cdb(c,"contents",str + tres->contents) ||
+
+    /* ndepends */
+    !resolve_add_cdb_uint(c,"ndepends",tres->ndepends) ||
+
+    /* nrequiredby */
+    !resolve_add_cdb_uint(c,"nrequiredby",tres->nrequiredby) ||
+
+    /* nallow */
+    !resolve_add_cdb_uint(c,"nallow",tres->nallow) ||
+
+    /* ngroups */
+    !resolve_add_cdb_uint(c,"ngroups",tres->ngroups) ||
+
+    /* ncontents */
+    !resolve_add_cdb_uint(c,"ncontents",tres->ncontents) ||
+
+    /* init */
+    !resolve_add_cdb_uint(c,"init",tres->init) ||
+
+    /* disen */
+    !resolve_add_cdb_uint(c,"disen",tres->disen)) return 0 ;
+
+    return 1 ;
+}
diff --git a/src/lib66/tree/tree_resolve_write_master_cdb.c b/src/lib66/tree/tree_resolve_write_master_cdb.c
new file mode 100644
index 0000000000000000000000000000000000000000..05a681853f6f3c97c43a4497ad95dee883a3290f
--- /dev/null
+++ b/src/lib66/tree/tree_resolve_write_master_cdb.c
@@ -0,0 +1,44 @@
+/*
+ * tree_resolve_write_master_cdb.c
+ *
+ * Copyright (c) 2018-2021 Eric Vidal <eric@obarun.org>
+ *
+ * All rights reserved.
+ *
+ * This file is part of Obarun. It is subject to the license terms in
+ * the LICENSE file found in the top-level directory of this
+ * distribution.
+ * This file may not be copied, modified, propagated, or distributed
+ * except according to the terms contained in the LICENSE file.
+ */
+
+#include <oblibs/log.h>
+
+#include <skalibs/cdbmake.h>
+
+#include <66/tree.h>
+#include <66/resolve.h>
+
+int tree_resolve_write_master_cdb(cdbmaker *c, resolve_tree_master_t *mres)
+{
+    log_flow() ;
+
+    char *str = mres->sa.s ;
+
+    /* name */
+    if (!resolve_add_cdb(c,"name",str + mres->name) ||
+
+    /* allow */
+    !resolve_add_cdb(c,"allow",str + mres->allow) ||
+
+    /* enabled */
+    !resolve_add_cdb(c,"enabled",str + mres->enabled) ||
+
+    /* current */
+    !resolve_add_cdb(c,"current",str + mres->current) ||
+
+    /* nenabled */
+    !resolve_add_cdb_uint(c,"nenabled",mres->nenabled)) return 0 ;
+
+    return 1 ;
+}
diff --git a/src/lib66/tree/tree_seed_file_isvalid.c b/src/lib66/tree/tree_seed_file_isvalid.c
new file mode 100644
index 0000000000000000000000000000000000000000..781dd06dbbf18bd4a2cdd0705d6cc3e729d2cf0a
--- /dev/null
+++ b/src/lib66/tree/tree_seed_file_isvalid.c
@@ -0,0 +1,38 @@
+/*
+ * tree_seed_file_isvalid.c
+ *
+ * Copyright (c) 2018-2021 Eric Vidal <eric@obarun.org>
+ *
+ * All rights reserved.
+ *
+ * This file is part of Obarun. It is subject to the license terms in
+ * the LICENSE file found in the top-level directory of this
+ * distribution.
+ * This file may not be copied, modified, propagated, or distributed
+ * except according to the terms contained in the LICENSE file./
+ */
+
+#include <string.h>
+#include <sys/types.h>
+
+#include <oblibs/string.h>
+#include <oblibs/types.h>
+
+#include <66/tree.h>
+
+/** @Return -1 bad format e.g want REG get DIR
+ * @Return  0 fail
+ * @Return success */
+static int tree_seed_file_isvalid(char const *seedpath, char const *treename)
+{
+    log_flow() ;
+
+    int r ;
+    size_t slen = strlen(seedpath), tlen = strlen(treename) ;
+    char seed[slen + tlen + 1] ;
+    auto_strings(seed, seedpath, treename) ;
+
+    r = scan_mode(seed, S_IFREG) ;
+
+    return r ;
+}
diff --git a/src/lib66/tree/tree_seed_free.c b/src/lib66/tree/tree_seed_free.c
new file mode 100644
index 0000000000000000000000000000000000000000..02327cef30929e18d09dee7da8a127c4ea5d0617
--- /dev/null
+++ b/src/lib66/tree/tree_seed_free.c
@@ -0,0 +1,22 @@
+/*
+ * tree_seed_free.c
+ *
+ * Copyright (c) 2018-2021 Eric Vidal <eric@obarun.org>
+ *
+ * All rights reserved.
+ *
+ * This file is part of Obarun. It is subject to the license terms in
+ * the LICENSE file found in the top-level directory of this
+ * distribution.
+ * This file may not be copied, modified, propagated, or distributed
+ * except according to the terms contained in the LICENSE file./
+ */
+
+#include <skalibs/stralloc.h>
+
+#include <66/tree.h>
+
+void tree_seed_free(tree_seed_t *seed)
+{
+    stralloc_free(&seed->sa) ;
+}
diff --git a/src/lib66/tree/tree_seed_get_group_permissions.c b/src/lib66/tree/tree_seed_get_group_permissions.c
new file mode 100644
index 0000000000000000000000000000000000000000..4b338bca35d2a455f8ac4abd8be9d5f6b9dd654a
--- /dev/null
+++ b/src/lib66/tree/tree_seed_get_group_permissions.c
@@ -0,0 +1,56 @@
+/*
+ * tree_seed_ismandatory.c
+ *
+ * Copyright (c) 2018-2021 Eric Vidal <eric@obarun.org>
+ *
+ * All rights reserved.
+ *
+ * This file is part of Obarun. It is subject to the license terms in
+ * the LICENSE file found in the top-level directory of this
+ * distribution.
+ * This file may not be copied, modified, propagated, or distributed
+ * except according to the terms contained in the LICENSE file./
+ */
+
+#include <unistd.h>//getuid
+#include <string.h>
+
+#include <oblibs/log.h>
+
+#include <skalibs/stralloc.h>
+
+#include <66/tree.h>
+
+int tree_seed_get_group_permissions(tree_seed_t *seed, uint8_t check_contents)
+{
+    log_flow() ;
+
+    int e = 0 ;
+    uid_t uid = getuid() ;
+
+    stralloc sv = STRALLOC_ZERO ;
+
+    char *groups = seed->sa.s + seed->groups ;
+
+    if (!uid && (!strcmp(groups, TREE_GROUPS_USER))) {
+
+        log_warn("Only regular user can use this seed") ;
+        goto err ;
+
+    } else if (uid && (strcmp(groups, TREE_GROUPS_USER))) {
+
+        log_warn("Only root user can use seed: ", seed->sa.s + seed->name) ;
+        goto err ;
+    }
+
+    if (!strcmp(groups, TREE_GROUPS_BOOT) && seed->disen) {
+
+        log_1_warn("enable was asked for a tree on group boot -- ignoring enable request") ;
+        seed->disen = 0 ;
+    }
+
+    e = 1 ;
+    err:
+        stralloc_free(&sv) ;
+        return e ;
+}
diff --git a/src/lib66/tree/tree_seed_get_key.c b/src/lib66/tree/tree_seed_get_key.c
new file mode 100644
index 0000000000000000000000000000000000000000..91d256784a65c9d3bc933ebcab35727971747a02
--- /dev/null
+++ b/src/lib66/tree/tree_seed_get_key.c
@@ -0,0 +1,40 @@
+/*
+ * tree_seed_get_key.c
+ *
+ * Copyright (c) 2018-2021 Eric Vidal <eric@obarun.org>
+ *
+ * All rights reserved.
+ *
+ * This file is part of Obarun. It is subject to the license terms in
+ * the LICENSE file found in the top-level directory of this
+ * distribution.
+ * This file may not be copied, modified, propagated, or distributed
+ * except according to the terms contained in the LICENSE file./
+ */
+
+#include <sys/types.h>
+
+#include <oblibs/string.h>
+#include <oblibs/log.h>
+
+#include <66/tree.h>
+
+static ssize_t tree_seed_get_key(char *table,char const *str)
+{
+    log_flow() ;
+
+    ssize_t pos = -1 ;
+
+    pos = get_len_until(str,'=') ;
+
+    if (pos == -1)
+        return -1 ;
+
+    auto_strings(table,str) ;
+
+    table[pos] = 0 ;
+
+    pos++ ; // remove '='
+
+    return pos ;
+}
diff --git a/src/lib66/tree/tree_seed_isvalid.c b/src/lib66/tree/tree_seed_isvalid.c
new file mode 100644
index 0000000000000000000000000000000000000000..cf1c0a42a8de512f770c0c545c4753f283650fe7
--- /dev/null
+++ b/src/lib66/tree/tree_seed_isvalid.c
@@ -0,0 +1,30 @@
+/*
+ * tree_seed_isvalid.c
+ *
+ * Copyright (c) 2018-2021 Eric Vidal <eric@obarun.org>
+ *
+ * All rights reserved.
+ *
+ * This file is part of Obarun. It is subject to the license terms in
+ * the LICENSE file found in the top-level directory of this
+ * distribution.
+ * This file may not be copied, modified, propagated, or distributed
+ * except according to the terms contained in the LICENSE file./
+ */
+
+#include <skalibs/stralloc.h>
+
+#include <66/tree.h>
+
+int tree_seed_isvalid(char const *seed)
+{
+    int e = 1 ;
+    stralloc src = STRALLOC_ZERO ;
+
+    if (!tree_seed_resolve_path(&src, seed))
+        e = 0 ;
+
+    stralloc_free(&src) ;
+
+    return e ;
+}
diff --git a/src/lib66/tree/tree_seed.c b/src/lib66/tree/tree_seed_parse_file.c
similarity index 53%
rename from src/lib66/tree/tree_seed.c
rename to src/lib66/tree/tree_seed_parse_file.c
index 4fe074306e55bdb240d711f34283b6d5117a5b51..48353d73a48611da106daeb041e5a680d721f724 100644
--- a/src/lib66/tree/tree_seed.c
+++ b/src/lib66/tree/tree_seed_parse_file.c
@@ -1,5 +1,5 @@
 /*
- * tree_seed.c
+ * tree_seed_parse_file.c
  *
  * Copyright (c) 2018-2021 Eric Vidal <eric@obarun.org>
  *
@@ -12,49 +12,20 @@
  * except according to the terms contained in the LICENSE file./
  */
 
-
-#include <66/tree.h>
-
 #include <sys/types.h>
 #include <string.h>
-#include <unistd.h>//getuid
 
 #include <oblibs/string.h>
 #include <oblibs/files.h>
 #include <oblibs/log.h>
 #include <oblibs/environ.h>
 #include <oblibs/sastr.h>
-#include <oblibs/types.h>
 
 #include <skalibs/stralloc.h>
 #include <skalibs/djbunix.h>
 
 #include <66/enum.h>
-#include <66/utils.h>
-#include <66/config.h>
-
-void tree_seed_free(tree_seed_t *seed)
-{
-    stralloc_free(&seed->sa) ;
-}
-
-static ssize_t tree_seed_get_key(char *table,char const *str)
-{
-    ssize_t pos = -1 ;
-
-    pos = get_len_until(str,'=') ;
-
-    if (pos == -1)
-        return -1 ;
-
-    auto_strings(table,str) ;
-
-    table[pos] = 0 ;
-
-    pos++ ; // remove '='
-
-    return pos ;
-}
+#include <66/tree.h>
 
 int tree_seed_parse_file(tree_seed_t *seed, char const *seedpath)
 {
@@ -202,144 +173,3 @@ int tree_seed_parse_file(tree_seed_t *seed, char const *seedpath)
         stralloc_free(&sa) ;
         return e ;
 }
-
-/** @Return -1 bad format e.g want REG get DIR
- * @Return  0 fail
- * @Return success */
-static int tree_seed_file_isvalid(char const *seedpath, char const *treename)
-{
-    log_flow() ;
-
-    int r ;
-    size_t slen = strlen(seedpath), tlen = strlen(treename) ;
-    char seed[slen + tlen + 1] ;
-    auto_strings(seed, seedpath, treename) ;
-
-    r = scan_mode(seed, S_IFREG) ;
-
-    return r ;
-}
-
-int tree_seed_resolve_path(stralloc *sa, char const *seed)
-{
-    log_flow() ;
-
-    int r ;
-
-    char *src = 0 ;
-    uid_t uid = getuid() ;
-    if (!uid) {
-
-        src = SS_SEED_ADMDIR ;
-
-    } else {
-
-        if (!set_ownerhome(sa, uid))
-            log_warnusys_return(LOG_EXIT_ZERO, "set home directory") ;
-
-        if (!auto_stra(sa, SS_SEED_USERDIR))
-            log_warnsys_return(LOG_EXIT_ZERO, "stralloc") ;
-
-        src = sa->s ;
-    }
-
-    r = tree_seed_file_isvalid(src, seed) ;
-    if (r == -1)
-        return 0 ;
-
-    if (!r) {
-
-        /** yeah double check because we can come from !uid */
-        src = SS_SEED_ADMDIR ;
-        r = tree_seed_file_isvalid(src, seed) ;
-        if (r == -1)
-            return 0 ;
-
-        if (!r) {
-
-            src = SS_SEED_SYSDIR ;
-            r = tree_seed_file_isvalid(src, seed) ;
-            if (r != 1)
-                return 0 ;
-
-        }
-    }
-
-    sa->len = 0 ;
-    if (!auto_stra(sa,src, seed))
-        log_warnsys_return(LOG_EXIT_ZERO, "stralloc") ;
-
-    return 1 ;
-
-}
-
-int tree_seed_isvalid(char const *seed)
-{
-    int e = 1 ;
-    stralloc src = STRALLOC_ZERO ;
-
-    if (!tree_seed_resolve_path(&src, seed))
-        e = 0 ;
-
-    stralloc_free(&src) ;
-
-    return e ;
-}
-
-int tree_seed_ismandatory(tree_seed_t *seed, uint8_t check_contents)
-{
-    log_flow() ;
-
-    int e = 0 ;
-    uid_t uid = getuid() ;
-    //size_t pos = 0 ;
-    stralloc sv = STRALLOC_ZERO ;
-
-    char *groups = seed->sa.s + seed->groups ;
-
-    if (!uid && (!strcmp(groups, TREE_GROUPS_USER))) {
-
-        log_warn("Only regular user can use this seed") ;
-        goto err ;
-
-    } else if (uid && (strcmp(groups, TREE_GROUPS_USER))) {
-
-        log_warn("Only root user can use seed: ", seed->sa.s + seed->name) ;
-        goto err ;
-    }
-
-    if (!strcmp(groups, TREE_GROUPS_BOOT) && seed->disen) {
-
-        log_1_warn("enable was asked for a tree on group boot -- ignoring enable request") ;
-        seed->disen = 0 ;
-    }
-
-    e = 1 ;
-    err:
-        stralloc_free(&sv) ;
-        return e ;
-}
-
-int tree_seed_setseed(tree_seed_t *seed, char const *treename, uint8_t check_service)
-{
-    log_flow() ;
-
-    int e = 0 ;
-    stralloc src = STRALLOC_ZERO ;
-
-    if (!tree_seed_resolve_path(&src, treename))
-        goto err ;
-
-    seed->name = seed->sa.len ;
-    if (!sastr_add_string(&seed->sa, treename))
-        goto err ;
-
-    if (!tree_seed_parse_file(seed, src.s) ||
-        !tree_seed_ismandatory(seed, check_service))
-            goto err ;
-
-    e = 1 ;
-    err:
-        stralloc_free(&src) ;
-        return e ;
-}
diff --git a/src/lib66/tree/tree_seed_resolve_path.c b/src/lib66/tree/tree_seed_resolve_path.c
new file mode 100644
index 0000000000000000000000000000000000000000..e5fe73bfeefc2625c238fb3e32ebcafc437c6849
--- /dev/null
+++ b/src/lib66/tree/tree_seed_resolve_path.c
@@ -0,0 +1,78 @@
+/*
+ * tree_seed_resolve_path.c
+ *
+ * Copyright (c) 2018-2021 Eric Vidal <eric@obarun.org>
+ *
+ * All rights reserved.
+ *
+ * This file is part of Obarun. It is subject to the license terms in
+ * the LICENSE file found in the top-level directory of this
+ * distribution.
+ * This file may not be copied, modified, propagated, or distributed
+ * except according to the terms contained in the LICENSE file./
+ */
+
+#include <unistd.h>//getuid
+#include <sys/types.h>
+
+#include <oblibs/string.h>
+#include <oblibs/log.h>
+
+#include <skalibs/stralloc.h>
+
+#include <66/constants.h>
+#include <66/utils.h>
+#include <66/tree.h>
+
+int tree_seed_resolve_path(stralloc *sa, char const *seed)
+{
+    log_flow() ;
+
+    int r ;
+
+    char *src = 0 ;
+    uid_t uid = getuid() ;
+    if (!uid) {
+
+        src = SS_SEED_ADMDIR ;
+
+    } else {
+
+        if (!set_ownerhome(sa, uid))
+            log_warnusys_return(LOG_EXIT_ZERO, "set home directory") ;
+
+        if (!auto_stra(sa, SS_SEED_USERDIR))
+            log_warnsys_return(LOG_EXIT_ZERO, "stralloc") ;
+
+        src = sa->s ;
+    }
+
+    r = tree_seed_file_isvalid(src, seed) ;
+    if (r == -1)
+        return 0 ;
+
+    if (!r) {
+
+        /** yeah double check because we can come from !uid */
+        src = SS_SEED_ADMDIR ;
+        r = tree_seed_file_isvalid(src, seed) ;
+        if (r == -1)
+            return 0 ;
+
+        if (!r) {
+
+            src = SS_SEED_SYSDIR ;
+            r = tree_seed_file_isvalid(src, seed) ;
+            if (r != 1)
+                return 0 ;
+
+        }
+    }
+
+    sa->len = 0 ;
+    if (!auto_stra(sa,src, seed))
+        log_warnsys_return(LOG_EXIT_ZERO, "stralloc") ;
+
+    return 1 ;
+
+}
diff --git a/src/lib66/tree/tree_seed_setseed.c b/src/lib66/tree/tree_seed_setseed.c
new file mode 100644
index 0000000000000000000000000000000000000000..c9dfd7c0debbe135206e51f9636c017e5c4c5806
--- /dev/null
+++ b/src/lib66/tree/tree_seed_setseed.c
@@ -0,0 +1,44 @@
+/*
+ * tree_seed_setseed.c
+ *
+ * Copyright (c) 2018-2021 Eric Vidal <eric@obarun.org>
+ *
+ * All rights reserved.
+ *
+ * This file is part of Obarun. It is subject to the license terms in
+ * the LICENSE file found in the top-level directory of this
+ * distribution.
+ * This file may not be copied, modified, propagated, or distributed
+ * except according to the terms contained in the LICENSE file./
+ */
+
+#include <oblibs/log.h>
+#include <oblibs/sastr.h>
+
+#include <skalibs/stralloc.h>
+
+#include <66/tree.h>
+
+int tree_seed_setseed(tree_seed_t *seed, char const *treename)
+{
+    log_flow() ;
+
+    int e = 0 ;
+    stralloc src = STRALLOC_ZERO ;
+
+    if (!tree_seed_resolve_path(&src, treename))
+        goto err ;
+
+    seed->name = seed->sa.len ;
+    if (!sastr_add_string(&seed->sa, treename))
+        goto err ;
+
+    if (!tree_seed_parse_file(seed, src.s) ||
+        !tree_seed_get_group_permissions(seed))
+            goto err ;
+
+    e = 1 ;
+    err:
+        stralloc_free(&src) ;
+        return e ;
+}
diff --git a/src/lib66/tree/tree_sethome.c b/src/lib66/tree/tree_sethome.c
index 86e98de0f453281407edd24de73ad66c24d7476f..8f95643a9f6dcfdfacbcd8191cbc0322fae059b3 100644
--- a/src/lib66/tree/tree_sethome.c
+++ b/src/lib66/tree/tree_sethome.c
@@ -12,22 +12,16 @@
  * except according to the terms contained in the LICENSE file./
  */
 
-#include <66/tree.h>
-
 #include <string.h>
-#include <sys/stat.h>
 #include <errno.h>
-#include <sys/types.h>
 
-#include <oblibs/types.h>
 #include <oblibs/log.h>
 #include <oblibs/string.h>
 #include <oblibs/environ.h> //char const **environ ;
 
-#include <skalibs/stralloc.h>
-
 #include <66/constants.h>
 #include <66/ssexec.h>
+#include <66/tree.h>
 
 /**
  * @Return -3 > unable to find current
diff --git a/src/lib66/tree/tree_switch_current.c b/src/lib66/tree/tree_switch_current.c
index 04dbd2aa2caee7b2d0ccb94d4b467ee190af57e9..7770e29c6f759e02b8b2598a153f1873d4930413 100644
--- a/src/lib66/tree/tree_switch_current.c
+++ b/src/lib66/tree/tree_switch_current.c
@@ -12,16 +12,11 @@
  * except according to the terms contained in the LICENSE file./
  */
 
-#include <66/tree.h>
-
-#include <sys/types.h>
-#include <string.h>
-
-#include <oblibs/string.h>
 #include <oblibs/log.h>
 
 #include <66/constants.h>
 #include <66/resolve.h>
+#include <66/tree.h>
 
 int tree_switch_current(char const *base, char const *treename)
 {