-
Eric Vidal authoredEric Vidal authored
resolve.c 33.69 KiB
/*
* resolve.c
*
* Copyright (c) 2018-2019 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/stat.h>
#include <stdlib.h>//realpath
//#include <stdio.h>
#include <oblibs/types.h>
#include <oblibs/error2.h>
#include <oblibs/directory.h>
#include <oblibs/files.h>
#include <oblibs/string.h>
#include <oblibs/stralist.h>
#include <oblibs/sastr.h>
#include <skalibs/stralloc.h>
#include <skalibs/djbunix.h>
#include <skalibs/direntry.h>
#include <skalibs/unix-transactional.h>
#include <skalibs/diuint32.h>
#include <66/constants.h>
#include <66/utils.h>
#include <66/enum.h>
#include <66/parser.h>//resolve need to find stralloc keep
#include <66/resolve.h>
#include <66/ssexec.h>
#include <66/state.h>
#include <s6/s6-supervise.h>
void ss_resolve_free(ss_resolve_t *res)
{
stralloc_free(&res->sa) ;
}
void ss_resolve_init(ss_resolve_t *res)
{
res->sa.len = 0 ;
ss_resolve_add_string(res,"") ;
}
int ss_resolve_pointo(stralloc *sa,ssexec_t *info,unsigned int type, unsigned int where)
{
stralloc tmp = STRALLOC_ZERO ;
char ownerstr[UID_FMT] ;
size_t ownerlen = uid_fmt(ownerstr,info->owner) ;
ownerstr[ownerlen] = 0 ;
if (where == SS_RESOLVE_STATE)
{
if (!stralloc_catb(&tmp,info->live.s,info->live.len - 1) ||
!stralloc_cats(&tmp,SS_STATE) ||
!stralloc_cats(&tmp,"/") ||
!stralloc_cats(&tmp,ownerstr) ||
!stralloc_cats(&tmp,"/") ||
!stralloc_cats(&tmp,info->treename.s)) goto err ;
}
else if (where == SS_RESOLVE_SRC)
{
if (!stralloc_cats(&tmp,info->tree.s) ||
!stralloc_cats(&tmp,SS_SVDIRS)) goto err ;
}
else if (where == SS_RESOLVE_BACK)
{
if (!stralloc_cats(&tmp,info->base.s) ||
!stralloc_cats(&tmp,SS_SYSTEM) ||
!stralloc_cats(&tmp,SS_BACKUP) ||
!stralloc_cats(&tmp,"/") ||
!stralloc_cats(&tmp,info->treename.s)) goto err ;
}
else if (where == SS_RESOLVE_LIVE)
{
if (!stralloc_catb(&tmp,info->live.s,info->live.len - 1) ||
!stralloc_cats(&tmp,SS_STATE) ||
!stralloc_cats(&tmp,"/") ||
!stralloc_cats(&tmp,ownerstr) ||
!stralloc_cats(&tmp,"/") ||
!stralloc_cats(&tmp,info->treename.s) ||
!stralloc_cats(&tmp,SS_SVDIRS)) goto err ;
}
if (type && where)
{
if (type == CLASSIC)
{
if (!stralloc_cats(&tmp,SS_SVC)) goto err ;
}
else if (!stralloc_cats(&tmp,SS_DB)) goto err ;
}
if (!stralloc_0(&tmp) ||
!stralloc_obreplace(sa,tmp.s)) goto err ;
stralloc_free(&tmp) ;
return 1 ;
err:
stralloc_free(&tmp) ;
return 0 ;
}
int ss_resolve_src_path(stralloc *sasrc,char const *sv, ssexec_t *info)
{
int r ;
char const *src = 0 ;
int found = 0 ;
stralloc home = STRALLOC_ZERO ;
if (!info->owner) src = SS_SERVICE_ADMDIR ;
else
{
if (!set_ownerhome(&home,info->owner)){ VERBO3 strerr_warnwu1sys("set home directory") ; goto err ; }
if (!stralloc_cats(&home,SS_SERVICE_USERDIR)) retstralloc(0,"ss_resolve_src_path") ;
if (!stralloc_0(&home)) retstralloc(0,"ss_resolve_src_path") ;
home.len-- ;
src = home.s ;
}
r = ss_resolve_src(sasrc,sv,src,&found) ;
if (r < 0){ VERBO3 strerr_warnwu2sys("parse source directory: ",src) ; goto err ; }
if (!r)
{
found = 0 ;
src = SS_SERVICE_ADMDIR ;
r = ss_resolve_src(sasrc,sv,src,&found) ;
if (r < 0) { VERBO3 strerr_warnwu2sys("parse source directory: ",src) ; goto err ; }
if (!r)
{
found = 0 ;
src = SS_SERVICE_SYSDIR ;
r = ss_resolve_src(sasrc,sv,src,&found) ;
if (r < 0) { VERBO3 strerr_warnwu2sys("parse source directory: ",src) ; goto err ; }
if (!r) { VERBO3 strerr_warnw2sys("unknown service: ",sv) ; goto err ; }
}
}
stralloc_free(&home) ;
return 1 ;
err:
stralloc_free(&home) ;
return 0 ;
}
int ss_resolve_service_isdir(char const *dir, char const *name)
{
size_t dirlen = strlen(dir) ;
char t[dirlen + 1] ;
if (!basename(t,dir)) return -1 ;
if (!strcmp(t,name)) return 1 ;
return 0 ;
}
int ss_resolve_src(stralloc *sasrc, char const *name, char const *src,int *found)
{
int fdsrc, obr, insta ;
size_t i, len, namelen = strlen(name), srclen = strlen(src) ;
stralloc sainsta = STRALLOC_ZERO ;
stralloc subdir = STRALLOC_ZERO ;
stralloc satmp = STRALLOC_ZERO ;
obr = insta = 0 ;
DIR *dir = opendir(src) ;
if (!dir)
{
VERBO3 strerr_warnwu2sys("open : ", src) ;
goto errstra ;
}
fdsrc = dir_fd(dir) ;
for (;;)
{
struct stat st ;
direntry *d ;
d = readdir(dir) ;
if (!d) break ;
if (d->d_name[0] == '.')
if (((d->d_name[1] == '.') && !d->d_name[2]) || !d->d_name[1])
continue ;
if (stat_at(fdsrc, d->d_name, &st) < 0)
{
VERBO3 strerr_warnwu3sys("stat ", src, d->d_name) ;
goto errdir ;
}
if (S_ISDIR(st.st_mode))
{
if (!stralloc_cats(&subdir,src)) goto errdir ;
if (!stralloc_cats(&subdir,d->d_name)) goto errdir ;
if (!stralloc_cats(&subdir,"/")) goto errdir ;
if (!stralloc_0(&subdir)) goto errdir ;
*found = ss_resolve_src(sasrc,name,subdir.s,found) ;
subdir.len = 0 ;
if (*found < 0) goto errdir ;
}
obr = 0 ;
insta = 0 ;
obr = obstr_equal(name,d->d_name) ;
insta = insta_check(name) ;
if (insta > 0)
{
if (!insta_splitname(&sainsta,name,insta,0)) goto errdir ;
obr = obstr_equal(sainsta.s,d->d_name) ;
}
if (obr)
{
*found = 1 ;
if (stat_at(fdsrc, d->d_name, &st) < 0)
{
VERBO3 strerr_warnwu3sys("stat ", src, d->d_name) ;
goto errdir ;
}
if (S_ISDIR(st.st_mode))
{
int r ;
if (!stralloc_cats(&subdir,src)) goto errstra ;
if (!stralloc_cats(&subdir,d->d_name)) goto errdir ;
if (!stralloc_0(&subdir)) goto errdir ;
r = ss_resolve_service_isdir(subdir.s,d->d_name) ;
if (r == -1) goto errdir ;
if (!r)
r = sastr_dir_get(&satmp,subdir.s,"",S_IFREG|S_IFDIR) ;
else r = sastr_dir_get(&satmp,subdir.s,"",S_IFREG) ;
if (!r)
{
VERBO3 strerr_warnwu2sys("get services from directory: ",subdir.s) ;
goto errdir ;
}
i = 0, len = satmp.len ;
subdir.len-- ;
for (;i < len; i += strlen(satmp.s + i) + 1)
{
size_t tlen = strlen(satmp.s+i) ;
char t[subdir.len + 1 + tlen + 2];
memcpy(t,subdir.s,subdir.len) ;
t[subdir.len] ='/' ;
memcpy(t+subdir.len + 1,satmp.s+i,tlen) ;
t[subdir.len + 1 + tlen] = '/' ;
t[subdir.len + 1 + tlen + 1] = 0 ;
int r = scan_mode(t,S_IFDIR) ;
if (r == 1)
{
t[subdir.len + 1] = 0 ;
*found = ss_resolve_src(sasrc,satmp.s+i,t,found) ;
if (*found < 0) goto errdir ;
}
else
{
namelen = strlen(satmp.s + i) ;
char t[subdir.len + 1 + namelen + 1] ;
memcpy(t,subdir.s,subdir.len) ;
t[subdir.len] = '/' ;
memcpy(t + subdir.len + 1,name,namelen) ;
t[srclen + 1 + namelen] = 0 ;
if (sastr_cmp(sasrc,t) == -1)
{
if (!stralloc_cats(sasrc,subdir.s)) goto errdir ;
if (!stralloc_cats(sasrc,"/")) goto errdir ;
if (!stralloc_catb(sasrc,satmp.s+i,strlen(satmp.s+i)+1)) goto errdir ;
}
}
}
stralloc_free(&subdir) ;
break ;
}
else if(S_ISREG(st.st_mode))
{
char t[srclen + namelen + 1] ;
memcpy(t,src,srclen) ;
memcpy(t + srclen,name,namelen) ;
t[srclen + namelen] = 0 ;
if (sastr_cmp(sasrc,t) == -1)
{
if (!stralloc_cats(sasrc,src)) goto errdir ;
if (!stralloc_catb(sasrc,name,namelen+1)) goto errdir ;
}
break ;
}
else goto errdir ;
}
}
dir_close(dir) ;
stralloc_free(&subdir) ;
stralloc_free(&sainsta) ;
stralloc_free(&satmp) ;
return (*found) ;
errdir:
dir_close(dir) ;
errstra:
stralloc_free(&subdir) ;
stralloc_free(&sainsta) ;
stralloc_free(&satmp) ;
return -1 ;
}
void ss_resolve_rmfile(char const *src,char const *name)
{
size_t srclen = strlen(src) ;
size_t namelen = strlen(name) ;
char tmp[srclen + SS_RESOLVE_LEN + 1 + namelen +1] ;
memcpy(tmp,src,srclen) ;
memcpy(tmp + srclen, SS_RESOLVE,SS_RESOLVE_LEN) ;
tmp[srclen + SS_RESOLVE_LEN] = '/' ;
memcpy(tmp + srclen + SS_RESOLVE_LEN + 1, name, namelen) ;
tmp[srclen + SS_RESOLVE_LEN + 1 + namelen] = 0 ;
unlink_void(tmp) ;
}
int ss_resolve_add_uint32(stralloc *sa, uint32_t data)
{
char pack[4] ;
uint32_pack_big(pack,data) ;
return stralloc_catb(sa,pack,4) ;
}
uint32_t ss_resolve_add_string(ss_resolve_t *res, char const *data)
{
uint32_t baselen = res->sa.len ;
if (!data)
{
if (!stralloc_catb(&res->sa,"",1)) strerr_diefu1sys(111,"stralloc:resolve_add_string") ;
return baselen ;
}
size_t datalen = strlen(data) ;
if (!stralloc_catb(&res->sa,data,datalen + 1)) strerr_diefu1sys(111,"stralloc:resolve_add_string") ;
return baselen ;
}
int ss_resolve_pack(stralloc *sa, ss_resolve_t *res)
{
if(!ss_resolve_add_uint32(sa,res->sa.len)) return 0 ;
if (!stralloc_catb(sa,res->sa.s,res->sa.len)) return 0 ;
if(!ss_resolve_add_uint32(sa,res->name) ||
!ss_resolve_add_uint32(sa,res->description) ||
!ss_resolve_add_uint32(sa,res->logger) ||
!ss_resolve_add_uint32(sa,res->logreal) ||
!ss_resolve_add_uint32(sa,res->logassoc) ||
!ss_resolve_add_uint32(sa,res->dstlog) ||
!ss_resolve_add_uint32(sa,res->deps) ||
!ss_resolve_add_uint32(sa,res->src) ||
!ss_resolve_add_uint32(sa,res->srconf) ||
!ss_resolve_add_uint32(sa,res->live) ||
!ss_resolve_add_uint32(sa,res->runat) ||
!ss_resolve_add_uint32(sa,res->tree) ||
!ss_resolve_add_uint32(sa,res->treename) ||
!ss_resolve_add_uint32(sa,res->state) ||
!ss_resolve_add_uint32(sa,res->exec_run) ||
!ss_resolve_add_uint32(sa,res->exec_finish) ||
!ss_resolve_add_uint32(sa,res->type) ||
!ss_resolve_add_uint32(sa,res->ndeps) ||
!ss_resolve_add_uint32(sa,res->down) ||
!ss_resolve_add_uint32(sa,res->disen)) return 0 ;
return 1 ;
}
int ss_resolve_write(ss_resolve_t *res, char const *dst, char const *name)
{
stralloc sa = STRALLOC_ZERO ;
size_t dstlen = strlen(dst) ;
size_t namelen = strlen(name) ;
char tmp[dstlen + SS_RESOLVE_LEN + 1 + namelen + 1] ;
memcpy(tmp,dst,dstlen) ;
memcpy(tmp + dstlen, SS_RESOLVE, SS_RESOLVE_LEN) ;
tmp[dstlen + SS_RESOLVE_LEN] = '/' ;
memcpy(tmp + dstlen + SS_RESOLVE_LEN + 1, name, namelen) ;
tmp[dstlen + SS_RESOLVE_LEN + 1 + namelen] = 0 ;
if (!ss_resolve_pack(&sa,res)) goto err ;
if (!openwritenclose_unsafe(tmp,sa.s,sa.len)) goto err ;
stralloc_free(&sa) ;
return 1 ;
err:
stralloc_free(&sa) ;
return 0 ;
}
int ss_resolve_read(ss_resolve_t *res, char const *src, char const *name)
{
stralloc sa = STRALLOC_ZERO ;
size_t srclen = strlen(src) ;
size_t namelen = strlen(name) ;
char tmp[srclen + SS_RESOLVE_LEN + 1 + namelen + 1] ;
memcpy(tmp,src,srclen) ;
memcpy(tmp + srclen, SS_RESOLVE, SS_RESOLVE_LEN) ;
tmp[srclen + SS_RESOLVE_LEN] = '/' ;
memcpy(tmp + srclen + SS_RESOLVE_LEN + 1, name, namelen) ;
tmp[srclen + SS_RESOLVE_LEN + 1 + namelen] = 0 ;
size_t global = 0 ;
size_t filen = file_get_size(tmp) ;
int r = openreadfileclose(tmp,&sa,filen) ;
if (r < 0) goto end ;
uint32_unpack_big(sa.s,&res->salen) ;
global += 4 ;
stralloc_copyb(&res->sa,sa.s+global,res->salen) ;
global += res->sa.len ;
uint32_unpack_big(sa.s + global,&res->name) ;
global += 4 ;
uint32_unpack_big(sa.s + global,&res->description) ;
global += 4 ;
uint32_unpack_big(sa.s + global,&res->logger) ;
global += 4 ;
uint32_unpack_big(sa.s + global,&res->logreal) ;
global += 4 ;
uint32_unpack_big(sa.s + global,&res->logassoc) ;
global += 4 ;
uint32_unpack_big(sa.s + global,&res->dstlog) ;
global += 4 ;
uint32_unpack_big(sa.s + global,&res->deps) ;
global += 4 ;
uint32_unpack_big(sa.s + global,&res->src) ;
global += 4 ;
uint32_unpack_big(sa.s + global,&res->srconf) ;
global += 4 ;
uint32_unpack_big(sa.s + global,&res->live) ;
global += 4 ;
uint32_unpack_big(sa.s + global,&res->runat) ;
global += 4 ;
uint32_unpack_big(sa.s + global,&res->tree) ;
global += 4 ;
uint32_unpack_big(sa.s + global,&res->treename) ;
global += 4 ;
uint32_unpack_big(sa.s + global,&res->state) ;
global += 4 ;
uint32_unpack_big(sa.s + global,&res->exec_run) ;
global += 4 ;
uint32_unpack_big(sa.s + global,&res->exec_finish) ;
global += 4 ;
uint32_unpack_big(sa.s + global,&res->type) ;
global += 4 ;
uint32_unpack_big(sa.s + global,&res->ndeps) ;
global += 4 ;
uint32_unpack_big(sa.s + global,&res->down) ;
global += 4 ;
uint32_unpack_big(sa.s + global,&res->disen) ;
stralloc_0(&res->sa) ;
stralloc_free(&sa) ;
return 1 ;
end :
stralloc_free(&sa) ;
return 0 ;
}
int ss_resolve_check_insrc(ssexec_t *info, char const *name)
{
stralloc sares = STRALLOC_ZERO ;
if (!ss_resolve_pointo(&sares,info,SS_NOTYPE,SS_RESOLVE_SRC)) goto err ;
if (!ss_resolve_check(sares.s,name)) goto err ;
stralloc_free(&sares) ;
return 1 ;
err:
stralloc_free(&sares) ;
return 0 ;
}
int ss_resolve_check(char const *src, char const *name)
{
int r ;
size_t srclen = strlen(src) ;
size_t namelen = strlen(name) ;
char tmp[srclen + SS_RESOLVE_LEN + 1 + namelen + 1] ;
memcpy(tmp,src,srclen) ;
memcpy(tmp + srclen, SS_RESOLVE,SS_RESOLVE_LEN) ;
tmp[srclen + SS_RESOLVE_LEN] = '/' ;
memcpy(tmp + srclen + SS_RESOLVE_LEN + 1,name,namelen) ;
tmp[srclen + SS_RESOLVE_LEN + 1 + namelen] = 0 ;
r = scan_mode(tmp,S_IFREG) ;
if (!r || r < 0) return 0 ;
return 1 ;
}
int ss_resolve_setlognwrite(ss_resolve_t *sv, char const *dst,ssexec_t *info)
{
if (!sv->logger) return 1 ;
ss_state_t sta = STATE_ZERO ;
ss_resolve_t res = RESOLVE_ZERO ;
ss_resolve_init(&res) ;
char *string = sv->sa.s ;
size_t svlen = strlen(string + sv->name) ;
char descrip[svlen + 7] ;
memcpy(descrip,string + sv->name,svlen) ;
memcpy(descrip + svlen," logger",7) ;
descrip[svlen + 7] = 0 ;
size_t runlen = strlen(string + sv->runat) ;
char live[runlen + 4 + 1] ;
memcpy(live,string + sv->runat,runlen) ;
if (sv->type >= BUNDLE)
{
memcpy(live + runlen,"-log",4) ;
}else memcpy(live + runlen,"/log",4) ;
live[runlen + 4] = 0 ;
res.name = ss_resolve_add_string(&res,string + sv->logger) ;
res.description = ss_resolve_add_string(&res,descrip) ;
res.logreal = ss_resolve_add_string(&res,string + sv->logreal) ;
res.logassoc = ss_resolve_add_string(&res,string + sv->name) ;
res.dstlog = ss_resolve_add_string(&res,string + sv->dstlog) ;
res.live = ss_resolve_add_string(&res,string + sv->live) ;
res.runat = ss_resolve_add_string(&res,live) ;
res.tree = ss_resolve_add_string(&res,string + sv->tree) ;
res.treename = ss_resolve_add_string(&res,string + sv->treename) ;
res.state = ss_resolve_add_string(&res,string + sv->state) ;
res.src = ss_resolve_add_string(&res,string + sv->src) ;
res.type = sv->type ;
res.down = sv->down ;
res.disen = sv->disen ;
if (ss_state_check(string + sv->state,string + sv->logger))
{
if (!ss_state_read(&sta,string + sv->state,string + sv->logger)) { VERBO1 strerr_warnwu2sys("read state file of: ",string + sv->logger) ; goto err ; }
if (!sta.init)
ss_state_setflag(&sta,SS_FLAGS_RELOAD,SS_FLAGS_TRUE) ;
ss_state_setflag(&sta,SS_FLAGS_INIT,SS_FLAGS_FALSE) ;
ss_state_setflag(&sta,SS_FLAGS_UNSUPERVISE,SS_FLAGS_FALSE) ;
if (!ss_state_write(&sta,string + sv->state,string + sv->logger)){ VERBO1 strerr_warnwu2sys("write state file of: ",string + sv->logger) ; goto err ; }
}
if (!ss_resolve_write(&res,dst,res.sa.s + res.name))
{
VERBO1 strerr_warnwu5sys("write resolve file: ",dst,SS_RESOLVE,"/",res.sa.s + res.name) ;
goto err ;
}
ss_resolve_free(&res) ;
return 1 ;
err:
ss_resolve_free(&res) ;
return 0 ;
}
int ss_resolve_setnwrite(sv_alltype *services, ssexec_t *info, char const *dst)
{
int r ;
char ownerstr[UID_FMT] ;
size_t ownerlen = uid_fmt(ownerstr,info->owner) ;
ownerstr[ownerlen] = 0 ;
stralloc destlog = STRALLOC_ZERO ;
stralloc namedeps = STRALLOC_ZERO ;
stralloc final = STRALLOC_ZERO ;
ss_state_t sta = STATE_ZERO ;
ss_resolve_t res = RESOLVE_ZERO ;
ss_resolve_init(&res) ;
char *name = keep.s + services->cname.name ;
size_t namelen = strlen(name) ;
char logname[namelen + SS_LOG_SUFFIX_LEN + 1] ;
char logreal[namelen + SS_LOG_SUFFIX_LEN + 1] ;
char stmp[info->livetree.len + 1 + info->treename.len + SS_SVDIRS_LEN + 1 + namelen + SS_LOG_SUFFIX_LEN + 1] ;
size_t livelen = info->live.len - 1 ;
char state[livelen + SS_STATE_LEN + 1 + ownerlen + 1 + info->treename.len + 1 + namelen + 1] ;
memcpy(state,info->live.s,livelen) ;
memcpy(state + livelen, SS_STATE,SS_STATE_LEN) ;
state[livelen+ SS_STATE_LEN] = '/' ;
memcpy(state + livelen + SS_STATE_LEN + 1,ownerstr,ownerlen) ;
state[livelen + SS_STATE_LEN + 1 + ownerlen] = '/' ;
memcpy(state + livelen + SS_STATE_LEN + 1 + ownerlen + 1,info->treename.s,info->treename.len) ;
state[livelen + SS_STATE_LEN + 1 + ownerlen + 1 + info->treename.len] = 0 ;
res.name = ss_resolve_add_string(&res,name) ;
res.description = ss_resolve_add_string(&res,keep.s + services->cname.description) ;
res.tree = ss_resolve_add_string(&res,info->tree.s) ;
res.treename = ss_resolve_add_string(&res,info->treename.s) ;
res.live = ss_resolve_add_string(&res,info->live.s) ;
res.state = ss_resolve_add_string(&res,state) ;
res.src = ss_resolve_add_string(&res,keep.s + services->src) ;
if (services->srconf)
res.srconf = ss_resolve_add_string(&res,keep.s + services->srconf) ;
if (services->type.classic_longrun.run.exec)
res.exec_run = ss_resolve_add_string(&res,keep.s + services->type.classic_longrun.run.exec) ;
if (services->type.classic_longrun.finish.exec)
res.exec_finish = ss_resolve_add_string(&res,keep.s + services->type.classic_longrun.finish.exec) ;
res.type = services->cname.itype ;
res.ndeps = services->cname.nga ;
if (services->flags[0]) res.down = 1 ;
res.disen = 1 ;
if (res.type == CLASSIC)
{
memcpy(stmp,info->scandir.s,info->scandir.len) ;
stmp[info->scandir.len] = '/' ;
memcpy(stmp + info->scandir.len + 1,name,namelen) ;
stmp[info->scandir.len + 1 + namelen] = 0 ;
res.runat = ss_resolve_add_string(&res,stmp) ;
}
else if (res.type >= BUNDLE)
{
memcpy(stmp,info->livetree.s,info->livetree.len) ;
stmp[info->livetree.len] = '/' ;
memcpy(stmp + info->livetree.len + 1,info->treename.s,info->treename.len) ;
memcpy(stmp + info->livetree.len + 1 + info->treename.len, SS_SVDIRS,SS_SVDIRS_LEN) ;
stmp[info->livetree.len + 1 + info->treename.len + SS_SVDIRS_LEN] = '/' ;
memcpy(stmp + info->livetree.len + 1 + info->treename.len + SS_SVDIRS_LEN + 1, name,namelen) ;
stmp[info->livetree.len + 1 + info->treename.len + SS_SVDIRS_LEN + 1 + namelen] = 0 ;
res.runat = ss_resolve_add_string(&res,stmp) ;
}
if (ss_state_check(state,name))
{
if (!ss_state_read(&sta,state,name)) { VERBO1 strerr_warnwu2sys("read state file of: ",name) ; goto err ; }
if (!sta.init)
ss_state_setflag(&sta,SS_FLAGS_RELOAD,SS_FLAGS_TRUE) ;
ss_state_setflag(&sta,SS_FLAGS_INIT,SS_FLAGS_FALSE) ;
ss_state_setflag(&sta,SS_FLAGS_UNSUPERVISE,SS_FLAGS_FALSE) ;
if (!ss_state_write(&sta,res.sa.s + res.state,name)){ VERBO1 strerr_warnwu2sys("write state file of: ",name) ; goto err ; }
}
if (res.ndeps)
{
for (unsigned int i = 0; i < res.ndeps; i++)
{
if (!stralloc_obreplace(&namedeps,deps.s+genalloc_s(unsigned int,&gadeps)[services->cname.idga+i])) goto err ;
r = insta_check(namedeps.s) ;
if (!r)
{
VERBO1 strerr_warnw2x(" invalid instance name: ",namedeps.s) ;
goto err ;
}
if (r > 0)
{
if (!insta_splitname(&namedeps,namedeps.s,r,1))
{
VERBO1 strerr_warnwu2x("split copy name of instance: ",namedeps.s) ;
goto err ;
}
}
namedeps.len--;
if (!stralloc_catb(&final,namedeps.s,namedeps.len)) { VERBO1 warnstralloc("ss_resolve_setnwrite") ; goto err ; }
if (!stralloc_catb(&final," ",1)) {VERBO1 warnstralloc("ss_resolve_setnwrite") ; goto err ; }
}
final.len-- ;
if (!stralloc_0(&final)){ VERBO1 warnstralloc("ss_resolve_setnwrite") ; goto err ; }
res.deps = ss_resolve_add_string(&res,final.s) ;
}
if (services->opts[0])
{
memcpy(logname,name,namelen) ;
memcpy(logname + namelen,SS_LOG_SUFFIX,SS_LOG_SUFFIX_LEN) ;
logname[namelen + SS_LOG_SUFFIX_LEN] = 0 ;
memcpy(logreal,name,namelen) ;
if (res.type == CLASSIC)
{
memcpy(logreal + namelen,"/log",SS_LOG_SUFFIX_LEN) ;
}
else memcpy(logreal + namelen,"-log",SS_LOG_SUFFIX_LEN) ;
logreal[namelen + SS_LOG_SUFFIX_LEN] = 0 ;
res.logger = ss_resolve_add_string(&res,logname) ;
res.logreal = ss_resolve_add_string(&res,logreal) ;
if (final.len) final.len--;
if (!stralloc_catb(&final," ",1)) { VERBO1 warnstralloc("ss_resolve_setnwrite") ; goto err ; }
if (!stralloc_cats(&final,res.sa.s + res.logger)) { VERBO1 warnstralloc("ss_resolve_setnwrite") ; goto err ; }
if (!stralloc_0(&final)){ VERBO1 warnstralloc("ss_resolve_setnwrite") ; goto err ; }
res.deps = ss_resolve_add_string(&res,final.s) ;
if (res.type == CLASSIC) res.ndeps = 1 ;
else if (res.type == LONGRUN) res.ndeps += 1 ;
// destination of the logger
if (!services->type.classic_longrun.log.destination)
{
if(info->owner > 0)
{
if (!stralloc_cats(&destlog,get_userhome(info->owner))) { VERBO1 warnstralloc("ss_resolve_setnwrite") ; goto err ; }
if (!stralloc_cats(&destlog,"/")) { VERBO1 warnstralloc("ss_resolve_setnwrite") ; goto err ; }
if (!stralloc_cats(&destlog,SS_LOGGER_USERDIR)) { VERBO1 warnstralloc("ss_resolve_setnwrite") ; goto err ; }
if (!stralloc_cats(&destlog,name)) { VERBO1 warnstralloc("ss_resolve_setnwrite") ; goto err ; }
}
else
{
if (!stralloc_cats(&destlog,SS_LOGGER_SYSDIR)) { VERBO1 warnstralloc("ss_resolve_setnwrite") ; goto err ; }
if (!stralloc_cats(&destlog,name)) { VERBO1 warnstralloc("ss_resolve_setnwrite") ; goto err ; }
}
}
else
{
if (!stralloc_cats(&destlog,keep.s+services->type.classic_longrun.log.destination)) { warnstralloc("ss_resolve_setnwrite") ; goto err ; }
}
if (!stralloc_0(&destlog)) { VERBO1 warnstralloc("ss_resolve_setnwrite") ; goto err ; }
res.dstlog = ss_resolve_add_string(&res,destlog.s) ;
if (!ss_resolve_setlognwrite(&res,dst,info)) goto err ;
}
/** may on workdir so a copy with made to source, write it SIMPLE */
if (!ss_resolve_write(&res,dst,res.sa.s + res.name))
{
VERBO1 strerr_warnwu5sys("write resolve file: ",dst,SS_RESOLVE,"/",res.sa.s + res.name) ;
goto err ;
}
ss_resolve_free(&res) ;
stralloc_free(&namedeps) ;
stralloc_free(&final) ;
stralloc_free(&destlog) ;
return 1 ;
err:
ss_resolve_free(&res) ;
stralloc_free(&namedeps) ;
stralloc_free(&final) ;
stralloc_free(&destlog) ;
return 0 ;
}
int ss_resolve_cmp(genalloc *ga,char const *name)
{
unsigned int i = 0 ;
for (;i < genalloc_len(ss_resolve_t,ga) ; i++)
{
char *string = genalloc_s(ss_resolve_t,ga)[i].sa.s ;
char *s = string + genalloc_s(ss_resolve_t,ga)[i].name ;
if (obstr_equal(name,s)) return 1 ;
}
return 0 ;
}
int ss_resolve_copy(ss_resolve_t *dst,ss_resolve_t *res)
{
size_t len = res->sa.len - 1 ;
dst->salen = res->salen ;
if (!stralloc_catb(&dst->sa,res->sa.s,len)) return 0 ;
dst->name = res->name ;
dst->description = res->description ;
dst->logger = res->logger ;
dst->logreal = res->logreal ;
dst->logassoc = res->logassoc ;
dst->dstlog = res->dstlog ;
dst->deps = res->deps ;
dst->src = res->src ;
dst->srconf = res->srconf ;
dst->live = res->live ;
dst->runat = res->runat ;
dst->tree = res->tree ;
dst->treename = res->treename ;
dst->state = res->state ;
dst->exec_run = res->exec_run ;
dst->exec_finish = res->exec_finish ;
dst->type = res->type ;
dst->ndeps = res->ndeps ;
dst->down = res->down ;
dst->disen = res->disen ;
if (!stralloc_0(&dst->sa)) return 0 ;
return 1 ;
}
int ss_resolve_append(genalloc *ga,ss_resolve_t *res)
{
ss_resolve_t cp = RESOLVE_ZERO ;
if (!ss_resolve_copy(&cp,res)) goto err ;
if (!genalloc_append(ss_resolve_t,ga,&cp)) goto err ;
return 1 ;
err:
ss_resolve_free(&cp) ;
return 0 ;
}
int ss_resolve_add_deps(genalloc *tokeep,ss_resolve_t *res, char const *src)
{
unsigned int i = 0 ;
genalloc tmp = GENALLOC_ZERO ;
char *name = res->sa.s + res->name ;
char *deps = res->sa.s + res->deps ;
if (!ss_resolve_cmp(tokeep,name) && (!obstr_equal(name,SS_MASTER+1)))
if (!ss_resolve_append(tokeep,res)) goto err ;
if (res->ndeps)
{
if (!clean_val(&tmp,deps)) return 0 ;
for (;i < genalloc_len(stralist,&tmp) ; i++)
{
ss_resolve_t dres = RESOLVE_ZERO ;
if (!ss_resolve_check(src,gaistr(&tmp,i))) goto err ;
if (!ss_resolve_read(&dres,src,gaistr(&tmp,i))) goto err ;
if (dres.ndeps && !ss_resolve_cmp(tokeep,gaistr(&tmp,i)))
{
if (!ss_resolve_add_deps(tokeep,&dres,src)) goto err ;
}
if (!ss_resolve_cmp(tokeep,gaistr(&tmp,i)))
{
if (!ss_resolve_append(tokeep,&dres)) goto err ;
}
ss_resolve_free(&dres) ;
}
}
genalloc_deepfree(stralist,&tmp,stra_free) ;
return 1 ;
err:
genalloc_deepfree(stralist,&tmp,stra_free) ;
return 0 ;
}
int ss_resolve_add_rdeps(genalloc *tokeep, ss_resolve_t *res, char const *src)
{
int type ;
genalloc tmp = GENALLOC_ZERO ;
genalloc nsv = GENALLOC_ZERO ;
ss_state_t sta = STATE_ZERO ;
char *name = res->sa.s + res->name ;
size_t srclen = strlen(src) ;
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 == CLASSIC) type = 0 ;
else type = 1 ;
if (!dir_get(&nsv,s,SS_MASTER+1,S_IFREG)) goto err ;
if (!ss_resolve_cmp(tokeep,name) && (!obstr_equal(name,SS_MASTER+1)))
{
if (!ss_resolve_append(tokeep,res)) goto err ;
}
if (res->type == BUNDLE && res->ndeps)
{
if (!clean_val(&tmp,res->sa.s + res->deps)) goto err ;
ss_resolve_t dres = RESOLVE_ZERO ;
for (unsigned int i = 0 ; i < genalloc_len(stralist,&tmp) ; i++)
{
if (!ss_resolve_check(src,gaistr(&tmp,i))) goto err ;
if (!ss_resolve_read(&dres,src,gaistr(&tmp,i))) goto err ;
if (!ss_resolve_cmp(tokeep,gaistr(&tmp,i)))
{
if (!ss_resolve_append(tokeep,&dres)) goto err ;
if (!ss_resolve_add_rdeps(tokeep,&dres,src)) goto err ;
}
ss_resolve_free(&dres) ;
}
}
for (unsigned int i = 0 ; i < genalloc_len(stralist,&nsv) ; i++)
{
int dtype = 0 ;
genalloc_deepfree(stralist,&tmp,stra_free) ;
ss_resolve_t dres = RESOLVE_ZERO ;
char *dname = gaistr(&nsv,i) ;
if (obstr_equal(name,dname)) { ss_resolve_free(&dres) ; continue ; }
if (!ss_resolve_check(src,dname)) goto err ;
if (!ss_resolve_read(&dres,src,dname)) goto err ;
if (dres.type == CLASSIC) dtype = 0 ;
else dtype = 1 ;
if (ss_state_check(dres.sa.s + dres.state,dname))
{
if (!ss_state_read(&sta,dres.sa.s + dres.state,dname)) goto err ;
if (dtype != type || (!dres.disen && !sta.unsupervise)){ ss_resolve_free(&dres) ; continue ; }
}
else if (dtype != type || (!dres.disen)){ ss_resolve_free(&dres) ; continue ; }
if (dres.type == BUNDLE && !dres.ndeps){ ss_resolve_free(&dres) ; continue ; }
if (!ss_resolve_cmp(tokeep,dname))
{
if (dres.ndeps)// || (dres.type == BUNDLE && dres.ndeps) || )
{
if (!clean_val(&tmp,dres.sa.s + dres.deps)) goto err ;
for (unsigned int j = 0 ; j < genalloc_len(stralist,&tmp) ; j++)
{
if (obstr_equal(name,gaistr(&tmp,j)))
{
if (!ss_resolve_append(tokeep,&dres)) goto err ;
if (!ss_resolve_add_rdeps(tokeep,&dres,src)) goto err ;
ss_resolve_free(&dres) ;
break ;
}
}
}
}
ss_resolve_free(&dres) ;
}
genalloc_deepfree(stralist,&tmp,stra_free) ;
genalloc_deepfree(stralist,&nsv,stra_free) ;
return 1 ;
err:
genalloc_deepfree(stralist,&tmp,stra_free) ;
genalloc_deepfree(stralist,&nsv,stra_free) ;
return 0 ;
}
int ss_resolve_add_logger(genalloc *ga,char const *src)
{
genalloc gatmp = GENALLOC_ZERO ;
for (unsigned int i = 0 ; i < genalloc_len(ss_resolve_t,ga) ; i++)
{
ss_resolve_t res = RESOLVE_ZERO ;
ss_resolve_t dres = RESOLVE_ZERO ;
if (!ss_resolve_copy(&res,&genalloc_s(ss_resolve_t,ga)[i])) goto err ;
char *string = res.sa.s ;
char *name = string + res.name ;
if (!ss_resolve_cmp(&gatmp,name))
{
if (!ss_resolve_append(&gatmp,&res))
goto err ;
if (res.logger)
{
if (!ss_resolve_check(src,string + res.logger)) goto err ;
if (!ss_resolve_read(&dres,src,string + res.logger))
goto err ;
if (!ss_resolve_cmp(&gatmp,string + res.logger))
if (!ss_resolve_append(&gatmp,&dres)) goto err ;
}
}
ss_resolve_free(&res) ;
ss_resolve_free(&dres) ;
}
genalloc_deepfree(ss_resolve_t,ga,ss_resolve_free) ;
if (!genalloc_copy(ss_resolve_t,ga,&gatmp)) goto err ;
genalloc_free(ss_resolve_t,&gatmp) ;
return 1 ;
err:
genalloc_deepfree(ss_resolve_t,&gatmp,ss_resolve_free) ;
return 0 ;
}
int ss_resolve_create_live(ssexec_t *info)
{
int r ;
gid_t gidowner ;
if (!yourgid(&gidowner,info->owner)) return 0 ;
stralloc sares = STRALLOC_ZERO ;
stralloc ressrc = STRALLOC_ZERO ;
if (!ss_resolve_pointo(&sares,info,SS_NOTYPE,SS_RESOLVE_SRC)) goto err ;
if (!stralloc_copy(&ressrc,&sares)) goto err ;
if (!ss_resolve_pointo(&sares,info,SS_NOTYPE,SS_RESOLVE_STATE)) goto err ;
r = scan_mode(sares.s,S_IFDIR) ;
if (r < 0) goto err ;
if (!r)
{
ssize_t len = get_rlen_until(sares.s,'/',sares.len) ;
char sym[sares.len + SS_RESOLVE_LEN + 1] ;
memcpy(sym,sares.s,len) ;
sym[len] = 0 ;
r = dir_create_under(sym,info->treename.s,0700) ;
if (!r) goto err ;
if (chown(sym,info->owner,gidowner) < 0) goto err ;
memcpy(sym,sares.s,sares.len - 1) ;
memcpy(sym + (sares.len - 1), SS_SVDIRS, SS_SVDIRS_LEN) ;
sym[(sares.len - 1) + SS_SVDIRS_LEN] = 0 ;
VERBO3 strerr_warnt4x("point symlink: ",sym," to ",ressrc.s) ;
if (symlink(ressrc.s,sym) < 0)
{
VERBO3 strerr_warnwu2sys("symlink: ", sym) ;
goto err ;
}
}
/** live/state/uid/treename/init file */
if (!file_write_unsafe(sares.s,"init","",0)) goto err ;
stralloc_free(&ressrc) ;
stralloc_free(&sares) ;
return 1 ;
err:
stralloc_free(&ressrc) ;
stralloc_free(&sares) ;
return 0 ;
}
int ss_resolve_search(genalloc *ga,char const *name)
{
unsigned int i = 0 ;
for (; i < genalloc_len(ss_resolve_t,ga) ; i++)
{
char *s = genalloc_s(ss_resolve_t,ga)[i].sa.s + genalloc_s(ss_resolve_t,ga)[i].name ;
if (obstr_equal(name,s)) return i ;
}
return -1 ;
}
int ss_resolve_write_master(ssexec_t *info,ss_resolve_graph_t *graph,char const *dir, unsigned int reverse)
{
int r ;
char ownerstr[UID_FMT] ;
size_t ownerlen = uid_fmt(ownerstr,info->owner) ;
ownerstr[ownerlen] = 0 ;
stralloc in = STRALLOC_ZERO ;
stralloc inres = STRALLOC_ZERO ;
stralloc already = STRALLOC_ZERO ;
genalloc gain = GENALLOC_ZERO ;
ss_resolve_t res = RESOLVE_ZERO ;
size_t dirlen = strlen(dir) ;
char runat[info->livetree.len + 1 + info->treename.len + SS_SVDIRS_LEN + SS_MASTER_LEN + 1] ;
memcpy(runat,info->livetree.s,info->livetree.len) ;
runat[info->livetree.len] = '/' ;
memcpy(runat + info->livetree.len + 1,info->treename.s,info->treename.len) ;
memcpy(runat + info->livetree.len + 1 + info->treename.len, SS_SVDIRS,SS_SVDIRS_LEN) ;
memcpy(runat + info->livetree.len + 1 + info->treename.len + SS_SVDIRS_LEN, SS_MASTER, SS_MASTER_LEN) ;
runat[info->livetree.len + 1 + info->treename.len + SS_SVDIRS_LEN + SS_MASTER_LEN] = 0 ;
char dst[dirlen + SS_DB_LEN + SS_SRC_LEN + SS_MASTER_LEN + 1] ;
memcpy(dst, dir, dirlen) ;
memcpy(dst + dirlen, SS_DB, SS_DB_LEN) ;
memcpy(dst + dirlen + SS_DB_LEN, SS_SRC, SS_SRC_LEN) ;
memcpy(dst + dirlen + SS_DB_LEN + SS_SRC_LEN, SS_MASTER, SS_MASTER_LEN) ;
dst[dirlen + SS_DB_LEN + SS_SRC_LEN + SS_MASTER_LEN] = 0 ;
size_t livelen = info->live.len - 1 ;
char state[livelen + SS_STATE_LEN + 1 + ownerlen + 1 + info->treename.len + 1] ;
memcpy(state,info->live.s,livelen) ;
memcpy(state + livelen, SS_STATE,SS_STATE_LEN) ;
state[livelen+ SS_STATE_LEN] = '/' ;
memcpy(state + livelen + SS_STATE_LEN + 1,ownerstr,ownerlen) ;
state[livelen + SS_STATE_LEN + 1 + ownerlen] = '/' ;
memcpy(state + livelen + SS_STATE_LEN + 1 + ownerlen + 1,info->treename.s,info->treename.len) ;
state[livelen + SS_STATE_LEN + 1 + ownerlen + 1 + info->treename.len] = 0 ;
if (reverse)
{
size_t dstlen = strlen(dst) ;
char file[dstlen + 1 + SS_CONTENTS_LEN + 1] ;
memcpy(file,dst,dstlen) ;
file[dstlen] = '/' ;
memcpy(file + dstlen + 1, SS_CONTENTS,SS_CONTENTS_LEN) ;
file[dstlen + 1 + SS_CONTENTS_LEN] = 0 ;
size_t filesize=file_get_size(file) ;
r = openreadfileclose(file,&already,filesize) ;
if(!r) goto err ;
/** ensure that we have an empty line at the end of the string*/
if (!stralloc_cats(&already,"\n")) goto err ;
if (!stralloc_0(&already)) goto err ;
if (!clean_val(&gain,already.s)) goto err ;
stralloc_free(&already) ;
}
for (unsigned int i = 0 ; i < genalloc_len(ss_resolve_t,&graph->sorted); i++)
{
char *string = genalloc_s(ss_resolve_t,&graph->sorted)[i].sa.s ;
char *name = string + genalloc_s(ss_resolve_t,&graph->sorted)[i].name ;
if (reverse)
if (!stra_cmp(&gain,name)) continue ;
if (!stralloc_cats(&in,name)) goto err ;
if (!stralloc_cats(&in,"\n")) goto err ;
if (!stralloc_cats(&inres,name)) goto err ;
if (!stralloc_cats(&inres," ")) goto err ;
}
if (inres.len) inres.len--;
if (!stralloc_0(&inres)) goto err ;
r = file_write_unsafe(dst,SS_CONTENTS,in.s,in.len) ;
if (!r)
{
VERBO3 strerr_warnwu3sys("write: ",dst,"contents") ;
goto err ;
}
ss_resolve_init(&res) ;
res.name = ss_resolve_add_string(&res,SS_MASTER+1) ;
res.description = ss_resolve_add_string(&res,"inner bundle - do not use it") ;
res.treename = ss_resolve_add_string(&res,info->treename.s) ;
res.tree = ss_resolve_add_string(&res,info->tree.s) ;
res.live = ss_resolve_add_string(&res,info->live.s) ;
res.type = BUNDLE ;
res.deps = ss_resolve_add_string(&res,inres.s) ;
res.ndeps = genalloc_len(ss_resolve_t,&graph->sorted) ;
res.runat = ss_resolve_add_string(&res,runat) ;
res.state = ss_resolve_add_string(&res,state) ;
if (!ss_resolve_write(&res,dir,SS_MASTER+1)) goto err ;
stralloc_free(&in) ;
stralloc_free(&inres) ;
ss_resolve_free(&res) ;
stralloc_free(&already) ;
genalloc_deepfree(stralist,&gain,stra_free) ;
return 1 ;
err:
ss_resolve_free(&res) ;
stralloc_free(&in) ;
stralloc_free(&inres) ;
stralloc_free(&already) ;
genalloc_deepfree(stralist,&gain,stra_free) ;
return 0 ;
}