From 69f24c1e0e2346dc7bc285a9ba9e250431884d22 Mon Sep 17 00:00:00 2001 From: obarun <eric@obarun.org> Date: Sun, 28 May 2023 16:37:59 +1100 Subject: [PATCH] pass through temporary directory. Parse the service and write the result in a temporary directory. When the write process is finished the directory is copied to the original service directory overwritten a same file. The symlink /var/lib/66/system/.resolve/service/<name> is made at the complete end of the process. So we can clean the mess removing the temporary directory and avoid to change the original service directory before the end of the process. The state of system should be clean event on crash of the parse process --- src/include/66/parse.h | 1 + src/include/66/sanitize.h | 5 +- src/include/66/write.h | 19 ++- src/lib66/parse/parse_service.c | 156 ++++++++++++++++--- src/lib66/sanitize/sanitize_write.c | 100 +----------- src/lib66/write/deps-lib/deps | 1 + src/lib66/write/write_classic.c | 34 +++- src/lib66/write/write_common.c | 112 +++++++++---- src/lib66/write/write_environ.c | 10 +- src/lib66/write/write_execute_scripts.c | 8 +- src/lib66/write/write_execute_scripts_user.c | 58 ------- src/lib66/write/write_logger.c | 55 +++++-- src/lib66/write/write_oneshot.c | 35 +++-- src/lib66/write/write_service.c | 16 +- src/lib66/write/write_uint.c | 6 +- 15 files changed, 363 insertions(+), 253 deletions(-) delete mode 100644 src/lib66/write/write_execute_scripts_user.c diff --git a/src/include/66/parse.h b/src/include/66/parse.h index de23ecb5..5860ed29 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 121c96de..a166e8f2 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 e20b3cf9..cca7812b 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 18536647..d1d21bad 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 4f685511..85785199 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 d07d1f64..8c3cc1ba 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 84e32b0c..f0de0219 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 12f760a9..ee2c8c3d 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 46482ef3..34d28576 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 ffac88a1..78c5d7b0 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 7ddd99a8..00000000 --- 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 f56e14bd..d175fa21 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 071f50ad..d5789684 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 e80dfcaf..c42c474d 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 4224fe6c..85e13d51 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 ; } -- GitLab