-
Eric Vidal authoredEric Vidal authored
rc_init.c 5.85 KiB
/*
* rc_init.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/rc.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <oblibs/log.h>
#include <oblibs/string.h>
#include <oblibs/types.h>
#include <oblibs/directory.h>
#include <oblibs/sastr.h>
#include <skalibs/genalloc.h>
#include <skalibs/djbunix.h>
#include <skalibs/types.h>
#include <66/resolve.h>
#include <66/ssexec.h>
#include <66/constants.h>
#include <66/utils.h>
#include <66/state.h>
#include <66/service.h>
#include <s6-rc/config.h>
/**@Return 1 on success
* @Return 2 on empty database
* @Return 0 on fail */
int rc_init(ssexec_t *info, char const *const *envp)
{
log_flow() ;
int r, wstat, empty = 0, e = 0 ;
pid_t pid ;
size_t pos = 0 ;
ss_state_t sta = STATE_ZERO ;
stralloc sares = STRALLOC_ZERO ;
resolve_service_t res = RESOLVE_SERVICE_ZERO ;
resolve_wrapper_t_ref wres = resolve_set_struct(DATA_SERVICE, &res) ;
stralloc sasvc = STRALLOC_ZERO ;
genalloc gares = GENALLOC_ZERO ; //resolve_service_t type
char svdir[info->tree.len + SS_SVDIRS_LEN + SS_DB_LEN + 1 + info->treename.len + 1] ;
char ltree[info->livetree.len + 1 + info->treename.len + 1] ;
char prefix[info->treename.len + 1 + 1] ;
char tt[UINT32_FMT] ;
char const *newargv[12] ;
unsigned int m = 0 ;
gid_t gidowner ;
if (!yourgid(&gidowner,info->owner)){ log_warnusys("set gid") ; goto err ; }
r = scan_mode(info->livetree.s,S_IFDIR) ;
if (r == -1) { errno = EEXIST ; log_warnsys("conflicting format of: ",info->livetree.s) ; goto err ; }
if (!r)
{
log_trace("create directory: ",info->livetree.s) ;
r = dir_create(info->livetree.s,0700) ;
if (!r){ log_warnusys("create directory: ",info->livetree.s) ; goto err ; }
log_trace("chown directory: ",info->livetree.s) ;
if (chown(info->livetree.s,info->owner,gidowner) < 0){ log_warnusys("chown directory: ",info->livetree.s) ; goto err ; }
}
if (!sa_pointo(&sares,info,SS_NOTYPE,SS_RESOLVE_SRC))
{ log_warnu("set revolve pointer to source") ; goto err ; }
if (!resolve_check(sares.s,SS_MASTER +1)) { log_warnu("find inner bundle -- please make a bug report") ; goto err ; }
if (!resolve_read(wres,sares.s,SS_MASTER + 1)) { log_warnusys("read resolve file of inner bundle") ; goto err ; }
if (!res.ndepends)
{
log_info("Initialization: no atomic services into tree: ",info->treename.s) ;
empty = 1 ;
goto end ;
}
if (!create_live(info)) { log_warnusys("create live state") ; goto err ; }
memcpy(svdir,info->tree.s,info->tree.len) ;
memcpy(svdir + info->tree.len ,SS_SVDIRS ,SS_SVDIRS_LEN) ;
memcpy(svdir + info->tree.len + SS_SVDIRS_LEN,SS_DB,SS_DB_LEN) ;
memcpy(svdir + info->tree.len + SS_SVDIRS_LEN + SS_DB_LEN, "/", 1) ;
memcpy(svdir + info->tree.len + SS_SVDIRS_LEN + SS_DB_LEN + 1, info->treename.s,info->treename.len) ;
svdir[info->tree.len + SS_SVDIRS_LEN + SS_DB_LEN + 1 + info->treename.len] = 0 ;
memcpy(ltree,info->livetree.s,info->livetree.len) ;
ltree[info->livetree.len] = '/' ;
memcpy(ltree + info->livetree.len + 1, info->treename.s, info->treename.len) ;
ltree[info->livetree.len + 1 + info->treename.len] = 0 ;
memcpy(prefix,info->treename.s,info->treename.len) ;
memcpy(prefix + info->treename.len, "-",1) ;
prefix[info->treename.len + 1] = 0 ;
tt[uint32_fmt(tt,info->timeout)] = 0 ;
newargv[m++] = S6RC_BINPREFIX "s6-rc-init" ;
newargv[m++] = "-l" ;
newargv[m++] = ltree ;
newargv[m++] = "-c" ;
newargv[m++] = svdir ;
newargv[m++] = "-p" ;
newargv[m++] = prefix ;
newargv[m++] = "-t" ;
newargv[m++] = tt ;
newargv[m++] = "--" ;
newargv[m++] = info->scandir.s ;
newargv[m++] = 0 ;
log_trace("initiate db of tree: ",info->treename.s," ...") ;
pid = child_spawn0(newargv[0],newargv,envp) ;
if (waitpid_nointr(pid,&wstat, 0) < 0)
{ log_warnusys("wait for ",newargv[0]) ; goto err ; }
if (wstat) { log_warnu("init db of tree: ",info->treename.s) ; goto err ; }
if (!sastr_clean_string(&sasvc,res.sa.s + res.depends)) { log_warnusys("clean dependencies of inner bundle") ; goto err ; }
for (; pos < sasvc.len ; pos += strlen(sasvc.s + pos) +1)
{
char *name = sasvc.s + pos ;
resolve_service_t tmp = RESOLVE_SERVICE_ZERO ;
resolve_wrapper_t_ref wres = resolve_set_struct(DATA_SERVICE, &tmp) ;
if (!resolve_check(sares.s,name)){ log_warnsys("unknown service: ",name) ; goto err ; }
if (!resolve_read(wres,sares.s,name)) { log_warnusys("read resolve file of: ",name) ; goto err ; }
if (!service_resolve_add_deps(&gares,&tmp,sares.s)) { log_warnusys("resolve dependencies of: ",name) ; goto err ; }
resolve_free(wres) ;
}
for (pos = 0 ; pos < genalloc_len(resolve_service_t,&gares) ; pos++)
{
char const *string = genalloc_s(resolve_service_t,&gares)[pos].sa.s ;
char const *name = string + genalloc_s(resolve_service_t,&gares)[pos].name ;
char const *state = string + genalloc_s(resolve_service_t,&gares)[pos].state ;
log_trace("Write state file of: ",name) ;
if (!state_write(&sta,state,name))
{
log_warnusys("write state file of: ",name) ;
goto err ;
}
log_info("Initialized successfully: ",name) ;
}
end:
e = empty ? 2 : 1 ;
err:
resolve_deep_free(DATA_SERVICE, &gares) ;
stralloc_free(&sasvc) ;
resolve_free(wres) ;
stralloc_free(&sares) ;
return e ;
}