Skip to content
Snippets Groups Projects
Commit b09b4b3a authored by Eric Vidal's avatar Eric Vidal :speech_balloon:
Browse files

pass 66-tree to ssexec_t struct, add the seed file feature

parent 51f3ea77
No related branches found
No related tags found
No related merge requests found
......@@ -12,789 +12,21 @@
* except according to the terms contained in the LICENSE file./
*/
#include <66/tree.h>
#include <string.h>
#include <stdint.h>//uintx_t
#include <sys/stat.h>
#include <stdio.h>//rename
#include <oblibs/obgetopt.h>
#include <oblibs/log.h>
#include <oblibs/types.h>
#include <oblibs/directory.h>
#include <oblibs/files.h>
#include <oblibs/string.h>
#include <oblibs/sastr.h>
#include <skalibs/stralloc.h>
#include <skalibs/djbunix.h>
#include <skalibs/bytestr.h>//byte_count
#include <skalibs/posixplz.h>//unlink_void
#include <66/config.h>
#include <66/utils.h>
#include <66/constants.h>
#include <66/db.h>
#include <66/enum.h>
#include <66/state.h>
#include <66/resolve.h>
#include <s6/supervise.h>
#include <s6-rc/s6rc-servicedir.h>
#include <s6-rc/s6rc-constants.h>
#define USAGE "66-tree [ -h ] [ -z ] [ -v verbosity ] [ -n|R ] [ -a|d ] [ -c ] [ -S after_tree ] [ -E|D ] [ -C clone ] tree"
static char const *cleantree = 0 ;
static inline void info_help (void)
{
DEFAULT_MSG = 0 ;
static char const *help =
"\n"
"options :\n"
" -h: print this help\n"
" -z: use color\n"
" -v: increase/decrease verbosity\n"
" -n: create a new empty tree\n"
" -a: allow user(s) at tree\n"
" -d: deny user(s) at tree\n"
" -c: set tree as default\n"
" -S: start the tree after after_tree\n"
" -E: enable the tree\n"
" -D: disable the tree\n"
" -R: remove the tree\n"
" -C: clone the tree\n"
;
log_info(USAGE,"\n",help) ;
}
static void cleanup(void)
{
log_flow() ;
if (cleantree)
{
log_trace("removing: ",cleantree,"...") ;
rm_rf(cleantree) ;
}
}
static void auto_string(char *strings,char const *str,size_t baselen)
{
log_flow() ;
size_t slen = strlen(str) ;
memcpy(strings + baselen,str,slen) ;
strings[baselen+slen] = 0 ;
}
static void auto_dir(char const *dst,mode_t mode)
{
log_flow() ;
log_trace("create directory: ",dst) ;
if (!dir_create_parent(dst,mode))
log_dieusys_nclean(LOG_EXIT_SYS,&cleanup,"create directory: ",dst) ;
}
static void auto_create(char *strings,char const *str,size_t baselen,mode_t mode)
{
log_flow() ;
auto_string(strings,str,baselen) ;
auto_dir(strings,mode) ;
}
static void auto_check(char *dst,char const *str,size_t baselen,mode_t mode)
{
log_flow() ;
auto_string(dst,str,baselen) ;
if (!scan_mode(dst,mode)) auto_dir(dst,0755) ;
}
static void auto_check_one(char *dst,mode_t mode)
{
log_flow() ;
if (!scan_mode(dst,mode)) auto_dir(dst,0755) ;
}
static void inline auto_stralloc(stralloc *sa,char const *str)
{
log_flow() ;
if (!stralloc_cats(sa,str)) log_die_nomem("stralloc") ;
}
static void inline auto_stralloc0(stralloc *sa)
{
log_flow() ;
if (!stralloc_0(sa)) log_die_nomem("stralloc") ;
sa->len-- ;
}
static void inline auto_stralloc_0(stralloc *sa,char const *str)
{
log_flow() ;
auto_stralloc(sa,str) ;
auto_stralloc0(sa) ;
}
int sanitize_tree(stralloc *dstree, char const *base, char const *tree,uid_t owner)
{
log_flow() ;
ssize_t r ;
size_t baselen = strlen(base) ;
size_t treelen = strlen(tree) ;
char dst[baselen + SS_SYSTEM_LEN + 1 + treelen + 1] ;
auto_string(dst,base,0) ;
/** base is /var/lib/66 or $HOME/.66*/
/** this verification is made in case of
* first use of 66-*** tools */
auto_check(dst,SS_SYSTEM,baselen,0755) ;
/** create extra directory for service part */
if (!owner)
{
auto_check_one(SS_LOGGER_SYSDIR,0755) ;
auto_check_one(SS_SERVICE_SYSDIR,0755) ;
auto_check_one(SS_SERVICE_ADMDIR,0755) ;
auto_check_one(SS_SERVICE_ADMCONFDIR,0755) ;
auto_check_one(SS_MODULE_SYSDIR,0755) ;
auto_check_one(SS_MODULE_ADMDIR,0755) ;
auto_check_one(SS_SCRIPT_SYSDIR,0755) ;
}
else
{
size_t extralen ;
stralloc extra = STRALLOC_ZERO ;
if (!set_ownerhome(&extra,owner))
log_dieusys(LOG_EXIT_SYS,"set home directory") ;
extralen = extra.len ;
auto_stralloc(&extra,SS_USER_DIR) ;
auto_stralloc_0(&extra,SS_SYSTEM) ;
auto_check_one(extra.s,0755) ;
extra.len = extralen ;
auto_stralloc_0(&extra,SS_LOGGER_USERDIR) ;
auto_check_one(extra.s,0755) ;
extra.len = extralen ;
auto_stralloc_0(&extra,SS_SERVICE_USERDIR) ;
auto_check_one(extra.s,0755) ;
extra.len = extralen ;
auto_stralloc_0(&extra,SS_SERVICE_USERCONFDIR) ;
auto_check_one(extra.s,0755) ;
extra.len = extralen ;
auto_stralloc_0(&extra,SS_MODULE_USERDIR) ;
auto_check_one(extra.s,0755) ;
extra.len = extralen ;
auto_stralloc_0(&extra,SS_SCRIPT_USERDIR) ;
auto_check_one(extra.s,0755) ;
stralloc_free(&extra) ;
}
auto_check(dst,SS_TREE_CURRENT,baselen,0755) ;
auto_string(dst,SS_SYSTEM,baselen) ;
auto_check(dst,SS_BACKUP,baselen + SS_SYSTEM_LEN,0755) ;
auto_string(dst,SS_STATE,baselen + SS_SYSTEM_LEN) ;
if (!scan_mode(dst,S_IFREG))
{
auto_string(dst,SS_SYSTEM,baselen) ;
if(!file_create_empty(dst,SS_STATE + 1,0644))
log_dieusys(LOG_EXIT_SYS,"create ",dst,SS_STATE) ;
}
auto_string(dst,"/",baselen + SS_SYSTEM_LEN) ;
auto_string(dst,tree,baselen + SS_SYSTEM_LEN + 1) ;
r = scan_mode(dst,S_IFDIR) ;
if (r == -1) log_die(LOG_EXIT_SYS,"invalid directory: ",dst) ;
/** we have one, keep it*/
if (!stralloc_cats(dstree,dst)) log_die_nomem("stralloc") ;
if (!stralloc_0(dstree)) log_die_nomem("stralloc") ;
if (!r) return 0 ;
return 1 ;
}
void create_tree(char const *tree,char const *treename)
{
log_flow() ;
size_t newlen = 0 ;
size_t treelen = strlen(tree) ;
char dst[treelen + SS_SVDIRS_LEN + SS_DB_LEN + SS_SRC_LEN + 16 + 1] ;
ss_resolve_t res = RESOLVE_ZERO ;
ss_resolve_init(&res) ;
memcpy(dst, tree, treelen) ;
newlen = treelen ;
dst[newlen] = 0 ;
res.name = ss_resolve_add_string(&res,SS_MASTER+1) ;
res.description = ss_resolve_add_string(&res,"inner bundle - do not use it") ;
res.tree = ss_resolve_add_string(&res,dst) ;
res.treename = ss_resolve_add_string(&res,treename) ;
res.type = TYPE_BUNDLE ;
res.disen = 1 ;
auto_create(dst,SS_SVDIRS,newlen,0755) ;
auto_create(dst,SS_RULES,newlen,0755) ;
auto_string(dst,SS_SVDIRS,newlen) ;
newlen = newlen + SS_SVDIRS_LEN ;
auto_create(dst,SS_DB,newlen,0755) ;
auto_create(dst,SS_SVC,newlen,0755) ;
auto_create(dst,SS_RESOLVE,newlen,0755) ;
dst[newlen] = 0 ;
log_trace("write resolve file of inner bundle") ;
if (!ss_resolve_write(&res,dst,SS_MASTER+1))
{
ss_resolve_free(&res) ;
log_dieusys_nclean(LOG_EXIT_SYS,&cleanup,"write resolve file of inner bundle") ;
}
ss_resolve_free(&res) ;
char sym[newlen + 1 + SS_SYM_SVC_LEN + 1] ;
char dstsym[newlen + SS_SVC_LEN + 1] ;
auto_string(sym,dst,0) ;
auto_string(sym,"/",newlen) ;
auto_string(sym,SS_SYM_SVC,newlen + 1) ;
auto_string(dstsym,dst,0) ;
auto_string(dstsym,SS_SVC,newlen) ;
log_trace("point symlink: ",sym," to ",dstsym) ;
if (symlink(dstsym,sym) < 0)
log_dieusys_nclean(LOG_EXIT_SYS,&cleanup,"symlink: ", sym) ;
auto_string(sym,SS_SYM_DB,newlen + 1) ;
auto_string(dstsym,SS_DB,newlen) ;
log_trace("point symlink: ",sym," to ",dstsym) ;
if (symlink(dstsym,sym) < 0)
log_dieusys_nclean(LOG_EXIT_SYS,&cleanup,"symlink: ", sym) ;
auto_string(dst,SS_DB,newlen) ;
newlen = newlen + SS_DB_LEN ;
auto_create(dst,SS_SRC,newlen,0755) ;
auto_string(dst,SS_SRC,newlen) ;
newlen = newlen + SS_SRC_LEN ;
auto_create(dst,SS_MASTER,newlen,0755) ;
auto_string(dst,SS_MASTER,newlen) ;
newlen = newlen + SS_MASTER_LEN ;
log_trace("create file: ",dst,"/contents") ;
if (!file_create_empty(dst,"contents",0644))
log_dieusys_nclean(LOG_EXIT_SYS,&cleanup,"create: ",dst,"/contents") ;
auto_string(dst,"/type",newlen) ;
log_trace("create file: ",dst) ;
if(!openwritenclose_unsafe(dst,"bundle\n",7))
log_dieusys_nclean(LOG_EXIT_SYS,&cleanup,"write: ",dst) ;
}
void create_backupdir(char const *base, char const *treename)
{
log_flow() ;
int r ;
size_t baselen = strlen(base) - 1 ;//remove the last slash
size_t treenamelen = strlen(treename) ;
char treetmp[baselen + 1 + SS_SYSTEM_LEN + SS_BACKUP_LEN + 1 + treenamelen + 1] ;
auto_string(treetmp,base,0) ;
auto_string(treetmp,"/",baselen) ;
auto_string(treetmp,SS_SYSTEM,baselen + 1) ;
auto_string(treetmp,SS_BACKUP,baselen + 1 + SS_SYSTEM_LEN) ;
auto_string(treetmp,"/",baselen + 1 + SS_SYSTEM_LEN + SS_BACKUP_LEN) ;
auto_string(treetmp,treename,baselen + 1 + SS_SYSTEM_LEN + SS_BACKUP_LEN + 1) ;
r = scan_mode(treetmp,S_IFDIR) ;
if (r || (r == -1))
{
log_trace("remove existing backup: ",treetmp) ;
if (rm_rf(treetmp) < 0)
log_dieusys_nclean(LOG_EXIT_SYS,&cleanup,"remove: ",treetmp) ;
}
if (!r) auto_dir(treetmp,0755) ;
}
/** @what -> 0 deny
* @what -> 1 allow */
void set_rules(char const *tree,uid_t *uids, size_t uidn,uint8_t what)
{
log_flow() ;
log_trace("set ", !what ? "denied" : "allowed"," user for tree: ",tree,"..." ) ;
int r ;
size_t treelen = strlen(tree) ;
char pack[256] ;
char tmp[treelen + SS_RULES_LEN + 1] ;
auto_string(tmp,tree,0) ;
auto_string(tmp,SS_RULES,treelen) ;
if (!uidn && what)
{
uids[0] = 1 ;
uids[1] = MYUID ;
uidn++ ;
}
if (what) //allow
{
for (size_t i = 0 ; i < uidn ; i++)
{
uint32_pack(pack,uids[i+1]) ;
pack[uint_fmt(pack,uids[i+1])] = 0 ;
log_trace("create file: ",pack," at ",tmp) ;
if(!file_create_empty(tmp,pack,0644) && errno != EEXIST)
log_dieu_nclean(LOG_EXIT_SYS,&cleanup,"set permissions access") ;
log_trace("user: ",pack," is allowed for tree: ",tree) ;
}
return ;
}
//else deny
for (size_t i = 0 ; i < uidn ; i++)
{
if (MYUID == uids[i+1]) continue ;
uint32_pack(pack,uids[i+1]) ;
pack[uint_fmt(pack,uids[i+1])] = 0 ;
char ut[treelen + SS_RULES_LEN + 1 + uint_fmt(pack,uids[i+1]) + 1] ;
memcpy(ut,tmp,treelen + SS_RULES_LEN) ;
memcpy(ut + treelen + SS_RULES_LEN,"/",1) ;
memcpy(ut + treelen + SS_RULES_LEN + 1,pack,uint_fmt(pack,uids[i+1])) ;
ut[treelen + SS_RULES_LEN + 1 + uint_fmt(pack,uids[i + 1])] = 0 ;
r = scan_mode(tmp,S_IFREG) ;
if (r == 1)
{
log_trace("unlink: ",ut) ;
r = unlink(ut) ;
if (r == -1)
log_dieu_nclean(LOG_EXIT_SYS,&cleanup,"set permissions access") ;
}
log_trace("user: ",pack," is denied for tree: ",tree) ;
}
}
/** @action -> 0 disable
* @action -> 1 enable */
void tree_enable_disable(char const *base, char const *dst, char const *tree,uint8_t action)
{
log_flow() ;
int r ;
log_trace(!action ? "disable " : "enable ",dst,"...") ;
r = tree_cmd_state(VERBOSITY,!action ? "-d" : "-a", tree) ;
if (!r) log_dieusys(LOG_EXIT_SYS,!action ? "disable: " : "enable: ",dst," at: ",base,SS_SYSTEM,SS_STATE) ;
else if (r == 1)
{
log_info(!action ? "Disabled" : "Enabled"," successfully tree: ",tree) ;
}
else log_info("Already ",!action ? "disabled" : "enabled"," tree: ",tree) ;
}
void tree_modify_resolve(ss_resolve_t *res,ss_resolve_enum_t field,char const *regex,char const *by)
{
log_flow() ;
stralloc sa = STRALLOC_ZERO ;
ss_resolve_t modif = RESOLVE_ZERO ;
log_trace("modify field: ",ss_resolve_field_table[field].field," of service: ",res->sa.s + res->name) ;
if (!ss_resolve_copy(&modif,res))
log_dieu_nclean(LOG_EXIT_SYS,&cleanup,"copy resolve file of: ", res->sa.s + res->name) ;
if (!ss_resolve_put_field_to_sa(&sa,&modif, field))
log_dieusys_nclean(LOG_EXIT_SYS,&cleanup,"get copy field: ",ss_resolve_field_table[field].field) ;
if (sa.len) {
if (!sastr_replace(&sa,regex,by))
log_dieu_nclean(LOG_EXIT_SYS,&cleanup,"replace field: ",ss_resolve_field_table[field].field) ;
if (!stralloc_0(&sa))
log_dieu_nclean(LOG_EXIT_SYS,&cleanup,"stralloc") ;
sa.len-- ;
}
if (!ss_resolve_modify_field(&modif,field,sa.s))
log_dieusys_nclean(LOG_EXIT_SYS,&cleanup,"modify field: ",ss_resolve_field_table[field].field) ;
if (!ss_resolve_copy(res,&modif))
log_dieu_nclean(LOG_EXIT_SYS,&cleanup,"copy resolve file of: ",res->sa.s + res->name) ;
stralloc_free(&sa) ;
ss_resolve_free(&modif) ;
}
void tree_remove(char const *base,char const *dst,char const *tree)
{
log_flow() ;
log_trace("delete: ",dst,"..." ) ;
int r ;
if (rm_rf(dst) < 0) log_dieusys(LOG_EXIT_SYS,"delete: ", dst) ;
size_t treelen = strlen(tree) ;
size_t baselen = strlen(base) ;
char treetmp[baselen + SS_SYSTEM_LEN + SS_BACKUP_LEN + 1 + treelen + 1] ;
auto_string(treetmp,base,0) ;
auto_string(treetmp,SS_SYSTEM,baselen) ;
auto_string(treetmp,SS_BACKUP,baselen + SS_SYSTEM_LEN) ;
auto_string(treetmp,"/",baselen + SS_SYSTEM_LEN + SS_BACKUP_LEN) ;
auto_string(treetmp,tree,baselen + SS_SYSTEM_LEN + SS_BACKUP_LEN + 1) ;
r = scan_mode(treetmp,S_IFDIR) ;
if (r || (r < 0))
{
log_trace("delete backup of tree: ",treetmp,"...") ;
if (rm_rf(treetmp) < 0) log_dieusys(LOG_EXIT_SYS,"delete: ",treetmp) ;
}
tree_enable_disable(base,dst,tree,0) ;
log_info("Deleted successfully: ",tree) ;
}
#include <66/ssexec.h>
int main(int argc, char const *const *argv,char const *const *envp)
{
int r, current, create, allow, deny, enable, disable, remove, snap ;
uid_t owner ;
size_t auidn = 0 ;
uid_t auids[256] = { 0 } ;
size_t duidn = 0 ;
uid_t duids[256] = { 0 } ;
char const *tree = 0 ;
char const *after_tree = 0 ;
stralloc base = STRALLOC_ZERO ;
stralloc dstree = STRALLOC_ZERO ;
stralloc clone = STRALLOC_ZERO ;
log_color = &log_color_disable ;
current = create = allow = deny = enable = disable = remove = snap = 0 ;
PROG = "66-tree" ;
{
subgetopt l = SUBGETOPT_ZERO ;
for (;;)
{
int opt = getopt_args(argc,argv, "hv:na:d:cS:EDRC:z", &l) ;
if (opt == -1) break ;
if (opt == -2) log_die(LOG_EXIT_USER,"options must be set first") ;
switch (opt)
{
case 'h' : info_help(); return 0 ;
case 'v' : if (!uint0_scan(l.arg, &VERBOSITY)) log_usage(USAGE) ; break ;
case 'n' : create = 1 ; break ;
case 'a' : if (!scan_uidlist_wdelim(l.arg,auids,',')) log_usage(USAGE) ;
auidn = auids[0] ;
allow = 1 ;
break ;
case 'd' : if (!scan_uidlist_wdelim(l.arg,duids,',')) log_usage(USAGE) ;
duidn = duids[0] ;
deny = 1 ;
break ;
case 'c' : current = 1 ; break ;
case 'S' : after_tree = l.arg ; break ;
case 'E' : enable = 1 ; if (disable) log_usage(USAGE) ; break ;
case 'D' : disable = 1 ; if (enable) log_usage (USAGE) ; break ;
case 'R' : remove = 1 ; if (create) log_usage(USAGE) ; break ;
case 'C' : if (remove) log_usage(USAGE) ;
if (!stralloc_cats(&clone,l.arg)) log_die_nomem("stralloc") ;
if (!stralloc_0(&clone)) log_die_nomem("stralloc") ;
snap = 1 ;
break ;
case 'z' : log_color = !isatty(1) ? &log_color_disable : &log_color_enable ; break ;
default : log_usage(USAGE) ;
}
}
argc -= l.ind ; argv += l.ind ;
}
if (argc != 1) log_usage(USAGE) ;
tree = argv[0] ;
owner = MYUID ;
if (!set_ownersysdir(&base, owner)) log_dieusys(LOG_EXIT_SYS,"set owner directory") ;
log_trace("sanitize ",tree,"..." ) ;
r = sanitize_tree(&dstree,base.s,tree,owner) ;
if(!r && create)
{
/** set cleanup */
cleantree = dstree.s ;
log_trace("creating: ",dstree.s,"..." ) ;
create_tree(dstree.s,tree) ;
log_trace("creating backup directory for: ", tree,"...") ;
create_backupdir(base.s,tree) ;
/** unset cleanup */
cleantree = 0 ;
log_trace("set permissions rules for: ",dstree.s,"..." ) ;
set_rules(dstree.s,auids,auidn,1) ;
size_t dblen = dstree.len - 1 ;
char newdb[dblen + SS_SVDIRS_LEN + 1] ;
auto_string(newdb,dstree.s,0) ;
auto_string(newdb,SS_SVDIRS,dblen) ;
log_trace("compile: ",newdb,"/db/",tree,"..." ) ;
if (!db_compile(newdb,dstree.s,tree,envp))
log_dieu_nclean(LOG_EXIT_SYS,&cleanup,"compile ",newdb,"/db/",tree) ;
r = 1 ;
create = 0 ;
log_info("Created successfully tree: ",tree) ;
}
if ((!r && !create) || (!r && enable)) log_dieusys(LOG_EXIT_SYS,"find tree: ",dstree.s) ;
if (r && create) log_dieu(LOG_EXIT_USER,"create: ",dstree.s,": already exist") ;
if (enable)
tree_enable_disable(base.s,dstree.s,tree,1) ;
if (disable)
tree_enable_disable(base.s,dstree.s,tree,0) ;
if (auidn)
set_rules(dstree.s,auids,auidn,1) ;
if (duidn)
set_rules(dstree.s,duids,duidn,0) ;
if(current)
{
log_trace("make: ",dstree.s," as default ..." ) ;
if (!tree_switch_current(base.s,tree)) log_dieusys(LOG_EXIT_SYS,"set: ",dstree.s," as default") ;
log_info("Set successfully: ",tree," as default") ;
}
if (remove)
tree_remove(base.s,dstree.s,tree) ;
if (snap)
{
stralloc salist = STRALLOC_ZERO ;
ss_resolve_t res = RESOLVE_ZERO ;
size_t syslen = base.len + SS_SYSTEM_LEN ;
size_t treelen = strlen(tree) ;
size_t pos = 0 ;
char system[syslen + 1] ;
auto_strings(system,base.s,SS_SYSTEM) ;
size_t clone_target_len = syslen + 1 + clone.len ;
char clone_target[clone_target_len + 1] ;
auto_strings(clone_target,system,"/",clone.s) ;
r = scan_mode(clone_target,S_IFDIR) ;
if ((r < 0) || r) log_die(LOG_EXIT_SYS,clone_target,": already exist") ;
// clone main directory
log_trace("clone: ",tree," as: ",clone.s,"..." ) ;
if (!hiercopy(dstree.s,clone_target))
log_dieusys(LOG_EXIT_SYS,"copy: ",dstree.s," to: ",clone_target) ;
// clone backup directory
size_t clone_backup_len = syslen + SS_BACKUP_LEN + 1 + clone.len ;
char clone_backup[clone_backup_len + 1] ;
auto_strings(clone_backup,system,SS_BACKUP,"/",clone.s) ;
char tree_backup[syslen + SS_BACKUP_LEN + 1 + treelen + 1] ;
auto_strings(tree_backup,system,SS_BACKUP,"/",tree) ;
/* make cleantree pointing to the clone to be able to remove it
* in case of crach */
cleantree = clone_target ;
log_trace("clone backup of: ",tree," as: ",clone.s,"..." ) ;
if (!hiercopy(tree_backup,clone_backup))
log_dieu_nclean(LOG_EXIT_SYS,&cleanup,"copy: ",tree_backup," to: ",clone_backup) ;
// modify the resolve file to match the new name
// main directory first
char src_resolve[clone_target_len + SS_SVDIRS_LEN + SS_RESOLVE_LEN + 1] ;
auto_strings(src_resolve,clone_target,SS_SVDIRS,SS_RESOLVE) ;
if (!sastr_dir_get(&salist,src_resolve,"",S_IFREG))
log_dieusys_nclean(LOG_EXIT_SYS,&cleanup,"get resolve file at: ",src_resolve) ;
char clone_res[clone_target_len + SS_SVDIRS_LEN + 1] ;
auto_strings(clone_res,clone_target,SS_SVDIRS) ;
for (;pos < salist.len ; pos += strlen(salist.s + pos) + 1)
{
char *name = salist.s + pos ;
if (!ss_resolve_read(&res,clone_res,name))
log_dieusys_nclean(LOG_EXIT_SYS,&cleanup,"read resolve file of: ",src_resolve,"/",name) ;
tree_modify_resolve(&res,SS_RESOLVE_ENUM_RUNAT,tree,clone.s) ;
tree_modify_resolve(&res,SS_RESOLVE_ENUM_TREENAME,tree,clone.s) ;
tree_modify_resolve(&res,SS_RESOLVE_ENUM_TREE,tree,clone.s) ;
tree_modify_resolve(&res,SS_RESOLVE_ENUM_STATE,tree,clone.s) ;
if (!ss_resolve_write(&res,clone_res,name))
log_dieusys_nclean(LOG_EXIT_SYS,&cleanup,"write resolve file of: ",src_resolve,"/",name) ;
}
// rename db
char clone_db_old[clone_target_len + SS_SVDIRS_LEN + SS_DB_LEN + 1 + treelen + 1] ;
auto_strings(clone_db_old,clone_target,SS_SVDIRS,SS_DB,"/",tree) ;
char clone_db_new[clone_target_len + SS_SVDIRS_LEN + SS_DB_LEN + 1 + clone.len + 1] ;
auto_strings(clone_db_new,clone_target,SS_SVDIRS,SS_DB,"/",clone.s) ;
log_trace("rename tree db: ",tree," as: ",clone.s,"..." ) ;
if (rename(clone_db_old,clone_db_new) == -1)
log_dieusys_nclean(LOG_EXIT_SYS,&cleanup,"rename: ",clone_db_old," to: ",clone_db_new) ;
// backup directory
char src_resolve_backup[clone_backup_len + SS_RESOLVE_LEN + 1] ;
auto_strings(src_resolve_backup,clone_backup,SS_RESOLVE) ;
salist.len = 0 ;
/** main and backup can be different,so rebuild the list
* Also, a backup directory can be empty, check it first */
r = scan_mode(src_resolve_backup,S_IFDIR) ;
if (r == 1)
{
if (!sastr_dir_get(&salist,src_resolve_backup,"",S_IFREG))
log_dieusys_nclean(LOG_EXIT_SYS,&cleanup,"get resolve file at: ",src_resolve_backup) ;
for (pos = 0 ; pos < salist.len ; pos += strlen(salist.s + pos) + 1)
{
char *name = salist.s + pos ;
if (!ss_resolve_read(&res,clone_backup,name))
log_dieusys_nclean(LOG_EXIT_SYS,&cleanup,"read resolve file of: ",src_resolve_backup,"/",name) ;
tree_modify_resolve(&res,SS_RESOLVE_ENUM_RUNAT,tree,clone.s) ;
tree_modify_resolve(&res,SS_RESOLVE_ENUM_TREENAME,tree,clone.s) ;
tree_modify_resolve(&res,SS_RESOLVE_ENUM_TREE,tree,clone.s) ;
tree_modify_resolve(&res,SS_RESOLVE_ENUM_STATE,tree,clone.s) ;
if (!ss_resolve_write(&res,clone_backup,name))
log_dieusys_nclean(LOG_EXIT_SYS,&cleanup,"write resolve file of: ",src_resolve,"/",name) ;
}
// rename db
char clone_db_backup_old[clone_backup_len + SS_DB_LEN + 1 + treelen + 1] ;
auto_strings(clone_db_backup_old,clone_backup,SS_DB,"/",tree) ;
char clone_db_backup_new[clone_backup_len + SS_DB_LEN + 1 + clone.len + 1] ;
auto_strings(clone_db_backup_new,clone_backup,SS_DB,"/",clone.s) ;
log_trace("rename tree backup db: ",tree," as: ",clone.s,"..." ) ;
if (rename(clone_db_backup_old,clone_db_backup_new) == -1)
log_dieusys_nclean(LOG_EXIT_SYS,&cleanup,"rename: ",clone_db_backup_old," to: ",clone_db_backup_new) ;
}
stralloc_free(&salist) ;
ss_resolve_free(&res) ;
log_info("Cloned successfully: ",tree," to ",clone.s) ;
}
if (after_tree)
{
stralloc contents = STRALLOC_ZERO ;
stralloc tmp = STRALLOC_ZERO ;
int befirst = obstr_equal(tree,after_tree) ;
size_t baselen = base.len, pos = 0 ;
char ste[baselen + SS_SYSTEM_LEN + 1] ;
auto_strings(ste,base.s,SS_SYSTEM) ;
int enabled = tree_cmd_state(VERBOSITY,"-s",tree) ;
if (enabled != 1)
log_die(LOG_EXIT_USER,"tree: ",tree," is not enabled") ;
enabled = tree_cmd_state(VERBOSITY,"-s",after_tree) ;
if (enabled != 1)
log_die(LOG_EXIT_USER,"tree: ",after_tree," is not enabled") ;
r = tree_cmd_state(VERBOSITY,"-d",tree) ;
if (!r) log_dieusys(LOG_EXIT_SYS,"disable: ",tree," at: ",ste,SS_STATE) ;
r = file_readputsa(&tmp,ste,SS_STATE + 1) ;
if(!r) log_dieusys(LOG_EXIT_SYS,"open: ", ste,SS_STATE) ;
/** if you have only one tree enabled, the state file will be
* empty because we disable it before reading the file(see line 803).
* This will make a crash at sastr_? call.
* So write directly the name of the tree at state file. */
if (tmp.len)
{
if (!sastr_rebuild_in_oneline(&tmp) ||
!sastr_clean_element(&tmp))
log_dieu(LOG_EXIT_SYS,"rebuild state list") ;
for (pos = 0 ;pos < tmp.len; pos += strlen(tmp.s + pos) + 1)
{
char *name = tmp.s + pos ;
/* e.g 66-tree -S root root -> meaning root need to
* be the first to start */
if ((befirst) && (pos == 0))
{
if (!auto_stra(&contents,tree,"\n"))
log_dieusys(LOG_EXIT_SYS,"stralloc") ;
}
if (!auto_stra(&contents,name,"\n"))
log_dieusys(LOG_EXIT_SYS,"stralloc") ;
if (obstr_equal(name,after_tree))
{
if (!auto_stra(&contents,tree,"\n"))
log_dieusys(LOG_EXIT_SYS,"stralloc") ;
}
}
}
else
{
if (!auto_stra(&contents,tree,"\n"))
log_dieusys(LOG_EXIT_SYS,"stralloc") ;
}
if (!file_write_unsafe(ste,SS_STATE + 1,contents.s,contents.len))
log_dieusys(LOG_EXIT_ZERO,"write: ",ste,SS_STATE) ;
ssexec_t info = SSEXEC_ZERO ;
log_info("Ordered successfully: ",tree," starts after tree: ",after_tree) ;
}
info.prog = PROG ;
info.help = help_tree ;
info.usage = usage_tree ;
stralloc_free(&base) ;
stralloc_free(&dstree) ;
stralloc_free(&clone) ;
info.skip_opt_tree = 1 ;
return 0 ;
return ssexec_main(argc,argv,envp,&ssexec_tree,&info) ;
}
......@@ -40,7 +40,7 @@ struct ssexec_s
uint8_t opt_timeout ;
uint8_t opt_color ;
// skip option definition 0->no,1-yes
uint8_t skip_opt_tree ; // tree,treename, treeallow and the permissions for the tree will be not set
uint8_t skip_opt_tree ; // tree,treename, treeallow will not be set. Also, trees permissions is not checked.
} ;
#define SSEXEC_ZERO { .base = STRALLOC_ZERO , \
......@@ -78,6 +78,7 @@ extern ssexec_func_t ssexec_svctl ;
extern ssexec_func_t ssexec_dbctl ;
extern ssexec_func_t ssexec_env ;
extern ssexec_func_t ssexec_all ;
extern ssexec_func_t ssexec_tree ;
extern char const *usage_enable ;
extern char const *help_enable ;
......@@ -97,6 +98,8 @@ extern char const *usage_env ;
extern char const *help_env ;
extern char const *usage_all ;
extern char const *help_all ;
extern char const *usage_tree ;
extern char const *help_tree ;
#define OPTS_INIT "cdb"
#define OPTS_INIT_LEN (sizeof OPTS_INIT - 1)
......@@ -116,7 +119,11 @@ extern char const *help_all ;
#define OPTS_ENV_LEN (sizeof OPTS_ENV - 1)
#define OPTS_ALL "f"
#define OPTS_ALL_LEN (sizeof OPTS_ALL - 1)
#define OPTS_TREE "na:d:cS:EDRC:"
#define OPTS_TREE_LEN (sizeof OPTS_TREE - 1)
extern int ssexec_main(int argc, char const *const *argv, char const *const *envp,ssexec_func_t *func,ssexec_t *info) ;
extern void ssexec_set_info(ssexec_t *info) ;
extern int ssexec_set_treeinfo(ssexec_t *info) ;
#endif
......@@ -154,3 +154,28 @@ char const *help_all =
" -t: tree to use\n"
" -f: fork the process\n"
;
char const *usage_tree = "66-tree [ -h ] [ -z ] [ -v verbosity ] [ -n|R ] [ -a|d ] [ -c ] [ -o depends=:requiredby= ] [ -E|D ] [ -C clone ] tree" ;
char const *help_tree =
"\n"
"options :\n"
" -h: print this help\n"
" -z: use color\n"
" -v: increase/decrease verbosity\n"
" -n: create a new empty tree\n"
" -R: remove the tree\n"
" -a: allow user(s) at tree\n"
" -d: deny user(s) at tree\n"
" -c: set tree as default\n"
" -o: colon separated list of dependencies\n"
" -E: enable the tree\n"
" -D: disable the tree\n"
" -C: clone the tree\n"
"\n"
"valid fields for -o options are:\n"
"\n"
" depends=: comma separated list of dependencies for tree\n"
" requiredby=: comma separated list of trees required by tree\n"
;
This diff is collapsed.
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment