/* * service.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 <stdint.h> #include <stdlib.h>//free #include <oblibs/log.h> #include <oblibs/string.h> #include <oblibs/sastr.h> #include <skalibs/genalloc.h> #include <skalibs/stralloc.h> #include <skalibs/types.h> #include <66/constants.h> #include <66/resolve.h> #include <66/service.h> #include <66/state.h> int service_resolve_add_deps(genalloc *tokeep, resolve_service_t *res, char const *src) { log_flow() ; int e = 0 ; size_t pos = 0 ; stralloc tmp = STRALLOC_ZERO ; resolve_wrapper_t_ref wres = resolve_set_struct(DATA_SERVICE, res) ; char *name = res->sa.s + res->name ; char *deps = res->sa.s + res->depends ; if (!resolve_cmp(tokeep, name, DATA_SERVICE) && (!obstr_equal(name,SS_MASTER+1))) if (!resolve_append(tokeep,wres)) goto err ; if (res->ndepends) { if (!sastr_clean_string(&tmp,deps)) return 0 ; for (;pos < tmp.len ; pos += strlen(tmp.s + pos) + 1) { resolve_service_t dres = RESOLVE_SERVICE_ZERO ; resolve_wrapper_t_ref dwres = resolve_set_struct(DATA_SERVICE, &dres) ; char *dname = tmp.s + pos ; if (!resolve_check(src,dname)) goto err ; if (!resolve_read(dwres,src,dname)) goto err ; if (dres.ndepends && !resolve_cmp(tokeep, dname, DATA_SERVICE)) { if (!service_resolve_add_deps(tokeep,&dres,src)) goto err ; } if (!resolve_cmp(tokeep, dname, DATA_SERVICE)) { if (!resolve_append(tokeep,dwres)) goto err ; } resolve_free(dwres) ; } } e = 1 ; err: stralloc_free(&tmp) ; free(wres) ; return e ; } int service_resolve_add_rdeps(genalloc *tokeep, resolve_service_t *res, char const *src) { log_flow() ; int type, e = 0 ; stralloc tmp = STRALLOC_ZERO ; stralloc nsv = STRALLOC_ZERO ; ss_state_t sta = STATE_ZERO ; resolve_wrapper_t_ref wres = resolve_set_struct(DATA_SERVICE, res) ; char const *exclude[2] = { SS_MASTER + 1, 0 } ; char *name = res->sa.s + res->name ; size_t srclen = strlen(src), a = 0, b = 0, c = 0 ; char s[srclen + SS_RESOLVE_LEN + 1] ; memcpy(s,src,srclen) ; memcpy(s + srclen,SS_RESOLVE,SS_RESOLVE_LEN) ; s[srclen + SS_RESOLVE_LEN] = 0 ; if (res->type == TYPE_CLASSIC) type = 0 ; else type = 1 ; if (!sastr_dir_get(&nsv,s,exclude,S_IFREG)) goto err ; if (!resolve_cmp(tokeep, name, DATA_SERVICE) && (!obstr_equal(name,SS_MASTER+1))) { if (!resolve_append(tokeep,wres)) goto err ; } if ((res->type == TYPE_BUNDLE || res->type == TYPE_MODULE) && res->ndepends) { uint32_t deps = res->type == TYPE_MODULE ? res->contents : res->depends ; if (!sastr_clean_string(&tmp,res->sa.s + deps)) goto err ; resolve_service_t dres = RESOLVE_SERVICE_ZERO ; resolve_wrapper_t_ref dwres = resolve_set_struct(DATA_SERVICE, &dres) ; for (; a < tmp.len ; a += strlen(tmp.s + a) + 1) { char *name = tmp.s + a ; if (!resolve_check(src,name)) goto err ; if (!resolve_read(dwres,src,name)) goto err ; if (dres.type == TYPE_CLASSIC) continue ; if (!resolve_cmp(tokeep, name, DATA_SERVICE)) { if (!resolve_append(tokeep,dwres)) goto err ; if (!service_resolve_add_rdeps(tokeep,&dres,src)) goto err ; } resolve_free(dwres) ; } } for (; b < nsv.len ; b += strlen(nsv.s + b) +1) { int dtype = 0 ; tmp.len = 0 ; resolve_service_t dres = RESOLVE_SERVICE_ZERO ; resolve_wrapper_t_ref dwres = resolve_set_struct(DATA_SERVICE, &dres) ; char *dname = nsv.s + b ; if (obstr_equal(name,dname)) { resolve_free(wres) ; continue ; } if (!resolve_check(src,dname)) goto err ; if (!resolve_read(dwres,src,dname)) goto err ; if (dres.type == TYPE_CLASSIC) dtype = 0 ; else dtype = 1 ; if (state_check(dres.sa.s + dres.state,dname)) { if (!state_read(&sta,dres.sa.s + dres.state,dname)) goto err ; if (dtype != type || (!dres.disen && !sta.unsupervise)){ resolve_free(dwres) ; continue ; } } else if (dtype != type || (!dres.disen)){ resolve_free(dwres) ; continue ; } if (dres.type == TYPE_BUNDLE && !dres.ndepends){ resolve_free(dwres) ; continue ; } if (!resolve_cmp(tokeep, dname, DATA_SERVICE)) { if (dres.ndepends)// || (dres.type == TYPE_BUNDLE && dres.ndepends) || ) { if (!sastr_clean_string(&tmp,dres.sa.s + dres.depends)) goto err ; /** we must check every service inside the module to not add as * rdeps a service declared inside the module. * eg. * module boot@system declare tty-rc@tty1 * we don't want boot@system as rdeps of tty-rc@tty1 but only * service inside the module as rdeps of tty-rc@tty1 */ if (dres.type == TYPE_MODULE) for (c = 0 ; c < tmp.len ; c += strlen(tmp.s + c) + 1) if (obstr_equal(name,tmp.s + c)) goto skip ; for (c = 0 ; c < tmp.len ; c += strlen(tmp.s + c) + 1) { if (obstr_equal(name,tmp.s + c)) { if (!resolve_append(tokeep,dwres)) goto err ; if (!service_resolve_add_rdeps(tokeep,&dres,src)) goto err ; resolve_free(dwres) ; break ; } } } } skip: resolve_free(dwres) ; } e = 1 ; err: free(wres) ; stralloc_free(&nsv) ; stralloc_free(&tmp) ; return e ; } int service_resolve_add_logger(genalloc *ga,char const *src) { log_flow() ; int e = 0 ; size_t i = 0 ; genalloc gatmp = GENALLOC_ZERO ; for (; i < genalloc_len(resolve_service_t,ga) ; i++) { resolve_service_t res = RESOLVE_SERVICE_ZERO ; resolve_wrapper_t_ref wres = resolve_set_struct(DATA_SERVICE, &res) ; resolve_service_t dres = RESOLVE_SERVICE_ZERO ; resolve_wrapper_t_ref dwres = resolve_set_struct(DATA_SERVICE, &dres) ; if (!service_resolve_copy(&res,&genalloc_s(resolve_service_t,ga)[i])) goto err ; char *string = res.sa.s ; char *name = string + res.name ; if (!resolve_cmp(&gatmp, name, DATA_SERVICE)) { if (!resolve_append(&gatmp,wres)) goto err ; if (res.logger) { if (!resolve_check(src,string + res.logger)) goto err ; if (!resolve_read(dwres,src,string + res.logger)) goto err ; if (!resolve_cmp(&gatmp, string + res.logger, DATA_SERVICE)) if (!resolve_append(&gatmp,dwres)) goto err ; } } resolve_free(wres) ; resolve_free(dwres) ; } resolve_deep_free(DATA_SERVICE, ga) ; if (!genalloc_copy(resolve_service_t,ga,&gatmp)) goto err ; e = 1 ; err: genalloc_free(resolve_service_t,&gatmp) ; resolve_deep_free(DATA_SERVICE, &gatmp) ; return e ; }