diff --git a/src/include/66/parse.h b/src/include/66/parse.h index de23ecb5295ac67d2f9866c82288b2bd67fa3932..5860ed29ed94c90b6fa5fd7b4e8869a10cdfb232 100644 --- a/src/include/66/parse.h +++ b/src/include/66/parse.h @@ -42,6 +42,7 @@ extern parse_mill_t MILL_GET_VALUE ; /** freed and cleanup*/ extern void ssexec_enable_cleanup(void) ; +extern void parse_cleanup(resolve_service_t *res, char const *tmpdir, uint8_t force) ; /** main */ extern void start_parser(char const *sv, ssexec_t *info, uint8_t disable_module, char const *directory_forced) ; diff --git a/src/include/66/sanitize.h b/src/include/66/sanitize.h index 121c96dee1f0dddfcc459b97ba174694f95526ea..a166e8f22ca61d8262b9766c085552b13359c237 100644 --- a/src/include/66/sanitize.h +++ b/src/include/66/sanitize.h @@ -28,6 +28,9 @@ extern void sanitize_livestate(resolve_service_t *res) ; extern void sanitize_scandir(resolve_service_t *res) ; extern void sanitize_init(unsigned int *alist, unsigned int alen, graph_t *g, resolve_service_t *ares, unsigned int areslen) ; extern void sanitize_graph(ssexec_t *info) ; -extern void sanitize_write(resolve_service_t *res, uint8_t force) ; +/** @Return 0 the service is already written + * @Return 1 the service will be overwritten + * die on system error */ +extern int sanitize_write(resolve_service_t *res, uint8_t force) ; #endif diff --git a/src/include/66/write.h b/src/include/66/write.h index e20b3cf9c2b8cd6d84b1ab7026d0c6b6ddbe53b3..cca7812b14593d2b2fbee4dfb634b95e3c9a922a 100644 --- a/src/include/66/write.h +++ b/src/include/66/write.h @@ -18,13 +18,16 @@ #include <stdint.h> #include <66/service.h> -extern void write_services(resolve_service_t *res, char const *workdir) ; -extern void write_classic(resolve_service_t *res, char const *dst) ; -extern void write_common(resolve_service_t *res, char const *dst) ; -extern void write_environ(char const *name, char const *contents, char const *dst) ; -extern void write_execute_scripts(char const *file, char const *contents, char const *dst) ; -extern void write_logger(resolve_service_t *res, char const *destination) ; -extern void write_oneshot(resolve_service_t *res, char const *dst) ; -extern void write_uint(char const *dst, char const *name, uint32_t ui) ; +extern void write_services(resolve_service_t *res, char const *dst, uint8_t force) ; +extern void write_classic(resolve_service_t *res, char const *dst, uint8_t force) ; +extern void write_oneshot(resolve_service_t *res, char const *dst, uint8_t force) ; +extern void write_logger(resolve_service_t *res, char const *dst, uint8_t force) ; + +extern int write_common(resolve_service_t *res, char const *dst) ; +extern int write_execute_scripts(char const *file, char const *contents, char const *dst) ; +extern int write_uint(char const *dst, char const *name, uint32_t ui) ; +extern int write_environ(char const *name, char const *contents, char const *dst) ; + +extern void write_make_symlink(resolve_service_t *res) ; #endif diff --git a/src/lib66/parse/parse_service.c b/src/lib66/parse/parse_service.c index 18536647b5a2391f890b9cf7e49280187794d35c..d1d21bad66eab2875ba1c70c85d73e8eeca8ce46 100644 --- a/src/lib66/parse/parse_service.c +++ b/src/lib66/parse/parse_service.c @@ -14,16 +14,15 @@ #include <string.h> #include <stdint.h> -#include <stdint.h> - -#include <stddef.h> +#include <stdlib.h> #include <oblibs/log.h> #include <oblibs/string.h> #include <oblibs/sastr.h> #include <oblibs/types.h> +#include <oblibs/directory.h> -#include <skalibs/genalloc.h> +#include <skalibs/djbunix.h> #include <66/enum.h> #include <66/constants.h> @@ -58,14 +57,120 @@ parse_mill_t MILL_GET_VALUE = \ .skip = " \t\r", .skiplen = 3, .forceskip = 1, \ .inner.debug = "get_value" } ; +void parse_cleanup(resolve_service_t *res, char const *tmpdir, uint8_t force) +{ + log_flow() ; + + size_t namelen = strlen(res->sa.s + res->name), homelen = strlen(res->sa.s + res->path.home) ; + char dir[homelen + SS_SYSTEM_LEN + SS_SERVICE_LEN + SS_SVC_LEN + 1 + namelen + 1] ; + + if (!dir_rm_rf(tmpdir)) + log_warnu("remove temporary directory: ", tmpdir) ; + + if (!force) { + + auto_strings(dir, res->sa.s + res->path.home, SS_SYSTEM, SS_SERVICE, SS_SVC, "/", res->sa.s + res->name) ; + + if (!dir_rm_rf(dir)) + log_warnu("remove service directory: ", dir) ; + } +} + +static void parse_copy_online(char const *dst, char const *src, resolve_service_t *res, uint8_t force) +{ + log_flow() ; + + size_t pos = 0 ; + stralloc sa = STRALLOC_ZERO ; + size_t srclen = strlen(src) ; + + if (!access(dst, F_OK)) { + + char const *exclude[6] = { SS_EVENTDIR + 1, SS_SUPERVISEDIR + 1, SS_SCANDIR, SS_STATE + 1, SS_RESOLVE + 1, 0 } ; + if (!sastr_dir_get_recursive(&sa, dst, exclude, S_IFDIR|S_IFREG, 1)) { + parse_cleanup(res, src, force) ; + stralloc_free(&sa) ; + log_dieusys(LOG_EXIT_SYS, "get file list of: ", dst) ; + } + + FOREACH_SASTR(&sa, pos) { + + char base[strlen(sa.s + pos) + 1] ; + if (!ob_basename(base, sa.s + pos)) { + parse_cleanup(res, src, force) ; + stralloc_free(&sa) ; + log_dieusys(LOG_EXIT_SYS, "basename of: ", sa.s + pos) ; + } + + char element[srclen + 1 + strlen(base) + 1] ; + + auto_strings(element, src, "/", base) ; + + if (access(element, F_OK) < 0) { + log_trace("remove element: ", sa.s + pos) ; + if (!dir_rm_rf(sa.s + pos)) { + parse_cleanup(res, src, force) ; + stralloc_free(&sa) ; + log_dieusys(LOG_EXIT_SYS, "remove element: ", sa.s + pos) ; + } + } + } + } + + stralloc_free(&sa) ; + + if (access(dst, F_OK) < 0) { + + log_trace("create directory: ", dst) ; + if (!dir_create_parent(dst, 0755)) { + parse_cleanup(res, src, force) ; + stralloc_free(&sa) ; + log_dieusys(LOG_EXIT_SYS, "create directory: ", dst) ; + } + } + + log_trace("copy:", src, " to: ", dst) ; + if (!hiercopy(src, dst)) { + parse_cleanup(res, src, force) ; + stralloc_free(&sa) ; + log_dieusys(LOG_EXIT_SYS, "copy: ", src, " to: ", dst) ; + } +} + +static void parse_write_state(resolve_service_t *res, char const *dst, uint8_t force) +{ + log_flow() ; + ss_state_t sta = STATE_ZERO ; + + if (state_check(res)) { + + if (!state_read(&sta, res)) { + parse_cleanup(res, dst, force) ; + log_dieu(LOG_EXIT_SYS, "read state file of: ", res->sa.s + res->name) ; + } + } + + state_set_flag(&sta, STATE_FLAGS_TOINIT, STATE_FLAGS_TRUE) ; + state_set_flag(&sta, STATE_FLAGS_TOPARSE, STATE_FLAGS_FALSE) ; + state_set_flag(&sta, STATE_FLAGS_ISPARSED, STATE_FLAGS_TRUE) ; + state_set_flag(&sta, STATE_FLAGS_ISEARLIER, res->earlier ? STATE_FLAGS_TRUE : STATE_FLAGS_FALSE) ; + state_set_flag(&sta, STATE_FLAGS_ISDOWNFILE, res->execute.down ? STATE_FLAGS_TRUE : STATE_FLAGS_FALSE) ; + + if (!state_write_tmp(&sta, dst)) { + parse_cleanup(res, dst, force) ; + log_dieu(LOG_EXIT_SYS, "write state file of: ", res->sa.s + res->name) ; + } +} + void parse_service(char const *sv, ssexec_t *info, uint8_t force, uint8_t conf) { log_flow(); int r ; unsigned int areslen = 0, count = 0, pos = 0 ; + uint8_t rforce = 0 ; resolve_service_t ares[SS_MAX_SERVICE] ; - ss_state_t sta = STATE_ZERO ; + stralloc sa = STRALLOC_ZERO ; char main[strlen(sv) + 1] ; if (!ob_basename(main, sv)) @@ -84,29 +189,44 @@ void parse_service(char const *sv, ssexec_t *info, uint8_t force, uint8_t conf) for (pos = 0 ; pos < areslen ; pos++) { - sanitize_write(&ares[pos], force) ; + sa.len = 0 ; + /** be paranoid */ + rforce = 0 ; + size_t namelen = strlen(ares[pos].sa.s + ares[pos].name), homelen = strlen(ares[pos].sa.s + ares[pos].path.home) ; - write_services(&ares[pos], ares[pos].sa.s + ares[pos].path.servicedir) ; + char servicedir[homelen + SS_SYSTEM_LEN + SS_SERVICE_LEN + SS_SVC_LEN + 1 + namelen + 1] ; - if (state_check(&ares[pos])) { + auto_strings(servicedir, ares[pos].sa.s + ares[pos].path.home, SS_SYSTEM, SS_SERVICE, SS_SVC, "/", ares[pos].sa.s + ares[pos].name) ; - if (!state_read(&sta, &ares[pos])) - log_dieu(LOG_EXIT_SYS, "read state file of: ", ares[pos].sa.s + ares[pos].name) ; - } + if (sanitize_write(&ares[pos], force)) + rforce = 1 ; - state_set_flag(&sta, STATE_FLAGS_TOINIT, STATE_FLAGS_TRUE) ; - state_set_flag(&sta, STATE_FLAGS_TOPARSE, STATE_FLAGS_FALSE) ; - state_set_flag(&sta, STATE_FLAGS_ISPARSED, STATE_FLAGS_TRUE) ; - state_set_flag(&sta, STATE_FLAGS_ISEARLIER, ares[pos].earlier ? STATE_FLAGS_TRUE : STATE_FLAGS_FALSE) ; - state_set_flag(&sta, STATE_FLAGS_ISDOWNFILE, ares[pos].execute.down ? STATE_FLAGS_TRUE : STATE_FLAGS_FALSE) ; + if (!auto_stra(&sa, "/tmp/", ares[pos].sa.s + ares[pos].name, ":XXXXXX")) + log_die_nomem("stralloc") ; - if (!state_write(&sta, &ares[pos])) - log_dieu(LOG_EXIT_SYS, "write state file of: ", ares[pos].sa.s + ares[pos].name) ; + if (!mkdtemp(sa.s)) + log_dieusys(LOG_EXIT_SYS, "create temporary directory") ; + + write_services(&ares[pos], sa.s, rforce) ; + + parse_write_state(&ares[pos], sa.s, rforce) ; + + service_resolve_write_tmp(&ares[pos], sa.s, rforce) ; + + parse_copy_online(servicedir, sa.s, &ares[pos], rforce) ; + + /** do not die here, just warn the user */ + log_trace("remove temporary directory: ", sa.s) ; + if (!dir_rm_rf(sa.s)) + log_warnu("remove temporary directory: ", sa.s) ; tree_service_add(info->base.s, ares[pos].sa.s + ares[pos].treename, ares[pos].sa.s + ares[pos].name) ; + write_make_symlink(&ares[pos]) ; + log_info("Parsed successfully: ", ares[pos].sa.s + ares[pos].name, " at tree: ", ares[pos].sa.s + ares[pos].treename) ; } service_resolve_array_free(ares, areslen) ; + stralloc_free(&sa) ; } diff --git a/src/lib66/sanitize/sanitize_write.c b/src/lib66/sanitize/sanitize_write.c index 4f685511acf15622b96041df2ca118e7499353e5..857851999d230b9242e43489cee8d6debd8de11a 100644 --- a/src/lib66/sanitize/sanitize_write.c +++ b/src/lib66/sanitize/sanitize_write.c @@ -35,25 +35,6 @@ #include <66/state.h> #include <66/svc.h> -static void remove_dir(char const *path, char const *name) -{ - size_t pos = 0 ; - stralloc sa = STRALLOC_ZERO ; - - char const *exclude[5] = { "event", "supervise", "scandir", 0 } ; - if (!sastr_dir_get_recursive(&sa, path, exclude, S_IFDIR|S_IFREG, 1)) - log_dieusys(LOG_EXIT_SYS, "get list of running services") ; - - FOREACH_SASTR(&sa, pos) { - log_trace("remove element: ", sa.s + pos, " from: ", name, " service directory") ; - - if (!dir_rm_rf(sa.s + pos)) - log_dieusys(LOG_EXIT_SYS, "remove: ", sa.s + pos) ; - } - - stralloc_free(&sa) ; -} - static void resolve_compare(resolve_service_t *res) { log_flow() ; @@ -86,11 +67,11 @@ static void resolve_compare(resolve_service_t *res) resolve_free(wres) ; } -static int delete(resolve_service_t *res, uint8_t force) +static int preserve(resolve_service_t *res, uint8_t force) { log_flow() ; - int r ; + int r = 0 ; char dir[strlen(res->sa.s + res->path.servicedir) + 1] ; @@ -98,96 +79,31 @@ static int delete(resolve_service_t *res, uint8_t force) r = scan_mode(dir, S_IFDIR) ; if (r < 0) - log_die(LOG_EXIT_SYS, "unvalid source: ", dir) ; + log_diesys(LOG_EXIT_SYS, "unvalid source: ", dir) ; if (r) { if (force) { - stralloc sa = STRALLOC_ZERO ; - ss_state_t sta = STATE_ZERO ; - - /** Keep the current symlink target. */ - if (sareadlink(&sa, dir) < 0 || - !stralloc_0(&sa)) - log_dieusys(LOG_EXIT_SYS, "readlink: ", dir) ; - resolve_compare(res) ; - if (state_check(res)) { - - if (!state_read(&sta, res)) - log_dieu(LOG_EXIT_SYS, "read state file of: ", res->sa.s + res->name) ; - } - - remove_dir(sa.s, res->sa.s + res->name) ; - - if (!state_write(&sta, res)) - log_dieu(LOG_EXIT_SYS, "write state file of: ", res->sa.s + res->name) ; - - stralloc_free(&sa) ; - } else /** This info should never be executed as long as the parse_frontend * check already verifies the service and prevents reaching this point if !force. */ - log_info_return(2, "Ignoring: ", res->sa.s + res->name, " -- service already written") ; + log_info_return(0, "Ignoring: ", res->sa.s + res->name, " -- service already written") ; } - return 1 ; + return r ; } -static void make_servicedir(resolve_service_t *res) +int sanitize_write(resolve_service_t *res, uint8_t force) { log_flow() ; int r ; - char *name = res->sa.s + res->name ; - size_t namelen = strlen(name), homelen = strlen(res->sa.s + res->path.home) ; - char sym[homelen + SS_SYSTEM_LEN + SS_RESOLVE_LEN + SS_SERVICE_LEN + 1 + namelen + 1] ; - char dst[homelen + SS_SYSTEM_LEN + SS_SERVICE_LEN + SS_SVC_LEN + SS_RESOLVE_LEN + 1 + namelen + 1] ; - - auto_strings(sym, res->sa.s + res->path.home, SS_SYSTEM, SS_RESOLVE, SS_SERVICE, "/", name) ; - - auto_strings(dst, res->sa.s + res->path.home, SS_SYSTEM, SS_SERVICE, SS_SVC, "/", name) ; - - struct stat st ; - r = lstat(sym, &st) ; - if (r < 0) { - - if (errno != ENOENT) { - - log_dieusys(LOG_EXIT_SYS, "lstat: ", sym) ; - - } else { - - log_trace("symlink: ", sym, " to: ", dst) ; - r = symlink(dst, sym) ; - if (r < 0 && errno != EEXIST) - log_dieusys(LOG_EXIT_SYS, "point symlink: ", sym, " to: ", dst) ; - } - } - - auto_strings(dst + homelen + SS_SYSTEM_LEN + SS_SERVICE_LEN + SS_SVC_LEN + 1 + namelen, SS_RESOLVE) ; - - r = scan_mode(dst, S_IFDIR) ; - if (r < 0) - log_die(LOG_EXIT_SYS, "unvalid source: ", dst) ; - - log_trace("create directory: ", dst) ; - if (!dir_create_parent(dst, 0755)) - log_dieusys(LOG_EXIT_SYS, "create directory: ", dst) ; -} - -void sanitize_write(resolve_service_t *res, uint8_t force) -{ - log_flow() ; - - if (delete(res, force) > 1) - return ; - make_servicedir(res) ; + r = preserve(res, force) ; - if (!service_resolve_write(res)) - log_dieu(LOG_EXIT_SYS, "write resolve file of service: ", res->sa.s + res->name) ; + return r ; } diff --git a/src/lib66/write/deps-lib/deps b/src/lib66/write/deps-lib/deps index d07d1f64466ea03a219318abadb3e78242d979e9..8c3cc1baec909e0c322fe12a5e86817a2d9eecc7 100644 --- a/src/lib66/write/deps-lib/deps +++ b/src/lib66/write/deps-lib/deps @@ -3,6 +3,7 @@ write_common.o write_environ.o write_execute_scripts.o write_logger.o +write_make_symlink.o write_oneshot.o write_service.o write_uint.o diff --git a/src/lib66/write/write_classic.c b/src/lib66/write/write_classic.c index 84e32b0c4e43933b5c19f041615b87e3485909a4..f0de0219dced9574f5c6935fd26751c5762d5745 100644 --- a/src/lib66/write/write_classic.c +++ b/src/lib66/write/write_classic.c @@ -19,27 +19,45 @@ #include <66/service.h> #include <66/write.h> +#include <66/parse.h> /* dst e.g. /var/lib/66/system/service/svc/<name> */ -void write_classic(resolve_service_t *res, char const *dst) +void write_classic(resolve_service_t *res, char const *dst, uint8_t force) { log_flow() ; /**notification,timeout, ... */ - write_common(res, dst) ; + if (!write_common(res, dst)) { + parse_cleanup(res, dst, force) ; + log_dieu(LOG_EXIT_SYS, "write common file of: ", res->sa.s + res->name) ; + } /** run file */ - write_execute_scripts("run", res->sa.s + res->execute.run.run, dst) ; + if (!write_execute_scripts("run", res->sa.s + res->execute.run.run, dst)) { + parse_cleanup(res, dst, force) ; + log_dieu(LOG_EXIT_SYS, "write execute script of: ", res->sa.s + res->name) ; + } /** finish file */ - if (res->execute.finish.run_user) - write_execute_scripts("finish", res->sa.s + res->execute.finish.run, dst) ; + if (res->execute.finish.run_user) { + if (!write_execute_scripts("finish", res->sa.s + res->execute.finish.run, dst)) { + parse_cleanup(res, dst, force) ; + log_dieu(LOG_EXIT_SYS, "write execute script of: ", res->sa.s + res->name) ; + } + } /** run.user file */ - write_execute_scripts( "run.user", res->sa.s + res->execute.run.run_user, dst) ; + if (!write_execute_scripts( "run.user", res->sa.s + res->execute.run.run_user, dst)) { + parse_cleanup(res, dst, force) ; + log_dieu(LOG_EXIT_SYS, "write execute script of: ", res->sa.s + res->name) ; + } /** finish.user file */ - if (res->execute.finish.run_user) - write_execute_scripts("finish.user", res->sa.s + res->execute.finish.run_user, dst) ; + if (res->execute.finish.run_user) { + if (!write_execute_scripts("finish.user", res->sa.s + res->execute.finish.run_user, dst)) { + parse_cleanup(res, dst, force) ; + log_dieu(LOG_EXIT_SYS, "write execute script of: ", res->sa.s + res->name) ; + } + } } diff --git a/src/lib66/write/write_common.c b/src/lib66/write/write_common.c index 12f760a99435ef7d465cbe14469c63acaaeb3436..ee2c8c3dc8ae033eb546bebd83b49a392cad9ba5 100644 --- a/src/lib66/write/write_common.c +++ b/src/lib66/write/write_common.c @@ -14,6 +14,7 @@ #include <string.h> +#include <stdlib.h> #include <errno.h> #include <oblibs/log.h> @@ -32,7 +33,7 @@ #include <66/environ.h> #include <66/enum.h> -void write_common(resolve_service_t *res, char const *dst) +int write_common(resolve_service_t *res, char const *dst) { log_flow() ; @@ -40,34 +41,38 @@ void write_common(resolve_service_t *res, char const *dst) if (res->execute.down) { log_trace("create file: ", dst, "/down") ; if (!file_create_empty(dst, "down", 0644)) - log_dieusys(LOG_EXIT_SYS, "create down file") ; + log_warnusys_return(LOG_EXIT_ZERO, "create down file") ; } /** notification-fd */ if (res->notify) - write_uint(dst, SS_NOTIFICATION, res->notify) ; + if (!write_uint(dst, SS_NOTIFICATION, res->notify)) + log_warnusys_return(LOG_EXIT_ZERO, "write uint file", SS_NOTIFICATION) ; /** timeout family * * Only write timeout file for classic service. - * All others services are read directly through - * the resolve file at start process. */ + * S6-supervise need it otherwise it's read directly + * from the resolve file at start process. */ if (res->execute.timeout.kill) - write_uint(dst, "timeout-kill", res->execute.timeout.kill) ; + if (!write_uint(dst, "timeout-kill", res->execute.timeout.kill)) + log_warnusys_return(LOG_EXIT_ZERO, "write uint file timeout-kill") ; if (res->execute.timeout.finish) - write_uint(dst, "timeout-finish", res->execute.timeout.finish) ; + if (!write_uint(dst, "timeout-finish", res->execute.timeout.finish)) + log_warnusys_return(LOG_EXIT_ZERO, "write uint file timeout-finish") ; /** max-death-tally */ if (res->maxdeath) - write_uint(dst, SS_MAXDEATHTALLY, res->maxdeath) ; + if (!write_uint(dst, SS_MAXDEATHTALLY, res->maxdeath)) + log_warnusys_return(LOG_EXIT_ZERO, "write uint file", SS_MAXDEATHTALLY) ; /** down-signal */ if (res->execute.downsignal) - write_uint(dst, "down-signal", res->execute.downsignal) ; + if (!write_uint(dst, "down-signal", res->execute.downsignal)) + log_warnusys_return(LOG_EXIT_ZERO, "write uint file down-signal") ; - /** environment - * environment for module is already written by the parse_module() function */ + /** environment for module is already written by the parse_module() function */ if (res->environ.env && res->type != TYPE_MODULE) { stralloc dst = STRALLOC_ZERO ; @@ -76,9 +81,10 @@ void write_common(resolve_service_t *res, char const *dst) auto_strings(name, ".", res->sa.s + res->name) ; if (!env_prepare_for_write(&dst, &contents, res)) - log_dieu(LOG_EXIT_SYS, "prepare environment for: ", res->sa.s + res->name) ; + log_warnusys_return(LOG_EXIT_ZERO, "prepare environment for: ", res->sa.s + res->name) ; - write_environ(name, contents.s, dst.s) ; + if (!write_environ(name, contents.s, dst.s)) + log_warnusys_return(LOG_EXIT_ZERO, "write environment for: ", res->sa.s + res->name) ; stralloc_free(&dst) ; stralloc_free(&contents) ; @@ -91,28 +97,71 @@ void write_common(resolve_service_t *res, char const *dst) size_t pos = 0 ; stralloc sa = STRALLOC_ZERO ; char *src = res->sa.s + res->path.frontend ; - size_t srclen = strlen(src) ; + size_t srclen = strlen(src), dstlen = strlen(dst) ; + char basedir[srclen + 1] ; + + if (!ob_dirname(basedir, src)) + log_warnusys_return(LOG_EXIT_ZERO, "get dirname of: ", src) ; + if (!sastr_clean_string(&sa, res->sa.s + res->hiercopy)) - log_dieu(LOG_EXIT_SYS, "clean string") ; + log_warnusys_return(LOG_EXIT_ZERO, "clean string") ; FOREACH_SASTR(&sa, pos) { char *what = sa.s + pos ; + int fd ; + size_t wlen = strlen(what) ; char tmp[SS_MAX_PATH_LEN + 1] ; - char basedir[srclen + 1] ; + char dest[dstlen + 1 + wlen + 1]; + char basename[SS_MAX_PATH_LEN + 1] ; + + if (what [0] == '/' ) { + + auto_strings(tmp, what) ; + + if (!ob_basename(basename, what)) + log_warnusys_return(LOG_EXIT_ZERO, "get basename of: ", what) ; - if (!ob_dirname(basedir, src)) - log_dieu(LOG_EXIT_SYS, "get dirname of: ", src) ; + what = basename ; - if (what[0] == '.') { + } else if (what[0] == '.' && ((what[1] == '/') || (what[1] == '.' && what[2] == '/'))) { + /** distinction between .file and ./ ../ directory */ + char b[strlen(src) + 1] ; - if (!dir_beabsolute(tmp, src)) - log_dieusys(LOG_EXIT_SYS, "find absolute path of: ", what) ; + if (!ob_dirname(b, src)) + log_warnusys_return(LOG_EXIT_ZERO, "get dirname of: ", src) ; + + fd = open_read(".") ; + if (fd < 0) + log_warnusys_return(LOG_EXIT_ZERO, "open current directory") ; + + if (chdir(b) < 0) { + fd_close(fd) ; + log_warnusys_return(LOG_EXIT_ZERO, "change directory") ; + } + + char *p = realpath(what, tmp) ; + if (!p) { + fd_close(fd) ; + log_warnusys_return(LOG_EXIT_ZERO, "get absolute path of: ", what) ; + } + + if (fd_chdir(fd) < 0) { + fd_close(fd) ; + log_warnusys_return(LOG_EXIT_ZERO, "change directory") ; + } + + fd_close(fd) ; + + if (!ob_basename(basename, what)) + log_warnusys_return(LOG_EXIT_ZERO, "get basename of: ", what) ; + + what = basename ; } else { - auto_strings(tmp, what) ; + auto_strings(tmp, basedir, what) ; } r = scan_mode(tmp, S_IFDIR) ; @@ -120,16 +169,23 @@ void write_common(resolve_service_t *res, char const *dst) r = scan_mode(tmp, S_IFREG) ; if (!r) - log_dieusys(LOG_EXIT_SYS, "find: ", tmp) ; - if (r < 0) { + log_warnusys_return(LOG_EXIT_ZERO, "find: ", tmp) ; + else if (r < 0) { errno = ENOTSUP ; - log_diesys(LOG_EXIT_SYS, "invalid format of: ", tmp) ; + log_warnusys_return(LOG_EXIT_ZERO, "invalid format of: ", tmp) ; } } - log_trace("copy: ", tmp, " to: ", dst) ; - if (!hiercopy(tmp, dst)) - log_dieusys(LOG_EXIT_SYS, "copy: ", tmp, " to: ", dst) ; + auto_strings(dest, dst, "/", what) ; + + log_trace("copy: ", tmp, " to: ", dest) ; + if (!hiercopy(tmp, dest)) + log_warnusys_return(LOG_EXIT_ZERO, "copy: ", tmp, " to: ", dest) ; } + stralloc_free(&sa) ; } + + + + return 1 ; } diff --git a/src/lib66/write/write_environ.c b/src/lib66/write/write_environ.c index 46482ef33e3ce9a85c8c7ff4bde66de6148ba397..34d285767dccda2e513b0ed94dd44c98b87b1819 100644 --- a/src/lib66/write/write_environ.c +++ b/src/lib66/write/write_environ.c @@ -18,7 +18,7 @@ #include <oblibs/files.h> #include <oblibs/types.h> -void write_environ(char const *name, char const *contents, char const *dst) +int write_environ(char const *name, char const *contents, char const *dst) { log_flow() ; @@ -27,10 +27,12 @@ void write_environ(char const *name, char const *contents, char const *dst) r = scan_mode(dst,S_IFDIR) ; if (r < 0) - log_die(LOG_EXIT_SYS, "conflicting format of the environment directory: ", dst) ; + log_warn_return(LOG_EXIT_ZERO, "conflicting format of the environment directory: ", dst) ; else if (!r) - log_dieusys(LOG_EXIT_SYS, "find environment directory: ", dst) ; + log_warnusys_return(LOG_EXIT_ZERO, "find environment directory: ", dst) ; if (!file_write_unsafe(dst, name, contents, len)) - log_dieusys(LOG_EXIT_SYS, "create file: ", dst, "/", name) ; + log_warnusys_return(LOG_EXIT_ZERO, "create file: ", dst, "/", name) ; + + return 1 ; } diff --git a/src/lib66/write/write_execute_scripts.c b/src/lib66/write/write_execute_scripts.c index ffac88a1486a4d68cc49987b6b23a377a61b78f3..78c5d7b0e45fa7c26a123cf9c03b03e3ca1da61e 100644 --- a/src/lib66/write/write_execute_scripts.c +++ b/src/lib66/write/write_execute_scripts.c @@ -23,7 +23,7 @@ #define FAKELEN strlen(run) #endif -void write_execute_scripts(char const *file, char const *contents, char const *dst) +int write_execute_scripts(char const *file, char const *contents, char const *dst) { log_flow() ; @@ -37,8 +37,10 @@ void write_execute_scripts(char const *file, char const *contents, char const *d log_trace("create file: ", dst, "/", file) ; if (!file_write_unsafe(dst, file, run, FAKELEN)) - log_dieusys(LOG_EXIT_SYS, "write: ", dst, "/", file) ; + log_warnusys_return(LOG_EXIT_ZERO, "write: ", dst, "/", file) ; if (chmod(write, 0755) < 0) - log_dieusys(LOG_EXIT_SYS, "chmod", write) ; + log_warnusys_return(LOG_EXIT_ZERO, "chmod", write) ; + + return 1 ; } diff --git a/src/lib66/write/write_execute_scripts_user.c b/src/lib66/write/write_execute_scripts_user.c deleted file mode 100644 index 7ddd99a8928b069f368399fc35b12251272f7c30..0000000000000000000000000000000000000000 --- a/src/lib66/write/write_execute_scripts_user.c +++ /dev/null @@ -1,58 +0,0 @@ -/* - * write_execute_scripts_user.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 <sys/stat.h> - -#include <oblibs/log.h> -#include <oblibs/string.h> -#include <oblibs/files.h> - -#include <66/service.h> -#include <66/config.h> -#include <66/enum.h> - -#ifndef FAKELEN -#define FAKELEN strlen(run) -#endif - -void write_execute_scripts_user(resolve_service_t *res, resolve_service_addon_scripts_t *scripts, char const *file, char const *dst) -{ - log_flow() ; - - char *shebang = scripts->shebang ? res->sa.s + scripts->shebang : SS_EXECLINE_SHEBANGPREFIX "execlineb -P\n" ; - size_t shebanglen = strlen(shebang) ; - size_t scriptlen = strlen(res->sa.s + scripts->run_user) ; - char run[shebanglen + scriptlen + 4 + 1] ; - int build = !strcmp(res->sa.s + scripts->build, "custom") ? 1 : 0 ; - char write[strlen(dst) + 1 + strlen(file) + 1] ; - - auto_strings(write, dst, "/", file) ; - - auto_strings(run, "#!") ; - - if (build && scripts->shebang) - auto_strings(run + FAKELEN, res->sa.s + scripts->shebang, "\n") ; - else - auto_strings(run + FAKELEN, shebang, "\n") ; - - auto_strings(run + FAKELEN, res->sa.s + scripts->run_user, "\n") ; - - if (!file_write_unsafe(dst, file, run, FAKELEN)) - log_dieusys(LOG_EXIT_SYS, "write: ", dst, "/", file) ; - - if (chmod(write, 0755) < 0) - log_dieusys(LOG_EXIT_SYS, "chmod", write) ; - -} diff --git a/src/lib66/write/write_logger.c b/src/lib66/write/write_logger.c index f56e14bdf68df9ba076d2583d6898aa6f754a18b..d175fa217ae423f0716a4fe58298ee2170d02c91 100644 --- a/src/lib66/write/write_logger.c +++ b/src/lib66/write/write_logger.c @@ -31,6 +31,7 @@ #include <66/utils.h> #include <s6/config.h> #include <66/constants.h> +#include <66/parse.h> #include <s6/config.h> @@ -40,7 +41,7 @@ /** @destination -> /var/lib/66/system/service/svc/<name> */ -void write_logger(resolve_service_t *res, char const *destination) +void write_logger(resolve_service_t *res, char const *destination, uint8_t force) { log_flow() ; @@ -50,48 +51,72 @@ void write_logger(resolve_service_t *res, char const *destination) char *logrunner = res->execute.run.runas ? res->sa.s + res->execute.run.runas : SS_LOGGER_RUNNER ; - if (res->execute.timeout.kill) - write_uint(destination, "timeout-kill", res->execute.timeout.kill) ; + if (res->execute.timeout.kill) { + if (!write_uint(destination, "timeout-kill", res->execute.timeout.kill)) { + parse_cleanup(res, destination, force) ; + log_dieusys(LOG_EXIT_SYS, "write uint file timeout-kill") ; + } + } - if (res->execute.timeout.finish) - write_uint(destination, "timeout-finish", res->execute.timeout.finish) ; + if (res->execute.timeout.finish) { + if (!write_uint(destination, "timeout-finish", res->execute.timeout.finish)) { + parse_cleanup(res, destination, force) ; + log_dieusys(LOG_EXIT_SYS, "write uint file timeout-finish") ; + } + } /** notification */ - write_uint(destination, "notification-fd", 3) ; + if (!write_uint(destination, SS_NOTIFICATION, 3)) { + parse_cleanup(res, destination, force) ; + log_dieusys(LOG_EXIT_SYS, "write uint file ", SS_NOTIFICATION) ; + } /** log destination */ log_trace("create directory: ", res->sa.s + res->logger.destination) ; - if (!dir_create_parent(res->sa.s + res->logger.destination, 0755)) + if (!dir_create_parent(res->sa.s + res->logger.destination, 0755)) { + parse_cleanup(res, destination, force) ; log_dieusys(LOG_EXIT_SYS, "create directory: ", res->sa.s + res->logger.destination) ; + } if (!owner && ((res->execute.run.build == BUILD_AUTO) || (!res->execute.run.build))) { - if (!youruid(&log_uid, logrunner) || !yourgid(&log_gid, log_uid)) + if (!youruid(&log_uid, logrunner) || !yourgid(&log_gid, log_uid)) { + parse_cleanup(res, destination, force) ; log_dieusys(LOG_EXIT_SYS, "get uid and gid of: ", logrunner) ; - - if (chown(res->sa.s + res->logger.destination, log_uid, log_gid) == -1) + } + if (chown(res->sa.s + res->logger.destination, log_uid, log_gid) == -1) { + parse_cleanup(res, destination, force) ; log_dieusys(LOG_EXIT_SYS, "chown: ", res->sa.s + res->logger.destination) ; + } } char write[strlen(destination) + 10] ; /** run script */ log_trace("create file: ", destination, "/run") ; - if (!file_write_unsafe(destination, "run", res->sa.s + res->execute.run.run, strlen(res->sa.s + res->execute.run.run))) + if (!file_write_unsafe(destination, "run", res->sa.s + res->execute.run.run, strlen(res->sa.s + res->execute.run.run))) { + parse_cleanup(res, destination, force) ; log_dieusys(LOG_EXIT_SYS, "write: ", destination, "/run.user") ; + } auto_strings(write, destination, "/run") ; - if (chmod(write, 0755) < 0) + if (chmod(write, 0755) < 0) { + parse_cleanup(res, destination, force) ; log_dieusys(LOG_EXIT_SYS, "chmod", write) ; + } /** run.user script */ -log_trace("create file: ", destination, "/run.user") ; - if (!file_write_unsafe(destination, "run.user", res->sa.s + res->execute.run.run_user, strlen(res->sa.s + res->execute.run.run_user))) + log_trace("create file: ", destination, "/run.user") ; + if (!file_write_unsafe(destination, "run.user", res->sa.s + res->execute.run.run_user, strlen(res->sa.s + res->execute.run.run_user))) { + parse_cleanup(res, destination, force) ; log_dieusys(LOG_EXIT_SYS, "write: ", destination, "/run.user") ; + } auto_strings(write, destination, "/run.user") ; - if (chmod(write, 0755) < 0) + if (chmod(write, 0755) < 0) { + parse_cleanup(res, destination, force) ; log_dieusys(LOG_EXIT_SYS, "chmod", write) ; + } } diff --git a/src/lib66/write/write_oneshot.c b/src/lib66/write/write_oneshot.c index 071f50adb2c9ef6d28c35eaa3ac860dd8d4bad9d..d5789684db2ffc3a28e7ff1b13b5a327ca33e345 100644 --- a/src/lib66/write/write_oneshot.c +++ b/src/lib66/write/write_oneshot.c @@ -16,26 +16,43 @@ #include <66/service.h> #include <66/write.h> +#include <66/parse.h> -void write_oneshot(resolve_service_t *res, char const *dst) +void write_oneshot(resolve_service_t *res, char const *dst, uint8_t force) { log_flow() ; /**notification,timeout, ... */ - write_common(res, dst) ; + if (!write_common(res, dst)) { + parse_cleanup(res, dst, force) ; + log_dieu(LOG_EXIT_SYS, "write common file of: ", res->sa.s + res->name) ; + } /** run file */ - write_execute_scripts("up", res->sa.s + res->execute.run.run, dst) ; + if (!write_execute_scripts("up", res->sa.s + res->execute.run.run, dst)) { + parse_cleanup(res, dst, force) ; + log_dieu(LOG_EXIT_SYS, "write execute script of: ", res->sa.s + res->name) ; + } /** finish file */ - if (res->execute.finish.run_user) - write_execute_scripts("down", res->sa.s + res->execute.finish.run, dst) ; + if (res->execute.finish.run_user) { + if (!write_execute_scripts("down", res->sa.s + res->execute.finish.run, dst)) { + parse_cleanup(res, dst, force) ; + log_dieu(LOG_EXIT_SYS, "write execute script of: ", res->sa.s + res->name) ; + } + } /** run.user file */ - write_execute_scripts("up.user", res->sa.s + res->execute.run.run_user, dst) ; + if (!write_execute_scripts("up.user", res->sa.s + res->execute.run.run_user, dst)) { + parse_cleanup(res, dst, force) ; + log_dieu(LOG_EXIT_SYS, "write execute script of: ", res->sa.s + res->name) ; + } /** finish.user file */ - if (res->execute.finish.run_user) - write_execute_scripts("down.user", res->sa.s + res->execute.finish.run_user, dst) ; - + if (res->execute.finish.run_user) { + if (!write_execute_scripts("down.user", res->sa.s + res->execute.finish.run_user, dst)) { + parse_cleanup(res, dst, force) ; + log_dieu(LOG_EXIT_SYS, "write execute script of: ", res->sa.s + res->name) ; + } + } } diff --git a/src/lib66/write/write_service.c b/src/lib66/write/write_service.c index e80dfcaf27ac9b7241dee31f8565509b5908c7cb..c42c474d0fc98da6b32663ea6afdbd6e6049e669 100644 --- a/src/lib66/write/write_service.c +++ b/src/lib66/write/write_service.c @@ -28,6 +28,7 @@ #include <66/write.h> #include <66/constants.h> #include <66/sanitize.h> +#include <66/parse.h> /** @Return 0 on fail * @Return 1 on success @@ -35,7 +36,7 @@ * * @workdir -> /var/lib/66/system/<tree>/servicedirs/ * */ -void write_services(resolve_service_t *res, char const *workdir) +void write_services(resolve_service_t *res, char const *workdir, uint8_t force) { log_flow() ; @@ -43,9 +44,9 @@ void write_services(resolve_service_t *res, char const *workdir) uint32_t type = res->type ; char logname = get_rstrlen_until(name, SS_LOG_SUFFIX) ; if (logname > 0) - type = 4 ; + type = 10 ; - log_trace("write service ", name) ; + log_trace("write service: ", name) ; switch(type) { @@ -55,20 +56,21 @@ void write_services(resolve_service_t *res, char const *workdir) case TYPE_CLASSIC: - write_classic(res, workdir) ; + write_classic(res, workdir, force) ; break ; case TYPE_ONESHOT: - write_oneshot(res, workdir) ; + write_oneshot(res, workdir, force) ; break ; - case 4: + case 10: - write_logger(res, workdir) ; + write_logger(res, workdir, force) ; break ; default: + parse_cleanup(res, workdir, force) ; log_die(LOG_EXIT_SYS, "unkown type: ", get_key_by_enum(ENUM_TYPE, type)) ; } diff --git a/src/lib66/write/write_uint.c b/src/lib66/write/write_uint.c index 4224fe6c86c04a00460129dbb1b5d351c7765e81..85e13d5130a1dc7a6671b07dc0f53bcc539582a8 100644 --- a/src/lib66/write/write_uint.c +++ b/src/lib66/write/write_uint.c @@ -20,7 +20,7 @@ #include <skalibs/types.h> -void write_uint(char const *dst, char const *name, uint32_t ui) +int write_uint(char const *dst, char const *name, uint32_t ui) { log_flow() ; @@ -28,5 +28,7 @@ void write_uint(char const *dst, char const *name, uint32_t ui) log_trace("write file: ", dst, "/", name) ; if (!file_write_unsafe(dst, name, number, uint32_fmt(number,ui))) - log_dieusys(LOG_EXIT_SYS, "write: ", dst, "/", name) ; + log_warnusys_return(LOG_EXIT_ZERO, "write: ", dst, "/", name) ; + + return 1 ; }