From d9de619cf957e1675bb44a9edd6d36a499ba604e Mon Sep 17 00:00:00 2001 From: obarun <eric@obarun.org> Date: Sat, 28 Jan 2023 22:39:09 +1100 Subject: [PATCH] [WIP]revamp ssexec_disable function --- src/lib66/exec/ssexec_disable.c | 377 ++++++-------------------------- 1 file changed, 69 insertions(+), 308 deletions(-) diff --git a/src/lib66/exec/ssexec_disable.c b/src/lib66/exec/ssexec_disable.c index e948c2fb..6091aeac 100644 --- a/src/lib66/exec/ssexec_disable.c +++ b/src/lib66/exec/ssexec_disable.c @@ -13,366 +13,127 @@ */ #include <string.h> -#include <errno.h> #include <stdint.h> -#include <stdlib.h> -#include <oblibs/obgetopt.h> #include <oblibs/log.h> +#include <oblibs/types.h> #include <oblibs/string.h> #include <oblibs/sastr.h> +#include <skalibs/sgetopt.h> #include <skalibs/stralloc.h> -#include <skalibs/genalloc.h> -#include <skalibs/djbunix.h> #include <66/constants.h> -#include <66/tree.h> -#include <66/db.h> -#include <66/resolve.h> -#include <66/svc.h> -#include <66/state.h> -#include <66/utils.h> +#include <66/ssexec.h> +#include <66/config.h> #include <66/service.h> +#include <66/graph.h> +#include <66/resolve.h> -static stralloc workdir = STRALLOC_ZERO ; -static uint8_t FORCE = 0 ; -static uint8_t REMOVE = 0 ; - -static void cleanup(void) +static void check_identifier(char const *name) { log_flow() ; - int e = errno ; - rm_rf(workdir.s) ; - errno = e ; + int logname = get_rstrlen_until(name,SS_LOG_SUFFIX) ; + if (logname > 0) log_die(LOG_EXIT_USER,"service: ",name,": ends with reserved suffix -log") ; + if (!memcmp(name,SS_MASTER+1,6)) log_die(LOG_EXIT_USER,"service: ",name,": starts with reserved prefix Master") ; + if (!strcmp(name,SS_SERVICE)) log_die(LOG_EXIT_USER,"service as service name is a reserved name") ; + if (!strcmp(name,"service@")) log_die(LOG_EXIT_USER,"service@ as service name is a reserved name") ; } -int svc_remove(genalloc *tostop,resolve_service_t *res, char const *src,ssexec_t *info) +int ssexec_disable(int argc, char const *const *argv, ssexec_t *info) { log_flow() ; - unsigned int i = 0 ; - int r, e = 0 ; - genalloc rdeps = GENALLOC_ZERO ; - stralloc dst = STRALLOC_ZERO ; - resolve_service_t cp = RESOLVE_SERVICE_ZERO ; - resolve_wrapper_t_ref wres = resolve_set_struct(DATA_SERVICE, &cp) ; - ss_state_t sta = STATE_ZERO ; - - size_t newlen ; - char *name = res->sa.s + res->name ; - if (!service_resolve_copy(&cp,res)) - { - log_warnusys("copy resolve file") ; - goto err ; - } - if (!stralloc_cats(&dst,src)) goto err ; - if (cp.type == TYPE_CLASSIC) - { - if (!stralloc_cats(&dst,SS_SVC)) goto err ; - } - else if (!stralloc_cats(&dst,SS_DB SS_SRC)) goto err ; - - if (!stralloc_cats(&dst,"/")) goto err ; - - newlen = dst.len ; - - if (!FORCE) - { - if (!service_resolve_add_rdeps(&rdeps,&cp,src)) - { - log_warnusys("resolve recursive dependencies of: ",name) ; - goto err ; - } - } - else - { - if (!resolve_append(&rdeps,wres)) goto err ; - } + uint32_t flag = 0 ; + uint8_t stop = 0, remove = 0 ; + int n = 0, e = 1 ; + size_t pos = 0 ; + graph_t graph = GRAPH_ZERO ; + stralloc sa = STRALLOC_ZERO ; - if (!service_resolve_add_logger(&rdeps,src)) - { - log_warnusys("resolve logger") ; - goto err ; - } + unsigned int areslen = 0 ; + resolve_service_t ares[SS_MAX_SERVICE] ; - resolve_free(wres) ; - - for (;i < genalloc_len(resolve_service_t,&rdeps) ; i++) - { - resolve_service_t_ref pres = &genalloc_s(resolve_service_t,&rdeps)[i] ; - resolve_wrapper_t_ref dwres = resolve_set_struct(DATA_SERVICE, pres) ; - char *str = pres->sa.s ; - char *name = str + pres->name ; - char *ste = str + pres->state ; - dst.len = newlen ; - if (!stralloc_cats(&dst,name)) goto err ; - if (!stralloc_0(&dst)) goto err ; - - log_trace("delete source service file of: ",name) ; - if (rm_rf(dst.s) < 0) - { - log_warnusys("delete source service file: ",dst.s) ; - goto err ; - } - /** r == -1 means the state file is not present, - * r > 0 means service need to be initialized, - * so not initialized at all.*/ - r = state_check_flags(ste,name,SS_FLAGS_INIT) ; - - if (!r) - { - /** modify the resolve file for 66-stop*/ - pres->disen = 0 ; - log_trace("Write resolve file of: ",name) ; - if (!resolve_write(dwres,src,name)) - { - log_warnusys("write resolve file of: ",name) ; - goto err ; - } - if (!state_read(&sta,ste,name)) { - log_warnusys("read state of: ",name) ; - goto err ; - } - state_setflag(&sta,SS_FLAGS_RELOAD,SS_FLAGS_FALSE) ; - state_setflag(&sta,SS_FLAGS_INIT,SS_FLAGS_FALSE) ; - state_setflag(&sta,SS_FLAGS_UNSUPERVISE,SS_FLAGS_TRUE) ; - log_trace("Write state file of: ",name) ; - if (!state_write(&sta,ste,name)) - { - log_warnusys("write state file of: ",name) ; - goto err ; - } - } - else - { - if (REMOVE) - { - // remove configuration file - log_trace("Delete configuration file of: ",name) ; - if (rm_rf(str + pres->srconf) == -1) - log_warnusys("remove configuration file of: ",name) ; - - // remove the logger directory - log_trace("Delete logger directory of: ",name) ; - if (rm_rf(str + pres->dstlog) == -1) - log_warnusys("remove logger directory of: ",name) ; - - if (pres->type == TYPE_MODULE) { - - // remove service source file - log_trace("Delete service file of: ",name) ; - if (rm_rf(str + pres->src) == -1) - log_warnusys("remove configuration file of: ",name) ; - } - - } - - log_trace("Delete resolve file of: ",name) ; - resolve_rmfile(src,name) ; - } - if (!resolve_cmp(tostop, name, DATA_SERVICE)) - if (!resolve_append(tostop,wres)) goto err ; - - free(dwres) ; - } - - e = 1 ; - - err: - resolve_free(wres) ; - resolve_deep_free(DATA_SERVICE, &rdeps) ; - stralloc_free(&dst) ; - return e ; -} - -int ssexec_disable(int argc, char const *const *argv,char const *const *envp,ssexec_t *info) -{ - int r, logname ; - unsigned int nlongrun, nclassic, stop, force ; - - genalloc tostop = GENALLOC_ZERO ;//resolve_service_t - genalloc gares = GENALLOC_ZERO ; //resolve_service_t - resolve_service_t res = RESOLVE_SERVICE_ZERO ; - resolve_service_t_ref pres ; - resolve_wrapper_t_ref wres = resolve_set_struct(DATA_SERVICE, &res) ; - - r = nclassic = nlongrun = stop = logname = force = 0 ; + FLAGS_SET(flag, STATE_FLAGS_TOPROPAGATE|STATE_FLAGS_WANTUP) ; { subgetopt l = SUBGETOPT_ZERO ; for (;;) { - int opt = getopt_args(argc,argv, ">" OPTS_DISABLE, &l) ; + int opt = subgetopt_r(argc, argv, OPTS_DISABLE, &l) ; if (opt == -1) break ; - if (opt == -2) log_die(LOG_EXIT_USER,"options must be set first") ; - switch (opt) - { - case 'S' : if (FORCE) log_usage(usage_disable) ; stop = 1 ; break ; - case 'F' : if (stop) log_usage(usage_disable) ; FORCE = 1 ; break ; - case 'R' : if (stop) log_usage(usage_disable) ; REMOVE = 1 ; break ; - default : log_usage(usage_disable) ; - } - } - argc -= l.ind ; argv += l.ind ; - } - - if (argc < 1) log_usage(usage_disable) ; - - if (!tree_copy(&workdir,info->tree.s,info->treename.s)) - log_dieusys(LOG_EXIT_SYS,"create tmp working directory") ; - - for (;*argv;argv++) - { - char const *name = *argv ; - if (!resolve_check(workdir.s,name)) - log_info_nclean_return(LOG_EXIT_ZERO,&cleanup,name," is not enabled") ; - if (!resolve_read(wres,workdir.s,name)) - log_dieusys_nclean(LOG_EXIT_SYS,&cleanup,"read resolve file of: ",name) ; + switch (opt) { - if (REMOVE) - { - stralloc sa = STRALLOC_ZERO ; - r = service_intree(&sa,name,0) ; - if (r > 2) - log_dieu_nclean(LOG_EXIT_SYS,&cleanup,"use -R option -- ",name," is set on different tree") ; - stralloc_free(&sa) ; - } - - if (res.type == TYPE_MODULE) - { - if (!module_in_cmdline(&gares,&res,workdir.s)) - log_dieu_nclean(LOG_EXIT_SYS,&cleanup,"add dependencies of module: ",name) ; - } - else - { - if (!resolve_append(&gares,wres)) - log_dieusys_nclean(LOG_EXIT_SYS,&cleanup,"append services selection with: ",name) ; - } - } + case 'S' : - for(unsigned int i = 0 ; i < genalloc_len(resolve_service_t,&gares) ; i++) - { - pres = &genalloc_s(resolve_service_t,&gares)[i] ; - char *string = pres->sa.s ; - char *name = string + pres->name ; - char *state = string + pres->state ; - uint8_t found = 0 ; - char module_name[256] ; - - /** The force options can be only used if the service is not marked initialized. - * This option should only be used when we have a inconsistent state between - * the /var/lib/66/system/<tree>/servicedirs/ and /var/lib/66/system/<tree>/.resolve - * directory meaning a service which is not present in the compiled db but its resolve file - * exist. - * Also, the remove option can be only used if the service is not marked initialized too.*/ - if (FORCE || REMOVE) { - - r = state_check_flags(state,name,SS_FLAGS_INIT) ; - - if (!r) - log_die_nclean(LOG_EXIT_USER,&cleanup,name," is marked initialized -- ",FORCE ? "-F" : "-R"," is not allowed") ; - } + stop = 1 ; + break ; - if (!module_search_service(workdir.s,&gares,name,&found,module_name)) - log_dieu_nclean(LOG_EXIT_SYS,&cleanup,"search in module") ; + case 'F' : - if (found && !FORCE) - log_die_nclean(LOG_EXIT_USER,&cleanup,name," is a part of: ",module_name," module -- it's not allowed to disable it alone") ; + log_1_warn("options -F is deprecated -- skipping it") ; + break ; - if (found && REMOVE) - log_die_nclean(LOG_EXIT_USER,&cleanup,name," is a part of: ",module_name," module -- -R options is not allowed") ; + case 'R' : - logname = 0 ; - if (obstr_equal(name,SS_MASTER + 1)) - log_die_nclean(LOG_EXIT_USER,&cleanup,"nice try peon") ; + if (stop) + log_usage(usage_disable) ; + remove = 1 ; + break ; - logname = get_rstrlen_until(name,SS_LOG_SUFFIX) ; - if (logname > 0 && (!resolve_cmp(&gares, string + pres->logassoc, DATA_SERVICE))) - log_die_nclean(LOG_EXIT_USER,&cleanup,"logger detected - disabling is not allowed") ; - - if (!pres->disen && !FORCE) - { - log_info(name,": is already disabled") ; - continue ; + default : + log_usage(usage_disable) ; + } } - if (!svc_remove(&tostop,pres,workdir.s,info)) - log_dieusys_nclean(LOG_EXIT_SYS,&cleanup,"remove service: ",name) ; - - if (pres->type == TYPE_CLASSIC) nclassic++ ; - else nlongrun++ ; + argc -= l.ind ; argv += l.ind ; } - if (nclassic) - { - if (!svc_switch_to(info,SS_SWBACK)) - log_dieusys_nclean(LOG_EXIT_SYS,&cleanup,"switch classic service to backup") ; - } + if (argc < 1) + log_usage(usage_disable) ; - if (nlongrun) - { - ss_resolve_graph_t graph = RESOLVE_GRAPH_ZERO ; - r = ss_resolve_graph_src(&graph,workdir.s,0,1) ; - if (!r) - log_dieu_nclean(LOG_EXIT_SYS,&cleanup,"resolve source of graph for tree: ",info->treename.s) ; + /** build the graph of the entire system */ + graph_build_service(&graph, ares, &areslen, info, flag) ; - r= ss_resolve_graph_publish(&graph,0) ; - if (r <= 0) - { - cleanup() ; - if (r < 0) log_die(LOG_EXIT_USER,"cyclic graph detected") ; - log_dieusys(LOG_EXIT_SYS,"publish service graph") ; - } - if (!service_resolve_master_write(info,&graph,workdir.s,1)) - log_dieusys_nclean(LOG_EXIT_SYS,&cleanup,"update inner bundle") ; + if (!graph.mlen) + log_die(LOG_EXIT_USER, "services selection is not available -- try to parse it first") ; - ss_resolve_graph_free(&graph) ; - if (!db_compile(workdir.s,info->tree.s, info->treename.s,envp)) - log_dieu_nclean(LOG_EXIT_SYS,&cleanup,"compile ",workdir.s,"/",info->treename.s) ; + for (; n < argc ; n++) { + check_identifier(argv[n]) ; + service_enable_disable(&graph, info->base.s, argv[n], 0) ; - /** this is an important part, we call s6-rc-update here */ - if (!db_switch_to(info,envp,SS_SWBACK)) - log_dieu_nclean(LOG_EXIT_SYS,&cleanup,"switch ",info->treename.s," to backup") ; + if (!sastr_add_string(&sa, argv[n])) + log_dieu(LOG_EXIT_SYS, "add string") ; } - if (!tree_copy_tmp(workdir.s,info)) - log_dieu_nclean(LOG_EXIT_SYS,&cleanup,"copy: ",workdir.s," to: ", info->tree.s) ; + if (stop && sa.len) { - cleanup() ; - - stralloc_free(&workdir) ; - resolve_free(wres) ; - resolve_deep_free(DATA_SERVICE, &gares) ; - - for (unsigned int i = 0 ; i < genalloc_len(resolve_service_t,&tostop); i++) - log_info("Disabled successfully: ",genalloc_s(resolve_service_t,&tostop)[i].sa.s + genalloc_s(resolve_service_t,&tostop)[i].name) ; - - if (stop && genalloc_len(resolve_service_t,&tostop)) - { - int nargc = 3 + genalloc_len(resolve_service_t,&tostop) ; + size_t len = sastr_nelement(&sa) ; + int nargc = 2 + len ; + char const *prog = PROG ; char const *newargv[nargc] ; unsigned int m = 0 ; - newargv[m++] = "fake_name" ; + newargv[m++] = "stop" ; newargv[m++] = "-u" ; - - for (unsigned int i = 0 ; i < genalloc_len(resolve_service_t,&tostop); i++) - newargv[m++] = genalloc_s(resolve_service_t,&tostop)[i].sa.s + genalloc_s(resolve_service_t,&tostop)[i].name ; - - newargv[m++] = 0 ; - - if (ssexec_stop(nargc,newargv,envp,info)) - { - resolve_deep_free(DATA_SERVICE, &tostop) ; - return 111 ; - } + FOREACH_SASTR(&sa, pos) + newargv[m++] = sa.s + pos ; + newargv[m] = 0 ; + + PROG = "stop" ; + e = ssexec_stop(nargc, newargv, info) ; + PROG = prog ; + goto end ; } + e = 0 ; - resolve_deep_free(DATA_SERVICE, &tostop) ; + end: + stralloc_free(&sa) ; + service_resolve_array_free(ares, areslen) ; + graph_free_all(&graph) ; - return 0 ; + return e ; } -- GitLab