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

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
parent 7daf7653
No related branches found
No related tags found
No related merge requests found
Showing with 363 additions and 253 deletions
...@@ -42,6 +42,7 @@ extern parse_mill_t MILL_GET_VALUE ; ...@@ -42,6 +42,7 @@ extern parse_mill_t MILL_GET_VALUE ;
/** freed and cleanup*/ /** freed and cleanup*/
extern void ssexec_enable_cleanup(void) ; extern void ssexec_enable_cleanup(void) ;
extern void parse_cleanup(resolve_service_t *res, char const *tmpdir, uint8_t force) ;
/** main */ /** main */
extern void start_parser(char const *sv, ssexec_t *info, uint8_t disable_module, char const *directory_forced) ; extern void start_parser(char const *sv, ssexec_t *info, uint8_t disable_module, char const *directory_forced) ;
......
...@@ -28,6 +28,9 @@ extern void sanitize_livestate(resolve_service_t *res) ; ...@@ -28,6 +28,9 @@ extern void sanitize_livestate(resolve_service_t *res) ;
extern void sanitize_scandir(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_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_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 #endif
...@@ -18,13 +18,16 @@ ...@@ -18,13 +18,16 @@
#include <stdint.h> #include <stdint.h>
#include <66/service.h> #include <66/service.h>
extern void write_services(resolve_service_t *res, char const *workdir) ; 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) ; extern void write_classic(resolve_service_t *res, char const *dst, uint8_t force) ;
extern void write_common(resolve_service_t *res, char const *dst) ; extern void write_oneshot(resolve_service_t *res, char const *dst, uint8_t force) ;
extern void write_environ(char const *name, char const *contents, char const *dst) ; extern void write_logger(resolve_service_t *res, char const *dst, uint8_t force) ;
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 int write_common(resolve_service_t *res, char const *dst) ;
extern void write_oneshot(resolve_service_t *res, char const *dst) ; extern int write_execute_scripts(char const *file, char const *contents, char const *dst) ;
extern void write_uint(char const *dst, char const *name, uint32_t ui) ; 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 #endif
...@@ -14,16 +14,15 @@ ...@@ -14,16 +14,15 @@
#include <string.h> #include <string.h>
#include <stdint.h> #include <stdint.h>
#include <stdint.h> #include <stdlib.h>
#include <stddef.h>
#include <oblibs/log.h> #include <oblibs/log.h>
#include <oblibs/string.h> #include <oblibs/string.h>
#include <oblibs/sastr.h> #include <oblibs/sastr.h>
#include <oblibs/types.h> #include <oblibs/types.h>
#include <oblibs/directory.h>
#include <skalibs/genalloc.h> #include <skalibs/djbunix.h>
#include <66/enum.h> #include <66/enum.h>
#include <66/constants.h> #include <66/constants.h>
...@@ -58,14 +57,120 @@ parse_mill_t MILL_GET_VALUE = \ ...@@ -58,14 +57,120 @@ parse_mill_t MILL_GET_VALUE = \
.skip = " \t\r", .skiplen = 3, .forceskip = 1, \ .skip = " \t\r", .skiplen = 3, .forceskip = 1, \
.inner.debug = "get_value" } ; .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) void parse_service(char const *sv, ssexec_t *info, uint8_t force, uint8_t conf)
{ {
log_flow(); log_flow();
int r ; int r ;
unsigned int areslen = 0, count = 0, pos = 0 ; unsigned int areslen = 0, count = 0, pos = 0 ;
uint8_t rforce = 0 ;
resolve_service_t ares[SS_MAX_SERVICE] ; resolve_service_t ares[SS_MAX_SERVICE] ;
ss_state_t sta = STATE_ZERO ; stralloc sa = STRALLOC_ZERO ;
char main[strlen(sv) + 1] ; char main[strlen(sv) + 1] ;
if (!ob_basename(main, sv)) if (!ob_basename(main, sv))
...@@ -84,29 +189,44 @@ void parse_service(char const *sv, ssexec_t *info, uint8_t force, uint8_t conf) ...@@ -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++) { 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])) if (sanitize_write(&ares[pos], force))
log_dieu(LOG_EXIT_SYS, "read state file of: ", ares[pos].sa.s + ares[pos].name) ; rforce = 1 ;
}
state_set_flag(&sta, STATE_FLAGS_TOINIT, STATE_FLAGS_TRUE) ; if (!auto_stra(&sa, "/tmp/", ares[pos].sa.s + ares[pos].name, ":XXXXXX"))
state_set_flag(&sta, STATE_FLAGS_TOPARSE, STATE_FLAGS_FALSE) ; log_die_nomem("stralloc") ;
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 (!state_write(&sta, &ares[pos])) if (!mkdtemp(sa.s))
log_dieu(LOG_EXIT_SYS, "write state file of: ", ares[pos].sa.s + ares[pos].name) ; 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) ; 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) ; 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) ; service_resolve_array_free(ares, areslen) ;
stralloc_free(&sa) ;
} }
...@@ -35,25 +35,6 @@ ...@@ -35,25 +35,6 @@
#include <66/state.h> #include <66/state.h>
#include <66/svc.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) static void resolve_compare(resolve_service_t *res)
{ {
log_flow() ; log_flow() ;
...@@ -86,11 +67,11 @@ static void resolve_compare(resolve_service_t *res) ...@@ -86,11 +67,11 @@ static void resolve_compare(resolve_service_t *res)
resolve_free(wres) ; 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() ; log_flow() ;
int r ; int r = 0 ;
char dir[strlen(res->sa.s + res->path.servicedir) + 1] ; char dir[strlen(res->sa.s + res->path.servicedir) + 1] ;
...@@ -98,96 +79,31 @@ static int delete(resolve_service_t *res, uint8_t force) ...@@ -98,96 +79,31 @@ static int delete(resolve_service_t *res, uint8_t force)
r = scan_mode(dir, S_IFDIR) ; r = scan_mode(dir, S_IFDIR) ;
if (r < 0) if (r < 0)
log_die(LOG_EXIT_SYS, "unvalid source: ", dir) ; log_diesys(LOG_EXIT_SYS, "unvalid source: ", dir) ;
if (r) { if (r) {
if (force) { 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) ; 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 } else
/** This info should never be executed as long as the parse_frontend /** This info should never be executed as long as the parse_frontend
* check already verifies the service and prevents reaching this point if !force. */ * 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() ; log_flow() ;
int r ; 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)) return r ;
log_dieu(LOG_EXIT_SYS, "write resolve file of service: ", res->sa.s + res->name) ;
} }
...@@ -3,6 +3,7 @@ write_common.o ...@@ -3,6 +3,7 @@ write_common.o
write_environ.o write_environ.o
write_execute_scripts.o write_execute_scripts.o
write_logger.o write_logger.o
write_make_symlink.o
write_oneshot.o write_oneshot.o
write_service.o write_service.o
write_uint.o write_uint.o
......
...@@ -19,27 +19,45 @@ ...@@ -19,27 +19,45 @@
#include <66/service.h> #include <66/service.h>
#include <66/write.h> #include <66/write.h>
#include <66/parse.h>
/* dst e.g. /var/lib/66/system/service/svc/<name> */ /* 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() ; log_flow() ;
/**notification,timeout, ... */ /**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 */ /** 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 */ /** finish file */
if (res->execute.finish.run_user) if (res->execute.finish.run_user) {
write_execute_scripts("finish", res->sa.s + res->execute.finish.run, dst) ; 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 */ /** 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 */ /** finish.user file */
if (res->execute.finish.run_user) if (res->execute.finish.run_user) {
write_execute_scripts("finish.user", res->sa.s + res->execute.finish.run_user, dst) ; 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) ;
}
}
} }
...@@ -14,6 +14,7 @@ ...@@ -14,6 +14,7 @@
#include <string.h> #include <string.h>
#include <stdlib.h>
#include <errno.h> #include <errno.h>
#include <oblibs/log.h> #include <oblibs/log.h>
...@@ -32,7 +33,7 @@ ...@@ -32,7 +33,7 @@
#include <66/environ.h> #include <66/environ.h>
#include <66/enum.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() ; log_flow() ;
...@@ -40,34 +41,38 @@ void write_common(resolve_service_t *res, char const *dst) ...@@ -40,34 +41,38 @@ void write_common(resolve_service_t *res, char const *dst)
if (res->execute.down) { if (res->execute.down) {
log_trace("create file: ", dst, "/down") ; log_trace("create file: ", dst, "/down") ;
if (!file_create_empty(dst, "down", 0644)) 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 */ /** notification-fd */
if (res->notify) 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 /** timeout family
* *
* Only write timeout file for classic service. * Only write timeout file for classic service.
* All others services are read directly through * S6-supervise need it otherwise it's read directly
* the resolve file at start process. */ * from the resolve file at start process. */
if (res->execute.timeout.kill) 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) 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 */ /** max-death-tally */
if (res->maxdeath) 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 */ /** down-signal */
if (res->execute.downsignal) 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) { if (res->environ.env && res->type != TYPE_MODULE) {
stralloc dst = STRALLOC_ZERO ; stralloc dst = STRALLOC_ZERO ;
...@@ -76,9 +81,10 @@ void write_common(resolve_service_t *res, char const *dst) ...@@ -76,9 +81,10 @@ void write_common(resolve_service_t *res, char const *dst)
auto_strings(name, ".", res->sa.s + res->name) ; auto_strings(name, ".", res->sa.s + res->name) ;
if (!env_prepare_for_write(&dst, &contents, res)) 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(&dst) ;
stralloc_free(&contents) ; stralloc_free(&contents) ;
...@@ -91,28 +97,71 @@ void write_common(resolve_service_t *res, char const *dst) ...@@ -91,28 +97,71 @@ void write_common(resolve_service_t *res, char const *dst)
size_t pos = 0 ; size_t pos = 0 ;
stralloc sa = STRALLOC_ZERO ; stralloc sa = STRALLOC_ZERO ;
char *src = res->sa.s + res->path.frontend ; 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)) 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) { FOREACH_SASTR(&sa, pos) {
char *what = sa.s + pos ; char *what = sa.s + pos ;
int fd ;
size_t wlen = strlen(what) ;
char tmp[SS_MAX_PATH_LEN + 1] ; 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)) what = basename ;
log_dieu(LOG_EXIT_SYS, "get dirname of: ", src) ;
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)) if (!ob_dirname(b, src))
log_dieusys(LOG_EXIT_SYS, "find absolute path of: ", what) ; 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 { } else {
auto_strings(tmp, what) ; auto_strings(tmp, basedir, what) ;
} }
r = scan_mode(tmp, S_IFDIR) ; r = scan_mode(tmp, S_IFDIR) ;
...@@ -120,16 +169,23 @@ void write_common(resolve_service_t *res, char const *dst) ...@@ -120,16 +169,23 @@ void write_common(resolve_service_t *res, char const *dst)
r = scan_mode(tmp, S_IFREG) ; r = scan_mode(tmp, S_IFREG) ;
if (!r) if (!r)
log_dieusys(LOG_EXIT_SYS, "find: ", tmp) ; log_warnusys_return(LOG_EXIT_ZERO, "find: ", tmp) ;
if (r < 0) { else if (r < 0) {
errno = ENOTSUP ; 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) ; auto_strings(dest, dst, "/", what) ;
if (!hiercopy(tmp, dst))
log_dieusys(LOG_EXIT_SYS, "copy: ", tmp, " to: ", dst) ; 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 ;
} }
...@@ -18,7 +18,7 @@ ...@@ -18,7 +18,7 @@
#include <oblibs/files.h> #include <oblibs/files.h>
#include <oblibs/types.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() ; log_flow() ;
...@@ -27,10 +27,12 @@ void write_environ(char const *name, char const *contents, char const *dst) ...@@ -27,10 +27,12 @@ void write_environ(char const *name, char const *contents, char const *dst)
r = scan_mode(dst,S_IFDIR) ; r = scan_mode(dst,S_IFDIR) ;
if (r < 0) 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) 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)) 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 ;
} }
...@@ -23,7 +23,7 @@ ...@@ -23,7 +23,7 @@
#define FAKELEN strlen(run) #define FAKELEN strlen(run)
#endif #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() ; log_flow() ;
...@@ -37,8 +37,10 @@ void write_execute_scripts(char const *file, char const *contents, char const *d ...@@ -37,8 +37,10 @@ void write_execute_scripts(char const *file, char const *contents, char const *d
log_trace("create file: ", dst, "/", file) ; log_trace("create file: ", dst, "/", file) ;
if (!file_write_unsafe(dst, file, run, FAKELEN)) 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) if (chmod(write, 0755) < 0)
log_dieusys(LOG_EXIT_SYS, "chmod", write) ; log_warnusys_return(LOG_EXIT_ZERO, "chmod", write) ;
return 1 ;
} }
/*
* 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) ;
}
...@@ -31,6 +31,7 @@ ...@@ -31,6 +31,7 @@
#include <66/utils.h> #include <66/utils.h>
#include <s6/config.h> #include <s6/config.h>
#include <66/constants.h> #include <66/constants.h>
#include <66/parse.h>
#include <s6/config.h> #include <s6/config.h>
...@@ -40,7 +41,7 @@ ...@@ -40,7 +41,7 @@
/** @destination -> /var/lib/66/system/service/svc/<name> */ /** @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() ; log_flow() ;
...@@ -50,48 +51,72 @@ void write_logger(resolve_service_t *res, char const *destination) ...@@ -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 ; char *logrunner = res->execute.run.runas ? res->sa.s + res->execute.run.runas : SS_LOGGER_RUNNER ;
if (res->execute.timeout.kill) if (res->execute.timeout.kill) {
write_uint(destination, "timeout-kill", 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) if (res->execute.timeout.finish) {
write_uint(destination, "timeout-finish", 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 */ /** 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 destination */
log_trace("create directory: ", res->sa.s + res->logger.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) ; 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 (!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) ; 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) ; log_dieusys(LOG_EXIT_SYS, "chown: ", res->sa.s + res->logger.destination) ;
}
} }
char write[strlen(destination) + 10] ; char write[strlen(destination) + 10] ;
/** run script */ /** run script */
log_trace("create file: ", destination, "/run") ; 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") ; log_dieusys(LOG_EXIT_SYS, "write: ", destination, "/run.user") ;
}
auto_strings(write, destination, "/run") ; 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) ; log_dieusys(LOG_EXIT_SYS, "chmod", write) ;
}
/** run.user script */ /** run.user script */
log_trace("create file: ", destination, "/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))) 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") ; log_dieusys(LOG_EXIT_SYS, "write: ", destination, "/run.user") ;
}
auto_strings(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) ; log_dieusys(LOG_EXIT_SYS, "chmod", write) ;
}
} }
...@@ -16,26 +16,43 @@ ...@@ -16,26 +16,43 @@
#include <66/service.h> #include <66/service.h>
#include <66/write.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() ; log_flow() ;
/**notification,timeout, ... */ /**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 */ /** 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 */ /** finish file */
if (res->execute.finish.run_user) if (res->execute.finish.run_user) {
write_execute_scripts("down", res->sa.s + res->execute.finish.run, dst) ; 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 */ /** 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 */ /** finish.user file */
if (res->execute.finish.run_user) if (res->execute.finish.run_user) {
write_execute_scripts("down.user", res->sa.s + res->execute.finish.run_user, dst) ; 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) ;
}
}
} }
...@@ -28,6 +28,7 @@ ...@@ -28,6 +28,7 @@
#include <66/write.h> #include <66/write.h>
#include <66/constants.h> #include <66/constants.h>
#include <66/sanitize.h> #include <66/sanitize.h>
#include <66/parse.h>
/** @Return 0 on fail /** @Return 0 on fail
* @Return 1 on success * @Return 1 on success
...@@ -35,7 +36,7 @@ ...@@ -35,7 +36,7 @@
* *
* @workdir -> /var/lib/66/system/<tree>/servicedirs/ * @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() ; log_flow() ;
...@@ -43,9 +44,9 @@ void write_services(resolve_service_t *res, char const *workdir) ...@@ -43,9 +44,9 @@ void write_services(resolve_service_t *res, char const *workdir)
uint32_t type = res->type ; uint32_t type = res->type ;
char logname = get_rstrlen_until(name, SS_LOG_SUFFIX) ; char logname = get_rstrlen_until(name, SS_LOG_SUFFIX) ;
if (logname > 0) if (logname > 0)
type = 4 ; type = 10 ;
log_trace("write service ", name) ; log_trace("write service: ", name) ;
switch(type) { switch(type) {
...@@ -55,20 +56,21 @@ void write_services(resolve_service_t *res, char const *workdir) ...@@ -55,20 +56,21 @@ void write_services(resolve_service_t *res, char const *workdir)
case TYPE_CLASSIC: case TYPE_CLASSIC:
write_classic(res, workdir) ; write_classic(res, workdir, force) ;
break ; break ;
case TYPE_ONESHOT: case TYPE_ONESHOT:
write_oneshot(res, workdir) ; write_oneshot(res, workdir, force) ;
break ; break ;
case 4: case 10:
write_logger(res, workdir) ; write_logger(res, workdir, force) ;
break ; break ;
default: default:
parse_cleanup(res, workdir, force) ;
log_die(LOG_EXIT_SYS, "unkown type: ", get_key_by_enum(ENUM_TYPE, type)) ; log_die(LOG_EXIT_SYS, "unkown type: ", get_key_by_enum(ENUM_TYPE, type)) ;
} }
......
...@@ -20,7 +20,7 @@ ...@@ -20,7 +20,7 @@
#include <skalibs/types.h> #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() ; log_flow() ;
...@@ -28,5 +28,7 @@ void write_uint(char const *dst, char const *name, uint32_t ui) ...@@ -28,5 +28,7 @@ void write_uint(char const *dst, char const *name, uint32_t ui)
log_trace("write file: ", dst, "/", name) ; log_trace("write file: ", dst, "/", name) ;
if (!file_write_unsafe(dst, name, number, uint32_fmt(number,ui))) 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 ;
} }
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