Skip to content
Snippets Groups Projects
sanitize_system.c 4.92 KiB
/*
 * sanitize_system.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 <sys/types.h>
#include <unistd.h>
#include <string.h>

#include <oblibs/log.h>
#include <oblibs/string.h>
#include <oblibs/types.h>
#include <oblibs/directory.h>

#include <skalibs/stralloc.h>

#include <66/ssexec.h>
#include <66/constants.h>
#include <66/sanitize.h>
#include <66/utils.h>
#include <66/state.h>
#include <66/tree.h>

static char const *cleantree = 0 ;

static void cleanup(void)
{
    log_flow() ;

    if (cleantree) {

        log_trace("removing: ",cleantree,"...") ;
        if (!dir_rm_rf(cleantree))
            log_dieusys(LOG_EXIT_SYS, "remove: ", cleantree) ;
    }
}

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_check(char *dst)
{
    log_flow() ;

    int r = scan_mode(dst,S_IFDIR) ;

    if (r == -1)
        log_diesys_nclean(LOG_EXIT_SYS, &cleanup, "conflicting format for: ", dst) ;

    if (!r)
        auto_dir(dst,0755) ;
}

static void inline auto_stralloc(stralloc *sa,char const *str)
{
    log_flow() ;

    if (!auto_stra(sa,str))
        log_die_nomem("stralloc") ;
}

int sanitize_system(ssexec_t *info)
{
    log_flow() ;

    log_trace("sanitize system..." ) ;

    /** set cleanup */
    cleantree = info->tree.s ;

    int r ;
    size_t baselen = info->base.len ;
    uid_t log_uid ;
    gid_t log_gid ;
    char dst[baselen + SS_SYSTEM_LEN + SS_RESOLVE_LEN + 1 + SS_SERVICE_LEN + 1] ;
    auto_strings(dst,info->base.s, SS_SYSTEM) ;

    /** base is /var/lib/66 or $HOME/.66*/
    /** this verification is made in case of
     * first use of 66-*** tools */
    auto_check(dst) ;
    /** create extra directory for service part */
    if (!info->owner) {

        auto_check(SS_LOGGER_SYSDIR) ;

        if (!youruid(&log_uid,SS_LOGGER_RUNNER) ||
        !yourgid(&log_gid,log_uid))
            log_dieusys(LOG_EXIT_SYS,"get uid and gid of: ",SS_LOGGER_RUNNER) ;

        if (chown(SS_LOGGER_SYSDIR,log_uid,log_gid) == -1)
            log_dieusys(LOG_EXIT_SYS,"chown: ",SS_LOGGER_RUNNER) ;

        auto_check(SS_SERVICE_SYSDIR) ;
        auto_check(SS_SERVICE_ADMDIR) ;
        auto_check(SS_SERVICE_ADMCONFDIR) ;
        auto_check(SS_MODULE_SYSDIR) ;
        auto_check(SS_MODULE_ADMDIR) ;
        auto_check(SS_SCRIPT_SYSDIR) ;
        auto_check(SS_SEED_ADMDIR) ;
        auto_check(SS_SEED_SYSDIR) ;

    } else {

        size_t extralen ;
        stralloc extra = STRALLOC_ZERO ;
        if (!set_ownerhome(&extra,info->owner))
            log_dieusys(LOG_EXIT_SYS,"set home directory") ;

        extralen = extra.len ;
        if (!auto_stra(&extra, SS_USER_DIR, SS_SYSTEM))
            log_die_nomem("stralloc") ;
        auto_check(extra.s) ;

        extra.len = extralen ;
        auto_stralloc(&extra,SS_LOGGER_USERDIR) ;
        auto_check(extra.s) ;

        extra.len = extralen ;
        auto_stralloc(&extra,SS_SERVICE_USERDIR) ;
        auto_check(extra.s) ;

        extra.len = extralen ;
        auto_stralloc(&extra,SS_SERVICE_USERCONFDIR) ;
        auto_check(extra.s) ;

        extra.len = extralen ;
        auto_stralloc(&extra,SS_MODULE_USERDIR) ;
        auto_check(extra.s) ;

        extra.len = extralen ;
        auto_stralloc(&extra,SS_SCRIPT_USERDIR) ;
        auto_check(extra.s) ;

        extra.len = extralen ;
        auto_stralloc(&extra,SS_SEED_USERDIR) ;
        auto_check(extra.s) ;

        stralloc_free(&extra) ;
    }

    auto_strings(dst, info->base.s, SS_SYSTEM, SS_RESOLVE, "/", SS_SERVICE) ;
    auto_check(dst) ;

    auto_strings(dst + baselen + SS_SYSTEM_LEN + SS_RESOLVE_LEN, SS_MASTER) ;

    if (!scan_mode(dst, S_IFREG))
        if (!tree_resolve_master_create(info->base.s, info->owner))
            log_dieu(LOG_EXIT_SYS, "write Master resolve file of trees") ;

    auto_strings(dst + baselen, SS_TREE_CURRENT) ;
    auto_check(dst) ;

    /** create the default tree if it doesn't exist yet */
    r = tree_isvalid(info->base.s, SS_DEFAULT_TREENAME) ;
    if (r < 0)
        log_dieu(LOG_EXIT_SYS, "check validity of tree: ", SS_DEFAULT_TREENAME) ;

    if (!r) {

        int nargc = 4 ;
        char const *newargv[nargc] ;
        unsigned int m = 0 ;

        newargv[m++] = "tree" ;
        newargv[m++] = "-E" ;
        newargv[m++] = SS_DEFAULT_TREENAME ;
        newargv[m++] = 0 ;

        char *prog = PROG ;
        PROG = "tree" ;

        if (ssexec_tree(nargc, newargv, info))
            log_dieu(LOG_EXIT_SYS, "create tree: ", SS_DEFAULT_TREENAME) ;

        PROG = prog ;
    }

    return 1 ;
}