From 51f3ea773858d8e84c1c663d2d0876c2f53f807d Mon Sep 17 00:00:00 2001
From: obarun <eric@obarun.org>
Date: Mon, 1 Nov 2021 17:02:44 +1100
Subject: [PATCH] change interface of tree_sethome() function and allow
 creation of the tree by seed file, add prototype declaration for
 tree_seed_xxx function() and ss_tree_seed_s struct

---
 src/include/66/tree.h    | 29 +++++++++++++--
 src/lib66/tree_sethome.c | 77 ++++++++++++++++++++++++++++++----------
 2 files changed, 85 insertions(+), 21 deletions(-)

diff --git a/src/include/66/tree.h b/src/include/66/tree.h
index f9cdf801..e415f14a 100644
--- a/src/include/66/tree.h
+++ b/src/include/66/tree.h
@@ -20,6 +20,26 @@
 #include <skalibs/stralloc.h>
 #include <66/ssexec.h>
 
+extern stralloc saseed ;
+
+typedef struct ss_tree_seed_s ss_tree_seed_t, ss_tree_seed_t_ref ;
+struct ss_tree_seed_s
+{
+    int name ;
+    int depends ;
+    int requiredby ;
+    uint8_t enabled ;
+    int allow ;
+    int deny ;
+    uint8_t current ;
+    int group ;
+    int services ;
+    uint8_t nopts ;
+
+} ;
+
+#define TREE_SEED_ZERO { -1, -1, -1, 0, -1, -1, 0, -1, -1, 0 }
+
 extern int tree_cmd_state(unsigned int verbosity,char const *cmd,char const *tree) ;
 extern int tree_state(int argc, char const *const *argv) ;
 
@@ -35,13 +55,18 @@ extern int tree_copy_tmp(char const *workdir, ssexec_t *info) ;
  * @Return 0 on fail */
 extern int tree_find_current(stralloc *tree, char const *base,uid_t owner) ;
 
-
 extern int tree_get_permissions(char const *tree, uid_t owner) ;
 
-extern int tree_sethome(stralloc *tree, char const *base,uid_t owner) ;
+extern int tree_sethome(ssexec_t *info) ;
 
 extern char tree_setname(stralloc *sa, char const *tree) ;
 
 extern int tree_switch_current(char const *base, char const *tree) ;
 
+extern int tree_isvalid(ssexec_t *info) ;
+
+// seed
+extern void tree_seed_free(void) ;
+extern int tree_seed_setseed(ss_tree_seed_t *seed, char const *treename, uint8_t check_service) ;
+extern int tree_seed_isvalid(char const *seed) ;
 #endif
diff --git a/src/lib66/tree_sethome.c b/src/lib66/tree_sethome.c
index 0084770e..f872a032 100644
--- a/src/lib66/tree_sethome.c
+++ b/src/lib66/tree_sethome.c
@@ -21,35 +21,74 @@
 
 #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>
 
-int tree_sethome(stralloc *tree, char const *base,uid_t owner)
+/**
+ * @Return -3 > unable to find current
+ * @Return -2 > unable to fix tree name
+ * @Return -1 > unable to parse seed file
+ * @Return 0 > tree doesn't exist
+ * @Return 1 > success */
+int tree_sethome(ssexec_t *info)
 {
     log_flow() ;
 
+    char const *base = info->base.s ;
+    uid_t owner = info->owner ;
+
     int r ;
 
-    if (!tree->len)
-    {
-        if (!tree_find_current(tree, base,owner)) return -1 ;
-    }
-    else
-    {
-        char treename[tree->len + 1] ;
-        memcpy(treename,tree->s,tree->len) ;
-        treename[tree->len] = 0 ;
-        tree->len = 0 ;
-        if (!stralloc_cats(tree,base) ||
-        !stralloc_cats(tree,SS_SYSTEM "/") ||
-        !stralloc_cats(tree,treename) ||
-        !stralloc_0(tree)) log_warnsys_return(LOG_EXIT_ZERO,"stralloc") ;
-        r = scan_mode(tree->s,S_IFDIR) ;
-        if (r < 0) errno = EEXIST ;
-        if (r != 1) return 0 ;
-        tree->len--;
+    if (!info->treename.len) {
+
+        if (!tree_find_current(&info->tree, base, owner))
+            return -3 ;
+
+        if (!tree_setname(&info->treename,info->tree.s))
+            return -2 ;
+
+    } else {
+
+        r = tree_isvalid(info) ;
+
+        if (r < 0) {
+            /** The tree name exist on the system
+             * but it's not a directory */
+             errno = EEXIST ;
+             return 0 ;
+
+        } else if (!r) {
+            /** Tree doesn't exist yet.
+             * Let see if we have a seed/<name> to create it,
+             * but only if we come from the 66-enable tool. */
+            if (strcmp(info->prog, "66-enable"))
+                return 0 ;
+
+            if (!tree_seed_isvalid(info->treename.s))
+                log_warnu_return(LOG_EXIT_ZERO,"find a seed file to create the tree: ", info->treename.s) ;
+
+            int nargc = 3 ;
+            char const *newargv[nargc] ;
+            unsigned int m = 0 ;
+
+            newargv[m++] = "fake_name" ;
+            newargv[m++] = info->treename.s ;
+            newargv[m++] = 0 ;
+
+            if (ssexec_tree(nargc, newargv,(char const *const *)environ, info))
+                log_warnu_return(LOG_EXIT_ZERO,"create tree: ",info->treename.s) ;
+        }
+        /** The tree_sethome() function can be recursively called. The info->tree may not empty.
+         * Be sure to clean up before using it. */
+        info->tree.len = 0 ;
+        if (!auto_stra(&info->tree, base, SS_SYSTEM, "/", info->treename.s))
+            log_warnsys_return(LOG_EXIT_ZERO,"stralloc") ;
+
     }
 
     return 1 ;
-- 
GitLab